]> mj.ucw.cz Git - libucw.git/commitdiff
Logging: Improved log-syslog.
authorMartin Mares <mj@ucw.cz>
Mon, 16 Feb 2009 22:38:22 +0000 (23:38 +0100)
committerMartin Mares <mj@ucw.cz>
Mon, 16 Feb 2009 22:38:22 +0000 (23:38 +0100)
It now accepts the name of the facility instead of the internal syslog code,
and also options for openlog(). Heavily commented on syslog deficiencies.

ucw/log-conf.c
ucw/log-syslog.c
ucw/log.c
ucw/log.h

index 9d36d8a94b27450022fb2cc4966c9571919bb1ad..9eea204eb0043fa9cf32a594faaf13ff025b9296 100644 (file)
@@ -13,7 +13,7 @@
 #include "ucw/simple-lists.h"
 
 #include <string.h>
-#include <syslog.h>    // FIXME
+#include <syslog.h>
 
 struct stream_config {
   cnode n;
@@ -32,6 +32,8 @@ stream_commit(void *ptr)
 
   if (c->file_name && c->syslog_facility)
     return "Both FileName and SyslogFacility selected";
+  if (c->syslog_facility && !log_syslog_facility_exists(c->syslog_facility))
+    return cf_printf("SyslogFacility `%s' is not recognized", c->syslog_facility);
   return NULL;
 }
 
@@ -134,7 +136,7 @@ do_new_configured(struct stream_config *c)
   if (c->file_name)
     ls = log_new_file(c->file_name);
   else if (c->syslog_facility)
-    ls = log_new_syslog(LOG_USER, NULL);       // FIXME: Facility
+    ls = log_new_syslog(c->syslog_facility, 0);                // FIXME: Logging of PID
   else
     ls = log_new_stream(sizeof(*ls));
 
@@ -170,6 +172,7 @@ int main(int argc, char **argv)
   struct log_stream *ls = log_new_configured("combined");
   msg(L_INFO | ls->regnum, "Hello, universe!");
 
+  log_close_all();
   return 0;
 }
 
index dae84005618899439df6310bbf0f923c8e071669..e3bbd6b5904273acf8341df15f7019ef3a16c634 100644 (file)
@@ -11,6 +11,7 @@
 #include "ucw/lib.h"
 #include "ucw/log.h"
 
+#include <string.h>
 #include <syslog.h>
 
 struct syslog_stream {
@@ -18,11 +19,50 @@ struct syslog_stream {
   int facility;
 };
 
+static int syslog_open_count;
+
 static void
-syslog_close(struct log_stream *ls)
+syslog_close(struct log_stream *ls UNUSED)
+{
+  if (!--syslog_open_count)
+    closelog();
+}
+
+/* Convert syslog facility to its identifier. */
+static int
+syslog_facility(const char *name)
 {
-  if (ls->name)
-    xfree(ls->name);
+  // Unfortunately, there is no standard way how to get at the list of facility names
+  static const struct {
+    const char *name;
+    int id;
+  } facilities[] = {
+    { "auth",          LOG_AUTH },
+    { "authpriv",      LOG_AUTHPRIV },
+    { "cron",          LOG_CRON },
+    { "daemon",                LOG_DAEMON },
+    { "ftp",           LOG_FTP },
+    { "kern",          LOG_KERN },
+    { "lpr",           LOG_LPR },
+    { "mail",          LOG_MAIL },
+    { "news",          LOG_NEWS },
+    { "syslog",                LOG_SYSLOG },
+    { "user",          LOG_USER },
+    { "uucp",          LOG_UUCP },
+    { "local0",                LOG_LOCAL0 },
+    { "local1",                LOG_LOCAL1 },
+    { "local2",                LOG_LOCAL2 },
+    { "local3",                LOG_LOCAL3 },
+    { "local4",                LOG_LOCAL4 },
+    { "local5",                LOG_LOCAL5 },
+    { "local6",                LOG_LOCAL6 },
+    { "local7",                LOG_LOCAL7 },
+  };
+
+  for (uns i=0; i < ARRAY_SIZE(facilities); i++)
+    if (!strcmp(facilities[i].name, name))
+      return facilities[i].id;
+  return -1;
 }
 
 /* Convert severity level to syslog constants */
@@ -51,26 +91,33 @@ syslog_handler(struct log_stream *ls, struct log_msg *m)
   ASSERT(ls);
   ASSERT(m);
 
-  // FIXME: Logging of PID
   prio = syslog_level(LS_GET_LEVEL(m->flags)) | ss->facility;
-  if (ls->name)
-    syslog(prio, "%s: %s", ls->name, m->m);
-  else
-    syslog(prio, "%s", m->m);
+  syslog(prio, "%s", m->m);
   return 0;
 }
 
 struct log_stream *
