2 * Copyright (c) 2009-2010 The FreeBSD Foundation
5 * This software was developed by Pawel Jakub Dawidek under sponsorship from
6 * the FreeBSD Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
43 static int pjdlog_mode = PJDLOG_MODE_STD;
44 static int pjdlog_debug_level = 0;
45 static char pjdlog_prefix[128];
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.
54 pjdlog_mode_set(int mode)
57 assert(mode == PJDLOG_MODE_STD || mode == PJDLOG_MODE_SYSLOG);
61 if (mode == PJDLOG_MODE_SYSLOG)
62 openlog(NULL, LOG_PID, LOG_DAEMON);
66 * Return current mode.
76 * Set debug level. All the logs above the level specified here will be
80 pjdlog_debug_set(int level)
85 pjdlog_debug_level = level;
89 * Return current debug level.
92 pjdlog_debug_get(void)
95 return (pjdlog_debug_level);
99 * Set prefix that will be used before each log.
100 * Setting prefix to NULL will remove it.
103 pjdlog_prefix_set(const char *fmt, ...)
108 pjdlog_prefix_setv(fmt, ap);
113 * Set prefix that will be used before each log.
114 * Setting prefix to NULL will remove it.
117 pjdlog_prefix_setv(const char *fmt, va_list ap)
122 vsnprintf(pjdlog_prefix, sizeof(pjdlog_prefix), fmt, ap);
126 * Convert log level into string.
129 pjdlog_level_string(int loglevel)
150 assert(!"Invalid log level.");
151 abort(); /* XXX: gcc */
155 * Common log routine.
158 pjdlog_common(int loglevel, int debuglevel, int error, const char *fmt, ...)
163 pjdlogv_common(loglevel, debuglevel, error, fmt, ap);
168 * Common log routine, which can handle regular log level as well as debug
169 * level. We decide here where to send the logs (stdout/stderr or syslog).
172 pjdlogv_common(int loglevel, int debuglevel, int error, const char *fmt,
176 assert(loglevel == LOG_EMERG || loglevel == LOG_ALERT ||
177 loglevel == LOG_CRIT || loglevel == LOG_ERR ||
178 loglevel == LOG_WARNING || loglevel == LOG_NOTICE ||
179 loglevel == LOG_INFO || loglevel == LOG_DEBUG);
180 assert(loglevel != LOG_DEBUG || debuglevel > 0);
183 /* Ignore debug above configured level. */
184 if (loglevel == LOG_DEBUG && debuglevel > pjdlog_debug_level)
187 switch (pjdlog_mode) {
188 case PJDLOG_MODE_STD:
193 * We send errors and warning to stderr and the rest to stdout.
209 assert(!"Invalid loglevel.");
210 abort(); /* XXX: gcc */
213 fprintf(out, "[%s]", pjdlog_level_string(loglevel));
214 /* Attach debuglevel if this is debug log. */
215 if (loglevel == LOG_DEBUG)
216 fprintf(out, "[%d]", debuglevel);
218 fprintf(out, "%s", pjdlog_prefix);
219 vfprintf(out, fmt, ap);
221 fprintf(out, ": %s.", strerror(error));
226 case PJDLOG_MODE_SYSLOG:
231 len = snprintf(log, sizeof(log), "%s", pjdlog_prefix);
232 if ((size_t)len < sizeof(log))
233 len += vsnprintf(log + len, sizeof(log) - len, fmt, ap);
234 if (error != -1 && (size_t)len < sizeof(log)) {
235 (void)snprintf(log + len, sizeof(log) - len, ": %s.",
238 syslog(loglevel, "%s", log);
242 assert(!"Invalid mode.");
250 pjdlogv(int loglevel, const char *fmt, va_list ap)
253 /* LOG_DEBUG is invalid here, pjdlogv?_debug() should be used. */
254 assert(loglevel == LOG_EMERG || loglevel == LOG_ALERT ||
255 loglevel == LOG_CRIT || loglevel == LOG_ERR ||
256 loglevel == LOG_WARNING || loglevel == LOG_NOTICE ||
257 loglevel == LOG_INFO);
259 pjdlogv_common(loglevel, 0, -1, fmt, ap);
266 pjdlog(int loglevel, const char *fmt, ...)
271 pjdlogv(loglevel, fmt, ap);
279 pjdlogv_debug(int debuglevel, const char *fmt, va_list ap)
282 pjdlogv_common(LOG_DEBUG, debuglevel, -1, fmt, ap);
289 pjdlog_debug(int debuglevel, const char *fmt, ...)
294 pjdlogv_debug(debuglevel, fmt, ap);
299 * Error logs with errno logging.
302 pjdlogv_errno(int loglevel, const char *fmt, va_list ap)
305 pjdlogv_common(loglevel, 0, errno, fmt, ap);
309 * Error logs with errno logging.
312 pjdlog_errno(int loglevel, const char *fmt, ...)
317 pjdlogv_errno(loglevel, fmt, ap);
322 * Log error, errno and exit.
325 pjdlogv_exit(int exitcode, const char *fmt, va_list ap)
328 pjdlogv_errno(LOG_ERR, fmt, ap);
334 * Log error, errno and exit.
337 pjdlog_exit(int exitcode, const char *fmt, ...)
342 pjdlogv_exit(exitcode, fmt, ap);
348 * Log error and exit.
351 pjdlogv_exitx(int exitcode, const char *fmt, va_list ap)
354 pjdlogv(LOG_ERR, fmt, ap);
360 * Log error and exit.
363 pjdlog_exitx(int exitcode, const char *fmt, ...)
368 pjdlogv_exitx(exitcode, fmt, ap);
374 * Log assertion and exit.
377 pjdlog_verify(const char *func, const char *file, int line,
378 const char *failedexpr)
382 pjdlog_critical("Assertion failed: (%s), file %s, line %d.",
383 failedexpr, file, line);
385 pjdlog_critical("Assertion failed: (%s), function %s, file %s, line %d.",
386 failedexpr, func, file, line);