]> mj.ucw.cz Git - libucw.git/blobdiff - ucw/log-syslog.c
Opt: Introduced contexts
[libucw.git] / ucw / log-syslog.c
index f92b616584910096d8e273258c80e00b96ecf1cc..ee8b9e8353d8fbe09599a3954085ab80ee1063ab 100644 (file)
  *     of the GNU Lesser General Public License.
  */
 
-#include "ucw/lib.h"
-#include "ucw/log.h"
+#include <ucw/lib.h>
+#include <ucw/log.h>
 
+#include <string.h>
 #include <syslog.h>
 
-/* destructor for syslog logs */
-static void ls_syslog_close(struct log_stream *ls)
+struct syslog_stream {
+  struct log_stream ls;
+  int facility;
+};
+
+static int syslog_open_count;
+
+static void
+syslog_close(struct log_stream *ls UNUSED)
 {
-  ASSERT(ls);
-  if(ls->name)
-    xfree(ls->name);
+  if (!--syslog_open_count)
+    closelog();
+}
+
+/* Convert syslog facility to its identifier. */
+static int
+syslog_facility(const char *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 */
-static int ls_syslog_convert_level(int level)
+/* Convert severity level to syslog constants */
+static int
+syslog_level(int level)
 {
-  switch(level)
-  {
-    case L_DEBUG: return LOG_DEBUG;
-    case L_INFO: return LOG_INFO;
-    case L_INFO_R: return LOG_INFO;
-    case L_WARN: return LOG_WARNING;
-    case L_WARN_R: return LOG_WARNING;
-    case L_ERROR: return LOG_ERR;
-    case L_ERROR_R: return LOG_ERR;
-    case L_FATAL: return LOG_CRIT;
-    default: return LOG_NOTICE;
-  }
+  static const int levels[] = {
+    [L_DEBUG] =                LOG_DEBUG,
+    [L_INFO] =         LOG_INFO,
+    [L_INFO_R] =       LOG_INFO,
+    [L_WARN] =         LOG_WARNING,
+    [L_WARN_R] =       LOG_WARNING,
+    [L_ERROR] =                LOG_ERR,
+    [L_ERROR_R] =      LOG_ERR,
+    [L_FATAL] =                LOG_CRIT,
+  };
+  return ((level < (int)ARRAY_SIZE(levels)) ? levels[level] : LOG_NOTICE);
 }
 
 /* simple syslog write handler */
-static int ls_syslog_handler(struct log_stream *ls, const char *m, uns flags)
+static int
+syslog_handler(struct log_stream *ls, struct log_msg *m)
 {
+  struct syslog_stream *ss = (struct syslog_stream *) ls;
   int prio;
   ASSERT(ls);
   ASSERT(m);
 
-  prio = ls_syslog_convert_level(LS_GET_LEVEL(flags)) | (ls->idata);
-  if (ls->name)
-    syslog(prio | (ls->idata), "%s: %s", ls->name, m);
-  else
-    syslog(prio | (ls->idata), "%s", m);
+  prio = syslog_level(LS_GET_LEVEL(m->flags)) | ss->facility;
+  syslog(prio, "%s", m->m);
   return 0;
 }
 
-/* assign log to a syslog facility */
-/* initialize with no formatting (syslog adds these inforamtion) */
-/* name is optional prefix (NULL for none) */
-struct log_stream *ls_syslog_new(int facility, const char *name)
+struct log_stream *
+log_new_syslog(const char *facility, int options)
 {
-  struct log_stream *ls=ls_new();
-  if (name) ls->name = xstrdup(name);
-  ls->idata = facility;
-  ls->msgfmt = LSFMT_NONE;
-  ls->handler = ls_syslog_handler;
-  ls->close = ls_syslog_close;
+  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;
+  ls->name = "syslog";
+  ls->msgfmt = 0;
+  ls->handler = syslog_handler;
+  ls->close = syslog_close;
+  ss->facility = fac;
+
+  if (!syslog_open_count++)
+    openlog(log_title, options, LOG_INFO);
   return ls;
 }
+
+int
+log_syslog_facility_exists(const char *facility)
+{
+  return (syslog_facility(facility) >= 0);
+}