1/*++ 2/* NAME 3/* msg_syslog 3 4/* SUMMARY 5/* direct diagnostics to syslog daemon 6/* SYNOPSIS 7/* #include <msg_syslog.h> 8/* 9/* void msg_syslog_init(progname, log_opt, facility) 10/* const char *progname; 11/* int log_opt; 12/* int facility; 13/* 14/* int msg_syslog_facility(facility_name) 15/* const char *facility_name; 16/* DESCRIPTION 17/* This module implements support to report msg(3) diagnostics 18/* via the syslog daemon. 19/* 20/* msg_syslog_init() is a wrapper around the openlog(3) routine 21/* that directs subsequent msg(3) output to the syslog daemon. 22/* 23/* msg_syslog_facility() is a helper routine that overrides the 24/* logging facility that is specified with msg_syslog_init(). 25/* The result is zero in case of an unknown facility name. 26/* SEE ALSO 27/* syslog(3) syslog library 28/* msg(3) diagnostics module 29/* BUGS 30/* Output records are truncated to 2000 characters. This is done in 31/* order to defend against a buffer overflow problem in some 32/* implementations of the syslog() library routine. 33/* LICENSE 34/* .ad 35/* .fi 36/* The Secure Mailer license must be distributed with this software. 37/* AUTHOR(S) 38/* Wietse Venema 39/* IBM T.J. Watson Research 40/* P.O. Box 704 41/* Yorktown Heights, NY 10598, USA 42/*--*/ 43 44/* System libraries. */ 45 46#include <sys_defs.h> 47#include <stdlib.h> /* 44BSD stdarg.h uses abort() */ 48#include <stdarg.h> 49#include <errno.h> 50#include <syslog.h> 51#include <string.h> 52#include <time.h> 53 54/* Application-specific. */ 55 56#include "vstring.h" 57#include "stringops.h" 58#include "msg.h" 59#include "msg_output.h" 60#include "msg_syslog.h" 61#include "safe.h" 62 63 /* 64 * Stay a little below the 2048-byte limit of older syslog() 65 * implementations. 66 */ 67#define MSG_SYSLOG_RECLEN 2000 68 69struct facility_list { 70 const char *name; 71 int facility; 72}; 73 74static struct facility_list facility_list[] = { 75#ifdef LOG_AUTH 76 "auth", LOG_AUTH, 77#endif 78#ifdef LOG_AUTHPRIV 79 "authpriv", LOG_AUTHPRIV, 80#endif 81#ifdef LOG_CRON 82 "cron", LOG_CRON, 83#endif 84#ifdef LOG_DAEMON 85 "daemon", LOG_DAEMON, 86#endif 87#ifdef LOG_FTP 88 "ftp", LOG_FTP, 89#endif 90#ifdef LOG_KERN 91 "kern", LOG_KERN, 92#endif 93#ifdef LOG_LPR 94 "lpr", LOG_LPR, 95#endif 96#ifdef LOG_MAIL 97 "mail", LOG_MAIL, 98#endif 99#ifdef LOG_NEWS 100 "news", LOG_NEWS, 101#endif 102#ifdef LOG_SECURITY 103 "security", LOG_SECURITY, 104#endif 105#ifdef LOG_SYSLOG 106 "syslog", LOG_SYSLOG, 107#endif 108#ifdef LOG_USER 109 "user", LOG_USER, 110#endif 111#ifdef LOG_UUCP 112 "uucp", LOG_UUCP, 113#endif 114#ifdef LOG_LOCAL0 115 "local0", LOG_LOCAL0, 116#endif 117#ifdef LOG_LOCAL1 118 "local1", LOG_LOCAL1, 119#endif 120#ifdef LOG_LOCAL2 121 "local2", LOG_LOCAL2, 122#endif 123#ifdef LOG_LOCAL3 124 "local3", LOG_LOCAL3, 125#endif 126#ifdef LOG_LOCAL4 127 "local4", LOG_LOCAL4, 128#endif 129#ifdef LOG_LOCAL5 130 "local5", LOG_LOCAL5, 131#endif 132#ifdef LOG_LOCAL6 133 "local6", LOG_LOCAL6, 134#endif 135#ifdef LOG_LOCAL7 136 "local7", LOG_LOCAL7, 137#endif 138 0, 139}; 140 141static int syslog_facility; 142 143/* msg_syslog_print - log info to syslog daemon */ 144 145static void msg_syslog_print(int level, const char *text) 146{ 147 static int log_level[] = { 148 LOG_INFO, LOG_WARNING, LOG_ERR, LOG_CRIT, LOG_CRIT, 149 }; 150 static char *severity_name[] = { 151 "info", "warning", "error", "fatal", "panic", 152 }; 153 154 if (level < 0 || level >= (int) (sizeof(log_level) / sizeof(log_level[0]))) 155 msg_panic("msg_syslog_print: invalid severity level: %d", level); 156 157 if (level == MSG_INFO) { 158 syslog(syslog_facility | log_level[level], "%.*s", 159 (int) MSG_SYSLOG_RECLEN, text); 160 } else { 161 syslog(syslog_facility | log_level[level], "%s: %.*s", 162 severity_name[level], (int) MSG_SYSLOG_RECLEN, text); 163 } 164} 165 166/* msg_syslog_init - initialize */ 167 168void msg_syslog_init(const char *name, int logopt, int facility) 169{ 170 static int first_call = 1; 171 172 /* 173 * XXX If this program is set-gid, then TZ must not be trusted. This 174 * scrubbing code is in the wrong place. 175 */ 176 if (unsafe()) 177 putenv("TZ=UTC"); 178 tzset(); 179 openlog(name, LOG_NDELAY | logopt, facility); 180 if (first_call) { 181 first_call = 0; 182 msg_output(msg_syslog_print); 183 } 184} 185 186/* msg_syslog_facility - set logging facility by name */ 187 188int msg_syslog_facility(const char *facility_name) 189{ 190 struct facility_list *fnp; 191 192 for (fnp = facility_list; fnp->name; ++fnp) { 193 if (!strcmp(fnp->name, facility_name)) { 194 syslog_facility = fnp->facility; 195 return (1); 196 } 197 } 198 return 0; 199} 200 201#ifdef TEST 202 203 /* 204 * Proof-of-concept program to test the syslogging diagnostics interface 205 * 206 * Usage: msg_syslog_test text... 207 */ 208 209int main(int argc, char **argv) 210{ 211 VSTRING *vp = vstring_alloc(256); 212 213 msg_syslog_init(argv[0], LOG_PID, LOG_MAIL); 214 if (argc < 2) 215 msg_error("usage: %s text to be logged", argv[0]); 216 while (--argc && *++argv) { 217 vstring_strcat(vp, *argv); 218 if (argv[1]) 219 vstring_strcat(vp, " "); 220 } 221 msg_warn("static text"); 222 msg_warn("dynamic text: >%s<", vstring_str(vp)); 223 msg_warn("dynamic numeric: >%d<", 42); 224 msg_warn("error text: >%m<"); 225 msg_warn("dynamic: >%s<: error: >%m<", vstring_str(vp)); 226 vstring_free(vp); 227 return (0); 228} 229 230#endif 231