Deleted Added
full compact
pjdlog.c (210873) pjdlog.c (210875)
1/*-
2 * Copyright (c) 2009-2010 The FreeBSD Foundation
3 * All rights reserved.
4 *
5 * This software was developed by Pawel Jakub Dawidek under sponsorship from
6 * the FreeBSD Foundation.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2009-2010 The FreeBSD Foundation
3 * All rights reserved.
4 *
5 * This software was developed by Pawel Jakub Dawidek under sponsorship from
6 * the FreeBSD Foundation.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD: head/sbin/hastd/pjdlog.c 210873 2010-08-05 18:23:43Z pjd $");
31__FBSDID("$FreeBSD: head/sbin/hastd/pjdlog.c 210875 2010-08-05 18:26:38Z pjd $");
32
33#include <assert.h>
34#include <errno.h>
35#include <stdarg.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39#include <syslog.h>
40
41#include "pjdlog.h"
42
43static int pjdlog_mode = PJDLOG_MODE_STD;
44static int pjdlog_debug_level = 0;
45static char pjdlog_prefix[128];
46
47/*
48 * Configure where the logs should go.
49 * By default they are send to stdout/stderr, but after going into background
50 * (eg. by calling daemon(3)) application is responsible for changing mode to
51 * PJDLOG_MODE_SYSLOG, so logs will be send to syslog.
52 */
53void
54pjdlog_mode_set(int mode)
55{
56
57 assert(mode == PJDLOG_MODE_STD || mode == PJDLOG_MODE_SYSLOG);
58
59 pjdlog_mode = mode;
60}
61
62/*
63 * Return current mode.
64 */
65int
66pjdlog_mode_get(void)
67{
68
69 return (pjdlog_mode);
70}
71
72/*
73 * Set debug level. All the logs above the level specified here will be
74 * ignored.
75 */
76void
77pjdlog_debug_set(int level)
78{
79
80 assert(level >= 0);
81
82 pjdlog_debug_level = level;
83}
84
85/*
86 * Return current debug level.
87 */
88int
89pjdlog_debug_get(void)
90{
91
92 return (pjdlog_debug_level);
93}
94
95/*
96 * Set prefix that will be used before each log.
97 * Setting prefix to NULL will remove it.
98 */
99void
100pjdlog_prefix_set(const char *fmt, ...)
101{
102 va_list ap;
103
104 va_start(ap, fmt);
105 pjdlog_prefix_setv(fmt, ap);
106 va_end(ap);
107}
108
109/*
110 * Set prefix that will be used before each log.
111 * Setting prefix to NULL will remove it.
112 */
113void
114pjdlog_prefix_setv(const char *fmt, va_list ap)
115{
116
117 assert(fmt != NULL);
118
119 vsnprintf(pjdlog_prefix, sizeof(pjdlog_prefix), fmt, ap);
120}
121
122/*
123 * Convert log level into string.
124 */
125static const char *
126pjdlog_level_string(int loglevel)
127{
128
129 switch (loglevel) {
130 case LOG_EMERG:
131 return ("EMERG");
132 case LOG_ALERT:
133 return ("ALERT");
134 case LOG_CRIT:
135 return ("CRIT");
136 case LOG_ERR:
137 return ("ERROR");
138 case LOG_WARNING:
139 return ("WARNING");
140 case LOG_NOTICE:
141 return ("NOTICE");
142 case LOG_INFO:
143 return ("INFO");
144 case LOG_DEBUG:
145 return ("DEBUG");
146 }
147 assert(!"Invalid log level.");
148 abort(); /* XXX: gcc */
149}
150
151/*
152 * Common log routine.
153 */
154void
155pjdlog_common(int loglevel, int debuglevel, int error, const char *fmt, ...)
156{
157 va_list ap;
158
159 va_start(ap, fmt);
160 pjdlogv_common(loglevel, debuglevel, error, fmt, ap);
161 va_end(ap);
162}
163
164/*
165 * Common log routine, which can handle regular log level as well as debug
166 * level. We decide here where to send the logs (stdout/stderr or syslog).
167 */
168void
169pjdlogv_common(int loglevel, int debuglevel, int error, const char *fmt,
170 va_list ap)
171{
172
173 assert(loglevel == LOG_EMERG || loglevel == LOG_ALERT ||
174 loglevel == LOG_CRIT || loglevel == LOG_ERR ||
175 loglevel == LOG_WARNING || loglevel == LOG_NOTICE ||
176 loglevel == LOG_INFO || loglevel == LOG_DEBUG);
177 assert(loglevel != LOG_DEBUG || debuglevel > 0);
178 assert(error >= -1);
179
180 /* Ignore debug above configured level. */
181 if (loglevel == LOG_DEBUG && debuglevel > pjdlog_debug_level)
182 return;
183
184 switch (pjdlog_mode) {
185 case PJDLOG_MODE_STD:
186 {
187 FILE *out;
188
189 /*
190 * We send errors and warning to stderr and the rest to stdout.
191 */
192 switch (loglevel) {
193 case LOG_EMERG:
194 case LOG_ALERT:
195 case LOG_CRIT:
196 case LOG_ERR:
197 case LOG_WARNING:
198 out = stderr;
199 break;
200 case LOG_NOTICE:
201 case LOG_INFO:
202 case LOG_DEBUG:
203 out = stdout;
204 break;
205 default:
206 assert(!"Invalid loglevel.");
207 abort(); /* XXX: gcc */
208 }
209
210 fprintf(out, "[%s]", pjdlog_level_string(loglevel));
211 /* Attach debuglevel if this is debug log. */
212 if (loglevel == LOG_DEBUG)
213 fprintf(out, "[%d]", debuglevel);
214 fprintf(out, " ");
215 fprintf(out, "%s", pjdlog_prefix);
216 vfprintf(out, fmt, ap);
217 if (error != -1)
218 fprintf(out, ": %s.", strerror(error));
219 fprintf(out, "\n");
220 break;
221 }
222 case PJDLOG_MODE_SYSLOG:
223 {
224 char log[1024];
225 int len;
226
227 len = snprintf(log, sizeof(log), "%s", pjdlog_prefix);
228 if ((size_t)len < sizeof(log))
229 len += vsnprintf(log + len, sizeof(log) - len, fmt, ap);
230 if (error != -1 && (size_t)len < sizeof(log)) {
231 (void)snprintf(log + len, sizeof(log) - len, ": %s.",
232 strerror(error));
233 }
234 syslog(loglevel, "%s", log);
235 break;
236 }
237 default:
238 assert(!"Invalid mode.");
239 }
240}
241
242/*
243 * Regular logs.
244 */
245void
246pjdlogv(int loglevel, const char *fmt, va_list ap)
247{
248
249 /* LOG_DEBUG is invalid here, pjdlogv?_debug() should be used. */
250 assert(loglevel == LOG_EMERG || loglevel == LOG_ALERT ||
251 loglevel == LOG_CRIT || loglevel == LOG_ERR ||
252 loglevel == LOG_WARNING || loglevel == LOG_NOTICE ||
253 loglevel == LOG_INFO);
254
255 pjdlogv_common(loglevel, 0, -1, fmt, ap);
256}
257
258/*
259 * Regular logs.
260 */
261void
262pjdlog(int loglevel, const char *fmt, ...)
263{
264 va_list ap;
265
266 va_start(ap, fmt);
267 pjdlogv(loglevel, fmt, ap);
268 va_end(ap);
269}
270
271/*
272 * Debug logs.
273 */
274void
275pjdlogv_debug(int debuglevel, const char *fmt, va_list ap)
276{
277
278 pjdlogv_common(LOG_DEBUG, debuglevel, -1, fmt, ap);
279}
280
281/*
282 * Debug logs.
283 */
284void
285pjdlog_debug(int debuglevel, const char *fmt, ...)
286{
287 va_list ap;
288
289 va_start(ap, fmt);
290 pjdlogv_debug(debuglevel, fmt, ap);
291 va_end(ap);
292}
293
294/*
295 * Error logs with errno logging.
296 */
297void
298pjdlogv_errno(int loglevel, const char *fmt, va_list ap)
299{
300
301 pjdlogv_common(loglevel, 0, errno, fmt, ap);
302}
303
304/*
305 * Error logs with errno logging.
306 */
307void
308pjdlog_errno(int loglevel, const char *fmt, ...)
309{
310 va_list ap;
311
312 va_start(ap, fmt);
313 pjdlogv_errno(loglevel, fmt, ap);
314 va_end(ap);
315}
316
317/*
318 * Log error, errno and exit.
319 */
320void
321pjdlogv_exit(int exitcode, const char *fmt, va_list ap)
322{
323
324 pjdlogv_errno(LOG_ERR, fmt, ap);
325 exit(exitcode);
326 /* NOTREACHED */
327}
328
329/*
330 * Log error, errno and exit.
331 */
332void
333pjdlog_exit(int exitcode, const char *fmt, ...)
334{
335 va_list ap;
336
337 va_start(ap, fmt);
338 pjdlogv_exit(exitcode, fmt, ap);
339 /* NOTREACHED */
340 va_end(ap);
341}
342
343/*
344 * Log error and exit.
345 */
346void
347pjdlogv_exitx(int exitcode, const char *fmt, va_list ap)
348{
349
350 pjdlogv(LOG_ERR, fmt, ap);
351 exit(exitcode);
352 /* NOTREACHED */
353}
354
355/*
356 * Log error and exit.
357 */
358void
359pjdlog_exitx(int exitcode, const char *fmt, ...)
360{
361 va_list ap;
362
363 va_start(ap, fmt);
364 pjdlogv_exitx(exitcode, fmt, ap);
365 /* NOTREACHED */
366 va_end(ap);
367}
32
33#include <assert.h>
34#include <errno.h>
35#include <stdarg.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39#include <syslog.h>
40
41#include "pjdlog.h"
42
43static int pjdlog_mode = PJDLOG_MODE_STD;
44static int pjdlog_debug_level = 0;
45static char pjdlog_prefix[128];
46
47/*
48 * Configure where the logs should go.
49 * By default they are send to stdout/stderr, but after going into background
50 * (eg. by calling daemon(3)) application is responsible for changing mode to
51 * PJDLOG_MODE_SYSLOG, so logs will be send to syslog.
52 */
53void
54pjdlog_mode_set(int mode)
55{
56
57 assert(mode == PJDLOG_MODE_STD || mode == PJDLOG_MODE_SYSLOG);
58
59 pjdlog_mode = mode;
60}
61
62/*
63 * Return current mode.
64 */
65int
66pjdlog_mode_get(void)
67{
68
69 return (pjdlog_mode);
70}
71
72/*
73 * Set debug level. All the logs above the level specified here will be
74 * ignored.
75 */
76void
77pjdlog_debug_set(int level)
78{
79
80 assert(level >= 0);
81
82 pjdlog_debug_level = level;
83}
84
85/*
86 * Return current debug level.
87 */
88int
89pjdlog_debug_get(void)
90{
91
92 return (pjdlog_debug_level);
93}
94
95/*
96 * Set prefix that will be used before each log.
97 * Setting prefix to NULL will remove it.
98 */
99void
100pjdlog_prefix_set(const char *fmt, ...)
101{
102 va_list ap;
103
104 va_start(ap, fmt);
105 pjdlog_prefix_setv(fmt, ap);
106 va_end(ap);
107}
108
109/*
110 * Set prefix that will be used before each log.
111 * Setting prefix to NULL will remove it.
112 */
113void
114pjdlog_prefix_setv(const char *fmt, va_list ap)
115{
116
117 assert(fmt != NULL);
118
119 vsnprintf(pjdlog_prefix, sizeof(pjdlog_prefix), fmt, ap);
120}
121
122/*
123 * Convert log level into string.
124 */
125static const char *
126pjdlog_level_string(int loglevel)
127{
128
129 switch (loglevel) {
130 case LOG_EMERG:
131 return ("EMERG");
132 case LOG_ALERT:
133 return ("ALERT");
134 case LOG_CRIT:
135 return ("CRIT");
136 case LOG_ERR:
137 return ("ERROR");
138 case LOG_WARNING:
139 return ("WARNING");
140 case LOG_NOTICE:
141 return ("NOTICE");
142 case LOG_INFO:
143 return ("INFO");
144 case LOG_DEBUG:
145 return ("DEBUG");
146 }
147 assert(!"Invalid log level.");
148 abort(); /* XXX: gcc */
149}
150
151/*
152 * Common log routine.
153 */
154void
155pjdlog_common(int loglevel, int debuglevel, int error, const char *fmt, ...)
156{
157 va_list ap;
158
159 va_start(ap, fmt);
160 pjdlogv_common(loglevel, debuglevel, error, fmt, ap);
161 va_end(ap);
162}
163
164/*
165 * Common log routine, which can handle regular log level as well as debug
166 * level. We decide here where to send the logs (stdout/stderr or syslog).
167 */
168void
169pjdlogv_common(int loglevel, int debuglevel, int error, const char *fmt,
170 va_list ap)
171{
172
173 assert(loglevel == LOG_EMERG || loglevel == LOG_ALERT ||
174 loglevel == LOG_CRIT || loglevel == LOG_ERR ||
175 loglevel == LOG_WARNING || loglevel == LOG_NOTICE ||
176 loglevel == LOG_INFO || loglevel == LOG_DEBUG);
177 assert(loglevel != LOG_DEBUG || debuglevel > 0);
178 assert(error >= -1);
179
180 /* Ignore debug above configured level. */
181 if (loglevel == LOG_DEBUG && debuglevel > pjdlog_debug_level)
182 return;
183
184 switch (pjdlog_mode) {
185 case PJDLOG_MODE_STD:
186 {
187 FILE *out;
188
189 /*
190 * We send errors and warning to stderr and the rest to stdout.
191 */
192 switch (loglevel) {
193 case LOG_EMERG:
194 case LOG_ALERT:
195 case LOG_CRIT:
196 case LOG_ERR:
197 case LOG_WARNING:
198 out = stderr;
199 break;
200 case LOG_NOTICE:
201 case LOG_INFO:
202 case LOG_DEBUG:
203 out = stdout;
204 break;
205 default:
206 assert(!"Invalid loglevel.");
207 abort(); /* XXX: gcc */
208 }
209
210 fprintf(out, "[%s]", pjdlog_level_string(loglevel));
211 /* Attach debuglevel if this is debug log. */
212 if (loglevel == LOG_DEBUG)
213 fprintf(out, "[%d]", debuglevel);
214 fprintf(out, " ");
215 fprintf(out, "%s", pjdlog_prefix);
216 vfprintf(out, fmt, ap);
217 if (error != -1)
218 fprintf(out, ": %s.", strerror(error));
219 fprintf(out, "\n");
220 break;
221 }
222 case PJDLOG_MODE_SYSLOG:
223 {
224 char log[1024];
225 int len;
226
227 len = snprintf(log, sizeof(log), "%s", pjdlog_prefix);
228 if ((size_t)len < sizeof(log))
229 len += vsnprintf(log + len, sizeof(log) - len, fmt, ap);
230 if (error != -1 && (size_t)len < sizeof(log)) {
231 (void)snprintf(log + len, sizeof(log) - len, ": %s.",
232 strerror(error));
233 }
234 syslog(loglevel, "%s", log);
235 break;
236 }
237 default:
238 assert(!"Invalid mode.");
239 }
240}
241
242/*
243 * Regular logs.
244 */
245void
246pjdlogv(int loglevel, const char *fmt, va_list ap)
247{
248
249 /* LOG_DEBUG is invalid here, pjdlogv?_debug() should be used. */
250 assert(loglevel == LOG_EMERG || loglevel == LOG_ALERT ||
251 loglevel == LOG_CRIT || loglevel == LOG_ERR ||
252 loglevel == LOG_WARNING || loglevel == LOG_NOTICE ||
253 loglevel == LOG_INFO);
254
255 pjdlogv_common(loglevel, 0, -1, fmt, ap);
256}
257
258/*
259 * Regular logs.
260 */
261void
262pjdlog(int loglevel, const char *fmt, ...)
263{
264 va_list ap;
265
266 va_start(ap, fmt);
267 pjdlogv(loglevel, fmt, ap);
268 va_end(ap);
269}
270
271/*
272 * Debug logs.
273 */
274void
275pjdlogv_debug(int debuglevel, const char *fmt, va_list ap)
276{
277
278 pjdlogv_common(LOG_DEBUG, debuglevel, -1, fmt, ap);
279}
280
281/*
282 * Debug logs.
283 */
284void
285pjdlog_debug(int debuglevel, const char *fmt, ...)
286{
287 va_list ap;
288
289 va_start(ap, fmt);
290 pjdlogv_debug(debuglevel, fmt, ap);
291 va_end(ap);
292}
293
294/*
295 * Error logs with errno logging.
296 */
297void
298pjdlogv_errno(int loglevel, const char *fmt, va_list ap)
299{
300
301 pjdlogv_common(loglevel, 0, errno, fmt, ap);
302}
303
304/*
305 * Error logs with errno logging.
306 */
307void
308pjdlog_errno(int loglevel, const char *fmt, ...)
309{
310 va_list ap;
311
312 va_start(ap, fmt);
313 pjdlogv_errno(loglevel, fmt, ap);
314 va_end(ap);
315}
316
317/*
318 * Log error, errno and exit.
319 */
320void
321pjdlogv_exit(int exitcode, const char *fmt, va_list ap)
322{
323
324 pjdlogv_errno(LOG_ERR, fmt, ap);
325 exit(exitcode);
326 /* NOTREACHED */
327}
328
329/*
330 * Log error, errno and exit.
331 */
332void
333pjdlog_exit(int exitcode, const char *fmt, ...)
334{
335 va_list ap;
336
337 va_start(ap, fmt);
338 pjdlogv_exit(exitcode, fmt, ap);
339 /* NOTREACHED */
340 va_end(ap);
341}
342
343/*
344 * Log error and exit.
345 */
346void
347pjdlogv_exitx(int exitcode, const char *fmt, va_list ap)
348{
349
350 pjdlogv(LOG_ERR, fmt, ap);
351 exit(exitcode);
352 /* NOTREACHED */
353}
354
355/*
356 * Log error and exit.
357 */
358void
359pjdlog_exitx(int exitcode, const char *fmt, ...)
360{
361 va_list ap;
362
363 va_start(ap, fmt);
364 pjdlogv_exitx(exitcode, fmt, ap);
365 /* NOTREACHED */
366 va_end(ap);
367}
368
369/*
370 * Log assertion and exit.
371 */
372void
373pjdlog_verify(const char *func, const char *file, int line,
374 const char *failedexpr)
375{
376
377 if (func == NULL) {
378 pjdlog_critical("Assertion failed: (%s), file %s, line %d.",
379 failedexpr, file, line);
380 } else {
381 pjdlog_critical("Assertion failed: (%s), function %s, file %s, line %d.",
382 failedexpr, func, file, line);
383 }
384 abort();
385 /* NOTREACHED */
386}
387