From 8c8fa302c10d646a49d1d7565cbb60c5356a60b3 Mon Sep 17 00:00:00 2001 From: Bjørn Mork Date: Tue, 2 Oct 2012 01:54:49 +0200 Subject: dmesg: fix console-level off-by-one commit f06ec64f dmesg; support level names (e.g. --console-level=alert) introduced an off-by-one error. The kernel will print messages with a *higher* level than the console-level. The bug made it impossible to set the level for debugging, like it is documented in e.g Documentation/networking/netconsole.txt : nemi:/tmp# dmesg -n 8 dmesg: unknown level '8' And attempting to set the "emerg" level would result in an invalid 0 value: nemi:/tmp# dmesg -n emerg dmesg: klogctl failed: Invalid argument Restoring the old behaviour for numeric levels, and mapping the level names so that "dmesg -n debug" behaves as expected: logging everything at level "debug" and higher. [kzak@redhat.com: - add comment to parse_level()] Signed-off-by: Bjørn Mork Signed-off-by: Karel Zak --- sys-utils/dmesg.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'sys-utils/dmesg.c') diff --git a/sys-utils/dmesg.c b/sys-utils/dmesg.c index 0ee03eeba..4c85f9fce 100644 --- a/sys-utils/dmesg.c +++ b/sys-utils/dmesg.c @@ -227,24 +227,36 @@ static void __attribute__((__noreturn__)) usage(FILE *out) /* * LEVEL ::= | - * ::= number in range <0..N>, where N < ARRAY_SIZE(level_names) + * ::= @len is set: number in range <0..N>, where N < ARRAY_SIZE(level_names) + * ::= @len not set: number in range <1..N>, where N <= ARRAY_SIZE(level_names) * ::= case-insensitive text + * + * Note that @len argument is not set when parsing "-n " command line + * option. The console_level is intepreted as "log level less than the value". + * + * For example "dmesg -n 8" or "dmesg -n debug" enables debug console log + * level by klogctl(SYSLOG_ACTION_CONSOLE_LEVEL, NULL, 8). The @str argument + * has to be parsed to number in range <1..8>. */ static int parse_level(const char *str, size_t len) { + int offset = 0; + if (!str) return -1; - if (!len) + if (!len) { len = strlen(str); + offset = 1; + } errno = 0; if (isdigit(*str)) { char *end = NULL; - long x = strtol(str, &end, 10); + long x = strtol(str, &end, 10) - offset; if (!errno && end && end > str && (size_t) (end - str) == len && x >= 0 && (size_t) x < ARRAY_SIZE(level_names)) - return x; + return x + offset; } else { size_t i; @@ -252,7 +264,7 @@ static int parse_level(const char *str, size_t len) const char *n = level_names[i].name; if (strncasecmp(str, n, len) == 0 && *(n + len) == '\0') - return i; + return i + offset; } } -- cgit v1.2.3-55-g7522