chiark / gitweb /
journalctl: strip TABs and ANSI color sequences from log messages when displaying...
authorLennart Poettering <lennart@poettering.net>
Sun, 23 Dec 2012 10:23:59 +0000 (11:23 +0100)
committerLennart Poettering <lennart@poettering.net>
Sun, 23 Dec 2012 10:28:14 +0000 (11:28 +0100)
.gitignore
Makefile.am
src/shared/logs-show.c
src/shared/util.c
src/shared/util.h
src/test/test-strip-tab-ansi.c [new file with mode: 0644]

index 2f3d981ac7fc61b9e83ff93e407e255037dfd1c9..a55190489e139f0a32ab2b7acef2ccdc336abcc0 100644 (file)
 /test-replace-var
 /test-sched-prio
 /test-sleep
+/test-strip-tab-ansi
 /test-strv
 /test-udev
 /test-unit-file
index 8021c9db25a1cece63a2249fa38c88ba74eadce8..65055b3fba7450842f1c47ccdaae42f38f2f7a0a 100644 (file)
@@ -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
 
index ca5ad43b633477fc8d76379f84a1a2e572c1bebb..04450a550466dd40894df16de4beb046569df1d5 100644 (file)
@@ -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';
 
index d5f975e7445724b5d28da3b5aa3267239027843d..9ec6e2fe2f5e2ad54bb373eb12da157806f7bab8 100644 (file)
@@ -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;
+}
index bf24272ea6940365869d277aea816e617f541d90..25b349a17a0c1ff9be109963635b7a69ee521186 100644 (file)
@@ -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 (file)
index 0000000..5016906
--- /dev/null
@@ -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;
+}