X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/disorder/blobdiff_plain/4942ee7d61bf22ba38bf026c7d05028cb7db0d54..92db088e5b292c1180a090ed369b9851e933e610:/lib/log.c diff --git a/lib/log.c b/lib/log.c index 00ec7cd..741059a 100644 --- a/lib/log.c +++ b/lib/log.c @@ -1,6 +1,6 @@ /* * This file is part of DisOrder. - * Copyright (C) 2004-2008 Richard Kettlewell + * Copyright (C) 2004-9, 2013 Richard Kettlewell * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,17 +17,18 @@ */ /** @file lib/log.c @brief Errors and logging * - * All messages are initially emitted by one of the four functions below. - * debug() is generally invoked via D() so that mostly you just do a test - * rather than a complete subroutine call. + * All messages are initially emitted by one of the four functions + * below. disorder_debug() is generally invoked via D() so that + * mostly you just do a test rather than a complete subroutine call. * * Messages are dispatched via @ref log_default. This defaults to @ref * log_stderr. daemonize() will turn off @ref log_stderr and use @ref * log_syslog instead. * - * fatal() will call exitfn() with a nonzero status. The default value is - * exit(), but it should be set to _exit() anywhere but the 'main line' of the - * program, to guarantee that exit() gets called at most once. + * disorder_fatal() will call exitfn() with a nonzero status. The + * default value is exit(), but it should be set to _exit() anywhere + * but the 'main line' of the program, to guarantee that exit() gets + * called at most once. */ #define NO_MEMORY_ALLOCATION @@ -36,8 +37,19 @@ #include "common.h" #include -#include -#include +#include +#if HAVE_SYSLOG_H +# include +#endif +#if HAVE_SYS_TIME_H +# include +#endif +#if HAVE_SYS_SOCKET_H +# include +#endif +#if HAVE_NETDB_H +# include +#endif #include #include "log.h" @@ -155,6 +167,7 @@ static void logfp(int pri, const char *msg, void *user) { fputc('\n', fp); } +#if HAVE_SYSLOG_H /** @brief Log to syslog */ static void logsyslog(int pri, const char *msg, void attribute((unused)) *user) { @@ -163,12 +176,15 @@ static void logsyslog(int pri, const char *msg, else syslog(pri, "%s:%d: %s", debug_filename, debug_lineno, msg); } +#endif /** @brief Log output that writes to @c stderr */ struct log_output log_stderr = { logfp, 0 }; +#if HAVE_SYSLOG_H /** @brief Log output that sends to syslog */ struct log_output log_syslog = { logsyslog, 0 }; +#endif /** @brief Format and log a message */ static void vlogger(int pri, const char *fmt, va_list ap) { @@ -189,12 +205,14 @@ static void logger(int pri, const char *fmt, ...) { /** @brief Format and log a message * @param pri Message priority (as per syslog) + * @param ec Error class * @param fmt Format string * @param errno_value Errno value to include as a string, or 0 * @param ap Argument list */ -void elog(int pri, int errno_value, const char *fmt, va_list ap) { +void elog(int pri, enum error_class ec, int errno_value, const char *fmt, va_list ap) { char buffer[1024]; + char errbuf[1024]; if(errno_value == 0) vlogger(pri, fmt, ap); @@ -202,7 +220,8 @@ void elog(int pri, int errno_value, const char *fmt, va_list ap) { memset(buffer, 0, sizeof buffer); byte_vsnprintf(buffer, sizeof buffer, fmt, ap); buffer[sizeof buffer - 1] = 0; - logger(pri, "%s: %s", buffer, strerror(errno_value)); + logger(pri, "%s: %s", buffer, + format_error(ec, errno_value, errbuf, sizeof errbuf)); } } @@ -215,7 +234,22 @@ void disorder_fatal(int errno_value, const char *msg, ...) { va_list ap; va_start(ap, msg); - elog(LOG_CRIT, errno_value, msg, ap); + elog(LOG_CRIT, ec_errno, errno_value, msg, ap); + va_end(ap); + if(getenv("DISORDER_FATAL_ABORT")) abort(); + exitfn(EXIT_FAILURE); +} + +/** @brief Log an error and quit + * + * If @c ${DISORDER_FATAL_ABORT} is defined (as anything) then the process + * is aborted, so you can get a backtrace. + */ +void disorder_fatal_ec(enum error_class ec, int errno_value, const char *msg, ...) { + va_list ap; + + va_start(ap, msg); + elog(LOG_CRIT, ec, errno_value, msg, ap); va_end(ap); if(getenv("DISORDER_FATAL_ABORT")) abort(); exitfn(EXIT_FAILURE); @@ -226,7 +260,16 @@ void disorder_error(int errno_value, const char *msg, ...) { va_list ap; va_start(ap, msg); - elog(LOG_ERR, errno_value, msg, ap); + elog(LOG_ERR, ec_errno, errno_value, msg, ap); + va_end(ap); +} + +/** @brief Log an error */ +void disorder_error_ec(enum error_class ec, int errno_value, const char *msg, ...) { + va_list ap; + + va_start(ap, msg); + elog(LOG_ERR, ec, errno_value, msg, ap); va_end(ap); } @@ -235,7 +278,7 @@ void disorder_info(const char *msg, ...) { va_list ap; va_start(ap, msg); - elog(LOG_INFO, 0, msg, ap); + elog(LOG_INFO, ec_none, 0, msg, ap); va_end(ap); } @@ -256,6 +299,27 @@ void set_progname(char **argv) { progname = argv[0]; } +/** @brief Format an error string + * @param ec Error class + * @param err Error code (interpretation defined by @p ec) + * @param buffer Output buffer + * @param bufsize Size of output buffer + * @return Pointer to error string + * + * The return value may or may not be @p buffer. + */ +#pragma GCC diagnostic ignored "-Wunused-parameter" +const char *format_error(enum error_class ec, int err, char buffer[], size_t bufsize) { + switch(ec) { + default: + return strerror(err); + case ec_getaddrinfo: + return gai_strerror(err); + case ec_none: + return "(none)"; + } +} + /* Local Variables: c-basic-offset:2