aboutsummaryrefslogtreecommitdiff
path: root/toys/pending/dmesg.c
diff options
context:
space:
mode:
Diffstat (limited to 'toys/pending/dmesg.c')
-rw-r--r--toys/pending/dmesg.c182
1 files changed, 0 insertions, 182 deletions
diff --git a/toys/pending/dmesg.c b/toys/pending/dmesg.c
deleted file mode 100644
index b9156562..00000000
--- a/toys/pending/dmesg.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/* dmesg.c - display/control kernel ring buffer.
- *
- * Copyright 2006, 2007 Rob Landley <rob@landley.net>
- *
- * See http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/dmesg.html
- *
- * Don't ask me why the horrible new dmesg API is still in "testing":
- * http://kernel.org/doc/Documentation/ABI/testing/dev-kmsg
-
-// We care that FLAG_c is 1, so keep c at the end.
-USE_DMESG(NEWTOY(dmesg, "w(follow)CSTtrs#<1n#c[!Ttr][!Cc][!Sw]", TOYFLAG_BIN))
-
-config DMESG
- bool "dmesg"
- default n
- help
- usage: dmesg [-Cc] [-r|-t|-T] [-n LEVEL] [-s SIZE] [-w]
-
- Print or control the kernel ring buffer.
-
- -C Clear ring buffer without printing
- -c Clear ring buffer after printing
- -n Set kernel logging LEVEL (1-9)
- -r Raw output (with <level markers>)
- -S Use syslog(2) rather than /dev/kmsg
- -s Show the last SIZE many bytes
- -T Show human-readable timestamps
- -t Don't print timestamps
- -w Keep waiting for more output (aka --follow)
-*/
-
-#define FOR_dmesg
-#include "toys.h"
-#include <sys/klog.h>
-
-GLOBALS(
- long level;
- long size;
-
- int use_color;
- time_t tea;
-)
-
-static void color(int c)
-{
- if (TT.use_color) printf("\033[%dm", c);
-}
-
-static void format_message(char *msg, int new)
-{
- unsigned long long time_s, time_us;
- int facpri, subsystem, pos;
- char *p, *text;
-
- // The new /dev/kmsg and the old syslog(2) formats differ slightly.
- if (new) {
- if (sscanf(msg, "%u,%*u,%llu,%*[^;]; %n", &facpri, &time_us, &pos) != 2)
- return;
-
- time_s = time_us/1000000;
- time_us %= 1000000;
- } else if (sscanf(msg, "<%u>[%llu.%llu] %n",
- &facpri, &time_s, &time_us, &pos) != 3) return;
-
- // Drop extras after end of message text.
- if ((p = strchr(text = msg+pos, '\n'))) *p = 0;
-
- // Is there a subsystem? (The ": " is just a convention.)
- p = strstr(text, ": ");
- subsystem = p ? (p-text) : 0;
-
- // To get "raw" output for /dev/kmsg we need to add priority to each line
- if (toys.optflags&FLAG_r) {
- color(0);
- printf("<%d>", facpri);
- }
-
- // Format the time.
- if (!(toys.optflags&FLAG_t)) {
- color(32);
- if (toys.optflags&FLAG_T) {
- time_t t = TT.tea+time_s;
- char *ts = ctime(&t);
-
- printf("[%.*s] ", (int)(strlen(ts)-1), ts);
- } else printf("[%5lld.%06lld] ", time_s, time_us);
- }
-
- // Errors (or worse) are shown in red, subsystems are shown in yellow.
- if (subsystem) {
- color(33);
- printf("%.*s", subsystem, text);
- text += subsystem;
- }
- color(31*((facpri&7)<=3));
- xputs(text);
-}
-
-static int xklogctl(int type, char *buf, int len)
-{
- int rc = klogctl(type, buf, len);
-
- if (rc<0) perror_exit("klogctl");
-
- return rc;
-}
-
-static void dmesg_cleanup(void)
-{
- color(0);
-}
-
-void dmesg_main(void)
-{
- TT.use_color = isatty(1);
-
- if (TT.use_color) sigatexit(dmesg_cleanup);
- // If we're displaying output, is it klogctl or /dev/kmsg?
- if (toys.optflags & (FLAG_C|FLAG_n)) goto no_output;
-
- if (toys.optflags&FLAG_T) {
- struct sysinfo info;
-
- sysinfo(&info);
- TT.tea = time(0)-info.uptime;
- }
-
- if (!(toys.optflags&FLAG_S)) {
- char msg[8193]; // CONSOLE_EXT_LOG_MAX+1
- ssize_t len;
- int fd;
-
- // Each read returns one message. By default, we block when there are no
- // more messages (--follow); O_NONBLOCK is needed for for usual behavior.
- fd = open("/dev/kmsg", O_RDONLY|(O_NONBLOCK*!(toys.optflags&FLAG_w)));
- if (fd == -1) goto klogctl_mode;
-
- // SYSLOG_ACTION_CLEAR(5) doesn't actually remove anything from /dev/kmsg,
- // you need to seek to the last clear point.
- lseek(fd, 0, SEEK_DATA);
-
- for (;;) {
- // why does /dev/kmesg return EPIPE instead of EAGAIN if oldest message
- // expires as we read it?
- if (-1==(len = read(fd, msg, sizeof(msg))) && errno==EPIPE) continue;
- // read() from kmsg always fails on a pre-3.5 kernel.
- if (len==-1 && errno==EINVAL) goto klogctl_mode;
- if (len<1) break;
-
- msg[len] = 0;
- format_message(msg, 1);
- }
- close(fd);
- } else {
- char *data, *to, *from, *end;
- int size;
-
-klogctl_mode:
- // Figure out how much data we need, and fetch it.
- if (!(size = TT.size)) size = xklogctl(10, 0, 0);
- data = from = xmalloc(size+1);
- data[size = xklogctl(3+(toys.optflags&FLAG_c), data, size)] = 0;
-
- // Send each line to format_message.
- to = data + size;
- while (from < to) {
- if (!(end = memchr(from, '\n', to-from))) break;
- *end = 0;
- format_message(from, 0);
- from = end + 1;
- }
-
- if (CFG_TOYBOX_FREE) free(data);
- }
-
-no_output:
- // Set the log level?
- if (toys.optflags & FLAG_n) xklogctl(8, 0, TT.level);
-
- // Clear the buffer?
- if (toys.optflags & (FLAG_C|FLAG_c)) xklogctl(5, 0, 0);
-}