summaryrefslogtreecommitdiffstats
path: root/sbin/dmesg
diff options
context:
space:
mode:
authoriedowse <iedowse@FreeBSD.org>2004-02-05 21:07:50 +0000
committeriedowse <iedowse@FreeBSD.org>2004-02-05 21:07:50 +0000
commit71d09d9016c9cd3b8ae04e05a91f46771d0878dc (patch)
tree5ad08047a115b18f1e45f6fd1851a664af4f6082 /sbin/dmesg
parent85386c7cf693d54b97291de5ede43e750dd30946 (diff)
downloadFreeBSD-src-71d09d9016c9cd3b8ae04e05a91f46771d0878dc.zip
FreeBSD-src-71d09d9016c9cd3b8ae04e05a91f46771d0878dc.tar.gz
Don't print the oldest line in the message buffer if the buffer is
full, since that line is almost always incomplete. Make the parsing of <%d> lines more strict. Also simplify the logic a little: - Start off by making the buffer linear so that we don't have to deal with it wrapping around (suggested by bde). - Process line by line rather than byte at a time.
Diffstat (limited to 'sbin/dmesg')
-rw-r--r--sbin/dmesg/dmesg.c105
1 files changed, 54 insertions, 51 deletions
diff --git a/sbin/dmesg/dmesg.c b/sbin/dmesg/dmesg.c
index 063e4b8..9033ceb 100644
--- a/sbin/dmesg/dmesg.c
+++ b/sbin/dmesg/dmesg.c
@@ -56,6 +56,7 @@ __FBSDID("$FreeBSD$");
#include <nlist.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#include <vis.h>
#include <sys/syslog.h>
@@ -74,16 +75,14 @@ void usage(void) __dead2;
int
main(int argc, char *argv[])
{
- int ch, newl, skip;
- char *p, *ep;
struct msgbuf *bufp, cur;
- char *bp, *memf, *nlistf;
+ char *bp, *ep, *memf, *nextp, *nlistf, *p, *q;
kvm_t *kd;
- char buf[5];
- int all = 0;
- int pri;
size_t buflen, bufpos;
+ int all, ch, pri;
+ char buf[5];
+ all = 0;
(void) setlocale(LC_CTYPE, "");
memf = nlistf = NULL;
while ((ch = getopt(argc, argv, "aM:N:")) != -1)
@@ -105,15 +104,13 @@ main(int argc, char *argv[])
argv += optind;
if (memf == NULL && nlistf == NULL) {
- /* Running kernel. Use sysctl. */
+ /* Running kernel. Use sysctl to get an unwrapped buffer. */
if (sysctlbyname("kern.msgbuf", NULL, &buflen, NULL, 0) == -1)
err(1, "sysctl kern.msgbuf");
if ((bp = malloc(buflen)) == NULL)
errx(1, "malloc failed");
if (sysctlbyname("kern.msgbuf", bp, &buflen, NULL, 0) == -1)
err(1, "sysctl kern.msgbuf");
- /* We get a dewrapped buffer using sysctl. */
- bufpos = 0;
} else {
/* Read in kernel message buffer, do sanity checks. */
kd = kvm_open(nlistf, memf, NULL, O_RDONLY, "dmesg");
@@ -132,58 +129,64 @@ main(int argc, char *argv[])
bp = malloc(cur.msg_size);
if (!bp)
errx(1, "malloc failed");
- if (kvm_read(kd, (long)cur.msg_ptr, bp, cur.msg_size) !=
- cur.msg_size)
+ /* Unwrap the circular buffer to start from the oldest data. */
+ bufpos = MSGBUF_SEQ_TO_POS(&cur, cur.msg_wseq);
+ if (kvm_read(kd, (long)&cur.msg_ptr[bufpos], bp,
+ cur.msg_size - bufpos) != cur.msg_size - bufpos)
+ errx(1, "kvm_read: %s", kvm_geterr(kd));
+ if (bufpos != 0 && kvm_read(kd, (long)cur.msg_ptr,
+ &bp[cur.msg_size - bufpos], bufpos) != bufpos)
errx(1, "kvm_read: %s", kvm_geterr(kd));
kvm_close(kd);
buflen = cur.msg_size;
- bufpos = MSGBUF_SEQ_TO_POS(&cur, cur.msg_wseq);
}
/*
- * The message buffer is circular. If the buffer has wrapped, the
- * write pointer points to the oldest data. Otherwise, the write
- * pointer points to \0's following the data. Read the entire
- * buffer starting at the write pointer and ignore nulls so that
- * we effectively start at the oldest data.
+ * The message buffer is circular, but has been unwrapped so that
+ * the oldest data comes first. The data will be preceded by \0's
+ * if the message buffer was not full.
*/
- p = bp + bufpos;
- ep = (bufpos == 0 ? bp + buflen : p);
- newl = skip = 0;
- do {
- if (p == bp + buflen)
- p = bp;
- ch = *p;
- /* Skip "\n<.*>" syslog sequences. */
- if (skip) {
- if (ch == '\n') {
- skip = 0;
- newl = 1;
- } if (ch == '>') {
- if (LOG_FAC(pri) == LOG_KERN || all)
- newl = skip = 0;
- } else if (ch >= '0' && ch <= '9') {
- pri *= 10;
- pri += ch - '0';
+ p = bp;
+ ep = &bp[buflen];
+ if (*p == '\0') {
+ /* Strip leading \0's */
+ while (p != ep && *p == '\0')
+ p++;
+ } else if (!all) {
+ /* Skip the first line, since it is probably incomplete. */
+ p = memchr(p, '\n', ep - p);
+ if (p == NULL)
+ p = ep;
+ else
+ p++;
+ }
+ for (; p != ep; p = nextp) {
+ nextp = memchr(p, '\n', ep - p);
+ if (nextp == NULL)
+ nextp = ep;
+ else
+ nextp++;
+ /* Skip ^<[0-9]+> syslog sequences. */
+ if (*p == '<') {
+ pri = 0;
+ for (q = p + 1; q != ep && *q >= '0' && *q <= '9'; q++)
+ pri = pri * 10 + (*q - '0');
+ if (q != ep && *q == '>' && q != p + 1) {
+ if (LOG_FAC(pri) != LOG_KERN && !all)
+ continue;
+ p = q + 1;
}
- continue;
}
- if (newl && ch == '<') {
- pri = 0;
- skip = 1;
- continue;
+ for (; p != nextp; p++) {
+ (void)vis(buf, *p, 0, 0);
+ if (buf[1] == 0)
+ (void)putchar(buf[0]);
+ else
+ (void)printf("%s", buf);
}
- if (ch == '\0')
- continue;
- newl = ch == '\n';
- (void)vis(buf, ch, 0, 0);
- if (buf[1] == 0)
- (void)putchar(buf[0]);
- else
- (void)printf("%s", buf);
- } while (++p != ep);
- if (!newl)
- (void)putchar('\n');
+ if (nextp == ep && ep[-1] != '\n')
+ (void)putchar('\n');
+ }
exit(0);
}
OpenPOWER on IntegriCloud