diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile.am | 12 | ||||
-rw-r--r-- | src/shared/logs-show.c | 3 | ||||
-rw-r--r-- | src/shared/util.c | 83 | ||||
-rw-r--r-- | src/shared/util.h | 2 | ||||
-rw-r--r-- | src/test/test-strip-tab-ansi.c | 52 |
6 files changed, 151 insertions, 2 deletions
diff --git a/.gitignore b/.gitignore index 2f3d981ac7..a55190489e 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 8021c9db25..65055b3fba 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 ca5ad43b63..04450a5504 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 d5f975e744..9ec6e2fe2f 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 bf24272ea6..25b349a17a 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 0000000000..5016906ad0 --- /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 <http://www.gnu.org/licenses/>. +***/ + +#include <stdio.h> + +#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; +} |