From fac9d2c52b3d046cf19025e391162999f2fda5ff Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Mon, 16 Feb 2009 23:38:22 +0100 Subject: [PATCH] Logging: Improved log-syslog. 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 | 7 +++-- ucw/log-syslog.c | 73 +++++++++++++++++++++++++++++++++++++++--------- ucw/log.c | 2 +- ucw/log.h | 26 +++++++++++++---- 4 files changed, 86 insertions(+), 22 deletions(-) diff --git a/ucw/log-conf.c b/ucw/log-conf.c index 9d36d8a9..9eea204e 100644 --- a/ucw/log-conf.c +++ b/ucw/log-conf.c @@ -13,7 +13,7 @@ #include "ucw/simple-lists.h" #include -#include // FIXME +#include 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; } diff --git a/ucw/log-syslog.c b/ucw/log-syslog.c index dae84005..e3bbd6b5 100644 --- a/ucw/log-syslog.c +++ b/ucw/log-syslog.c @@ -11,6 +11,7 @@ #include "ucw/lib.h" #include "ucw/log.h" +#include #include 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); } diff --git a/ucw/log.c b/ucw/log.c index c6a095be..2563c799 100644 --- 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>", ":-)"); diff --git a/ucw/log.h b/ucw/log.h index bb53dad0..798fc2e7 100644 --- 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 -- 2.39.5