Annotation of src/usr.bin/cvs/log.c, Revision 1.2
1.1 jfb 1: /* $OpenBSD$ */
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"
38:
39: extern char *__progname;
40:
1.2 ! jfb 41: #ifdef unused
1.1 jfb 42: static char *cvs_log_levels[] = {
43: "debug",
44: "info",
45: "notice",
46: "warning",
47: "error",
48: "alert",
49: "error"
50: };
1.2 ! jfb 51: #endif
1.1 jfb 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);
1.2 ! jfb 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);
1.1 jfb 277: }