]> git.ipfire.org Git - thirdparty/util-linux.git/blame - sys-utils/dmesg.c
blkid: fix compiler warnings [-Wunused-parameter]
[thirdparty/util-linux.git] / sys-utils / dmesg.c
CommitLineData
5ef05369
KZ
1/*
2 * dmesg.c -- Print out the contents of the kernel ring buffer
7eda085c 3 *
5ef05369
KZ
4 * Copyright (C) 1993 Theodore Ts'o <tytso@athena.mit.edu>
5 * Copyright (C) 2011 Karel Zak <kzak@redhat.com>
6 *
7 * This program comes with ABSOLUTELY NO WARRANTY.
6dbe3af9 8 */
6dbe3af9
KZ
9#include <linux/unistd.h>
10#include <stdio.h>
11#include <getopt.h>
fd6b7a7f 12#include <stdlib.h>
15673c15 13#include <sys/klog.h>
f06ec64f 14#include <sys/syslog.h>
bd304d92 15#include <sys/time.h>
42fac79a 16#include <sys/sysinfo.h>
15103c4b 17#include <ctype.h>
bd304d92 18#include <time.h>
5423ccb1 19
15103c4b 20#include "c.h"
5423ccb1 21#include "nls.h"
15673c15 22#include "strutils.h"
15103c4b 23#include "xalloc.h"
b8300c0a
KZ
24#include "widechar.h"
25#include "writeall.h"
636a6207 26#include "bitops.h"
6dbe3af9 27
59a14899
KZ
28/* Close the log. Currently a NOP. */
29#define SYSLOG_ACTION_CLOSE 0
30/* Open the log. Currently a NOP. */
31#define SYSLOG_ACTION_OPEN 1
32/* Read from the log. */
33#define SYSLOG_ACTION_READ 2
34/* Read all messages remaining in the ring buffer. (allowed for non-root) */
35#define SYSLOG_ACTION_READ_ALL 3
36/* Read and clear all messages remaining in the ring buffer */
37#define SYSLOG_ACTION_READ_CLEAR 4
38/* Clear ring buffer. */
39#define SYSLOG_ACTION_CLEAR 5
40/* Disable printk's to console */
41#define SYSLOG_ACTION_CONSOLE_OFF 6
42/* Enable printk's to console */
43#define SYSLOG_ACTION_CONSOLE_ON 7
44/* Set level of messages printed to console */
45#define SYSLOG_ACTION_CONSOLE_LEVEL 8
46/* Return number of unread characters in the log buffer */
47#define SYSLOG_ACTION_SIZE_UNREAD 9
48/* Return size of the log buffer */
49#define SYSLOG_ACTION_SIZE_BUFFER 10
50
f06ec64f 51/*
5ef05369 52 * Priority and facility names
f06ec64f
KZ
53 */
54struct dmesg_name {
55 const char *name;
56 const char *help;
57};
58
5ef05369
KZ
59/*
60 * Priority names -- based on sys/syslog.h
61 */
f06ec64f
KZ
62static const struct dmesg_name level_names[] =
63{
64 [LOG_EMERG] = { "emerg", N_("system is unusable") },
65 [LOG_ALERT] = { "alert", N_("action must be taken immediately") },
66 [LOG_CRIT] = { "crit", N_("critical conditions") },
67 [LOG_ERR] = { "err", N_("error conditions") },
68 [LOG_WARNING] = { "warn", N_("warning conditions") },
69 [LOG_NOTICE] = { "notice",N_("normal but significant condition") },
70 [LOG_INFO] = { "info", N_("informational") },
71 [LOG_DEBUG] = { "debug", N_("debug-level messages") }
72};
73
85f3cc55
KZ
74/*
75 * sys/syslog.h uses (f << 3) for all facility codes.
76 * We want to use the codes as array idexes, so shift back...
77 *
78 * Note that libc LOG_FAC() macro returns the base codes, not the
79 * shifted code :-)
80 */
81#define FAC_BASE(f) ((f) >> 3)
82
83static const struct dmesg_name facility_names[] =
84{
85 [FAC_BASE(LOG_KERN)] = { "kern", N_("kernel messages") },
86 [FAC_BASE(LOG_USER)] = { "user", N_("random user-level messages") },
87 [FAC_BASE(LOG_MAIL)] = { "mail", N_("mail system") },
88 [FAC_BASE(LOG_DAEMON)] = { "daemon", N_("system daemons") },
89 [FAC_BASE(LOG_AUTH)] = { "auth", N_("security/authorization messages") },
90 [FAC_BASE(LOG_SYSLOG)] = { "syslog", N_("messages generated internally by syslogd") },
91 [FAC_BASE(LOG_LPR)] = { "lpr", N_("line printer subsystem") },
92 [FAC_BASE(LOG_NEWS)] = { "news", N_("network news subsystem") },
93 [FAC_BASE(LOG_UUCP)] = { "uucp", N_("UUCP subsystem") },
94 [FAC_BASE(LOG_CRON)] = { "cron", N_("clock daemon") },
95 [FAC_BASE(LOG_AUTHPRIV)] = { "authpriv", N_("security/authorization messages (private)") },
96 [FAC_BASE(LOG_FTP)] = { "ftp", N_("ftp daemon") },
97};
98
aca1633a
KZ
99struct dmesg_control {
100 /* bit arrays -- see include/bitops.h */
101 char levels[ARRAY_SIZE(level_names) / NBBY + 1];
102 char facilities[ARRAY_SIZE(facility_names) / NBBY + 1];
103
bd304d92 104 struct timeval lasttime; /* last printed timestamp */
42fac79a 105 time_t boot_time; /* system boot time */
bd304d92 106
9feec79c
KZ
107 unsigned int raw:1, /* raw mode */
108 fltr_lev:1, /* filter out by levels[] */
109 fltr_fac:1, /* filter out by facilities[] */
110 decode:1, /* use "facility: level: " prefix */
111 notime:1, /* don't print timestamp */
112 delta:1, /* show time deltas */
113 ctime:1; /* show human readable time */
aca1633a 114};
f4fa5b44 115
a7ee94f2
KZ
116struct dmesg_record {
117 const char *mesg;
118 size_t mesg_size;
119
120 int level;
121 int facility;
bd304d92 122 struct timeval tv;
a7ee94f2
KZ
123
124 const char *next; /* buffer with next unparsed record */
125 size_t next_size; /* size of the next buffer */
126};
127
4a3b7949 128static void __attribute__((__noreturn__)) usage(FILE *out)
15103c4b 129{
f06ec64f
KZ
130 int i;
131
4a3b7949
KZ
132 fprintf(out, _(
133 "\nUsage:\n"
134 " %s [options]\n"), program_invocation_short_name);
135
136 fprintf(out, _(
137 "\nOptions:\n"
04199860 138 " -C, --clear clear the kernel ring buffer\n"
4a3b7949 139 " -c, --read-clear read and clear all messages\n"
bd304d92
KZ
140 " -D, --console-off disable printing messages to console\n"
141 " -d, --show-delta show time delta between printed messages\n"
142 " -E, --console-on enable printing messages to console\n"
0e24df3b 143 " -f, --facility=LIST restrict output to defined facilities\n"
2170174e 144 " -h, --help display this help and exit\n"
25000180 145 " -k, --kernel display kernel messages\n"
636a6207 146 " -l, --level=LIST restrict output to defined levels\n"
2170174e 147 " -n, --console-level=LEVEL set level of messages printed to console\n"
4a3b7949
KZ
148 " -r, --raw print the raw message buffer\n"
149 " -s, --buffer-size=SIZE buffer size to query the kernel ring buffer\n"
42fac79a
KZ
150 " -T, --ctime show human readable timestamp (could be \n"
151 " inaccurate if you have used SUSPEND/RESUME)\n"
d74b8dfc 152 " -t, --notime don't print messages timestamp\n"
25000180 153 " -u, --userspace display userspace messages\n"
872a1575
KZ
154 " -V, --version output version information and exit\n"
155 " -x, --decode decode facility and level to readable string\n\n"));
4a3b7949 156
85f3cc55 157 fprintf(out, _("Supported log facilities:\n"));
f06ec64f 158 for (i = 0; i < ARRAY_SIZE(level_names); i++) {
85f3cc55
KZ
159 fprintf(stderr, " %7s - %s\n",
160 facility_names[i].name,
161 _(facility_names[i].help));
162 }
163
164 fprintf(out, _("\nSupported log levels (priorities):\n"));
165 for (i = 0; i < ARRAY_SIZE(level_names); i++) {
166 fprintf(stderr, " %7s - %s\n",
f06ec64f
KZ
167 level_names[i].name,
168 _(level_names[i].help));
169 }
170
171 fputc('\n', out);
172
4a3b7949 173 exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
6dbe3af9
KZ
174}
175
5ef05369
KZ
176/*
177 * LEVEL ::= <number> | <name>
178 * <number> ::= number in range <0..N>, where N < ARRAY_SIZE(level_names)
179 * <name> ::= case-insensitive text
180 */
5c8f6bc6 181static int parse_level(const char *str, size_t len)
f06ec64f
KZ
182{
183 int i;
184
5c8f6bc6 185 if (!str)
f06ec64f 186 return -1;
5c8f6bc6
KZ
187 if (!len)
188 len = strlen(str);
189 errno = 0;
f06ec64f 190
5c8f6bc6
KZ
191 if (isdigit(*str)) {
192 char *end = NULL;
193
194 i = strtol(str, &end, 10);
195 if (!errno && end && end > str && end - str == len &&
196 i >= 0 && i < ARRAY_SIZE(level_names))
f06ec64f 197 return i;
5c8f6bc6
KZ
198 } else {
199 for (i = 0; i < ARRAY_SIZE(level_names); i++) {
200 const char *n = level_names[i].name;
201
202 if (strncasecmp(str, n, len) == 0 && *(n + len) == '\0')
203 return i;
204 }
205 }
206
207 if (errno)
208 err(EXIT_FAILURE, _("failed to parse level '%s'"), str);
209
210 errx(EXIT_FAILURE, _("unknown level '%s'"), str);
f06ec64f
KZ
211 return -1;
212}
213
5ef05369
KZ
214/*
215 * FACILITY ::= <number> | <name>
216 * <number> ::= number in range <0..N>, where N < ARRAY_SIZE(facility_names)
217 * <name> ::= case-insensitive text
218 */
0e24df3b
KZ
219static int parse_facility(const char *str, size_t len)
220{
221 int i;
222
223 if (!str)
224 return -1;
225 if (!len)
226 len = strlen(str);
227 errno = 0;
228
229 if (isdigit(*str)) {
230 char *end = NULL;
231
232 i = strtol(str, &end, 10);
233 if (!errno && end && end > str && end - str == len &&
234 i >= 0 && i < ARRAY_SIZE(facility_names))
235 return i;
236 } else {
237 for (i = 0; i < ARRAY_SIZE(facility_names); i++) {
238 const char *n = facility_names[i].name;
239
240 if (strncasecmp(str, n, len) == 0 && *(n + len) == '\0')
241 return i;
242 }
243 }
244
245 if (errno)
246 err(EXIT_FAILURE, _("failed to parse facility '%s'"), str);
247
248 errx(EXIT_FAILURE, _("unknown facility '%s'"), str);
249 return -1;
250}
251
5ef05369
KZ
252/*
253 * Parses numerical prefix used for all messages in kernel ring buffer.
254 *
255 * Priorities/facilities are encoded into a single 32-bit quantity, where the
256 * bottom 3 bits are the priority (0-7) and the top 28 bits are the facility
257 * (0-big number).
258 *
259 * Note that the number has to end with '>' char.
260 */
636a6207
KZ
261static const char *parse_faclev(const char *str, int *fac, int *lev)
262{
263 long num;
264 char *end = NULL;
265
266 if (!str)
267 return str;
268
269 errno = 0;
270 num = strtol(str, &end, 10);
271
272 if (!errno && end && end > str) {
273 *fac = LOG_FAC(num);
274 *lev = LOG_PRI(num);
85f3cc55
KZ
275
276 if (*lev > ARRAY_SIZE(level_names))
277 *lev = -1;
278 if (*fac > ARRAY_SIZE(facility_names))
279 *fac = -1;
636a6207
KZ
280 return end + 1; /* skip '<' */
281 }
282
283 return str;
284}
285
bd304d92
KZ
286static const char *parse_timestamp(const char *str0, struct timeval *tv)
287{
288 const char *str = str0;
289 char *end = NULL;
290
291 if (!str0)
292 return str0;
293
294 errno = 0;
295 tv->tv_sec = strtol(str, &end, 10);
296
297 if (!errno && end && *end == '.' && *(end + 1)) {
298 str = end + 1;
299 end = NULL;
300 tv->tv_usec = strtol(str, &end, 10);
301 }
302 if (errno || !end || end == str || *end != ']')
303 return str0;
304
305 return end + 1; /* skip ']' */
306}
307
308
309static double time_diff(struct timeval *a, struct timeval *b)
310{
311 return (a->tv_sec - b->tv_sec) + (a->tv_usec - b->tv_usec) / 1E6;
312}
313
eed99b2a
KZ
314static int get_buffer_size()
315{
316 int n = klogctl(SYSLOG_ACTION_SIZE_BUFFER, NULL, 0);
317
318 return n > 0 ? n : 0;
319}
320
42fac79a
KZ
321static time_t get_boot_time(void)
322{
323 struct sysinfo info;
324 struct timeval tv;
325
326 if (sysinfo(&info) != 0)
327 warn(_("sysinfo failed"));
328 else if (gettimeofday(&tv, NULL) != 0)
329 warn(_("gettimeofday failed"));
330 else
331 return tv.tv_sec -= info.uptime;
332 return 0;
333}
334
5ef05369
KZ
335/*
336 * Reads messages from kernel ring buffer
337 */
65e3eed9
KZ
338static int read_buffer(char **buf, size_t bufsize, int clear)
339{
340 size_t sz;
341 int rc = -1;
342 int cmd = clear ? SYSLOG_ACTION_READ_CLEAR :
343 SYSLOG_ACTION_READ_ALL;
344
345 if (bufsize) {
346 sz = bufsize + 8;
347 *buf = xmalloc(sz * sizeof(char));
348 rc = klogctl(cmd, *buf, sz);
349 } else {
350 sz = 16392;
351 while (1) {
352 *buf = xmalloc(sz * sizeof(char));
353 rc = klogctl(SYSLOG_ACTION_READ_ALL, *buf, sz);
354 if (rc != sz || sz > (1 << 28))
355 break;
356 free(*buf);
357 *buf = NULL;
358 sz *= 4;
359 }
360
361 if (rc > 0 && clear)
362 rc = klogctl(SYSLOG_ACTION_READ_CLEAR, *buf, sz);
363 }
364
365 return rc;
366}
367
b8300c0a
KZ
368static int fwrite_hex(const char *buf, size_t size, FILE *out)
369{
370 int i;
371
372 for (i = 0; i < size; i++) {
373 int rc = fprintf(out, "\\x%02x", buf[i]);
374 if (rc < 0)
375 return rc;
376 }
377 return 0;
378}
379
5ef05369
KZ
380/*
381 * Prints to 'out' and non-printable chars are replaced with \x<hex> sequences.
382 */
b8300c0a
KZ
383static void safe_fwrite(const char *buf, size_t size, FILE *out)
384{
385 int i;
386#ifdef HAVE_WIDECHAR
387 mbstate_t s;
388 memset(&s, 0, sizeof (s));
389#endif
390 for (i = 0; i < size; i++) {
391 const char *p = buf + i;
392 int rc, hex = 0;
393
394#ifdef HAVE_WIDECHAR
395 wchar_t wc;
396 size_t len = mbrtowc(&wc, p, size - i, &s);
397
398 if (len == 0) /* L'\0' */
399 return;
400
730d5e77 401 if (len == (size_t)-1 || len == (size_t)-2) { /* invalid sequence */
b8300c0a
KZ
402 memset(&s, 0, sizeof (s));
403 len = hex = 1;
404
405 } else if (len > 1 && !iswprint(wc)) { /* non-printable multibyte */
406 hex = 1;
407 } else
408#endif
409 {
410 if (!isprint((unsigned int) *p) &&
411 !isspace((unsigned int) *p)) /* non-printable */
412 hex = 1;
413 }
414 if (hex)
415 rc = fwrite_hex(p, len, out);
416 else
85f3cc55 417 rc = fwrite(p, 1, len, out) != len;
b8300c0a
KZ
418 if (rc != 0)
419 err(EXIT_FAILURE, _("write failed"));
420 }
421}
422
a7ee94f2 423static int get_next_record(struct dmesg_control *ctl, struct dmesg_record *rec)
f4fa5b44 424{
f4fa5b44 425 int i;
b8300c0a
KZ
426 const char *begin = NULL;
427
a7ee94f2
KZ
428 if (!rec->next || !rec->next_size)
429 return 1;
f4fa5b44 430
a7ee94f2
KZ
431 rec->mesg = NULL;
432 rec->mesg_size = 0;
433 rec->facility = -1;
434 rec->level = -1;
bd304d92
KZ
435 rec->tv.tv_sec = 0;
436 rec->tv.tv_usec = 0;
a7ee94f2
KZ
437
438 for (i = 0; i < rec->next_size; i++) {
439 const char *p = rec->next + i;
440 const char *end = NULL;
b8300c0a
KZ
441
442 if (!begin)
443 begin = p;
444 if (*p == '\n')
445 end = p;
a7ee94f2 446 if (i + 1 == rec->next_size) {
b8300c0a 447 end = p + 1;
f4fa5b44 448 i++;
f4fa5b44 449 }
a7ee94f2
KZ
450 if (begin && !*begin)
451 begin = NULL; /* zero(s) at the end of the buffer? */
b8300c0a
KZ
452 if (!begin || !end)
453 continue;
454 if (end <= begin)
455 continue; /* error or empty line? */
456
636a6207 457 if (*begin == '<') {
aca1633a 458 if (ctl->fltr_lev || ctl->fltr_fac || ctl->decode) {
a7ee94f2
KZ
459 begin = parse_faclev(begin + 1, &rec->facility,
460 &rec->level);
636a6207
KZ
461 } else {
462 /* ignore facility and level */
463 while (begin < end) {
464 begin++;
465 if (*(begin - 1) == '>')
466 break;
467 }
b8300c0a
KZ
468 }
469 }
470
a7ee94f2
KZ
471 if (end <= begin)
472 return -1; /* error */
d74b8dfc 473
bd304d92
KZ
474 if (*begin == '[' && (*(begin + 1) == ' ' ||
475 isdigit(*(begin + 1)))) {
608d4501
KZ
476 if (ctl->delta || ctl->ctime) {
477 begin = parse_timestamp(begin + 1, &rec->tv);
478 } else if (ctl->notime) {
bd304d92
KZ
479 while (begin < end) {
480 begin++;
481 if (*(begin - 1) == ']')
482 break;
483 }
d74b8dfc 484 }
a7ee94f2 485 }
d74b8dfc 486
a7ee94f2
KZ
487 if (begin < end && *begin == ' ')
488 begin++;
d74b8dfc 489
a7ee94f2
KZ
490 rec->mesg = begin;
491 rec->mesg_size = end - begin;
b8300c0a 492
a7ee94f2
KZ
493 rec->next_size -= end - rec->next;
494 rec->next = rec->next_size > 0 ? end + 1 : NULL;
495
496 return 0;
497 }
498
499 return 1;
500}
501
502static int accept_record(struct dmesg_control *ctl, struct dmesg_record *rec)
503{
504 if (ctl->fltr_lev && (rec->facility < 0 ||
505 !isset(ctl->levels, rec->level)))
506 return 0;
507
508 if (ctl->fltr_fac && (rec->facility < 0 ||
509 !isset(ctl->facilities, rec->facility)))
510 return 0;
511
512 return 1;
513}
514
515/*
516 * Prints the 'buf' kernel ring buffer; the messages are filtered out according
517 * to 'levels' and 'facilities' bitarrays.
518 */
519static void print_buffer(const char *buf, size_t size,
520 struct dmesg_control *ctl)
521{
522 struct dmesg_record rec = { .next = buf, .next_size = size };
42fac79a 523 char tbuf[256];
a7ee94f2
KZ
524
525 if (ctl->raw) {
526 /* print whole buffer */
527 safe_fwrite(buf, size, stdout);
528 if (buf[size - 1] != '\n')
529 putchar('\n');
530 return;
531 }
532
bd304d92 533 while (get_next_record(ctl, &rec) == 0) {
bd304d92
KZ
534 if (!rec.mesg_size)
535 continue;
a7ee94f2
KZ
536
537 if (!accept_record(ctl, &rec))
538 continue;
539
540 if (ctl->decode && rec.level >= 0 && rec.facility >= 0)
541 printf("%-6s:%-6s: ", facility_names[rec.facility].name,
542 level_names[rec.level].name);
543
42fac79a
KZ
544 *tbuf = '\0';
545 if (ctl->ctime) {
546 time_t t = ctl->boot_time + rec.tv.tv_sec;
547 if (strftime(tbuf, sizeof(tbuf), "%a %b %e %H:%M:%S %Y",
548 localtime(&t)) == 0)
549 *tbuf = '\0';
550 }
bd304d92
KZ
551 if (ctl->delta) {
552 double delta = 0;
553
42fac79a 554 if (timerisset(&ctl->lasttime))
bd304d92
KZ
555 delta = time_diff(&rec.tv, &ctl->lasttime);
556 ctl->lasttime = rec.tv;
557
42fac79a
KZ
558 if (ctl->ctime && *tbuf)
559 printf("[%s ", tbuf);
608d4501
KZ
560 else if (ctl->notime)
561 putchar('[');
42fac79a
KZ
562 else
563 printf("[%5d.%06d ", (int) rec.tv.tv_sec,
564 (int) rec.tv.tv_usec);
565 printf("<%12.06f>] ", delta);
566 } else if (ctl->ctime && *tbuf) {
567 printf("[%s] ", tbuf);
bd304d92
KZ
568 }
569
a7ee94f2
KZ
570 safe_fwrite(rec.mesg, rec.mesg_size, stdout);
571
572 if (*(rec.mesg + rec.mesg_size - 1) != '\n')
573 putchar('\n');
f4fa5b44 574 }
f4fa5b44
KZ
575}
576
15103c4b
MP
577int main(int argc, char *argv[])
578{
579 char *buf = NULL;
c129767e 580 int bufsize = 0;
df1dddf9
KZ
581 int n;
582 int c;
48c5c662 583 int console_level = 0;
0506537a 584 int cmd = -1;
aca1633a 585 static struct dmesg_control ctl;
6dbe3af9 586
4a3b7949 587 static const struct option longopts[] = {
4a3b7949 588 { "buffer-size", required_argument, NULL, 's' },
5ef05369 589 { "clear", no_argument, NULL, 'C' },
4a3b7949 590 { "console-level", required_argument, NULL, 'n' },
bd304d92
KZ
591 { "console-off", no_argument, NULL, 'D' },
592 { "console-on", no_argument, NULL, 'E' },
5ef05369 593 { "decode", no_argument, NULL, 'x' },
0e24df3b 594 { "facility", required_argument, NULL, 'f' },
4a3b7949 595 { "help", no_argument, NULL, 'h' },
25000180 596 { "kernel", no_argument, NULL, 'k' },
5ef05369
KZ
597 { "level", required_argument, NULL, 'l' },
598 { "raw", no_argument, NULL, 'r' },
599 { "read-clear", no_argument, NULL, 'c' },
bd304d92 600 { "show-delta", no_argument, NULL, 'd' },
42fac79a 601 { "ctime", no_argument, NULL, 'T' },
d74b8dfc 602 { "notime", no_argument, NULL, 't' },
25000180 603 { "userspace", no_argument, NULL, 'u' },
5ef05369 604 { "version", no_argument, NULL, 'V' },
4a3b7949
KZ
605 { NULL, 0, NULL, 0 }
606 };
607
df1dddf9
KZ
608 setlocale(LC_ALL, "");
609 bindtextdomain(PACKAGE, LOCALEDIR);
610 textdomain(PACKAGE);
7eda085c 611
42fac79a 612 while ((c = getopt_long(argc, argv, "CcDdEf:hkl:n:rs:TtuVx",
aca1633a 613 longopts, NULL)) != -1) {
0506537a 614
bd304d92 615 if (cmd != -1 && strchr("CcnDE", c))
641986cf
KZ
616 errx(EXIT_FAILURE, _("clear, read-clear, console-level, "
617 "console-on, and console-off options are mutually "
618 "exclusive"));
0506537a 619
df1dddf9 620 switch (c) {
04199860
KZ
621 case 'C':
622 cmd = SYSLOG_ACTION_CLEAR;
623 break;
df1dddf9 624 case 'c':
59a14899 625 cmd = SYSLOG_ACTION_READ_CLEAR;
df1dddf9 626 break;
bd304d92 627 case 'D':
2170174e
KZ
628 cmd = SYSLOG_ACTION_CONSOLE_OFF;
629 break;
bd304d92
KZ
630 case 'd':
631 ctl.delta = 1;
632 break;
633 case 'E':
2170174e
KZ
634 cmd = SYSLOG_ACTION_CONSOLE_ON;
635 break;
0e24df3b 636 case 'f':
aca1633a 637 ctl.fltr_fac = 1;
c87638ad
KZ
638 if (string_to_bitarray(optarg,
639 ctl.facilities, parse_facility) < 0)
640 return EXIT_FAILURE;
0e24df3b 641 break;
5ef05369
KZ
642 case 'h':
643 usage(stdout);
df1dddf9 644 break;
25000180 645 case 'k':
aca1633a
KZ
646 ctl.fltr_fac = 1;
647 setbit(ctl.facilities, FAC_BASE(LOG_KERN));
25000180 648 break;
636a6207 649 case 'l':
aca1633a 650 ctl.fltr_lev= 1;
c87638ad
KZ
651 if (string_to_bitarray(optarg,
652 ctl.levels, parse_level) < 0)
653 return EXIT_FAILURE;
636a6207 654 break;
5ef05369
KZ
655 case 'n':
656 cmd = SYSLOG_ACTION_CONSOLE_LEVEL;
657 console_level = parse_level(optarg, 0);
658 break;
11ea22d5 659 case 'r':
aca1633a 660 ctl.raw = 1;
11ea22d5 661 break;
df1dddf9 662 case 's':
0506537a
KZ
663 bufsize = strtol_or_err(optarg,
664 _("failed to parse buffer size"));
c129767e
KZ
665 if (bufsize < 4096)
666 bufsize = 4096;
df1dddf9 667 break;
42fac79a
KZ
668 case 'T':
669 ctl.boot_time = get_boot_time();
670 if (ctl.boot_time)
671 ctl.ctime = 1;
672 break;
d74b8dfc 673 case 't':
aca1633a 674 ctl.notime = 1;
d74b8dfc 675 break;
25000180 676 case 'u':
aca1633a 677 ctl.fltr_fac = 1;
25000180 678 for (n = 1; n < ARRAY_SIZE(facility_names); n++)
aca1633a 679 setbit(ctl.facilities, n);
25000180 680 break;
4a3b7949
KZ
681 case 'V':
682 printf(_("%s from %s\n"), program_invocation_short_name,
683 PACKAGE_STRING);
684 return EXIT_SUCCESS;
5ef05369 685 case 'x':
aca1633a 686 ctl.decode = 1;
4a3b7949 687 break;
df1dddf9
KZ
688 case '?':
689 default:
4a3b7949 690 usage(stderr);
df1dddf9
KZ
691 }
692 }
693 argc -= optind;
694 argv += optind;
25000180 695 n = 0;
e6c379eb 696
15103c4b 697 if (argc > 1)
4a3b7949 698 usage(stderr);
6dbe3af9 699
0506537a
KZ
700 if (cmd == -1)
701 cmd = SYSLOG_ACTION_READ_ALL; /* default */
702
641986cf
KZ
703 if (ctl.raw && (ctl.fltr_lev || ctl.fltr_fac || ctl.delta ||
704 ctl.notime || ctl.ctime || ctl.decode))
705 errx(EXIT_FAILURE, _("--raw can't be used together with level, "
706 "facility, decode, delta, ctime or notime options"));
707
608d4501
KZ
708 if (ctl.notime && ctl.ctime)
709 errx(EXIT_FAILURE, _("--notime can't be used together with ctime "));
85f3cc55 710
48c5c662
KZ
711 switch (cmd) {
712 case SYSLOG_ACTION_READ_ALL:
713 case SYSLOG_ACTION_READ_CLEAR:
714 if (!bufsize)
715 bufsize = get_buffer_size();
716 n = read_buffer(&buf, bufsize, cmd == SYSLOG_ACTION_READ_CLEAR);
717 if (n > 0)
aca1633a 718 print_buffer(buf, n, &ctl);
48c5c662
KZ
719 free(buf);
720 break;
04199860 721 case SYSLOG_ACTION_CLEAR:
2170174e
KZ
722 case SYSLOG_ACTION_CONSOLE_OFF:
723 case SYSLOG_ACTION_CONSOLE_ON:
04199860
KZ
724 n = klogctl(cmd, NULL, 0);
725 break;
48c5c662
KZ
726 case SYSLOG_ACTION_CONSOLE_LEVEL:
727 n = klogctl(cmd, NULL, console_level);
728 break;
729 default:
730 errx(EXIT_FAILURE, _("unsupported command"));
731 break;
df1dddf9 732 }
6dbe3af9 733
15103c4b
MP
734 if (n < 0)
735 err(EXIT_FAILURE, _("klogctl failed"));
6dbe3af9 736
15103c4b 737 return EXIT_SUCCESS;
6dbe3af9 738}