X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fshared%2Flogs-show.c;h=c72ebc11f57c1644ec777249299b5d31c0fba737;hp=540b5a2a2cb3770416afea05745df470996c3846;hb=498261871dfa2a930ec84b13a176e3bdc43aa212;hpb=e02d1cf72d115d1d61defdca5b551672d876c6bd diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index 540b5a2a2..c72ebc11f 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -28,19 +28,10 @@ #include "logs-show.h" #include "log.h" #include "util.h" +#include "utf8.h" #define PRINT_THRESHOLD 128 -static bool contains_unprintable(const void *p, size_t l) { - const char *j; - - for (j = p; j < (const char *) p + l; j++) - if (*j < ' ' || *j >= 127) - return true; - - return false; -} - static int parse_field(const void *data, size_t length, const char *field, char **target, size_t *target_size) { size_t fl, nl; void *buf; @@ -59,12 +50,11 @@ static int parse_field(const void *data, size_t length, const char *field, char nl = length - fl; buf = malloc(nl+1); + if (!buf) + return log_oom(); + memcpy(buf, (const char*) data + fl, nl); ((char*)buf)[nl] = 0; - if (!buf) { - log_error("Out of memory"); - return -ENOMEM; - } free(*target); *target = buf; @@ -80,24 +70,33 @@ static bool shall_print(bool show_all, char *p, size_t l) { if (l > PRINT_THRESHOLD) return false; - if (contains_unprintable(p, l)) + if (!utf8_is_printable_n(p, l)) return false; return true; } -static int output_short(sd_journal *j, unsigned line, unsigned n_columns, bool show_all, bool monotonic_mode) { +static int output_short(sd_journal *j, unsigned line, unsigned n_columns, + OutputFlags flags) { int r; const void *data; size_t length; size_t n = 0; - char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL; - size_t hostname_len = 0, identifier_len = 0, comm_len = 0, pid_len = 0, fake_pid_len = 0, message_len = 0, realtime_len = 0, monotonic_len = 0; + char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL, *priority = NULL; + size_t hostname_len = 0, identifier_len = 0, comm_len = 0, pid_len = 0, fake_pid_len = 0, message_len = 0, realtime_len = 0, monotonic_len = 0, priority_len = 0; + int p = LOG_INFO; + const char *color_on = "", *color_off = ""; assert(j); SD_JOURNAL_FOREACH_DATA(j, data, length) { + r = parse_field(data, length, "PRIORITY=", &priority, &priority_len); + if (r < 0) + goto finish; + else if (r > 0) + continue; + r = parse_field(data, length, "_HOSTNAME=", &hostname, &hostname_len); if (r < 0) goto finish; @@ -150,7 +149,10 @@ static int output_short(sd_journal *j, unsigned line, unsigned n_columns, bool s goto finish; } - if (monotonic_mode) { + if (priority_len == 1 && *priority >= '0' && *priority <= '7') + p = *priority - '0'; + + if (flags & OUTPUT_MONOTONIC_MODE) { uint64_t t; sd_id128_t boot_id; @@ -202,44 +204,59 @@ static int output_short(sd_journal *j, unsigned line, unsigned n_columns, bool s n += strlen(buf); } - if (hostname && shall_print(show_all, hostname, hostname_len)) { + if (hostname && shall_print(flags & OUTPUT_SHOW_ALL, + hostname, hostname_len)) { printf(" %.*s", (int) hostname_len, hostname); n += hostname_len + 1; } - if (identifier && shall_print(show_all, identifier, identifier_len)) { + if (identifier && shall_print(flags & OUTPUT_SHOW_ALL, + identifier, identifier_len)) { printf(" %.*s", (int) identifier_len, identifier); n += identifier_len + 1; - } else if (comm && shall_print(show_all, comm, comm_len)) { + } else if (comm && shall_print(flags & OUTPUT_SHOW_ALL, + comm, comm_len)) { printf(" %.*s", (int) comm_len, comm); n += comm_len + 1; } else putchar(' '); - if (pid && shall_print(show_all, pid, pid_len)) { + if (pid && shall_print(flags & OUTPUT_SHOW_ALL, pid, pid_len)) { printf("[%.*s]", (int) pid_len, pid); n += pid_len + 2; - } else if (fake_pid && shall_print(show_all, fake_pid, fake_pid_len)) { + } else if (fake_pid && shall_print(flags & OUTPUT_SHOW_ALL, + fake_pid, fake_pid_len)) { printf("[%.*s]", (int) fake_pid_len, fake_pid); n += fake_pid_len + 2; } - if (show_all) - printf(": %.*s\n", (int) message_len, message); - else if (contains_unprintable(message, message_len)) { + if (flags & OUTPUT_COLOR) { + if (p <= LOG_ERR) { + color_on = ANSI_HIGHLIGHT_RED_ON; + color_off = ANSI_HIGHLIGHT_OFF; + } else if (p <= LOG_NOTICE) { + color_on = ANSI_HIGHLIGHT_ON; + color_off = ANSI_HIGHLIGHT_OFF; + } + } + + if (flags & OUTPUT_SHOW_ALL) + printf(": %s%.*s%s\n", color_on, (int) message_len, message, color_off); + else if (!utf8_is_printable_n(message, message_len)) { char bytes[FORMAT_BYTES_MAX]; printf(": [%s blob data]\n", format_bytes(bytes, sizeof(bytes), message_len)); - } else if (message_len + n < n_columns) - printf(": %.*s\n", (int) message_len, message); - else if (n < n_columns) { + } else if ((flags & OUTPUT_FULL_WIDTH) || + (message_len + n < n_columns)) + printf(": %s%.*s%s\n", color_on, (int) message_len, message, color_off); + else if (n < n_columns && n_columns - n - 2 >= 3) { char *e; e = ellipsize_mem(message, message_len, n_columns - n - 2, 90); if (!e) - printf(": %.*s\n", (int) message_len, message); + printf(": %s%.*s%s\n", color_on, (int) message_len, message, color_off); else - printf(": %s\n", e); + printf(": %s%s%s\n", color_on, e, color_off); free(e); } else @@ -260,15 +277,18 @@ finish: return r; } -static int output_short_realtime(sd_journal *j, unsigned line, unsigned n_columns, bool show_all) { - return output_short(j, line, n_columns, show_all, false); +static int output_short_realtime(sd_journal *j, unsigned line, + unsigned n_columns, OutputFlags flags) { + return output_short(j, line, n_columns, flags & ~OUTPUT_MONOTONIC_MODE); } -static int output_short_monotonic(sd_journal *j, unsigned line, unsigned n_columns, bool show_all) { - return output_short(j, line, n_columns, show_all, true); +static int output_short_monotonic(sd_journal *j, unsigned line, + unsigned n_columns, OutputFlags flags) { + return output_short(j, line, n_columns, flags | OUTPUT_MONOTONIC_MODE); } -static int output_verbose(sd_journal *j, unsigned line, unsigned n_columns, bool show_all) { +static int output_verbose(sd_journal *j, unsigned line, + unsigned n_columns, OutputFlags flags) { const void *data; size_t length; char *cursor; @@ -297,8 +317,8 @@ static int output_verbose(sd_journal *j, unsigned line, unsigned n_columns, bool free(cursor); SD_JOURNAL_FOREACH_DATA(j, data, length) { - if (!show_all && (length > PRINT_THRESHOLD || - contains_unprintable(data, length))) { + if (!(flags & OUTPUT_SHOW_ALL) && (length > PRINT_THRESHOLD || + !utf8_is_printable_n(data, length))) { const char *c; char bytes[FORMAT_BYTES_MAX]; @@ -319,7 +339,8 @@ static int output_verbose(sd_journal *j, unsigned line, unsigned n_columns, bool return 0; } -static int output_export(sd_journal *j, unsigned line, unsigned n_columns, bool show_all) { +static int output_export(sd_journal *j, unsigned line, + unsigned n_columns, OutputFlags flags) { sd_id128_t boot_id; char sid[33]; int r; @@ -367,7 +388,7 @@ static int output_export(sd_journal *j, unsigned line, unsigned n_columns, bool memcmp(data, "_BOOT_ID=", 9) == 0) continue; - if (contains_unprintable(data, length)) { + if (!utf8_is_printable_n(data, length)) { const char *c; uint64_t le64; @@ -394,8 +415,7 @@ static int output_export(sd_journal *j, unsigned line, unsigned n_columns, bool } static void json_escape(const char* p, size_t l) { - - if (contains_unprintable(p, l)) { + if (!utf8_is_printable_n(p, l)) { bool not_first = false; fputs("[ ", stdout); @@ -431,7 +451,8 @@ static void json_escape(const char* p, size_t l) { } } -static int output_json(sd_journal *j, unsigned line, unsigned n_columns, bool show_all) { +static int output_json(sd_journal *j, unsigned line, + unsigned n_columns, OutputFlags flags) { uint64_t realtime, monotonic; char *cursor; const void *data; @@ -504,7 +525,8 @@ static int output_json(sd_journal *j, unsigned line, unsigned n_columns, bool sh return 0; } -static int output_cat(sd_journal *j, unsigned line, unsigned n_columns, bool show_all) { +static int output_cat(sd_journal *j, unsigned line, + unsigned n_columns, OutputFlags flags) { const void *data; size_t l; int r; @@ -525,7 +547,8 @@ static int output_cat(sd_journal *j, unsigned line, unsigned n_columns, bool sho return 0; } -static int (*output_funcs[_OUTPUT_MODE_MAX])(sd_journal*j, unsigned line, unsigned n_columns, bool show_all) = { +static int (*output_funcs[_OUTPUT_MODE_MAX])(sd_journal*j, unsigned line, + unsigned n_columns, OutputFlags flags) = { [OUTPUT_SHORT] = output_short_realtime, [OUTPUT_SHORT_MONOTONIC] = output_short_monotonic, [OUTPUT_VERBOSE] = output_verbose, @@ -534,14 +557,15 @@ static int (*output_funcs[_OUTPUT_MODE_MAX])(sd_journal*j, unsigned line, unsign [OUTPUT_CAT] = output_cat }; -int output_journal(sd_journal *j, OutputMode mode, unsigned line, unsigned n_columns, bool show_all) { +int output_journal(sd_journal *j, OutputMode mode, unsigned line, + unsigned n_columns, OutputFlags flags) { assert(mode >= 0); assert(mode < _OUTPUT_MODE_MAX); if (n_columns <= 0) n_columns = columns(); - return output_funcs[mode](j, line, n_columns, show_all); + return output_funcs[mode](j, line, n_columns, flags); } int show_journal_by_unit( @@ -550,15 +574,14 @@ int show_journal_by_unit( unsigned n_columns, usec_t not_before, unsigned how_many, - bool show_all, - bool follow, - bool warn_cutoff) { + OutputFlags flags) { char *m = NULL; sd_journal *j = NULL; int r; unsigned line = 0; bool need_seek = false; + int warn_cutoff = flags & OUTPUT_WARN_CUTOFF; assert(mode >= 0); assert(mode < _OUTPUT_MODE_MAX); @@ -630,7 +653,7 @@ int show_journal_by_unit( line ++; - r = output_journal(j, mode, line, n_columns, show_all); + r = output_journal(j, mode, line, n_columns, flags); if (r < 0) goto finish; } @@ -649,13 +672,13 @@ int show_journal_by_unit( if (r < 0) goto finish; - if (not_before < cutoff) + if (r > 0 && not_before < cutoff) printf("Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.\n"); warn_cutoff = false; } - if (!follow) + if (!(flags & OUTPUT_FOLLOW)) break; r = sd_journal_wait(j, (usec_t) -1);