X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=log.c;h=e1c9ed7471611a30699b8f1b567372238ee2e136;hp=da1c4f61e3575505d4e0b2e6de7582239d7e8312;hb=2a1a539789190c2d413710bcd88f1e351400d700;hpb=16801e901e87f4ca0c83ea8c09df1ab3d344129e diff --git a/log.c b/log.c index da1c4f61e..e1c9ed747 100644 --- a/log.c +++ b/log.c @@ -31,8 +31,6 @@ #include "util.h" #include "macro.h" -extern char * __progname; - #define SYSLOG_TIMEOUT_USEC (5*USEC_PER_SEC) #define LOG_BUFFER_MAX 1024 @@ -42,10 +40,14 @@ static int log_max_level = LOG_DEBUG; static int syslog_fd = -1; static int kmsg_fd = -1; +/* Akin to glibc's __abort_msg; which is private and we hance cannot + * use here. */ +static char *log_abort_msg = NULL; + void log_close_kmsg(void) { if (kmsg_fd >= 0) { - close_nointr(kmsg_fd); + close_nointr_nofail(kmsg_fd); kmsg_fd = -1; } } @@ -60,8 +62,12 @@ int log_open_kmsg(void) { if (kmsg_fd >= 0) return 0; - if ((kmsg_fd = open("/dev/kmsg", O_WRONLY|O_NOCTTY|O_CLOEXEC)) < 0) + if ((kmsg_fd = open("/dev/kmsg", O_WRONLY|O_NOCTTY|O_CLOEXEC)) < 0) { + log_info("Failed to open syslog for logging: %s", strerror(errno)); return -errno; + } + + log_info("Succesfully opened /dev/kmsg for logging."); return 0; } @@ -69,7 +75,7 @@ int log_open_kmsg(void) { void log_close_syslog(void) { if (syslog_fd >= 0) { - close_nointr(syslog_fd); + close_nointr_nofail(syslog_fd); syslog_fd = -1; } } @@ -109,9 +115,13 @@ int log_open_syslog(void) { if (connect(syslog_fd, &sa.sa, sizeof(sa)) < 0) { r = -errno; log_close_syslog(); - return -errno; + + log_info("Failed to open syslog for logging: %s", strerror(-r)); + return r; } + log_info("Succesfully opened syslog for logging."); + return 0; } @@ -188,7 +198,7 @@ static int write_to_syslog( zero(iovec); IOVEC_SET_STRING(iovec[0], header_priority); IOVEC_SET_STRING(iovec[1], header_time); - IOVEC_SET_STRING(iovec[2], file_name_from_path(__progname)); + IOVEC_SET_STRING(iovec[2], __progname); IOVEC_SET_STRING(iovec[3], header_pid); IOVEC_SET_STRING(iovec[4], buffer); @@ -228,7 +238,7 @@ static int write_to_kmsg( zero(iovec); IOVEC_SET_STRING(iovec[0], header_priority); - IOVEC_SET_STRING(iovec[1], file_name_from_path(__progname)); + IOVEC_SET_STRING(iovec[1], __progname); IOVEC_SET_STRING(iovec[2], header_pid); IOVEC_SET_STRING(iovec[3], buffer); IOVEC_SET_STRING(iovec[4], (char*) "\n"); @@ -239,6 +249,26 @@ static int write_to_kmsg( return 0; } +#define LOG_DISPATCH(level,file,line,func,format) \ + do { \ + va_list _ap; \ + bool written = false; \ + if (log_target == LOG_TARGET_KMSG) { \ + va_start(_ap, format); \ + written = write_to_kmsg(level, file, line, func, format, _ap) >= 0; \ + va_end(_ap); \ + } else if (log_target == LOG_TARGET_SYSLOG) { \ + va_start(_ap, format); \ + written = write_to_syslog(level, file, line, func, format, _ap) >= 0; \ + va_end(_ap); \ + } \ + if (!written) { \ + va_start(_ap, format); \ + write_to_console(level, file, line, func, format, _ap); \ + va_end(_ap); \ + } \ + } while (false) + void log_meta( int level, const char*file, @@ -246,31 +276,84 @@ void log_meta( const char *func, const char *format, ...) { - va_list ap; - bool written; int saved_errno; - if (LOG_PRI(level) > log_max_level) + if (_likely(LOG_PRI(level) > log_max_level)) return; saved_errno = errno; - written = false; - - if (log_target == LOG_TARGET_KMSG) { - va_start(ap, format); - written = write_to_kmsg(level, file, line, func, format, ap) >= 0; - va_end(ap); - } else if (log_target == LOG_TARGET_SYSLOG) { - va_start(ap, format); - written = write_to_syslog(level, file, line, func, format, ap) >= 0; - va_end(ap); - } + LOG_DISPATCH(level, file, line, func, format); + errno = saved_errno; +} - if (!written) { - va_start(ap, format); - write_to_console(level, file, line, func, format, ap); - va_end(ap); - } +void log_assert( + const char*file, + int line, + const char *func, + const char *format, ...) { + + static char buffer[LOG_BUFFER_MAX]; + va_list ap; + int saved_errno = errno; + + va_start(ap, format); + vsnprintf(buffer, sizeof(buffer), format, ap); + va_end(ap); + + char_array_0(buffer); + log_abort_msg = buffer; + LOG_DISPATCH(LOG_CRIT, file, line, func, format); + abort(); + + /* If the user chose to ignore this SIGABRT, we are happy to go on, as if nothing happened. */ errno = saved_errno; } + +int log_set_target_from_string(const char *e) { + LogTarget t; + + if ((t = log_target_from_string(e)) < 0) + return -EINVAL; + + log_set_target(t); + return 0; +} + +int log_set_max_level_from_string(const char *e) { + int t; + + if ((t = log_level_from_string(e)) < 0) + return -EINVAL; + + log_set_max_level(t); + return 0; +} + +void log_parse_environment(void) { + const char *e; + + if ((e = getenv("SYSTEMD_LOG_TARGET"))) + if (log_set_target_from_string(e) < 0) + log_warning("Failed to parse log target %s. Ignoring.", e); + + if ((e = getenv("SYSTEMD_LOG_LEVEL"))) + if (log_set_max_level_from_string(e) < 0) + log_warning("Failed to parse log level %s. Ignoring.", e); +} + +LogTarget log_get_target(void) { + return log_target; +} + +int log_get_max_level(void) { + return log_max_level; +} + +static const char *const log_target_table[] = { + [LOG_TARGET_CONSOLE] = "console", + [LOG_TARGET_SYSLOG] = "syslog", + [LOG_TARGET_KMSG] = "kmsg", +}; + +DEFINE_STRING_TABLE_LOOKUP(log_target, LogTarget);