X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fshared%2Flog.c;h=b39b5acb5bd469e4ae8cabc681031c91f87da267;hb=41a79f1062d77f95248b92b91b3b788f886aa93f;hp=b61845859f3cca5300b7750fa812a564cd2c3913;hpb=e98055de981b568c31f18f470181ae166b56f172;p=elogind.git diff --git a/src/shared/log.c b/src/shared/log.c index b61845859..b39b5acb5 100644 --- a/src/shared/log.c +++ b/src/shared/log.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "log.h" #include "util.h" @@ -307,6 +308,8 @@ static int write_to_console( const char*file, int line, const char *func, + const char *object_name, + const char *object, const char *buffer) { char location[64]; @@ -345,6 +348,8 @@ static int write_to_syslog( const char*file, int line, const char *func, + const char *object_name, + const char *object, const char *buffer) { char header_priority[16], header_time[64], header_pid[16]; @@ -360,7 +365,8 @@ static int write_to_syslog( char_array_0(header_priority); t = (time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC); - if (!(tm = localtime(&t))) + tm = localtime(&t); + if (!tm) return -EINVAL; if (strftime(header_time, sizeof(header_time), "%h %e %T ", tm) <= 0) @@ -406,6 +412,8 @@ static int write_to_kmsg( const char*file, int line, const char *func, + const char *object_name, + const char *object, const char *buffer) { char header_priority[16], header_pid[16]; @@ -433,43 +441,55 @@ static int write_to_kmsg( return 1; } -static int write_to_journal( - int level, - const char*file, - int line, - const char *func, - const char *buffer) { - - char header[LINE_MAX]; - struct iovec iovec[3]; - struct msghdr mh; - - if (journal_fd < 0) - return 0; - - snprintf(header, sizeof(header), +static int log_do_header(char *header, size_t size, + int level, + const char *file, int line, const char *func, + const char *object_name, const char *object) { + snprintf(header, size, "PRIORITY=%i\n" "SYSLOG_FACILITY=%i\n" "CODE_FILE=%s\n" "CODE_LINE=%i\n" "CODE_FUNCTION=%s\n" - "SYSLOG_IDENTIFIER=%s\n" - "MESSAGE=", + "%s%.*s%s" + "SYSLOG_IDENTIFIER=%s\n", LOG_PRI(level), LOG_FAC(level), file, line, func, + object ? object_name : "", + object ? LINE_MAX : 0, object, /* %.0s means no output */ + object ? "\n" : "", program_invocation_short_name); + header[size - 1] = '\0'; + return 0; +} + +static int write_to_journal( + int level, + const char*file, + int line, + const char *func, + const char *object_name, + const char *object, + const char *buffer) { - char_array_0(header); + char header[LINE_MAX]; + struct iovec iovec[4] = {{0}}; + struct msghdr mh = {0}; + + if (journal_fd < 0) + return 0; + + log_do_header(header, sizeof(header), level, + file, line, func, object_name, object); - zero(iovec); IOVEC_SET_STRING(iovec[0], header); - IOVEC_SET_STRING(iovec[1], buffer); - IOVEC_SET_STRING(iovec[2], "\n"); + IOVEC_SET_STRING(iovec[1], "MESSAGE="); + IOVEC_SET_STRING(iovec[2], buffer); + IOVEC_SET_STRING(iovec[3], "\n"); - zero(mh); mh.msg_iov = iovec; mh.msg_iovlen = ELEMENTSOF(iovec); @@ -484,6 +504,8 @@ static int log_dispatch( const char*file, int line, const char *func, + const char *object_name, + const char *object, char *buffer) { int r = 0; @@ -511,7 +533,8 @@ static int log_dispatch( log_target == LOG_TARGET_JOURNAL_OR_KMSG || log_target == LOG_TARGET_JOURNAL) { - k = write_to_journal(level, file, line, func, buffer); + k = write_to_journal(level, file, line, func, + object_name, object, buffer); if (k < 0) { if (k != -EAGAIN) log_close_journal(); @@ -523,7 +546,8 @@ static int log_dispatch( if (log_target == LOG_TARGET_SYSLOG_OR_KMSG || log_target == LOG_TARGET_SYSLOG) { - k = write_to_syslog(level, file, line, func, buffer); + k = write_to_syslog(level, file, line, func, + object_name, object, buffer); if (k < 0) { if (k != -EAGAIN) log_close_syslog(); @@ -539,7 +563,8 @@ static int log_dispatch( log_target == LOG_TARGET_JOURNAL_OR_KMSG || log_target == LOG_TARGET_KMSG)) { - k = write_to_kmsg(level, file, line, func, buffer); + k = write_to_kmsg(level, file, line, func, + object_name, object, buffer); if (k < 0) { log_close_kmsg(); log_open_console(); @@ -548,7 +573,8 @@ static int log_dispatch( } if (k <= 0) { - k = write_to_console(level, file, line, func, buffer); + k = write_to_console(level, file, line, func, + object_name, object, buffer); if (k < 0) return k; } @@ -574,7 +600,7 @@ int log_dump_internal( return 0; saved_errno = errno; - r = log_dispatch(level, file, line, func, buffer); + r = log_dispatch(level, file, line, func, NULL, NULL, buffer); errno = saved_errno; return r; @@ -598,7 +624,7 @@ int log_metav( vsnprintf(buffer, sizeof(buffer), format, ap); char_array_0(buffer); - r = log_dispatch(level, file, line, func, buffer); + r = log_dispatch(level, file, line, func, NULL, NULL, buffer); errno = saved_errno; return r; @@ -621,6 +647,53 @@ int log_meta( return r; } +int log_metav_object( + int level, + const char*file, + int line, + const char *func, + const char *object_name, + const char *object, + const char *format, + va_list ap) { + + char buffer[LINE_MAX]; + int saved_errno, r; + + if (_likely_(LOG_PRI(level) > log_max_level)) + return 0; + + saved_errno = errno; + vsnprintf(buffer, sizeof(buffer), format, ap); + char_array_0(buffer); + + r = log_dispatch(level, file, line, func, + object_name, object, buffer); + errno = saved_errno; + + return r; +} + +int log_meta_object( + int level, + const char*file, + int line, + const char *func, + const char *object_name, + const char *object, + const char *format, ...) { + + int r; + va_list ap; + + va_start(ap, format); + r = log_metav_object(level, file, line, func, + object_name, object, format, ap); + va_end(ap); + + return r; +} + #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wformat-nonliteral" _noreturn_ static void log_assert(const char *text, const char *file, int line, const char *func, const char *format) { @@ -631,7 +704,7 @@ _noreturn_ static void log_assert(const char *text, const char *file, int line, char_array_0(buffer); log_abort_msg = buffer; - log_dispatch(LOG_CRIT, file, line, func, buffer); + log_dispatch(LOG_CRIT, file, line, func, NULL, NULL, buffer); abort(); } #pragma GCC diagnostic pop @@ -677,39 +750,36 @@ int log_struct_internal( journal_fd >= 0) { char header[LINE_MAX]; - struct iovec iovec[17]; + struct iovec iovec[17] = {{0}}; unsigned n = 0, i; struct msghdr mh; - const char nl = '\n'; + static const char nl = '\n'; /* If the journal is available do structured logging */ - - snprintf(header, sizeof(header), - "PRIORITY=%i\n" - "SYSLOG_FACILITY=%i\n" - "CODE_FILE=%s\n" - "CODE_LINE=%i\n" - "CODE_FUNCTION=%s\n" - "SYSLOG_IDENTIFIER=%s\n", - LOG_PRI(level), - LOG_FAC(level), - file, - line, - func, - program_invocation_short_name); - char_array_0(header); - - zero(iovec); + log_do_header(header, sizeof(header), level, + file, line, func, NULL, NULL); IOVEC_SET_STRING(iovec[n++], header); va_start(ap, format); while (format && n + 1 < ELEMENTSOF(iovec)) { char *buf; + va_list aq; + + /* We need to copy the va_list structure, + * since vasprintf() leaves it afterwards at + * an undefined location */ - if (vasprintf(&buf, format, ap) < 0) { + va_copy(aq, ap); + if (vasprintf(&buf, format, aq) < 0) { + va_end(aq); r = -ENOMEM; goto finish; } + va_end(aq); + + /* Now, jump enough ahead, so that we point to + * the next format string */ + VA_FORMAT_ADVANCE(format, ap); IOVEC_SET_STRING(iovec[n++], buf); @@ -742,8 +812,11 @@ int log_struct_internal( va_start(ap, format); while (format) { + va_list aq; - vsnprintf(buf, sizeof(buf), format, ap); + va_copy(aq, ap); + vsnprintf(buf, sizeof(buf), format, aq); + va_end(aq); char_array_0(buf); if (startswith(buf, "MESSAGE=")) { @@ -751,12 +824,15 @@ int log_struct_internal( break; } + VA_FORMAT_ADVANCE(format, ap); + format = va_arg(ap, char *); } va_end(ap); if (found) - r = log_dispatch(level, file, line, func, buf + 8); + r = log_dispatch(level, file, line, func, + NULL, NULL, buf + 8); else r = -EINVAL; }