diff options
Diffstat (limited to '')
-rw-r--r-- | src/util/msg_syslog.c | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/src/util/msg_syslog.c b/src/util/msg_syslog.c new file mode 100644 index 0000000..7c979c6 --- /dev/null +++ b/src/util/msg_syslog.c @@ -0,0 +1,266 @@ +/*++ +/* NAME +/* msg_syslog 3 +/* SUMMARY +/* direct diagnostics to syslog daemon +/* SYNOPSIS +/* #include <msg_syslog.h> +/* +/* void msg_syslog_init(progname, log_opt, facility) +/* const char *progname; +/* int log_opt; +/* int facility; +/* +/* int msg_syslog_set_facility(facility_name) +/* const char *facility_name; +/* +/* void msg_syslog_disable(void) +/* DESCRIPTION +/* This module implements support to report msg(3) diagnostics +/* via the syslog daemon. +/* +/* msg_syslog_init() is a wrapper around the openlog(3) routine +/* that directs subsequent msg(3) output to the syslog daemon. +/* This function may also be called to update msg_syslog +/* settings. If the program name appears to contain a process ID +/* then msg_syslog_init will attempt to suppress its own PID. +/* +/* msg_syslog_set_facility() is a helper routine that overrides the +/* logging facility that is specified with msg_syslog_init(). +/* The result is zero in case of an unknown facility name. +/* +/* msg_syslog_disable() turns off the msg_syslog client, +/* until a subsequent msg_syslog_init() call. +/* SEE ALSO +/* syslog(3) syslog library +/* msg(3) diagnostics module +/* BUGS +/* Output records are truncated to 2000 characters. This is done in +/* order to defend against a buffer overflow problem in some +/* implementations of the syslog() library routine. +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/*--*/ + +/* System libraries. */ + +#include <sys_defs.h> +#include <stdlib.h> /* 44BSD stdarg.h uses abort() */ +#include <stdarg.h> +#include <errno.h> +#include <syslog.h> +#include <string.h> +#include <time.h> + +/* Application-specific. */ + +#include "vstring.h" +#include "stringops.h" +#include "msg.h" +#include "msg_output.h" +#include "msg_syslog.h" +#include "safe.h" +#include <mymalloc.h> + + /* + * Stay a little below the 2048-byte limit of older syslog() + * implementations. + */ +#define MSG_SYSLOG_RECLEN 2000 + +struct facility_list { + const char *name; + int facility; +}; + +static struct facility_list facility_list[] = { +#ifdef LOG_AUTH + "auth", LOG_AUTH, +#endif +#ifdef LOG_AUTHPRIV + "authpriv", LOG_AUTHPRIV, +#endif +#ifdef LOG_CRON + "cron", LOG_CRON, +#endif +#ifdef LOG_DAEMON + "daemon", LOG_DAEMON, +#endif +#ifdef LOG_FTP + "ftp", LOG_FTP, +#endif +#ifdef LOG_KERN + "kern", LOG_KERN, +#endif +#ifdef LOG_LPR + "lpr", LOG_LPR, +#endif +#ifdef LOG_MAIL + "mail", LOG_MAIL, +#endif +#ifdef LOG_NEWS + "news", LOG_NEWS, +#endif +#ifdef LOG_SECURITY + "security", LOG_SECURITY, +#endif +#ifdef LOG_SYSLOG + "syslog", LOG_SYSLOG, +#endif +#ifdef LOG_USER + "user", LOG_USER, +#endif +#ifdef LOG_UUCP + "uucp", LOG_UUCP, +#endif +#ifdef LOG_LOCAL0 + "local0", LOG_LOCAL0, +#endif +#ifdef LOG_LOCAL1 + "local1", LOG_LOCAL1, +#endif +#ifdef LOG_LOCAL2 + "local2", LOG_LOCAL2, +#endif +#ifdef LOG_LOCAL3 + "local3", LOG_LOCAL3, +#endif +#ifdef LOG_LOCAL4 + "local4", LOG_LOCAL4, +#endif +#ifdef LOG_LOCAL5 + "local5", LOG_LOCAL5, +#endif +#ifdef LOG_LOCAL6 + "local6", LOG_LOCAL6, +#endif +#ifdef LOG_LOCAL7 + "local7", LOG_LOCAL7, +#endif + 0, +}; + +static int msg_syslog_facility; +static int msg_syslog_enable; + +/* msg_syslog_print - log info to syslog daemon */ + +static void msg_syslog_print(int level, const char *text) +{ + static int log_level[] = { + LOG_INFO, LOG_WARNING, LOG_ERR, LOG_CRIT, LOG_CRIT, + }; + static char *severity_name[] = { + "info", "warning", "error", "fatal", "panic", + }; + + if (msg_syslog_enable == 0) + return; + + if (level < 0 || level >= (int) (sizeof(log_level) / sizeof(log_level[0]))) + msg_panic("msg_syslog_print: invalid severity level: %d", level); + + if (level == MSG_INFO) { + syslog(msg_syslog_facility | log_level[level], "%.*s", + (int) MSG_SYSLOG_RECLEN, text); + } else { + syslog(msg_syslog_facility | log_level[level], "%s: %.*s", + severity_name[level], (int) MSG_SYSLOG_RECLEN, text); + } +} + +/* msg_syslog_init - initialize */ + +void msg_syslog_init(const char *name, int logopt, int facility) +{ + static int first_call = 1; + extern char **environ; + + /* + * XXX If this program is set-gid, then TZ must not be trusted. This + * scrubbing code is in the wrong place. + */ + if (first_call) { + if (unsafe()) + while (getenv("TZ")) /* There may be multiple. */ + if (unsetenv("TZ") < 0) { /* Desperate measures. */ + environ[0] = 0; + msg_fatal("unsetenv: %m"); + } + tzset(); + } + /* Hack for internal logging forwarding after config change. */ + if (strchr(name, '[') != 0) + logopt &= ~LOG_PID; + openlog(name, LOG_NDELAY | logopt, facility); + if (first_call) { + first_call = 0; + msg_output(msg_syslog_print); + } + msg_syslog_enable = 1; +} + +/* msg_syslog_set_facility - set logging facility by name */ + +int msg_syslog_set_facility(const char *facility_name) +{ + struct facility_list *fnp; + + for (fnp = facility_list; fnp->name; ++fnp) { + if (!strcmp(fnp->name, facility_name)) { + msg_syslog_facility = fnp->facility; + return (1); + } + } + return 0; +} + +/* msg_syslog_disable - disable the msg_syslog client */ + +void msg_syslog_disable(void) +{ + msg_syslog_enable = 0; +} + +#ifdef TEST + + /* + * Proof-of-concept program to test the syslogging diagnostics interface + * + * Usage: msg_syslog_test text... + */ + +int main(int argc, char **argv) +{ + VSTRING *vp = vstring_alloc(256); + + msg_syslog_init(argv[0], LOG_PID, LOG_MAIL); + if (argc < 2) + msg_error("usage: %s text to be logged", argv[0]); + while (--argc && *++argv) { + vstring_strcat(vp, *argv); + if (argv[1]) + vstring_strcat(vp, " "); + } + msg_warn("static text"); + msg_warn("dynamic text: >%s<", vstring_str(vp)); + msg_warn("dynamic numeric: >%d<", 42); + msg_warn("error text: >%m<"); + msg_warn("dynamic: >%s<: error: >%m<", vstring_str(vp)); + vstring_free(vp); + return (0); +} + +#endif |