summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile.am12
-rw-r--r--src/shared/logs-show.c3
-rw-r--r--src/shared/util.c83
-rw-r--r--src/shared/util.h2
-rw-r--r--src/test/test-strip-tab-ansi.c52
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;
+}