1 /* vi: set sw=4 ts=4: */
2 /*
3  *
4  * dmesg - display/control kernel ring buffer.
5  *
6  * Copyright 2006 Rob Landley <rob@landley.net>
7  * Copyright 2006 Bernhard Reutner-Fischer <rep.nop@aon.at>
8  *
9  * Licensed under GPLv2, see file LICENSE in this source tree.
10  */
11 //config:config DMESG
12 //config:	bool "dmesg (3.7 kb)"
13 //config:	default y
14 //config:	help
15 //config:	dmesg is used to examine or control the kernel ring buffer. When the
16 //config:	Linux kernel prints messages to the system log, they are stored in
17 //config:	the kernel ring buffer. You can use dmesg to print the kernel's ring
18 //config:	buffer, clear the kernel ring buffer, change the size of the kernel
19 //config:	ring buffer, and change the priority level at which kernel messages
20 //config:	are also logged to the system console. Enable this option if you
21 //config:	wish to enable the 'dmesg' utility.
22 //config:
23 //config:config FEATURE_DMESG_PRETTY
24 //config:	bool "Pretty output"
25 //config:	default y
26 //config:	depends on DMESG
27 //config:	help
28 //config:	If you wish to scrub the syslog level from the output, say 'Y' here.
29 //config:	The syslog level is a string prefixed to every line with the form
30 //config:	"<#>".
31 //config:
32 //config:	With this option you will see:
33 //config:		# dmesg
34 //config:		Linux version 2.6.17.4 .....
35 //config:		BIOS-provided physical RAM map:
36 //config:		 BIOS-e820: 0000000000000000 - 000000000009f000 (usable)
37 //config:
38 //config:	Without this option you will see:
39 //config:		# dmesg
40 //config:		<5>Linux version 2.6.17.4 .....
41 //config:		<6>BIOS-provided physical RAM map:
42 //config:		<6> BIOS-e820: 0000000000000000 - 000000000009f000 (usable)
43 
44 //applet:IF_DMESG(APPLET(dmesg, BB_DIR_BIN, BB_SUID_DROP))
45 
46 //kbuild:lib-$(CONFIG_DMESG) += dmesg.o
47 
48 //usage:#define dmesg_trivial_usage
49 //usage:       "[-cr] [-n LEVEL] [-s SIZE]"
50 //usage:#define dmesg_full_usage "\n\n"
51 //usage:       "Print or control the kernel ring buffer\n"
52 //usage:     "\n	-c		Clear ring buffer after printing"
53 //usage:     "\n	-n LEVEL	Set console logging level"
54 //usage:     "\n	-s SIZE		Buffer size"
55 //usage:     "\n	-r		Print raw message buffer"
56 
57 #include <sys/klog.h>
58 #include "libbb.h"
59 
60 int dmesg_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
dmesg_main(int argc UNUSED_PARAM,char ** argv)61 int dmesg_main(int argc UNUSED_PARAM, char **argv)
62 {
63 	int len, level;
64 	char *buf;
65 	unsigned opts;
66 	enum {
67 		OPT_c = 1 << 0,
68 		OPT_s = 1 << 1,
69 		OPT_n = 1 << 2,
70 		OPT_r = 1 << 3
71 	};
72 
73 	opts = getopt32(argv, "cs:+n:+r", &len, &level);
74 	if (opts & OPT_n) {
75 		if (klogctl(8, NULL, (long) level))
76 			bb_simple_perror_msg_and_die("klogctl");
77 		return EXIT_SUCCESS;
78 	}
79 
80 	if (!(opts & OPT_s))
81 		len = klogctl(10, NULL, 0); /* read ring buffer size */
82 	if (len < 16*1024)
83 		len = 16*1024;
84 	if (len > 16*1024*1024)
85 		len = 16*1024*1024;
86 
87 	buf = xmalloc(len);
88 	len = klogctl(3 + (opts & OPT_c), buf, len); /* read ring buffer */
89 	if (len < 0)
90 		bb_simple_perror_msg_and_die("klogctl");
91 	if (len == 0)
92 		return EXIT_SUCCESS;
93 
94 
95 	if (ENABLE_FEATURE_DMESG_PRETTY && !(opts & OPT_r)) {
96 		int last = '\n';
97 		int in = 0;
98 
99 		/* Skip <[0-9]+> at the start of lines */
100 		while (1) {
101 			if (last == '\n' && buf[in] == '<') {
102 				while (buf[in++] != '>' && in < len)
103 					;
104 			} else {
105 				last = buf[in++];
106 				putchar(last);
107 			}
108 			if (in >= len)
109 				break;
110 		}
111 		/* Make sure we end with a newline */
112 		if (last != '\n')
113 			bb_putchar('\n');
114 	} else {
115 		full_write(STDOUT_FILENO, buf, len);
116 		if (buf[len-1] != '\n')
117 			bb_putchar('\n');
118 	}
119 
120 	if (ENABLE_FEATURE_CLEAN_UP) free(buf);
121 
122 	return EXIT_SUCCESS;
123 }
124