xref: /openbsd-src/sbin/dmesg/dmesg.c (revision d7259957e8a5d4370d76bfccd4a30d5d1fe80f38)
1*d7259957Scheloha /*	$OpenBSD: dmesg.c,v 1.33 2022/12/04 23:50:46 cheloha Exp $	*/
2df930be7Sderaadt /*	$NetBSD: dmesg.c,v 1.8 1995/03/18 14:54:49 cgd Exp $	*/
3df930be7Sderaadt 
4df930be7Sderaadt /*-
5df930be7Sderaadt  * Copyright (c) 1991, 1993
6df930be7Sderaadt  *	The Regents of the University of California.  All rights reserved.
7df930be7Sderaadt  *
8df930be7Sderaadt  * Redistribution and use in source and binary forms, with or without
9df930be7Sderaadt  * modification, are permitted provided that the following conditions
10df930be7Sderaadt  * are met:
11df930be7Sderaadt  * 1. Redistributions of source code must retain the above copyright
12df930be7Sderaadt  *    notice, this list of conditions and the following disclaimer.
13df930be7Sderaadt  * 2. Redistributions in binary form must reproduce the above copyright
14df930be7Sderaadt  *    notice, this list of conditions and the following disclaimer in the
15df930be7Sderaadt  *    documentation and/or other materials provided with the distribution.
161ef0d710Smillert  * 3. Neither the name of the University nor the names of its contributors
17df930be7Sderaadt  *    may be used to endorse or promote products derived from this software
18df930be7Sderaadt  *    without specific prior written permission.
19df930be7Sderaadt  *
20df930be7Sderaadt  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21df930be7Sderaadt  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22df930be7Sderaadt  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23df930be7Sderaadt  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24df930be7Sderaadt  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25df930be7Sderaadt  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26df930be7Sderaadt  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27df930be7Sderaadt  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28df930be7Sderaadt  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29df930be7Sderaadt  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30df930be7Sderaadt  * SUCH DAMAGE.
31df930be7Sderaadt  */
32df930be7Sderaadt 
33b9fc9a72Sderaadt #include <sys/types.h>
34df930be7Sderaadt #include <sys/msgbuf.h>
3508593e5cSmickey #include <sys/sysctl.h>
36df930be7Sderaadt 
37df930be7Sderaadt #include <err.h>
38df930be7Sderaadt #include <fcntl.h>
39df930be7Sderaadt #include <kvm.h>
40df930be7Sderaadt #include <limits.h>
41df930be7Sderaadt #include <nlist.h>
42ea4e325cSbluhm #include <stddef.h>
43df930be7Sderaadt #include <stdio.h>
44df930be7Sderaadt #include <stdlib.h>
45e2dd1ff4Smillert #include <string.h>
46df930be7Sderaadt #include <unistd.h>
47df930be7Sderaadt #include <vis.h>
48df930be7Sderaadt 
49df3ac657Sderaadt #ifndef NOKVM
50df930be7Sderaadt struct nlist nl[] = {
51df930be7Sderaadt #define	X_MSGBUF	0
52df930be7Sderaadt 	{ "_msgbufp" },
53df930be7Sderaadt 	{ NULL },
54df930be7Sderaadt };
55df3ac657Sderaadt #endif
56df930be7Sderaadt 
57c72b5b24Smillert void usage(void);
58df930be7Sderaadt 
59df930be7Sderaadt #define	KREAD(addr, var) \
60df930be7Sderaadt 	kvm_read(kd, addr, &var, sizeof(var)) != sizeof(var)
61df930be7Sderaadt 
62df930be7Sderaadt int
main(int argc,char * argv[])63bc52e260Sderaadt main(int argc, char *argv[])
64df930be7Sderaadt {
65e073c79dSmpech 	int ch, newl, skip, i;
66e073c79dSmpech 	char *p;
6708593e5cSmickey 	struct msgbuf cur;
681791bdc3Sderaadt 	char *memf, *nlistf, *bufdata = NULL;
69870f7eb4Stom 	char *allocated = NULL;
70bf0946fcSmpf 	int startupmsgs = 0;
71df930be7Sderaadt 	char buf[5];
72df930be7Sderaadt 
73df930be7Sderaadt 	memf = nlistf = NULL;
74bf0946fcSmpf 	while ((ch = getopt(argc, argv, "sM:N:")) != -1)
75df930be7Sderaadt 		switch(ch) {
76bf0946fcSmpf 		case 's':
77bf0946fcSmpf 			startupmsgs = 1;
78bf0946fcSmpf 			break;
79df930be7Sderaadt 		case 'M':
80df930be7Sderaadt 			memf = optarg;
81df930be7Sderaadt 			break;
82df930be7Sderaadt 		case 'N':
83df930be7Sderaadt 			nlistf = optarg;
84df930be7Sderaadt 			break;
85df930be7Sderaadt 		default:
86df930be7Sderaadt 			usage();
87df930be7Sderaadt 		}
88df930be7Sderaadt 	argc -= optind;
89df930be7Sderaadt 	argv += optind;
90df930be7Sderaadt 
91e7c9998bScheloha 	if (argc != 0)
92e7c9998bScheloha 		usage();
93e7c9998bScheloha 
9408593e5cSmickey 	if (memf == NULL && nlistf == NULL) {
9508593e5cSmickey 		int mib[2], msgbufsize;
9608593e5cSmickey 		size_t len;
9708593e5cSmickey 
9808593e5cSmickey 		mib[0] = CTL_KERN;
99bf0946fcSmpf 		mib[1] = startupmsgs ? KERN_CONSBUFSIZE : KERN_MSGBUFSIZE;
10008593e5cSmickey 		len = sizeof(msgbufsize);
10108593e5cSmickey 		if (sysctl(mib, 2, &msgbufsize, &len, NULL, 0))
10239e8b6eeStom 			err(1, "sysctl: %s", startupmsgs ? "KERN_CONSBUFSIZE" :
10339e8b6eeStom 			    "KERN_MSGBUFSIZE");
10408593e5cSmickey 
105ea4e325cSbluhm 		msgbufsize += offsetof(struct msgbuf, msg_bufc);
106870f7eb4Stom 		allocated = bufdata = calloc(1, msgbufsize);
10708593e5cSmickey 		if (bufdata == NULL)
10808593e5cSmickey 			errx(1, "couldn't allocate space for buffer data");
10908593e5cSmickey 
110bf0946fcSmpf 		mib[1] = startupmsgs ? KERN_CONSBUF : KERN_MSGBUF;
11108593e5cSmickey 		len = msgbufsize;
11208593e5cSmickey 		if (sysctl(mib, 2, bufdata, &len, NULL, 0))
11339e8b6eeStom 			err(1, "sysctl: %s",
11439e8b6eeStom 			    startupmsgs ? "KERN_CONSBUF" : "KERN_MSGBUF");
11508593e5cSmickey 
1160bd1216cSderaadt 		if (pledge("stdio", NULL) == -1)
1170bd1216cSderaadt 			err(1, "pledge");
118d85e1e30Sderaadt 
11908593e5cSmickey 		memcpy(&cur, bufdata, sizeof(cur));
12008593e5cSmickey 		bufdata = ((struct msgbuf *)bufdata)->msg_bufc;
12108593e5cSmickey 	} else {
12278262a1dSderaadt #ifndef NOKVM
12308593e5cSmickey 		struct msgbuf *bufp;
12408593e5cSmickey 		kvm_t *kd;
125df930be7Sderaadt 
126df930be7Sderaadt 		/* Read in kernel message buffer, do sanity checks. */
12708593e5cSmickey 		if ((kd = kvm_open(nlistf, memf, NULL, O_RDONLY,
12808593e5cSmickey 		    "dmesg")) == NULL)
12966420897Smickey 			return (1);
130e46873ebSderaadt 
1310bd1216cSderaadt 		if (pledge("stdio", NULL) == -1)
1320bd1216cSderaadt 			err(1, "pledge");
133d85e1e30Sderaadt 
134df930be7Sderaadt 		if (kvm_nlist(kd, nl) == -1)
135df930be7Sderaadt 			errx(1, "kvm_nlist: %s", kvm_geterr(kd));
136df930be7Sderaadt 		if (nl[X_MSGBUF].n_type == 0)
13708593e5cSmickey 			errx(1, "%s: msgbufp not found",
13808593e5cSmickey 			    nlistf ? nlistf : "namelist");
1396136241bSderaadt 		if (KREAD(nl[X_MSGBUF].n_value, bufp))
1406136241bSderaadt 			errx(1, "kvm_read: %s: (0x%lx)", kvm_geterr(kd),
1416136241bSderaadt 			    nl[X_MSGBUF].n_value);
1426136241bSderaadt 		if (KREAD((long)bufp, cur))
1436136241bSderaadt 			errx(1, "kvm_read: %s (%0lx)", kvm_geterr(kd),
1446136241bSderaadt 			    (unsigned long)bufp);
145df930be7Sderaadt 		if (cur.msg_magic != MSG_MAGIC)
146df930be7Sderaadt 			errx(1, "magic number incorrect");
147870f7eb4Stom 		allocated = bufdata = malloc(cur.msg_bufs);
148067cbd75Sderaadt 		if (bufdata == NULL)
149067cbd75Sderaadt 			errx(1, "couldn't allocate space for buffer data");
150067cbd75Sderaadt 		if (kvm_read(kd, (long)&bufp->msg_bufc, bufdata,
151067cbd75Sderaadt 		    cur.msg_bufs) != cur.msg_bufs)
152067cbd75Sderaadt 			errx(1, "kvm_read: %s", kvm_geterr(kd));
15308593e5cSmickey 		kvm_close(kd);
15478262a1dSderaadt #endif
15508593e5cSmickey 	}
15608593e5cSmickey 
157067cbd75Sderaadt 	if (cur.msg_bufx >= cur.msg_bufs)
158df930be7Sderaadt 		cur.msg_bufx = 0;
159df930be7Sderaadt 	/*
160df930be7Sderaadt 	 * The message buffer is circular; start at the read pointer, and
161df930be7Sderaadt 	 * go to the write pointer - 1.
162df930be7Sderaadt 	 */
163067cbd75Sderaadt 	for (newl = skip = i = 0, p = bufdata + cur.msg_bufx;
164067cbd75Sderaadt 	    i < cur.msg_bufs; i++, p++) {
165067cbd75Sderaadt 		if (p == bufdata + cur.msg_bufs)
166067cbd75Sderaadt 			p = bufdata;
167df930be7Sderaadt 		ch = *p;
168df930be7Sderaadt 		/* Skip "\n<.*>" syslog sequences. */
169df930be7Sderaadt 		if (skip) {
170df930be7Sderaadt 			if (ch == '>')
171df930be7Sderaadt 				newl = skip = 0;
172df930be7Sderaadt 			continue;
173df930be7Sderaadt 		}
174df930be7Sderaadt 		if (newl && ch == '<') {
175df930be7Sderaadt 			skip = 1;
176df930be7Sderaadt 			continue;
177df930be7Sderaadt 		}
178df930be7Sderaadt 		if (ch == '\0')
179df930be7Sderaadt 			continue;
180df930be7Sderaadt 		newl = ch == '\n';
1815a8ecc43Shenning 		vis(buf, ch, 0, 0);
182df930be7Sderaadt 		if (buf[1] == 0)
1835a8ecc43Shenning 			putchar(buf[0]);
184df930be7Sderaadt 		else
1855a8ecc43Shenning 			printf("%s", buf);
186067cbd75Sderaadt 	}
187df930be7Sderaadt 	if (!newl)
1885a8ecc43Shenning 		putchar('\n');
189870f7eb4Stom 	free(allocated);
19066420897Smickey 	return (0);
191df930be7Sderaadt }
192df930be7Sderaadt 
193df930be7Sderaadt void
usage(void)194bc52e260Sderaadt usage(void)
195df930be7Sderaadt {
1965a8ecc43Shenning 	extern char *__progname;
1975a8ecc43Shenning 
198bf0946fcSmpf 	fprintf(stderr, "usage: %s [-s] [-M core] [-N system]\n", __progname);
199df930be7Sderaadt 	exit(1);
200df930be7Sderaadt }
201