1 /* dmesg.c - display/control kernel ring buffer.
3 * Copyright 2006, 2007 Rob Landley <rob@landley.net>
5 * See http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/dmesg.html
7 * Don't ask me why the horrible new dmesg API is still in "testing":
8 * http://kernel.org/doc/Documentation/ABI/testing/dev-kmsg
10 // We care that FLAG_c is 1, so keep c at the end.
11 USE_DMESG(NEWTOY(dmesg, "w(follow)CSTtrs#<1n#c[!Ttr][!Cc][!Sw]", TOYFLAG_BIN))
17 usage: dmesg [-Cc] [-r|-t|-T] [-n LEVEL] [-s SIZE] [-w]
19 Print or control the kernel ring buffer.
21 -C Clear ring buffer without printing
22 -c Clear ring buffer after printing
23 -n Set kernel logging LEVEL (1-9)
24 -r Raw output (with <level markers>)
25 -S Use syslog(2) rather than /dev/kmsg
26 -s Show the last SIZE many bytes
27 -T Show human-readable timestamps
28 -t Don't print timestamps
29 -w Keep waiting for more output (aka --follow)
44 static void color(int c)
46 if (TT.use_color) printf("\033[%dm", c);
49 static void format_message(char *msg, int new)
51 unsigned long long time_s, time_us;
52 int facpri, subsystem, pos;
55 // The new /dev/kmsg and the old syslog(2) formats differ slightly.
57 if (sscanf(msg, "%u,%*u,%llu,%*[^;]; %n", &facpri, &time_us, &pos) != 2)
60 time_s = time_us/1000000;
62 } else if (sscanf(msg, "<%u>[%llu.%llu] %n",
63 &facpri, &time_s, &time_us, &pos) != 3) return;
65 // Drop extras after end of message text.
66 if ((p = strchr(text = msg+pos, '\n'))) *p = 0;
68 // Is there a subsystem? (The ": " is just a convention.)
69 p = strstr(text, ": ");
70 subsystem = p ? (p-text) : 0;
72 // To get "raw" output for /dev/kmsg we need to add priority to each line
73 if (toys.optflags&FLAG_r) {
75 printf("<%d>", facpri);
79 if (!(toys.optflags&FLAG_t)) {
81 if (toys.optflags&FLAG_T) {
82 time_t t = TT.tea+time_s;
85 printf("[%.*s] ", (int)(strlen(ts)-1), ts);
86 } else printf("[%5lld.%06lld] ", time_s, time_us);
89 // Errors (or worse) are shown in red, subsystems are shown in yellow.
92 printf("%.*s", subsystem, text);
95 color(31*((facpri&7)<=3));
99 static int xklogctl(int type, char *buf, int len)
101 int rc = klogctl(type, buf, len);
103 if (rc<0) perror_exit("klogctl");
108 static void dmesg_cleanup(void)
113 void dmesg_main(void)
115 TT.use_color = isatty(1);
117 if (TT.use_color) sigatexit(dmesg_cleanup);
118 // If we're displaying output, is it klogctl or /dev/kmsg?
119 if (toys.optflags & (FLAG_C|FLAG_n)) goto no_output;
121 if (toys.optflags&FLAG_T) {
125 TT.tea = time(0)-info.uptime;
128 if (!(toys.optflags&FLAG_S)) {
129 char msg[8193]; // CONSOLE_EXT_LOG_MAX+1
133 // Each read returns one message. By default, we block when there are no
134 // more messages (--follow); O_NONBLOCK is needed for for usual behavior.
135 fd = open("/dev/kmsg", O_RDONLY|(O_NONBLOCK*!(toys.optflags&FLAG_w)));
136 if (fd == -1) goto klogctl_mode;
138 // SYSLOG_ACTION_CLEAR(5) doesn't actually remove anything from /dev/kmsg,
139 // you need to seek to the last clear point.
140 lseek(fd, 0, SEEK_DATA);
143 // why does /dev/kmesg return EPIPE instead of EAGAIN if oldest message
144 // expires as we read it?
145 if (-1==(len = read(fd, msg, sizeof(msg))) && errno==EPIPE) continue;
146 // read() from kmsg always fails on a pre-3.5 kernel.
147 if (len==-1 && errno==EINVAL) goto klogctl_mode;
151 format_message(msg, 1);
155 char *data, *to, *from, *end;
159 // Figure out how much data we need, and fetch it.
160 if (!(size = TT.size)) size = xklogctl(10, 0, 0);
161 data = from = xmalloc(size+1);
162 data[size = xklogctl(3+(toys.optflags&FLAG_c), data, size)] = 0;
164 // Send each line to format_message.
167 if (!(end = memchr(from, '\n', to-from))) break;
169 format_message(from, 0);
173 if (CFG_TOYBOX_FREE) free(data);
177 // Set the log level?
178 if (toys.optflags & FLAG_n) xklogctl(8, 0, TT.level);
181 if (toys.optflags & (FLAG_C|FLAG_c)) xklogctl(5, 0, 0);