Skip to content

Commit

Permalink
journalctl: strip TABs and ANSI color sequences from log messages whe…
Browse files Browse the repository at this point in the history
…n displaying them
  • Loading branch information
poettering committed Dec 23, 2012
1 parent 2d0b052 commit e8bc0ea
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 2 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@
/test-replace-var
/test-sched-prio
/test-sleep
/test-strip-tab-ansi
/test-strv
/test-udev
/test-unit-file
Expand Down
12 changes: 10 additions & 2 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand All @@ -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 \
Expand Down Expand Up @@ -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

Expand Down
3 changes: 3 additions & 0 deletions src/shared/logs-show.c
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down
83 changes: 83 additions & 0 deletions src/shared/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -5666,3 +5666,86 @@ char *strreplace(const char *text, const char *old_string, const char *new_strin
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;
}
2 changes: 2 additions & 0 deletions src/shared/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
52 changes: 52 additions & 0 deletions src/test/test-strip-tab-ansi.c
Original file line number Diff line number Diff line change
@@ -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;
}

0 comments on commit e8bc0ea

Please sign in to comment.