xref: /openbsd-src/usr.bin/cvs/log.c (revision 06ccd5dad87daa7ede3ae33928857a729a8043ea)
1 /*	$OpenBSD: log.c,v 1.2 2004/07/27 16:19:41 jfb Exp $	*/
2 /*
3  * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. The name of the author may not be used to endorse or promote products
13  *    derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
16  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
17  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
18  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include <sys/types.h>
28 
29 #include <errno.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <stdarg.h>
35 #include <syslog.h>
36 
37 #include "log.h"
38 
39 extern char *__progname;
40 
41 #ifdef unused
42 static char *cvs_log_levels[] = {
43 	"debug",
44 	"info",
45 	"notice",
46 	"warning",
47 	"error",
48 	"alert",
49 	"error"
50 };
51 #endif
52 
53 static int cvs_slpriomap[] = {
54 	LOG_DEBUG,
55 	LOG_INFO,
56 	LOG_NOTICE,
57 	LOG_WARNING,
58 	LOG_ERR,
59 	LOG_ALERT,
60 	LOG_ERR,
61 };
62 
63 
64 
65 static u_int cvs_log_dest = LD_STD;
66 static u_int cvs_log_flags = 0;
67 
68 static u_int cvs_log_filters[LP_MAX + 1];
69 #define NB_FILTERS  sizeof(cvs_log_filters)/sizeof(cvs_log_filters[0])
70 
71 
72 static struct syslog_data cvs_sl;
73 
74 
75 /*
76  * cvs_log_init()
77  *
78  * Initialize the logging facility of the server.
79  * Returns 0 on success, or -1 on failure.
80  */
81 
82 int
83 cvs_log_init(u_int dest, u_int flags)
84 {
85 	int slopt;
86 
87 	cvs_log_dest = dest;
88 	cvs_log_flags = flags;
89 
90 	/* by default, filter only LP_DEBUG and LP_INFO levels */
91 	memset(cvs_log_filters, 0, sizeof(cvs_log_filters));
92 	cvs_log_filters[LP_DEBUG] = 1;
93 	cvs_log_filters[LP_INFO] = 1;
94 
95 	if (dest & LD_SYSLOG) {
96 		slopt = 0;
97 
98 		if (dest & LD_CONS)
99 			slopt |= LOG_CONS;
100 		if (flags & LF_PID)
101 			slopt |= LOG_PID;
102 
103 		openlog_r(__progname, slopt, LOG_DAEMON, &cvs_sl);
104 	}
105 
106 	return (0);
107 }
108 
109 
110 /*
111  * cvs_log_cleanup()
112  *
113  * Cleanup the logging facility.
114  */
115 
116 void
117 cvs_log_cleanup(void)
118 {
119 	closelog_r(&cvs_sl);
120 
121 }
122 
123 
124 /*
125  * cvs_log_filter()
126  *
127  * Apply or remove filters on the logging facility.  The exact operation is
128  * specified by the <how> and <level> arguments.  The <how> arguments tells
129  * how the filters will be affected, and <level> gives the log levels that
130  * will be affected by the change.
131  * Returns 0 on success, or -1 on failure.
132  */
133 
134 int
135 cvs_log_filter(u_int how, u_int level)
136 {
137 	u_int i;
138 
139 	if ((level > LP_MAX) && (level != LP_ALL)) {
140 		cvs_log(LP_ERR, "invalid log level for filter");
141 		return (-1);
142 	}
143 
144 	switch (how) {
145 	case LP_FILTER_SET:
146 		if (level == LP_ALL)
147 			for (i = 0; i < NB_FILTERS; i++)
148 				cvs_log_filters[i] = 1;
149 		else
150 			cvs_log_filters[level] = 1;
151 		break;
152 	case LP_FILTER_UNSET:
153 		if (level == LP_ALL)
154 			for (i = 0; i < NB_FILTERS; i++)
155 				cvs_log_filters[i] = 0;
156 		else
157 			cvs_log_filters[level] = 0;
158 		break;
159 	case LP_FILTER_TOGGLE:
160 		if (level == LP_ALL)
161 			for (i = 0; i < NB_FILTERS; i++)
162 				cvs_log_filters[i] =
163 				    (cvs_log_filters[i] == 0) ? 1 : 0;
164 		else
165 			cvs_log_filters[level] =
166 			    (cvs_log_filters[level] == 0) ? 1 : 0;
167 		break;
168 	default:
169 		return (-1);
170 	}
171 
172 	return (0);
173 }
174 
175 
176 /*
177  * cvs_log()
178  *
179  * Log the format-string message
180  * The <fmt> argument should not have a terminating newline, as this is taken
181  * care of by the logging facility.
182  */
183 
184 int
185 cvs_log(u_int level, const char *fmt, ...)
186 {
187 	int ret;
188 	va_list vap;
189 
190 	va_start(vap, fmt);
191 	ret = cvs_vlog(level, fmt, vap);
192 	va_end(vap);
193 
194 	return (ret);
195 }
196 
197 
198 /*
199  * cvs_vlog()
200  *
201  * The <fmt> argument should not have a terminating newline, as this is taken
202  * care of by the logging facility.
203  */
204 
205 int
206 cvs_vlog(u_int level, const char *fmt, va_list vap)
207 {
208 	int ecp;
209 	char prefix[64], buf[1024], ebuf[32];
210 	FILE *out;
211 
212 	ecp = 0;
213 
214 	if (level > LP_MAX) {
215 		return (-1);
216 	}
217 
218 	/* apply any filters */
219 	if (cvs_log_filters[level] == 1)
220 		return (0);
221 
222 	if (level == LP_ERRNO)
223 		ecp = errno;
224 
225 	strlcpy(prefix, __progname, sizeof(prefix));
226 	if (cvs_log_flags & LF_PID) {
227 		snprintf(buf, sizeof(buf), "[%d]", (int)getpid());
228 		strlcat(prefix, buf, sizeof(prefix));
229 	}
230 
231 	vsnprintf(buf, sizeof(buf), fmt, vap);
232 	if (level == LP_ERRNO) {
233 		snprintf(ebuf, sizeof(ebuf), ": %s", strerror(errno));
234 		strlcat(buf, ebuf, sizeof(buf));
235 	}
236 
237 	if (cvs_log_dest & LD_STD) {
238 		if (level <= LP_NOTICE)
239 			out = stdout;
240 		else
241 			out = stderr;
242 
243 		fprintf(out, "%s: %s\n", prefix, buf);
244 	}
245 
246 	if (cvs_log_dest & LD_SYSLOG)
247 		syslog_r(cvs_slpriomap[level], &cvs_sl, "%s", buf);
248 
249 	/* preserve it just in case we changed it? */
250 	if (level == LP_ERRNO)
251 		errno = ecp;
252 
253 	return (0);
254 }
255 
256 
257 /*
258  * cvs_printf()
259  *
260  * Wrapper function around printf() that prepends a 'M' or 'E' command when
261  * the program is acting as server.
262  */
263 
264 int
265 cvs_printf(const char *fmt, ...)
266 {
267 	int ret;
268 	va_list vap;
269 
270 	va_start(vap, fmt);
271 
272 	ret = vprintf(fmt, vap);
273 
274 	va_end(vap);
275 
276 	return (ret);
277 }
278