2 * Message and error reporting (possibly fatal).
6 * extern int cleanup(void);
7 * extern void log(int, const char *, va_list, int);
9 * message_fatal_cleanup = cleanup;
10 * message_program_name = argv[0];
12 * warn("Something horrible happened at %lu", time);
13 * syswarn("Couldn't unlink temporary file %s", tmpfile);
15 * die("Something fatal happened at %lu", time);
16 * sysdie("open of %s failed", filename);
18 * debug("Some debugging message about %s", string);
19 * notice("Informational notices");
21 * message_handlers_warn(1, log);
22 * warn("This now goes through our log function");
24 * These functions implement message reporting through user-configurable
25 * handler functions. debug() only does something if DEBUG is defined, and
26 * notice() and warn() just output messages as configured. die() similarly
27 * outputs a message but then exits, normally with a status of 1.
29 * The sys* versions do the same, but append a colon, a space, and the results
30 * of strerror(errno) to the end of the message. All functions accept
31 * printf-style formatting strings and arguments.
33 * If message_fatal_cleanup is non-NULL, it is called before exit by die and
34 * sysdie and its return value is used as the argument to exit. It is a
35 * pointer to a function taking no arguments and returning an int, and can be
36 * used to call cleanup functions or to exit in some alternate fashion (such
37 * as by calling _exit).
39 * If message_program_name is non-NULL, the string it points to, followed by a
40 * colon and a space, is prepended to all error messages logged through the
41 * message_log_stdout and message_log_stderr message handlers (the former is
42 * the default for notice, and the latter is the default for warn and die).
44 * Honoring error_program_name and printing to stderr is just the default
45 * handler; with message_handlers_* the handlers for any message function can
46 * be changed. By default, notice prints to stdout, warn and die print to
47 * stderr, and the others don't do anything at all. These functions take a
48 * count of handlers and then that many function pointers, each one to a
49 * function that takes a message length (the number of characters snprintf
50 * generates given the format and arguments), a format, an argument list as a
51 * va_list, and the applicable errno value (if any).
53 * The canonical version of this file is maintained in the rra-c-util package,
54 * which can be found at <https://www.eyrie.org/~eagle/software/rra-c-util/>.
56 * Written by Russ Allbery <eagle@eyrie.org>
57 * Copyright 2015, 2016 Russ Allbery <eagle@eyrie.org>
58 * Copyright 2008, 2009, 2010, 2013, 2014
59 * The Board of Trustees of the Leland Stanford Junior University
60 * Copyright (c) 2004, 2005, 2006
61 * by Internet Systems Consortium, Inc. ("ISC")
62 * Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
63 * 2002, 2003 by The Internet Software Consortium and Rich Salz
65 * This code is derived from software contributed to the Internet Software
66 * Consortium by Rich Salz.
68 * Permission to use, copy, modify, and distribute this software for any
69 * purpose with or without fee is hereby granted, provided that the above
70 * copyright notice and this permission notice appear in all copies.
72 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
73 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
74 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
75 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
76 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
77 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
78 * PERFORMANCE OF THIS SOFTWARE.
82 #include <portable/system.h>
91 # define LOG_DEBUG EVENTLOG_SUCCESS
92 # define LOG_INFO EVENTLOG_INFORMATION_TYPE
93 # define LOG_NOTICE EVENTLOG_INFORMATION_TYPE
94 # define LOG_WARNING EVENTLOG_WARNING_TYPE
95 # define LOG_ERR EVENTLOG_ERROR_TYPE
96 # define LOG_CRIT EVENTLOG_ERROR_TYPE
99 #include <util/macros.h>
100 #include <util/messages.h>
101 #include <util/xmalloc.h>
103 /* The default handler lists. */
104 static message_handler_func stdout_handlers[2] = {
105 message_log_stdout, NULL
107 static message_handler_func stderr_handlers[2] = {
108 message_log_stderr, NULL
111 /* The list of logging functions currently in effect. */
112 static message_handler_func *debug_handlers = NULL;
113 static message_handler_func *notice_handlers = stdout_handlers;
114 static message_handler_func *warn_handlers = stderr_handlers;
115 static message_handler_func *die_handlers = stderr_handlers;
117 /* If non-NULL, called before exit and its return value passed to exit. */
118 int (*message_fatal_cleanup)(void) = NULL;
120 /* If non-NULL, prepended (followed by ": ") to messages. */
121 const char *message_program_name = NULL;
125 * Set the handlers for a particular message function. Takes a pointer to the
126 * handler list, the count of handlers, and the argument list.
129 message_handlers(message_handler_func **list, unsigned int count, va_list args)
133 if (*list != stdout_handlers && *list != stderr_handlers)
135 *list = xcalloc(count + 1, sizeof(message_handler_func));
136 for (i = 0; i < count; i++)
137 (*list)[i] = (message_handler_func) va_arg(args, message_handler_func);
138 (*list)[count] = NULL;
143 * There's no good way of writing these handlers without a bunch of code
144 * duplication since we can't assume variadic macros, but I can at least make
145 * it easier to write and keep them consistent.
147 #define HANDLER_FUNCTION(type) \
149 message_handlers_ ## type(unsigned int count, ...) \
153 va_start(args, count); \
154 message_handlers(& type ## _handlers, count, args); \
157 HANDLER_FUNCTION(debug)
158 HANDLER_FUNCTION(notice)
159 HANDLER_FUNCTION(warn)
160 HANDLER_FUNCTION(die)
164 * Reset all handlers back to the defaults and free all allocated memory.
165 * This is primarily useful for programs that undergo comprehensive memory
166 * allocation analysis.
169 message_handlers_reset(void)
171 free(debug_handlers);
172 debug_handlers = NULL;
173 if (notice_handlers != stdout_handlers) {
174 free(notice_handlers);
175 notice_handlers = stdout_handlers;
177 if (warn_handlers != stderr_handlers) {
179 warn_handlers = stderr_handlers;
181 if (die_handlers != stderr_handlers) {
183 die_handlers = stderr_handlers;
189 * Print a message to stdout, supporting message_program_name.
192 message_log_stdout(size_t len UNUSED, const char *fmt, va_list args, int err)
194 if (message_program_name != NULL)
195 fprintf(stdout, "%s: ", message_program_name);
196 vfprintf(stdout, fmt, args);
198 fprintf(stdout, ": %s", strerror(err));
199 fprintf(stdout, "\n");
205 * Print a message to stderr, supporting message_program_name. Also flush
206 * stdout so that errors and regular output occur in the right order.
209 message_log_stderr(size_t len UNUSED, const char *fmt, va_list args, int err)
212 if (message_program_name != NULL)
213 fprintf(stderr, "%s: ", message_program_name);
214 vfprintf(stderr, fmt, args);
216 fprintf(stderr, ": %s", strerror(err));
217 fprintf(stderr, "\n");
222 * Log a message to syslog. This is a helper function used to implement all
223 * of the syslog message log handlers. It takes the same arguments as a
224 * regular message handler function but with an additional priority argument.
226 * This needs further attention on Windows. For example, it currently doesn't
227 * log the errno information.
229 static void __attribute__((__format__(printf, 3, 0)))
230 message_log_syslog(int pri, size_t len, const char *fmt, va_list args, int err)
235 buffer = malloc(len + 1);
236 if (buffer == NULL) {
237 fprintf(stderr, "failed to malloc %lu bytes at %s line %d: %s",
238 (unsigned long) len + 1, __FILE__, __LINE__, strerror(errno));
239 exit(message_fatal_cleanup ? (*message_fatal_cleanup)() : 1);
241 status = vsnprintf(buffer, len + 1, fmt, args);
242 if (status < 0 || (size_t) status >= len + 1) {
243 warn("failed to format output with vsnprintf in syslog handler");
251 eventlog = RegisterEventSource(NULL, message_program_name);
252 if (eventlog != NULL) {
253 ReportEvent(eventlog, (WORD) pri, 0, 0, NULL, 1, 0, &buffer, NULL);
254 CloseEventLog(eventlog);
259 syslog(pri, "%s", buffer);
261 syslog(pri, "%s: %s", buffer, strerror(err));
268 * Do the same sort of wrapper to generate all of the separate syslog logging
271 #define SYSLOG_FUNCTION(name, type) \
273 message_log_syslog_ ## name(size_t l, const char *f, va_list a, int e) \
275 message_log_syslog(LOG_ ## type, l, f, a, e); \
277 SYSLOG_FUNCTION(debug, DEBUG)
278 SYSLOG_FUNCTION(info, INFO)
279 SYSLOG_FUNCTION(notice, NOTICE)
280 SYSLOG_FUNCTION(warning, WARNING)
281 SYSLOG_FUNCTION(err, ERR)
282 SYSLOG_FUNCTION(crit, CRIT)
286 * All of the message handlers. There's a lot of code duplication here too,
287 * but each one is still *slightly* different and va_start has to be called
288 * multiple times, so it's hard to get rid of the duplication.
292 debug(const char *format, ...)
295 message_handler_func *log;
298 if (debug_handlers == NULL)
300 va_start(args, format);
301 length = vsnprintf(NULL, 0, format, args);
305 for (log = debug_handlers; *log != NULL; log++) {
306 va_start(args, format);
307 (**log)((size_t) length, format, args, 0);
313 notice(const char *format, ...)
316 message_handler_func *log;
319 va_start(args, format);
320 length = vsnprintf(NULL, 0, format, args);
324 for (log = notice_handlers; *log != NULL; log++) {
325 va_start(args, format);
326 (**log)((size_t) length, format, args, 0);
332 sysnotice(const char *format, ...)
335 message_handler_func *log;
339 va_start(args, format);
340 length = vsnprintf(NULL, 0, format, args);
344 for (log = notice_handlers; *log != NULL; log++) {
345 va_start(args, format);
346 (**log)((size_t) length, format, args, error);
352 warn(const char *format, ...)
355 message_handler_func *log;
358 va_start(args, format);
359 length = vsnprintf(NULL, 0, format, args);
363 for (log = warn_handlers; *log != NULL; log++) {
364 va_start(args, format);
365 (**log)((size_t) length, format, args, 0);
371 syswarn(const char *format, ...)
374 message_handler_func *log;
378 va_start(args, format);
379 length = vsnprintf(NULL, 0, format, args);
383 for (log = warn_handlers; *log != NULL; log++) {
384 va_start(args, format);
385 (**log)((size_t) length, format, args, error);
391 die(const char *format, ...)
394 message_handler_func *log;
397 va_start(args, format);
398 length = vsnprintf(NULL, 0, format, args);
401 for (log = die_handlers; *log != NULL; log++) {
402 va_start(args, format);
403 (**log)((size_t) length, format, args, 0);
406 exit(message_fatal_cleanup ? (*message_fatal_cleanup)() : 1);
410 sysdie(const char *format, ...)
413 message_handler_func *log;
417 va_start(args, format);
418 length = vsnprintf(NULL, 0, format, args);
421 for (log = die_handlers; *log != NULL; log++) {
422 va_start(args, format);
423 (**log)((size_t) length, format, args, error);
426 exit(message_fatal_cleanup ? (*message_fatal_cleanup)() : 1);