Annotation of src/usr.bin/cvs/log.c, Revision 1.9
1.9 ! jfb 1: /* $OpenBSD: log.c,v 1.8 2004/12/15 06:11:40 jfb Exp $ */
1.1 jfb 2: /*
1.2 jfb 3: * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
1.1 jfb 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"
1.3 jfb 38: #include "cvs.h"
1.1 jfb 39:
40: extern char *__progname;
41:
1.3 jfb 42:
1.2 jfb 43: #ifdef unused
1.1 jfb 44: static char *cvs_log_levels[] = {
45: "debug",
46: "info",
47: "notice",
48: "warning",
49: "error",
50: "alert",
1.4 jfb 51: "error",
52: "abort",
1.1 jfb 53: };
1.2 jfb 54: #endif
1.1 jfb 55:
56: static int cvs_slpriomap[] = {
57: LOG_DEBUG,
58: LOG_INFO,
59: LOG_NOTICE,
60: LOG_WARNING,
61: LOG_ERR,
62: LOG_ALERT,
63: LOG_ERR,
1.4 jfb 64: LOG_ERR,
1.1 jfb 65: };
66:
67: static u_int cvs_log_dest = LD_STD;
68: static u_int cvs_log_flags = 0;
69:
1.9 ! jfb 70: static struct syslog_data cvs_sl;
1.1 jfb 71:
1.9 ! jfb 72: /* filter manipulation macros */
! 73: #define CVS_LOG_FLTRRST() (cvs_log_filters = 0)
! 74: #define CVS_LOG_FLTRSET(l) (cvs_log_filters |= (1 << l))
! 75: #define CVS_LOG_FLTRGET(l) (cvs_log_filters & (1 << l))
! 76: #define CVS_LOG_FLTRCLR(l) (cvs_log_filters &= ~(1 << l))
1.1 jfb 77:
1.9 ! jfb 78: static u_int cvs_log_filters;
1.1 jfb 79:
80:
81: /*
82: * cvs_log_init()
83: *
84: * Initialize the logging facility of the server.
85: * Returns 0 on success, or -1 on failure.
86: */
87: int
88: cvs_log_init(u_int dest, u_int flags)
89: {
90: int slopt;
91:
92: cvs_log_dest = dest;
93: cvs_log_flags = flags;
94:
95: /* by default, filter only LP_DEBUG and LP_INFO levels */
1.9 ! jfb 96: CVS_LOG_FLTRRST();
! 97: CVS_LOG_FLTRSET(LP_DEBUG);
! 98: CVS_LOG_FLTRSET(LP_INFO);
1.1 jfb 99:
1.8 jfb 100: /* traces are enabled with the -t command-line option */
1.9 ! jfb 101: CVS_LOG_FLTRSET(LP_TRACE);
1.8 jfb 102:
1.1 jfb 103: if (dest & LD_SYSLOG) {
104: slopt = 0;
105:
106: if (dest & LD_CONS)
107: slopt |= LOG_CONS;
108: if (flags & LF_PID)
109: slopt |= LOG_PID;
110:
111: openlog_r(__progname, slopt, LOG_DAEMON, &cvs_sl);
112: }
113:
114: return (0);
115: }
116:
117:
118: /*
119: * cvs_log_cleanup()
120: *
121: * Cleanup the logging facility.
122: */
123: void
124: cvs_log_cleanup(void)
125: {
1.7 tedu 126:
1.1 jfb 127: closelog_r(&cvs_sl);
128: }
129:
130:
131: /*
132: * cvs_log_filter()
133: *
134: * Apply or remove filters on the logging facility. The exact operation is
135: * specified by the <how> and <level> arguments. The <how> arguments tells
136: * how the filters will be affected, and <level> gives the log levels that
137: * will be affected by the change.
138: * Returns 0 on success, or -1 on failure.
139: */
140:
141: int
142: cvs_log_filter(u_int how, u_int level)
143: {
144: u_int i;
145:
146: if ((level > LP_MAX) && (level != LP_ALL)) {
147: cvs_log(LP_ERR, "invalid log level for filter");
148: return (-1);
149: }
150:
151: switch (how) {
152: case LP_FILTER_SET:
153: if (level == LP_ALL)
1.9 ! jfb 154: for (i = 0; i <= LP_MAX; i++)
! 155: CVS_LOG_FLTRSET(i);
1.1 jfb 156: else
1.9 ! jfb 157: CVS_LOG_FLTRSET(level);
1.1 jfb 158: break;
159: case LP_FILTER_UNSET:
160: if (level == LP_ALL)
1.9 ! jfb 161: CVS_LOG_FLTRRST();
1.1 jfb 162: else
1.9 ! jfb 163: CVS_LOG_FLTRCLR(level);
1.1 jfb 164: break;
165: default:
166: return (-1);
167: }
168:
169: return (0);
170: }
171:
172:
173: /*
174: * cvs_log()
175: *
176: * Log the format-string message
177: * The <fmt> argument should not have a terminating newline, as this is taken
178: * care of by the logging facility.
179: */
180: int
181: cvs_log(u_int level, const char *fmt, ...)
182: {
183: int ret;
184: va_list vap;
185:
186: va_start(vap, fmt);
187: ret = cvs_vlog(level, fmt, vap);
188: va_end(vap);
189:
190: return (ret);
191: }
192:
193:
194: /*
195: * cvs_vlog()
196: *
197: * The <fmt> argument should not have a terminating newline, as this is taken
198: * care of by the logging facility.
199: */
200: int
201: cvs_vlog(u_int level, const char *fmt, va_list vap)
202: {
203: int ecp;
204: char prefix[64], buf[1024], ebuf[32];
205: FILE *out;
206:
1.4 jfb 207: if (level > LP_MAX)
208: return (-1);
1.1 jfb 209:
210: /* apply any filters */
1.9 ! jfb 211: if (CVS_LOG_FLTRGET(level))
1.1 jfb 212: return (0);
213:
214: if (level == LP_ERRNO)
215: ecp = errno;
1.4 jfb 216: else
217: ecp = 0;
1.1 jfb 218:
1.3 jfb 219: #ifdef CVS
220: /* The cvs program appends the command name to the program name */
1.8 jfb 221: if (level == LP_TRACE) {
222: strlcpy(prefix, " -> ", sizeof(prefix));
223: if (cvs_cmdop == CVS_OP_SERVER)
224: prefix[0] = 'S';
225: } else if (cvs_command != NULL) {
1.4 jfb 226: if (level == LP_ABORT)
227: snprintf(prefix, sizeof(prefix), "%s [%s aborted]",
228: __progname, cvs_command);
229: else
230: snprintf(prefix, sizeof(prefix), "%s %s", __progname,
231: cvs_command);
1.6 deraadt 232: } else /* just use the standard strlcpy */
1.3 jfb 233: #endif
234: strlcpy(prefix, __progname, sizeof(prefix));
235:
1.8 jfb 236: if ((cvs_log_flags & LF_PID) && (level != LP_TRACE)) {
1.1 jfb 237: snprintf(buf, sizeof(buf), "[%d]", (int)getpid());
238: strlcat(prefix, buf, sizeof(prefix));
239: }
240:
241: vsnprintf(buf, sizeof(buf), fmt, vap);
242: if (level == LP_ERRNO) {
243: snprintf(ebuf, sizeof(ebuf), ": %s", strerror(errno));
244: strlcat(buf, ebuf, sizeof(buf));
245: }
246:
247: if (cvs_log_dest & LD_STD) {
248: if (level <= LP_NOTICE)
249: out = stdout;
250: else
251: out = stderr;
1.3 jfb 252:
253: #ifdef CVS
254: if (cvs_cmdop == CVS_OP_SERVER) {
255: if (out == stdout)
256: putc('M', out);
257: else
258: putc('E', out);
259: putc(' ', out);
260: }
261: #endif
1.1 jfb 262:
1.8 jfb 263: fputs(prefix, out);
264: if (level != LP_TRACE)
265: fputs(": ", out);
266: fputs(buf, out);
267: fputc('\n', out);
1.1 jfb 268: }
269:
270: if (cvs_log_dest & LD_SYSLOG)
271: syslog_r(cvs_slpriomap[level], &cvs_sl, "%s", buf);
272:
273: /* preserve it just in case we changed it? */
274: if (level == LP_ERRNO)
275: errno = ecp;
276:
277: return (0);
1.2 jfb 278: }
279:
280:
281: /*
282: * cvs_printf()
283: *
284: * Wrapper function around printf() that prepends a 'M' or 'E' command when
285: * the program is acting as server.
286: */
287: int
288: cvs_printf(const char *fmt, ...)
289: {
290: int ret;
291: va_list vap;
292:
293: va_start(vap, fmt);
294: ret = vprintf(fmt, vap);
295: va_end(vap);
296:
297: return (ret);
1.1 jfb 298: }