Author: visnov
Date: Tue Sep 9 15:51:00 2008
New Revision: 50908
URL: http://svn.opensuse.org/viewcvs/yast?rev=50908&view=rev
Log:
- implemented y2useritem, y2usernote for fate #100386
Added:
trunk/core/liby2util-r/src/include/y2util/y2changes.h
trunk/core/liby2util-r/src/y2changes.cc
Modified:
trunk/core/liby2util-r/src/Makefile.am
trunk/core/liby2util-r/src/include/y2util/Makefile.am
trunk/core/libycp/src/YCPBuiltinMisc.cc
trunk/core/package/yast2-core.changes
Modified: trunk/core/liby2util-r/src/Makefile.am
URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/liby2util-r/src/Makefile.am?rev=50908&r1=50907&r2=50908&view=diff
==============================================================================
--- trunk/core/liby2util-r/src/Makefile.am (original)
+++ trunk/core/liby2util-r/src/Makefile.am Tue Sep 9 15:51:00 2008
@@ -22,7 +22,8 @@
Y2SLog.cc \
miniini.cc \
stringutil.cc \
- y2log.cc
+ y2log.cc \
+ y2changes.cc
liby2util_la_LDFLAGS = -version-info 4:0:0
Modified: trunk/core/liby2util-r/src/include/y2util/Makefile.am
URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/liby2util-r/src/include/y2util/Makefile.am?rev=50908&r1=50907&r2=50908&view=diff
==============================================================================
--- trunk/core/liby2util-r/src/include/y2util/Makefile.am (original)
+++ trunk/core/liby2util-r/src/include/y2util/Makefile.am Tue Sep 9 15:51:00 2008
@@ -19,7 +19,8 @@
Y2SLog.h \
miniini.h \
stringutil.h \
- y2log.h
+ y2log.h \
+ y2changes.h
#<INSTALL-HEADER-TARGET>
Added: trunk/core/liby2util-r/src/include/y2util/y2changes.h
URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/liby2util-r/src/include/y2util/y2changes.h?rev=50908&view=auto
==============================================================================
--- trunk/core/liby2util-r/src/include/y2util/y2changes.h (added)
+++ trunk/core/liby2util-r/src/include/y2util/y2changes.h Tue Sep 9 15:51:00 2008
@@ -0,0 +1,33 @@
+/* y2changes.h
+ *
+ * YaST2: Core system
+ *
+ * YaST2 user-level logging implementation
+ *
+ * Authors: Mathias Kettner
+ * Michal Svec
+ * Stanislav Visnovsky
+ */
+
+#ifndef _y2changes_h
+#define _y2changes_h
+
+#include <string>
+#include
+
+using std::string;
+
+/* Logging functions */
+
+enum logcategory_t {
+ CHANGES_ITEM = 0, // system view, typically execution of a file
+ CHANGES_NOTE = 1, // additional information for the user, e.g. start of a module
+};
+
+// Implements y2changes_function
+void y2changes_function (logcategory_t category, const char *format, ...) __attribute__ ((format (printf, 2, 3)));
+
+#define y2useritem(format, args...) y2changes_function(CHANGES_ITEM, format,##args)
+#define y2usernote(format, args...) y2changes_function(CHANGES_NOTE, format,##args)
+
+#endif /* _y2changes_h */
Added: trunk/core/liby2util-r/src/y2changes.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/liby2util-r/src/y2changes.cc?rev=50908&view=auto
==============================================================================
--- trunk/core/liby2util-r/src/y2changes.cc (added)
+++ trunk/core/liby2util-r/src/y2changes.cc Tue Sep 9 15:51:00 2008
@@ -0,0 +1,306 @@
+/* y2changes.cc
+ *
+ * YaST2: Core system
+ *
+ * YaST2 user-level logging implementation (based on y2log.cc)
+ *
+ * Authors: Mathias Kettner
+ * Thomas Roelz
+ * Michal Svec
+ * Arvin Schnell
+ * Martin Vidner
+ * Stanislav Visnovsky
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include <limits>
+#include <list>
+
+#include "y2util/y2changes.h"
+#include "y2util/stringutil.h"
+#include "y2util/PathInfo.h"
+#include
+
+/* Defines */
+
+#define _GNU_SOURCE 1 /* Needed for vasprintf below */
+
+#define Y2CHANGES_DATE "%Y-%m-%d %H:%M:%S" /* The date format */
+
+// 1 timestamp, 2 level, 3 hostname
+#define Y2CHANGES_FORMAT "%s <%s> %s "
+// 1 level, 2 common part
+#define Y2CHANGES_SYSLOG "<%d>%s "
+
+#define Y2CHANGES_MAXSIZE 10* 1024 * 1024 /* Maximal logfile size */
+#define Y2CHANGES_MAXNUM 10 /* Maximum logfiles number */
+
+#define LOGDIR "/var/log/YaST2"
+
+#define Y2CHANGES_ROOT LOGDIR "/y2changes"
+#define Y2CHANGES_USER "/.y2changes" /* Relative to $HOME */
+#define Y2CHANGES_FALLBACK "/y2changes"
+
+#define Y2CHANGES_VAR_SIZE "Y2MAXLOGSIZE"
+#define Y2CHANGES_VAR_NUM "Y2MAXLOGNUM"
+
+#define Y2CHANGES_FACILITY "yast2"
+
+static bool did_set_logname = false;
+
+static const char *logname;
+
+static off_t maxlogsize;
+static int maxlognum;
+
+static bool log_to_file = true;
+static bool log_to_syslog = false;
+
+static FILE *Y2CHANGES_STDERR = stderr; /* Default output */
+
+/* static prototypes */
+static void do_log_syslog( const char* logmessage );
+static void do_log_yast( const char* logmessage );
+static void shift_log_files(string filename);
+
+static const char *log_messages[] = {
+ "item",
+ "note",
+};
+
+/**
+ * y2changes must use a private copy of stderr, esp. in case we're always logging
+ * to it (option "-l -"). Some classes like liby2(ExternalProgram) redirect
+ * stderr in order to redirect an external programs error output. As a side
+ * effect Y2CHANGES output done after the redirection would show up in the external
+ * programs output file instead of yast2's stderr.
+ */
+static int dup_stderr()
+{
+ int dupstderr = dup( 2 );
+ if ( dupstderr != -1 ) {
+ FILE * newstderr = fdopen( dupstderr, "a" );
+
+ if ( newstderr == NULL ) {
+ fprintf( Y2CHANGES_STDERR, "y2log: Can't fdopen new stderr: %s.\n", strerror (errno) );
+ }
+ else {
+ fcntl (fileno (newstderr), F_SETFD, fcntl (fileno (newstderr), F_GETFD) | FD_CLOEXEC);
+ Y2CHANGES_STDERR = newstderr;
+ }
+ }
+ else {
+ fprintf( Y2CHANGES_STDERR, "y2log: Can't dup stderr: %s.\n", strerror (errno) );
+ }
+ return 1;
+}
+static int variable_not_used = dup_stderr();
+
+static FILE * open_logfile()
+{
+ FILE *logfile = Y2CHANGES_STDERR;
+ if (*logname != '-') {
+ logfile = fopen (logname, "a");
+ // try creating the directory if it may be missing
+ if (!logfile && errno == ENOENT) {
+ PathInfo::assert_dir (Pathname::dirname(logname), 0700);
+ // and retry
+ logfile = fopen (logname, "a");
+ }
+ if (!logfile) {
+ fprintf (Y2CHANGES_STDERR, "y2log: Error opening logfile '%s': %s.\n",
+ logname, strerror (errno));
+ return NULL;
+ }
+ }
+ return logfile;
+}
+
+string y2_changesfmt_prefix (logcategory_t category)
+{
+ /* Prepare the host name */
+ char hostname[1024];
+ if (gethostname(hostname, 1024))
+ strncpy(hostname, "unknown", 1024);
+
+ // just 1 second precision
+ time_t timestamp = time (NULL);
+ struct tm *brokentime = localtime (×tamp);
+ char date[50]; // that's big enough
+ strftime (date, sizeof (date), Y2CHANGES_DATE, brokentime);
+
+ char * result_c = NULL;
+ asprintf (&result_c, Y2CHANGES_FORMAT, date, log_messages[category], hostname );
+ string result = result_c;
+ free (result_c);
+
+ return result;
+}
+
+/**
+ * The universal logger function
+ */
+void y2changes_function (logcategory_t category, const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+
+ /* Prepare the log text */
+ char *logtext = NULL;
+ vasprintf(&logtext, format, ap); /* GNU extension needs the define above */
+ string common = logtext;
+ common += '\n';
+ free (logtext);
+
+ if(log_to_syslog) {
+ syslog (LOG_NOTICE, Y2CHANGES_SYSLOG, category, common.c_str ());
+ }
+
+ if(log_to_file) {
+ string tolog = y2_changesfmt_prefix (category) + common;
+ do_log_yast (tolog.c_str ());
+ }
+
+ va_end(ap);
+}
+
+
+static
+void do_log_syslog( const char* logmessage )
+{
+ syslog (LOG_NOTICE, "%s", logmessage);
+}
+
+/**
+ * Logfile name initialization
+ */
+static void set_log_filename (string fname)
+{
+ did_set_logname = true;
+
+ if(log_to_syslog) openlog("yast2", LOG_PID, LOG_DAEMON);
+ if(!log_to_file) return;
+
+ struct passwd *pw = getpwuid( geteuid() );
+ const char *filename = fname.c_str();
+
+ char *env_maxlogsize = getenv(Y2CHANGES_VAR_SIZE);
+ if ( env_maxlogsize ) {
+ stringutil::strtonum( env_maxlogsize, maxlogsize );
+ // prevent overflow (#156149)
+ const off_t limit = std::numeric_limits::max();
+ const off_t limit_k = limit / 1024;
+ if (maxlogsize <= limit_k)
+ maxlogsize *= 1024;
+ else
+ maxlogsize = limit;
+ } else
+ maxlogsize = Y2CHANGES_MAXSIZE;
+
+ char *env_maxlognum = getenv(Y2CHANGES_VAR_NUM);
+ maxlognum = env_maxlognum ? atoi(env_maxlognum) : Y2CHANGES_MAXNUM;
+
+ /* Assign logfile name */
+
+ if ((filename == 0) || (*filename == 0))
+ { /* No filename --> use defaults */
+ if (geteuid()) { /* Non root */
+ if (!pw)
+ {
+ fprintf( Y2CHANGES_STDERR,
+ "Cannot read pwd entry of user id %d. Logfile will be '%s'.\n",
+ geteuid(), Y2CHANGES_FALLBACK );
+
+ logname = Y2CHANGES_FALLBACK;
+ }
+ else
+ {
+ // never freed
+ char * my_logname = (char *)malloc (strlen (pw->pw_dir) + strlen (Y2CHANGES_USER) + 1);
+ strcpy (my_logname, pw->pw_dir);
+ logname = strcat (my_logname, Y2CHANGES_USER);
+ }
+ }
+ else /* Root */
+ logname = Y2CHANGES_ROOT;
+ }
+ else
+ logname = strdup (filename); /* Explicit assignment */
+}
+
+
+static
+void do_log_yast( const char* logmessage )
+{
+ /* Prepare the logfile name */
+ if(!did_set_logname) set_log_filename("");
+
+ /* Prepare the logfile */
+ shift_log_files (string (logname));
+
+ FILE *logfile = open_logfile ();
+ if (!logfile)
+ return;
+
+ fprintf (logfile, "%s", logmessage);
+
+ /* Clean everything */
+ if (logfile && logfile != Y2CHANGES_STDERR)
+ fclose (logfile);
+ else
+ fflush (logfile);
+}
+
+static string old (const string & filename, int i, const char * suffix) {
+ char numbuf[8];
+ sprintf (numbuf, "%d", i);
+ return filename + "-" + numbuf + suffix;
+}
+
+/**
+ * Maintain logfiles
+ * We do all of this ourselves because during the installation
+ * logrotate does not run
+ */
+static void shift_log_files(string filename)
+{
+ struct stat buf;
+
+ if( stat(filename.c_str(), &buf) )
+ return;
+
+ if( buf.st_size <= maxlogsize )
+ return;
+
+ static const char * gz = ".gz";
+ // Delete the last logfile
+ remove (old (filename, maxlognum - 1, "" ).c_str());
+ remove (old (filename, maxlognum - 1, gz).c_str());
+
+ // rename existing ones
+ for( int f = maxlognum-2; f > 0; f-- )
+ {
+ rename (old (filename, f, "").c_str(), old (filename, f+1, "").c_str());
+ rename (old (filename, f, gz).c_str(), old (filename, f+1, gz).c_str());
+ }
+
+ // rename and compress first one
+ rename( filename.c_str(), old (filename, 1, "").c_str() );
+ // fate#300637: compress!
+ // may fail, but so what
+ system( ("nice -n 20 gzip " + old (filename, 1, "") + " &").c_str());
+}
+
+
+/* EOF */
Modified: trunk/core/libycp/src/YCPBuiltinMisc.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/libycp/src/YCPBuiltinMisc.cc?rev=50908&r1=50907&r2=50908&view=diff
==============================================================================
--- trunk/core/libycp/src/YCPBuiltinMisc.cc (original)
+++ trunk/core/libycp/src/YCPBuiltinMisc.cc Tue Sep 9 15:51:00 2008
@@ -35,6 +35,7 @@
#include "ycp/StaticDeclaration.h"
#include "ycp/y2log.h"
+#include "y2util/y2changes.h"
#include "ycp/ExecutionEnvironment.h"
extern StaticDeclaration static_declarations;
@@ -614,6 +615,64 @@
}
+static YCPValue
+Y2UserItem (const YCPString & format, const YCPList & args)
+{
+ /**
+ * @builtin y2useritem
+ * @short Log an user-level system message to the y2changes
+ *
+ * @param string FORMAT
+ * @param any PAR1
+ * @param any PAR2
+ * @param any ...
+ * @return void
+ * @see sformat
+ *
+ * @usage y2useritem("Executing reboot")
+ */
+
+ YCPString arg = s_sformat (format, args);
+ if (arg.isNull () || !arg->isString ())
+ {
+ return YCPNull ();
+ }
+
+ y2useritem ("%s", arg->value().c_str());
+
+ return YCPVoid();
+}
+
+
+static YCPValue
+Y2UserNote (const YCPString & format, const YCPList & args)
+{
+ /**
+ * @builtin y2usernote
+ * @short Log an user-level addional message to the y2changes
+ *
+ * @param string FORMAT
+ * @param any PAR1
+ * @param any PAR2
+ * @param any ...
+ * @return void
+ * @see sformat
+ *
+ * @usage y2usernote("Starting module Bee")
+ */
+
+ YCPString arg = s_sformat (format, args);
+ if (arg.isNull () || !arg->isString ())
+ {
+ return YCPNull ();
+ }
+
+ y2usernote ("%s", arg->value().c_str());
+
+ return YCPVoid();
+}
+
+
YCPBuiltinMisc::YCPBuiltinMisc ()
{
// must be static, registerDeclarations saves a pointer to it!
@@ -643,6 +702,9 @@
{ "y2error", "void (integer, string, ...)", (void *)Y2FError, DECL_NIL|DECL_WILD },
{ "y2security", "void (integer, string, ...)", (void *)Y2FSecurity, DECL_NIL|DECL_WILD },
{ "y2internal", "void (integer, string, ...)", (void *)Y2FInternal, DECL_NIL|DECL_WILD },
+ // user-level logging
+ { "y2useritem", "void (string, ...)", (void *)Y2UserItem, DECL_NIL|DECL_WILD|DECL_FORMATTED },
+ { "y2usernote", "void (string, ...)", (void *)Y2UserNote, DECL_NIL|DECL_WILD|DECL_FORMATTED },
{ 0 }
};
Modified: trunk/core/package/yast2-core.changes
URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/package/yast2-core.changes?rev=50908&r1=50907&r2=50908&view=diff
==============================================================================
--- trunk/core/package/yast2-core.changes (original)
+++ trunk/core/package/yast2-core.changes Tue Sep 9 15:51:00 2008
@@ -1,4 +1,10 @@
-------------------------------------------------------------------
+Tue Sep 9 15:49:07 CEST 2008 - visnov@suse.cz
+
+- Added y2useritem and y2usernote builtins for user-level
+ action log (Fate #100386)
+
+-------------------------------------------------------------------
Tue Sep 9 11:39:07 CEST 2008 - locilka@suse.cz
- Adjusted STDOUT in ycp.pm to use 'utf8'.
--
To unsubscribe, e-mail: yast-commit+unsubscribe@opensuse.org
For additional commands, e-mail: yast-commit+help@opensuse.org