[systemd-devel] [RFC PATCH] logs-show: print multiline messages
Zbigniew Jędrzejewski-Szmek
zbyszek at in.waw.pl
Wed Apr 24 07:30:22 PDT 2013
[ 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
More information about the systemd-devel
mailing list