summaryrefslogtreecommitdiffstats
path: root/src/util/msg_syslog.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/msg_syslog.c')
-rw-r--r--src/util/msg_syslog.c266
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