-log_new_syslog(int facility, const char *name)
+log_new_syslog(const char *facility, int options)
 {
+  int fac = syslog_facility(facility);
+  if (fac < 0)
+    die("No such syslog facility: %s", facility);
+
   struct log_stream *ls = log_new_stream(sizeof(struct syslog_stream));
   struct syslog_stream *ss = (struct syslog_stream *) ls;
-  if (name)
-    ls->name = xstrdup(name);
+  ls->name = "syslog";
   ls->msgfmt = 0;
   ls->handler = syslog_handler;
   ls->close = syslog_close;
-  ss->facility = facility;
+  ss->facility = fac;
+
+  if (!syslog_open_count++)
+    openlog(log_title, options, LOG_INFO);
   return ls;
-  // FIXME: L_SIGHANDLER?
+}
+
+int
+log_syslog_facility_exists(const char *facility)
+{
+  return (syslog_facility(facility) >= 0);
 }
index c6a095be4b218cfb8af5728000c6903913fdfb96..2563c799aa0b09f995e54b42592ad08deef228a7 100644 (file)
--- a/ucw/log.c
+++ b/ucw/log.c
@@ -332,7 +332,7 @@ log_fork(void)
 
 int main(void)
 {
-  struct log_stream *ls = log_new_syslog(LOG_USER, "syslog");
+  struct log_stream *ls = log_new_syslog("local3", 0);
   msg(L_INFO | ls->regnum, "Brum <%300s>", ":-)");
   log_set_format(log_default_stream(), ~0U, LSFMT_USEC);
   msg(L_INFO, "Brum <%300s>", ":-)");
index bb53dad01936757b5415622820331043de5b5428..798fc2e75b162893202afaa34026c1526ce032c7 100644 (file)
--- a/ucw/log.h
+++ b/ucw/log.h
@@ -190,18 +190,32 @@ int log_switch(void);                     /** Switch log files manually. **/
  * === Logging to syslog
  *
  * This log stream uses the libc interface to the system logging daemon (`syslogd`).
- * As syslog serverities differ from our scheme, they are translated; if you
- * are interested in details, search for syslog_level().
+ * This interface has several limitations:
  *
- * Syslog also provides its own timestamps, so we turn off all formatting
- * of the LibUCW logger.
+ *   * Syslog are poorer than our scheme, so they are translated with a slight
+ *     loss of information (most importantly, the distinction between local and
+ *     remote messages is lost). If you are interested in details, search the
+ *     source for syslog_level().
+ *   * Syslog options (especially logging of PID with each message) must be fixed
+ *     during initialization of the logger
+ *   * Syslog provides its own formatting, so we turn off all formatting flags
+ *     of the LibUCW logger. You can override this manually by setting the @msgfmt
+ *     field of the log stream, but the result won't be nice.
+ *   * Syslog does not support timestamps with sub-second precision.
  ***/
 
 /**
  * Create a log stream for logging to a selected syslog facility.
- * The @name is an optional prefix of the messages.
+ * The @options are passed to openlog(). (Beware, due to limitations of the
+ * syslog interface in libc, the @options are shared for all syslog streams
+ * and they are applied when the first stream is created.)
  **/
-struct log_stream *log_new_syslog(int facility, const char *name);
+struct log_stream *log_new_syslog(const char *facility, int options);
+
+/**
+ * Verify that a facility of the given name exists. Return 1 if it does, 0 otherwise.
+ **/
+int log_syslog_facility_exists(const char *facility);
 
 /***
  * === Configuring log streams