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