[ 0.019862] fedora kernel: CPU0: Thermal monitoring enabled (TM1) [ 0.019900] fedora kernel: Last level iTLB entries: 4KB 512, 2MB 0, 4MB 0 Last level dTLB entries: 4KB 512, 2MB 32, 4MB 32 tlb_flushall_shift: 5 [ 0.020118] fedora kernel: Freeing SMP alternatives: 24k freed --- A beginning of support for multiline messages. Is this the right approach?
(Not all formats are updated). Zbyszek src/shared/logs-show.c | 76 +++++++++++++++++++++++++++++++------------------- src/shared/utf8.c | 25 +++++++++-------- src/shared/utf8.h | 5 +++- 3 files changed, 64 insertions(+), 42 deletions(-) diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index 116dc8a..1e9d22b 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -95,12 +95,54 @@ static bool shall_print(const char *p, size_t l, OutputFlags flags) { if (l >= PRINT_THRESHOLD) return false; - if (!utf8_is_printable_n(p, l)) + if (!utf8_is_printable_oneline(p, l)) return false; return true; } +static void print_multiline(FILE *f, unsigned n, unsigned n_columns, int flags, int priority, const char* message, size_t message_len) { + const char *color_on = "", *color_off = ""; + const char *pos, *end; + bool continuation = false; + + if (flags & OUTPUT_COLOR) { + if (priority <= LOG_ERR) { + color_on = ANSI_HIGHLIGHT_RED_ON; + color_off = ANSI_HIGHLIGHT_OFF; + } else if (priority <= LOG_NOTICE) { + color_on = ANSI_HIGHLIGHT_ON; + color_off = ANSI_HIGHLIGHT_OFF; + } + } + + for (pos = message; pos < message + message_len; pos = end + 1) { + int len; + for (end = pos; end < message + message_len && *end != '\n'; end++) + ; + len = end - pos; + assert(len >= 0); + + if ((flags & OUTPUT_FULL_WIDTH) || (len + n + 1 < n_columns)) + fprintf(f, "%*s %s%.*s%s\n", + continuation * n + 1, continuation ? " " : ":", + color_on, len, pos, color_off); + else if (n < n_columns && n_columns - n - 2 >= 3) { + _cleanup_free_ char *e; + + e = ellipsize_mem(pos, len, n_columns - n - 2, 90); + + if (!e) + fprintf(f, ": %s%.*s%s\n", color_on, len, pos, color_off); + else + fprintf(f, ": %s%s%s\n", color_on, e, color_off); + } else + fputs("\n", f); + + continuation = true; + } +} + static int output_short( FILE *f, sd_journal *j, @@ -115,7 +157,6 @@ static int output_short( _cleanup_free_ 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(f); assert(j); @@ -260,34 +301,11 @@ static int output_short( n += fake_pid_len + 2; } - 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) - fprintf(f, ": %s%.*s%s\n", color_on, (int) message_len, message, color_off); - else if (!utf8_is_printable_n(message, message_len)) { + if (!(flags & OUTPUT_SHOW_ALL) && !utf8_is_printable(message, message_len)) { char bytes[FORMAT_BYTES_MAX]; fprintf(f, ": [%s blob data]\n", format_bytes(bytes, sizeof(bytes), message_len)); - } else if ((flags & OUTPUT_FULL_WIDTH) || (message_len + n + 1 < n_columns)) - fprintf(f, ": %s%.*s%s\n", color_on, (int) message_len, message, color_off); - else if (n < n_columns && n_columns - n - 2 >= 3) { - _cleanup_free_ char *e; - - e = ellipsize_mem(message, message_len, n_columns - n - 2, 90); - - if (!e) - fprintf(f, ": %s%.*s%s\n", color_on, (int) message_len, message, color_off); - else - fprintf(f, ": %s%s%s\n", color_on, e, color_off); } else - fputs("\n", f); + print_multiline(f, n, n_columns, flags, p, message, message_len); if (flags & OUTPUT_CATALOG) print_catalog(f, j); @@ -410,7 +428,7 @@ static int output_export( memcmp(data, "_BOOT_ID=", 9) == 0) continue; - if (!utf8_is_printable_n(data, length)) { + if (!utf8_is_printable_oneline(data, length)) { const char *c; uint64_t le64; @@ -449,7 +467,7 @@ void json_escape( fputs("null", f); - else if (!utf8_is_printable_n(p, l)) { + else if (!utf8_is_printable_oneline(p, l)) { bool not_first = false; fputs("[ ", f); diff --git a/src/shared/utf8.c b/src/shared/utf8.c index 3964e8b..f42a33b 100644 --- a/src/shared/utf8.c +++ b/src/shared/utf8.c @@ -86,14 +86,15 @@ static bool is_unicode_control(uint32_t ch) { '\t' is in C0 range, but more or less harmless and commonly used. */ - return (ch < ' ' && ch != '\t') || + return (ch < ' ' && ch != '\t' && ch != '\n') || (0x7F <= ch && ch <= 0x9F); } -char* utf8_is_printable_n(const char* str, size_t length) { +int utf8_is_printable(const char* str, size_t length) { uint32_t val = 0; uint32_t min = 0; const uint8_t *p; + int ans = 2; /* printable, no newlines */ assert(str); @@ -113,40 +114,40 @@ char* utf8_is_printable_n(const char* str, size_t length) { min = (1 << 16); val = (uint32_t) (*p & 0x07); } else - goto error; + return 0; p++; length--; if (!length || !is_continuation_char(*p)) - goto error; + return 0; merge_continuation_char(&val, *p); TWO_REMAINING: p++; length--; if (!is_continuation_char(*p)) - goto error; + return 0; merge_continuation_char(&val, *p); ONE_REMAINING: p++; length--; if (!is_continuation_char(*p)) - goto error; + return 0; merge_continuation_char(&val, *p); if (val < min) - goto error; + return 0; } if (is_unicode_control(val)) - goto error; - } + return 0; - return (char*) str; + if (val == '\n') + ans = 1; /* printable, with newlines */ + } -error: - return NULL; + return ans; } static char* utf8_validate(const char *str, char *output) { diff --git a/src/shared/utf8.h b/src/shared/utf8.h index 794ae15..6381a49 100644 --- a/src/shared/utf8.h +++ b/src/shared/utf8.h @@ -26,7 +26,10 @@ char *utf8_is_valid(const char *s) _pure_; char *ascii_is_valid(const char *s) _pure_; -char *utf8_is_printable_n(const char* str, size_t length) _pure_; +int utf8_is_printable(const char* str, size_t length) _pure_; +static inline bool utf8_is_printable_oneline(const char* str, size_t length) { + return utf8_is_printable(str, length) == 2; +}; char *utf8_filter(const char *s); char *ascii_filter(const char *s); -- 1.8.2.1 _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel