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