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