dmesg: add --noescape

We have no way how to print the kernel message buffer in really raw
way. The new option --noescape disables all \x<hex> translations.

Addresses: https://github.com/karelzak/util-linux/issues/858
Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
Karel Zak 2019-09-09 12:53:08 +02:00
parent a6cc5c16f4
commit 646bba41fd
3 changed files with 43 additions and 26 deletions

View File

@ -45,6 +45,7 @@ _dmesg_module()
--color
--level
--console-level
--noespace
--nopager
--raw
--syslog

View File

@ -113,12 +113,19 @@ option is used,
will
.I not
print or clear the kernel ring buffer.
.IP "\fB\-\-noescape\fR"
The unprintable and potentially unsafe characters (e.g. broken multi-byte
sequences, terminal controlling chars, etc.) are escaped in format \\x<hex> for
security reason by default. This option disables this feature at all. It's
usable for example for debugging purpose together with \fB\-\-raw\fR. Be
careful and don't use it by default.
.IP "\fB\-P\fR, \fB\-\-nopager\fR"
Do not pipe output into a pager. A pager is enabled by default for \fB\-\-human\fR output.
.IP "\fB\-p\fR, \fB\-\-force\-prefix\fR"
Add facility, level or timestamp information to each line of a multi-line message.
.IP "\fB\-r\fR, \fB\-\-raw\fR"
Print the raw message buffer, i.e. do not strip the log-level prefixes.
Print the raw message buffer, i.e. do not strip the log-level prefixes, but
all unprintable characters are still escaped (see also \fB\-\-noescape\fR).
Note that the real raw format depends on the method how
.BR dmesg (1)

View File

@ -191,6 +191,7 @@ struct dmesg_control {
unsigned int follow:1, /* wait for new messages */
raw:1, /* raw mode */
noesc:1, /* no escape */
fltr_lev:1, /* filter out by levels[] */
fltr_fac:1, /* filter out by facilities[] */
decode:1, /* use "facility: level: " prefix */
@ -286,6 +287,7 @@ static void __attribute__((__noreturn__)) usage(void)
fputs(_(" -P, --nopager do not pipe output into a pager\n"), out);
fputs(_(" -p, --force-prefix force timestamp output on each line of multi-line messages\n"), out);
fputs(_(" -r, --raw print the raw message buffer\n"), out);
fputs(_(" --noescape don't escape unprintable character\n"), out);
fputs(_(" -S, --syslog force to use syslog(2) rather than /dev/kmsg\n"), out);
fputs(_(" -s, --buffer-size <size> buffer size to query the kernel ring buffer\n"), out);
fputs(_(" -u, --userspace display userspace messages\n"), out);
@ -616,7 +618,7 @@ static int fwrite_hex(const char *buf, size_t size, FILE *out)
/*
* Prints to 'out' and non-printable chars are replaced with \x<hex> sequences.
*/
static void safe_fwrite(const char *buf, size_t size, int indent, FILE *out)
static void safe_fwrite(struct dmesg_control *ctl, const char *buf, size_t size, int indent, FILE *out)
{
size_t i;
#ifdef HAVE_WIDECHAR
@ -626,30 +628,32 @@ static void safe_fwrite(const char *buf, size_t size, int indent, FILE *out)
for (i = 0; i < size; i++) {
const char *p = buf + i;
int rc, hex = 0;
size_t len;
size_t len = 1;
if (!ctl->noesc) {
#ifdef HAVE_WIDECHAR
wchar_t wc;
len = mbrtowc(&wc, p, size - i, &s);
wchar_t wc;
len = mbrtowc(&wc, p, size - i, &s);
if (len == 0) /* L'\0' */
return;
if (len == 0) /* L'\0' */
return;
if (len == (size_t)-1 || len == (size_t)-2) { /* invalid sequence */
memset(&s, 0, sizeof (s));
len = hex = 1;
i += len - 1;
} else if (len > 1) {
if (!iswprint(wc) && !iswspace(wc)) /* non-printable multibyte */
hex = 1;
i += len - 1;
} else
if (len == (size_t)-1 || len == (size_t)-2) { /* invalid sequence */
memset(&s, 0, sizeof (s));
len = hex = 1;
i += len - 1;
} else if (len > 1) {
if (!iswprint(wc) && !iswspace(wc)) /* non-printable multibyte */
hex = 1;
i += len - 1;
} else
#endif
{
len = 1;
if (!isprint((unsigned char) *p) &&
!isspace((unsigned char) *p)) /* non-printable */
hex = 1;
{
len = 1;
if (!isprint((unsigned char) *p) &&
!isspace((unsigned char) *p)) /* non-printable */
hex = 1;
}
}
if (hex)
@ -787,7 +791,7 @@ static void raw_print(struct dmesg_control *ctl, const char *buf, size_t size)
/*
* Print whole ring buffer
*/
safe_fwrite(buf, size, 0, stdout);
safe_fwrite(ctl, buf, size, 0, stdout);
lastc = buf[size - 1];
} else {
/*
@ -797,7 +801,7 @@ static void raw_print(struct dmesg_control *ctl, const char *buf, size_t size)
size_t sz = size > ctl->pagesize ? ctl->pagesize : size;
char *x = ctl->mmap_buff;
safe_fwrite(x, sz, 0, stdout);
safe_fwrite(ctl, x, sz, 0, stdout);
lastc = x[sz - 1];
size -= sz;
ctl->mmap_buff += sz;
@ -1039,7 +1043,7 @@ full_output:
if (subsys) {
dmesg_enable_color(DMESG_COLOR_SUBSYS);
safe_fwrite(line, subsys - line, ctl->indent, stdout);
safe_fwrite(ctl, line, subsys - line, ctl->indent, stdout);
color_disable();
mesg_size -= subsys - line;
@ -1047,11 +1051,11 @@ full_output:
}
/* Error, alert .. etc. colors */
has_color = set_level_color(rec->level, line, mesg_size) == 0;
safe_fwrite(line, mesg_size, ctl->indent, stdout);
safe_fwrite(ctl, line, mesg_size, ctl->indent, stdout);
if (has_color)
color_disable();
} else
safe_fwrite(line, mesg_size, ctl->indent, stdout);
safe_fwrite(ctl, line, mesg_size, ctl->indent, stdout);
/* Get the next line */
if (ctl->force_prefix) {
@ -1313,6 +1317,7 @@ int main(int argc, char *argv[])
int colormode = UL_COLORMODE_UNDEF;
enum {
OPT_TIME_FORMAT = CHAR_MAX + 1,
OPT_NOESC
};
static const struct option longopts[] = {
@ -1336,6 +1341,7 @@ int main(int argc, char *argv[])
{ "reltime", no_argument, NULL, 'e' },
{ "show-delta", no_argument, NULL, 'd' },
{ "ctime", no_argument, NULL, 'T' },
{ "noescape", no_argument, NULL, OPT_NOESC },
{ "notime", no_argument, NULL, 't' },
{ "nopager", no_argument, NULL, 'P' },
{ "userspace", no_argument, NULL, 'u' },
@ -1461,6 +1467,9 @@ int main(int argc, char *argv[])
case OPT_TIME_FORMAT:
ctl.time_fmt = which_time_format(optarg);
break;
case OPT_NOESC:
ctl.noesc = 1;
break;
case 'h':
usage();