From: Lennart Poettering Date: Sun, 23 Dec 2012 10:23:59 +0000 (+0100) Subject: journalctl: strip TABs and ANSI color sequences from log messages when displaying... X-Git-Tag: v197~103 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=e8bc0ea2b100158bf35c635039226235aa879068;ds=sidebyside journalctl: strip TABs and ANSI color sequences from log messages when displaying them --- diff --git a/.gitignore b/.gitignore index 2f3d981ac..a55190489 100644 --- a/.gitignore +++ b/.gitignore @@ -103,6 +103,7 @@ /test-replace-var /test-sched-prio /test-sleep +/test-strip-tab-ansi /test-strv /test-udev /test-unit-file diff --git a/Makefile.am b/Makefile.am index 8021c9db2..65055b3fb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1232,7 +1232,8 @@ noinst_PROGRAMS += \ test-sleep \ test-replace-var \ test-sched-prio \ - test-calendarspec + test-calendarspec \ + test-strip-tab-ansi TESTS += \ test-job-type \ @@ -1244,7 +1245,8 @@ TESTS += \ test-sleep \ test-replace-var \ test-sched-prio \ - test-calendarspec + test-calendarspec \ + test-strip-tab-ansi EXTRA_DIST += \ test/sched_idle_bad.service \ @@ -1341,6 +1343,12 @@ test_calendarspec_SOURCES = \ test_calendarspec_LDADD = \ libsystemd-shared.la +test_strip_tab_ansi_SOURCES = \ + src/test/test-strip-tab-ansi.c + +test_strip_tab_ansi_LDADD = \ + libsystemd-shared.la + test_daemon_SOURCES = \ src/test/test-daemon.c diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index ca5ad43b6..04450a550 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -179,6 +179,9 @@ static int output_short( if (!message) return 0; + if (!(flags & OUTPUT_SHOW_ALL)) + strip_tab_ansi(&message, &message_len); + if (priority_len == 1 && *priority >= '0' && *priority <= '7') p = *priority - '0'; diff --git a/src/shared/util.c b/src/shared/util.c index d5f975e74..9ec6e2fe2 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -5666,3 +5666,86 @@ oom: free(r); return NULL; } + +char *strip_tab_ansi(char **ibuf, size_t *_isz) { + const char *i, *begin; + enum { + STATE_OTHER, + STATE_ESCAPE, + STATE_BRACKET + } state = STATE_OTHER; + char *obuf = NULL; + size_t osz = 0, isz; + FILE *f; + + assert(ibuf); + assert(*ibuf); + + /* Strips ANSI color and replaces TABs by 8 spaces */ + + isz = _isz ? *_isz : strlen(*ibuf); + + f = open_memstream(&obuf, &osz); + if (!f) + return NULL; + + for (i = *ibuf; i < *ibuf + isz + 1; i++) { + + switch (state) { + + case STATE_OTHER: + if (i >= *ibuf + isz) /* EOT */ + break; + else if (*i == '\x1B') + state = STATE_ESCAPE; + else if (*i == '\t') + fputs(" ", f); + else + fputc(*i, f); + break; + + case STATE_ESCAPE: + if (i >= *ibuf + isz) { /* EOT */ + fputc('\x1B', f); + break; + } else if (*i == '[') { + state = STATE_BRACKET; + begin = i + 1; + } else { + fputc('\x1B', f); + fputc(*i, f); + state = STATE_OTHER; + } + + break; + + case STATE_BRACKET: + + if (i >= *ibuf + isz || /* EOT */ + (!(*i >= '0' && *i <= '9') && *i != ';' && *i != 'm')) { + fputc('\x1B', f); + fputc('[', f); + state = STATE_OTHER; + i = begin-1; + } else if (*i == 'm') + state = STATE_OTHER; + break; + } + } + + if (ferror(f)) { + fclose(f); + free(obuf); + return NULL; + } + + fclose(f); + + free(*ibuf); + *ibuf = obuf; + + if (_isz) + *_isz = osz; + + return obuf; +} diff --git a/src/shared/util.h b/src/shared/util.h index bf24272ea..25b349a17 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -559,3 +559,5 @@ typedef enum DrawSpecialChar { const char *draw_special_char(DrawSpecialChar ch); char *strreplace(const char *text, const char *old_string, const char *new_string); + +char *strip_tab_ansi(char **p, size_t *l); diff --git a/src/test/test-strip-tab-ansi.c b/src/test/test-strip-tab-ansi.c new file mode 100644 index 000000000..5016906ad --- /dev/null +++ b/src/test/test-strip-tab-ansi.c @@ -0,0 +1,52 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2012 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include + +#include "util.h" + +int main(int argc, char *argv[]) { + char *p; + + assert_se(p = strdup("\tFoobar\tbar\twaldo\t")); + assert_se(strip_tab_ansi(&p, NULL)); + fprintf(stdout, "<%s>\n", p); + assert_se(streq(p, " Foobar bar waldo ")); + free(p); + + assert_se(p = strdup(ANSI_HIGHLIGHT_ON "Hello" ANSI_HIGHLIGHT_OFF ANSI_HIGHLIGHT_RED_ON " world!" ANSI_HIGHLIGHT_OFF)); + assert_se(strip_tab_ansi(&p, NULL)); + fprintf(stdout, "<%s>\n", p); + assert_se(streq(p, "Hello world!")); + free(p); + + assert_se(p = strdup("\x1B[\x1B[\t\x1B[" ANSI_HIGHLIGHT_ON "\x1B[" "Hello" ANSI_HIGHLIGHT_OFF ANSI_HIGHLIGHT_RED_ON " world!" ANSI_HIGHLIGHT_OFF)); + assert_se(strip_tab_ansi(&p, NULL)); + assert_se(streq(p, "\x1B[\x1B[ \x1B[\x1B[Hello world!")); + free(p); + + assert_se(p = strdup("\x1B[waldo")); + assert_se(strip_tab_ansi(&p, NULL)); + assert_se(streq(p, "\x1B[waldo")); + free(p); + + return 0; +}