dmesg.c revision 22990
1213267Sluigi/*-
2204591Sluigi * Copyright (c) 1991, 1993
3204591Sluigi *	The Regents of the University of California.  All rights reserved.
4204591Sluigi *
5204591Sluigi * Redistribution and use in source and binary forms, with or without
6204591Sluigi * modification, are permitted provided that the following conditions
7204591Sluigi * are met:
8204591Sluigi * 1. Redistributions of source code must retain the above copyright
9204591Sluigi *    notice, this list of conditions and the following disclaimer.
10204591Sluigi * 2. Redistributions in binary form must reproduce the above copyright
11204591Sluigi *    notice, this list of conditions and the following disclaimer in the
12204591Sluigi *    documentation and/or other materials provided with the distribution.
13204591Sluigi * 3. All advertising materials mentioning features or use of this software
14204591Sluigi *    must display the following acknowledgement:
15204591Sluigi *	This product includes software developed by the University of
16204591Sluigi *	California, Berkeley and its contributors.
17204591Sluigi * 4. Neither the name of the University nor the names of its contributors
18204591Sluigi *    may be used to endorse or promote products derived from this software
19204591Sluigi *    without specific prior written permission.
20204591Sluigi *
21204591Sluigi * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22204591Sluigi * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23204591Sluigi * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24204591Sluigi * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25204591Sluigi * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26204591Sluigi * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27204591Sluigi * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28204591Sluigi * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29204591Sluigi * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30204591Sluigi * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31204591Sluigi * SUCH DAMAGE.
32204591Sluigi */
33204591Sluigi
34204591Sluigi#ifndef lint
35204591Sluigistatic const char copyright[] =
36204591Sluigi"@(#) Copyright (c) 1991, 1993\n\
37204591Sluigi	The Regents of the University of California.  All rights reserved.\n";
38204591Sluigi#endif /* not lint */
39204591Sluigi
40204591Sluigi#ifndef lint
41204591Sluigi#if 0
42204591Sluigistatic const char sccsid[] = "@(#)dmesg.c	8.1 (Berkeley) 6/5/93";
43204591Sluigi#endif
44204591Sluigistatic const char rcsid[] =
45204591Sluigi	"$Id$";
46204591Sluigi#endif /* not lint */
47204591Sluigi
48204591Sluigi#include <sys/cdefs.h>
49204591Sluigi#include <sys/msgbuf.h>
50204591Sluigi
51204591Sluigi#include <err.h>
52204591Sluigi#include <fcntl.h>
53204591Sluigi#include <kvm.h>
54204591Sluigi#include <limits.h>
55240494Sglebius#include <locale.h>
56240494Sglebius#include <nlist.h>
57240494Sglebius#include <stdio.h>
58240494Sglebius#include <stdlib.h>
59240494Sglebius#include <time.h>
60204591Sluigi#include <unistd.h>
61204591Sluigi#include <vis.h>
62204591Sluigi
63204591Sluigistruct nlist nl[] = {
64204591Sluigi#define	X_MSGBUF	0
65204591Sluigi	{ "_msgbufp" },
66204591Sluigi	{ NULL },
67204591Sluigi};
68204591Sluigi
69204591Sluigivoid usage __P((void));
70204591Sluigi
71204591Sluigi#define	KREAD(addr, var) \
72204591Sluigi	kvm_read(kd, addr, &var, sizeof(var)) != sizeof(var)
73204591Sluigi
74204591Sluigiint
75204591Sluigimain(argc, argv)
76204591Sluigi	int argc;
77204591Sluigi	char *argv[];
78204591Sluigi{
79204591Sluigi	register int ch, newl, skip;
80204591Sluigi	register char *p, *ep;
81204591Sluigi	struct msgbuf *bufp, cur;
82204591Sluigi	char *memf, *nlistf;
83204591Sluigi	kvm_t *kd;
84204591Sluigi	char buf[5];
85204591Sluigi
86204591Sluigi	(void) setlocale(LC_CTYPE, "");
87204591Sluigi	memf = nlistf = NULL;
88204591Sluigi	while ((ch = getopt(argc, argv, "M:N:")) != EOF)
89204591Sluigi		switch(ch) {
90204591Sluigi		case 'M':
91204591Sluigi			memf = optarg;
92204591Sluigi			break;
93204591Sluigi		case 'N':
94204591Sluigi			nlistf = optarg;
95204591Sluigi			break;
96204591Sluigi		case '?':
97204591Sluigi		default:
98204591Sluigi			usage();
99204591Sluigi		}
100204591Sluigi	argc -= optind;
101204591Sluigi	argv += optind;
102204591Sluigi
103204591Sluigi	/*
104204591Sluigi	 * Discard setgid privileges if not the running kernel so that bad
105204591Sluigi	 * guys can't print interesting stuff from kernel memory.
106204591Sluigi	 */
107204591Sluigi	if (memf != NULL || nlistf != NULL)
108204591Sluigi		setgid(getgid());
109204591Sluigi
110204591Sluigi	/* Read in kernel message buffer, do sanity checks. */
111204591Sluigi	if ((kd = kvm_open(nlistf, memf, NULL, O_RDONLY, "dmesg")) == NULL)
112204591Sluigi		exit (1);
113204591Sluigi	if (kvm_nlist(kd, nl) == -1)
114204591Sluigi		errx(1, "kvm_nlist: %s", kvm_geterr(kd));
115204591Sluigi	if (nl[X_MSGBUF].n_type == 0)
116204591Sluigi		errx(1, "%s: msgbufp not found", nlistf ? nlistf : "namelist");
117204591Sluigi	if (KREAD(nl[X_MSGBUF].n_value, bufp) || KREAD((long)bufp, cur))
118204591Sluigi		errx(1, "kvm_read: %s", kvm_geterr(kd));
119204591Sluigi	kvm_close(kd);
120204591Sluigi	if (cur.msg_magic != MSG_MAGIC)
121204591Sluigi		errx(1, "magic number incorrect");
122204591Sluigi	if (cur.msg_bufx >= MSG_BSIZE)
123204591Sluigi		cur.msg_bufx = 0;
124204591Sluigi
125204591Sluigi	/*
126204591Sluigi	 * The message buffer is circular.  If the buffer has wrapped, the
127204591Sluigi	 * write pointer points to the oldest data.  Otherwise, the write
128204591Sluigi	 * pointer points to \0's following the data.  Read the entire
129204591Sluigi	 * buffer starting at the write pointer and ignore nulls so that
130204591Sluigi	 * we effectively start at the oldest data.
131204591Sluigi	 */
132204591Sluigi	p = cur.msg_bufc + cur.msg_bufx;
133204591Sluigi	ep = (cur.msg_bufx == 0 ? cur.msg_bufc + MSG_BSIZE : p);
134204591Sluigi	newl = skip = 0;
135204591Sluigi	do {
136204591Sluigi		if (p == cur.msg_bufc + MSG_BSIZE)
137204591Sluigi			p = cur.msg_bufc;
138204591Sluigi		ch = *p;
139204591Sluigi		/* Skip "\n<.*>" syslog sequences. */
140204591Sluigi		if (skip) {
141204591Sluigi			if (ch == '>')
142204591Sluigi				newl = skip = 0;
143204591Sluigi			continue;
144204591Sluigi		}
145204591Sluigi		if (newl && ch == '<') {
146204591Sluigi			skip = 1;
147204591Sluigi			continue;
148204591Sluigi		}
149204591Sluigi		if (ch == '\0')
150204591Sluigi			continue;
151204591Sluigi		newl = ch == '\n';
152204591Sluigi		(void)vis(buf, ch, 0, 0);
153204591Sluigi		if (buf[1] == 0)
154204591Sluigi			(void)putchar(buf[0]);
155204591Sluigi		else
156204591Sluigi			(void)printf("%s", buf);
157204591Sluigi	} while (++p != ep);
158204591Sluigi	if (!newl)
159204591Sluigi		(void)putchar('\n');
160204591Sluigi	exit(0);
161204591Sluigi}
162204591Sluigi
163204591Sluigivoid
164204591Sluigiusage()
165204591Sluigi{
166204591Sluigi	(void)fprintf(stderr, "usage: dmesg [-M core] [-N system]\n");
167204591Sluigi	exit(1);
168204591Sluigi}
169204591Sluigi