Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sbin/dmesg/dmesg.c
39475 views
1
/*-
2
* SPDX-License-Identifier: BSD-3-Clause
3
*
4
* Copyright (c) 1991, 1993
5
* The Regents of the University of California. All rights reserved.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
* 2. Redistributions in binary form must reproduce the above copyright
13
* notice, this list of conditions and the following disclaimer in the
14
* documentation and/or other materials provided with the distribution.
15
* 3. Neither the name of the University nor the names of its contributors
16
* may be used to endorse or promote products derived from this software
17
* without specific prior written permission.
18
*
19
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29
* SUCH DAMAGE.
30
*/
31
32
#include <sys/types.h>
33
#include <sys/msgbuf.h>
34
#include <sys/sysctl.h>
35
36
#include <ctype.h>
37
#include <err.h>
38
#include <errno.h>
39
#include <fcntl.h>
40
#include <kvm.h>
41
#include <limits.h>
42
#include <locale.h>
43
#include <nlist.h>
44
#include <stdio.h>
45
#include <stdbool.h>
46
#include <stdlib.h>
47
#include <string.h>
48
#include <unistd.h>
49
#include <vis.h>
50
#include <sys/syslog.h>
51
52
static struct nlist nl[] = {
53
#define X_MSGBUF 0
54
{ "_msgbufp", 0, 0, 0, 0 },
55
{ NULL, 0, 0, 0, 0 },
56
};
57
58
void usage(void) __dead2;
59
60
#define KREAD(addr, var) \
61
kvm_read(kd, addr, &var, sizeof(var)) != sizeof(var)
62
63
int
64
main(int argc, char *argv[])
65
{
66
struct msgbuf *bufp, cur;
67
char *bp, *ep, *memf, *nextp, *nlistf, *p, *q, *visbp;
68
kvm_t *kd;
69
size_t buflen, bufpos;
70
long pri;
71
int ch, clear;
72
bool all;
73
74
all = false;
75
clear = false;
76
(void) setlocale(LC_CTYPE, "");
77
memf = nlistf = NULL;
78
while ((ch = getopt(argc, argv, "acM:N:")) != -1)
79
switch(ch) {
80
case 'a':
81
all = true;
82
break;
83
case 'c':
84
clear = true;
85
break;
86
case 'M':
87
memf = optarg;
88
break;
89
case 'N':
90
nlistf = optarg;
91
break;
92
case '?':
93
default:
94
usage();
95
}
96
argc -= optind;
97
if (argc != 0)
98
usage();
99
100
if (memf == NULL) {
101
/*
102
* Running kernel. Use sysctl. This gives an unwrapped buffer
103
* as a side effect. Remove nulterm (if present) so the value
104
* returned by sysctl is formatted as the rest of the code
105
* expects (the same as the value read from a core file below).
106
*/
107
if (sysctlbyname("kern.msgbuf", NULL, &buflen, NULL, 0) == -1)
108
err(1, "sysctl kern.msgbuf");
109
/* Allocate extra room for growth between the sysctl calls. */
110
buflen += buflen/8;
111
/* Allocate more than sysctl sees, for room to append \n\0. */
112
if ((bp = malloc(buflen + 2)) == NULL)
113
errx(1, "malloc failed");
114
if (sysctlbyname("kern.msgbuf", bp, &buflen, NULL, 0) == -1)
115
err(1, "sysctl kern.msgbuf");
116
if (buflen > 0 && bp[buflen - 1] == '\0')
117
buflen--;
118
if (clear)
119
if (sysctlbyname("kern.msgbuf_clear", NULL, NULL, &clear, sizeof(int)))
120
err(1, "sysctl kern.msgbuf_clear");
121
} else {
122
/* Read in kernel message buffer and do sanity checks. */
123
kd = kvm_open(nlistf, memf, NULL, O_RDONLY, "dmesg");
124
if (kd == NULL)
125
exit (1);
126
if (kvm_nlist(kd, nl) == -1)
127
errx(1, "kvm_nlist: %s", kvm_geterr(kd));
128
if (nl[X_MSGBUF].n_type == 0)
129
errx(1, "%s: msgbufp not found",
130
nlistf ? nlistf : "namelist");
131
if (KREAD(nl[X_MSGBUF].n_value, bufp) || KREAD((long)bufp, cur))
132
errx(1, "kvm_read: %s", kvm_geterr(kd));
133
if (cur.msg_magic != MSG_MAGIC)
134
errx(1, "kernel message buffer has different magic "
135
"number");
136
if ((bp = malloc(cur.msg_size + 2)) == NULL)
137
errx(1, "malloc failed");
138
139
/* Unwrap the circular buffer to start from the oldest data. */
140
bufpos = MSGBUF_SEQ_TO_POS(&cur, cur.msg_wseq);
141
if (kvm_read(kd, (long)&cur.msg_ptr[bufpos], bp,
142
cur.msg_size - bufpos) != (ssize_t)(cur.msg_size - bufpos))
143
errx(1, "kvm_read: %s", kvm_geterr(kd));
144
if (bufpos != 0 && kvm_read(kd, (long)cur.msg_ptr,
145
&bp[cur.msg_size - bufpos], bufpos) != (ssize_t)bufpos)
146
errx(1, "kvm_read: %s", kvm_geterr(kd));
147
kvm_close(kd);
148
buflen = cur.msg_size;
149
}
150
151
/*
152
* Ensure that the buffer ends with a newline and a \0 to avoid
153
* complications below. We left space above.
154
*/
155
if (buflen == 0 || bp[buflen - 1] != '\n')
156
bp[buflen++] = '\n';
157
bp[buflen] = '\0';
158
159
if ((visbp = malloc(4 * buflen + 1)) == NULL)
160
errx(1, "malloc failed");
161
162
/*
163
* The message buffer is circular, but has been unwrapped so that
164
* the oldest data comes first. The data will be preceded by \0's
165
* if the message buffer was not full.
166
*/
167
p = bp;
168
ep = &bp[buflen];
169
if (*p == '\0') {
170
/* Strip leading \0's */
171
while (*p == '\0')
172
p++;
173
}
174
for (; p < ep; p = nextp) {
175
nextp = memchr(p, '\n', ep - p);
176
nextp++;
177
178
/* Skip ^<[0-9]+> syslog sequences. */
179
if (*p == '<' && isdigit(*(p+1))) {
180
errno = 0;
181
pri = strtol(p + 1, &q, 10);
182
if (*q == '>' && pri >= 0 && pri < INT_MAX &&
183
errno == 0) {
184
if (LOG_FAC(pri) != LOG_KERN && !all)
185
continue;
186
p = q + 1;
187
}
188
}
189
190
(void)strvisx(visbp, p, nextp - p, 0);
191
(void)printf("%s", visbp);
192
}
193
exit(0);
194
}
195
196
void
197
usage(void)
198
{
199
fprintf(stderr, "usage: dmesg [-ac] [-M core [-N system]]\n");
200
exit(1);
201
}
202
203