/* dmesg.c -- Print out the contents of the kernel ring buffer * Created: Sat Oct 9 16:19:47 1993 * Revised: Thu Oct 28 21:52:17 1993 by faith@cs.unc.edu * Copyright 1993 Theodore Ts'o (tytso@athena.mit.edu) * This program comes with ABSOLUTELY NO WARRANTY. * Modifications by Rick Sladkey (jrs@world.std.com) * Larger buffersize 3 June 1998 by Nicolai Langfeldt, based on a patch * by Peeter Joot. This was also suggested by John Hudson. * 1999-02-22 Arkadiusz Mi¶kiewicz * - added Native Language Support * */ #include #include #include #include #include #include #include "c.h" #include "nls.h" #include "strutils.h" #include "xalloc.h" /* Close the log. Currently a NOP. */ #define SYSLOG_ACTION_CLOSE 0 /* Open the log. Currently a NOP. */ #define SYSLOG_ACTION_OPEN 1 /* Read from the log. */ #define SYSLOG_ACTION_READ 2 /* Read all messages remaining in the ring buffer. (allowed for non-root) */ #define SYSLOG_ACTION_READ_ALL 3 /* Read and clear all messages remaining in the ring buffer */ #define SYSLOG_ACTION_READ_CLEAR 4 /* Clear ring buffer. */ #define SYSLOG_ACTION_CLEAR 5 /* Disable printk's to console */ #define SYSLOG_ACTION_CONSOLE_OFF 6 /* Enable printk's to console */ #define SYSLOG_ACTION_CONSOLE_ON 7 /* Set level of messages printed to console */ #define SYSLOG_ACTION_CONSOLE_LEVEL 8 /* Return number of unread characters in the log buffer */ #define SYSLOG_ACTION_SIZE_UNREAD 9 /* Return size of the log buffer */ #define SYSLOG_ACTION_SIZE_BUFFER 10 static void __attribute__((__noreturn__)) usage(FILE *out) { fprintf(out, _( "\nUsage:\n" " %s [options]\n"), program_invocation_short_name); fprintf(out, _( "\nOptions:\n" " -c, --read-clear read and clear all messages\n" " -r, --raw print the raw message buffer\n" " -s, --buffer-size=SIZE buffer size to query the kernel ring buffer\n" " -n, --console-level=LEVEL set level of messages printed to console\n" " -V, --version output version information and exit\n" " -h, --help display this help and exit\n\n")); exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS); } static int get_buffer_size() { int n = klogctl(SYSLOG_ACTION_SIZE_BUFFER, NULL, 0); return n > 0 ? n : 0; } int main(int argc, char *argv[]) { char *buf = NULL; int sz; int bufsize = 0; int i; int n; int c; int level = 0; int lastc; int cmd = SYSLOG_ACTION_READ_ALL; int raw = 0; static const struct option longopts[] = { { "read-clear", no_argument, NULL, 'c' }, { "raw", no_argument, NULL, 'r' }, { "buffer-size", required_argument, NULL, 's' }, { "console-level", required_argument, NULL, 'n' }, { "version", no_argument, NULL, 'V' }, { "help", no_argument, NULL, 'h' }, { NULL, 0, NULL, 0 } }; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); while ((c = getopt_long(argc, argv, "chrn:s:V", longopts, NULL)) != -1) { switch (c) { case 'c': cmd = SYSLOG_ACTION_READ_CLEAR; break; case 'n': cmd = SYSLOG_ACTION_CONSOLE_LEVEL; level = strtol_or_err(optarg, _("failed to parse level")); break; case 'r': raw = 1; break; case 's': bufsize = strtol_or_err(optarg, _("failed to parse buffer size")); if (bufsize < 4096) bufsize = 4096; break; case 'V': printf(_("%s from %s\n"), program_invocation_short_name, PACKAGE_STRING); return EXIT_SUCCESS; case 'h': usage(stdout); break; case '?': default: usage(stderr); } } argc -= optind; argv += optind; if (argc > 1) usage(stderr); if (cmd == SYSLOG_ACTION_CONSOLE_LEVEL) { n = klogctl(cmd, NULL, level); if (n < 0) err(EXIT_FAILURE, _("klogctl failed")); return EXIT_SUCCESS; } if (!bufsize) bufsize = get_buffer_size(); if (bufsize) { sz = bufsize + 8; buf = xmalloc(sz * sizeof(char)); n = klogctl(cmd, buf, sz); } else { sz = 16392; while (1) { buf = xmalloc(sz * sizeof(char)); n = klogctl(SYSLOG_ACTION_READ_ALL, buf, sz); /* read only */ if (n != sz || sz > (1 << 28)) break; free(buf); sz *= 4; } if (n > 0 && cmd == SYSLOG_ACTION_READ_CLEAR) n = klogctl(cmd, buf, sz); /* read and clear */ } if (n < 0) err(EXIT_FAILURE, _("klogctl failed")); lastc = '\n'; for (i = 0; i < n; i++) { if (!raw && (i == 0 || buf[i - 1] == '\n') && buf[i] == '<') { i++; while (isdigit(buf[i])) i++; if (buf[i] == '>') i++; } lastc = buf[i]; putchar(lastc); } if (lastc != '\n') putchar('\n'); free(buf); return EXIT_SUCCESS; }