xref: /original-bsd/sbin/dmesg/dmesg.c (revision 122f4730)
1 /*-
2  * Copyright (c) 1991 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 char copyright[] =
10 "@(#) Copyright (c) 1991 The Regents of the University of California.\n\
11  All rights reserved.\n";
12 #endif /* not lint */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)dmesg.c	5.16 (Berkeley) 04/30/93";
16 #endif /* not lint */
17 
18 #include <sys/cdefs.h>
19 #include <sys/msgbuf.h>
20 
21 #include <fcntl.h>
22 #include <kvm.h>
23 #include <limits.h>
24 #include <nlist.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <time.h>
28 #include <unistd.h>
29 #include <vis.h>
30 
31 struct nlist nl[] = {
32 #define	X_MSGBUF	0
33 	{ "_msgbufp" },
34 	{ NULL },
35 };
36 
37 void usage __P((void));
38 
39 #define	KREAD(addr, var) \
40 	kvm_read(kd, addr, &var, sizeof(var)) != sizeof(var)
41 
42 int
43 main(argc, argv)
44 	int argc;
45 	char *argv[];
46 {
47 	register int ch, newl, skip;
48 	register char *p, *ep;
49 	struct msgbuf *bufp, cur;
50 	char *memf, *nlistf;
51 	kvm_t *kd;
52 	char buf[5];
53 
54 	memf = nlistf = NULL;
55 	while ((ch = getopt(argc, argv, "M:N:")) != EOF)
56 		switch(ch) {
57 		case 'M':
58 			memf = optarg;
59 			break;
60 		case 'N':
61 			nlistf = optarg;
62 			break;
63 		case '?':
64 		default:
65 			usage();
66 		}
67 	argc -= optind;
68 	argv += optind;
69 
70 	/*
71 	 * Discard setgid privileges if not the running kernel so that bad
72 	 * guys can't print interesting stuff from kernel memory.
73 	 */
74 	if (memf != NULL || nlistf != NULL)
75 		setgid(getgid());
76 
77 	/* Read in kernel message buffer, do sanity checks. */
78 	if ((kd = kvm_open(nlistf, memf, NULL, O_RDONLY, "dmesg")) == NULL)
79 		exit (1);
80 	if (kvm_nlist(kd, nl) == -1)
81 		errx(1, "kvm_nlist: %s", kvm_geterr(kd));
82 	if (nl[X_MSGBUF].n_type == 0)
83 		errx(1, "%s: msgbufp not found", nlistf ? nlistf : "namelist");
84 	if (KREAD(nl[X_MSGBUF].n_value, bufp) || KREAD((long)bufp, cur))
85 		errx(1, "kvm_read: %s", kvm_geterr(kd));
86 	kvm_close(kd);
87 	if (cur.msg_magic != MSG_MAGIC)
88 		errx(1, "magic number incorrect");
89 	if (cur.msg_bufx >= MSG_BSIZE)
90 		cur.msg_bufx = 0;
91 
92 	/*
93 	 * The message buffer is circular; start at the read pointer, and
94 	 * go to the write pointer - 1.
95 	 */
96 	p = cur.msg_bufc + cur.msg_bufx;
97 	ep = cur.msg_bufc + cur.msg_bufx - 1;
98 	for (newl = skip = 0; p != ep; ++p) {
99 		if (p == cur.msg_bufc + MSG_BSIZE)
100 			p = cur.msg_bufc;
101 		ch = *p;
102 		/* Skip "\n<.*>" syslog sequences. */
103 		if (skip) {
104 			if (ch == '>')
105 				newl = skip = 0;
106 			continue;
107 		}
108 		if (newl && ch == '<') {
109 			skip = 1;
110 			continue;
111 		}
112 		if (ch == '\0')
113 			continue;
114 		newl = ch == '\n';
115 		(void)vis(buf, ch, 0, 0);
116 		if (buf[1] == 0)
117 			(void)putchar(buf[0]);
118 		else
119 			(void)printf("%s", buf);
120 	}
121 	if (!newl)
122 		(void)putchar('\n');
123 	exit(0);
124 }
125 
126 void
127 usage()
128 {
129 	(void)fprintf(stderr, "usage: dmesg [-M core] [-N system]\n");
130 	exit(1);
131 }
132