xref: /netbsd-src/external/ibm-public/postfix/dist/src/util/msg_syslog.c (revision 33881f779a77dce6440bdc44610d94de75bebefe)
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 
msg_syslog_print(int level,const char * text)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 
msg_syslog_init(const char * name,int logopt,int facility)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 
msg_syslog_set_facility(const char * facility_name)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 
msg_syslog_disable(void)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 
main(int argc,char ** argv)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