xref: /netbsd-src/sbin/dmesg/dmesg.c (revision 422de7d163b835424a2fc84b6ffb030839998dd3)
1*422de7d1Srin /*	$NetBSD: dmesg.c,v 1.51 2022/08/06 10:22:22 rin Exp $	*/
261f28255Scgd /*-
37b442030Scgd  * Copyright (c) 1991, 1993
47b442030Scgd  *	The Regents of the University of California.  All rights reserved.
561f28255Scgd  *
661f28255Scgd  * Redistribution and use in source and binary forms, with or without
761f28255Scgd  * modification, are permitted provided that the following conditions
861f28255Scgd  * are met:
961f28255Scgd  * 1. Redistributions of source code must retain the above copyright
1061f28255Scgd  *    notice, this list of conditions and the following disclaimer.
1161f28255Scgd  * 2. Redistributions in binary form must reproduce the above copyright
1261f28255Scgd  *    notice, this list of conditions and the following disclaimer in the
1361f28255Scgd  *    documentation and/or other materials provided with the distribution.
14bf07c871Sagc  * 3. Neither the name of the University nor the names of its contributors
1561f28255Scgd  *    may be used to endorse or promote products derived from this software
1661f28255Scgd  *    without specific prior written permission.
1761f28255Scgd  *
1861f28255Scgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1961f28255Scgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2061f28255Scgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2161f28255Scgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2261f28255Scgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2361f28255Scgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2461f28255Scgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2561f28255Scgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2661f28255Scgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2761f28255Scgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2861f28255Scgd  * SUCH DAMAGE.
2961f28255Scgd  */
3061f28255Scgd 
315f4e3656Slukem #include <sys/cdefs.h>
3261f28255Scgd #ifndef lint
336543a91fSlukem __COPYRIGHT("@(#) Copyright (c) 1991, 1993\
346543a91fSlukem  The Regents of the University of California.  All rights reserved.");
3561f28255Scgd #endif /* not lint */
3661f28255Scgd 
3761f28255Scgd #ifndef lint
380114e805Scgd #if 0
397b442030Scgd static char sccsid[] = "@(#)dmesg.c	8.1 (Berkeley) 6/5/93";
400114e805Scgd #else
41*422de7d1Srin __RCSID("$NetBSD: dmesg.c,v 1.51 2022/08/06 10:22:22 rin Exp $");
420114e805Scgd #endif
4361f28255Scgd #endif /* not lint */
4461f28255Scgd 
45a7d9e1f9Ssimonb #include <sys/param.h>
4661f28255Scgd #include <sys/msgbuf.h>
47a7d9e1f9Ssimonb #include <sys/sysctl.h>
487b442030Scgd 
495eeab43eScgd #include <err.h>
50a1d2abcaSchristos #include <ctype.h>
517b442030Scgd #include <fcntl.h>
52db02d1fbSchristos #include <time.h>
5361f28255Scgd #include <kvm.h>
547b442030Scgd #include <nlist.h>
5561f28255Scgd #include <stdio.h>
56a7d9e1f9Ssimonb #include <stddef.h>
577b442030Scgd #include <stdlib.h>
582ddbb97fSjtc #include <unistd.h>
597b442030Scgd #include <vis.h>
6061f28255Scgd 
6173dfacb5Ssimonb #ifndef SMALL
629f61665bSchristos #include <langinfo.h>
639f61665bSchristos #include <locale.h>
649f61665bSchristos 
65baa8e84bSjoerg static struct nlist nl[] = {
667b442030Scgd #define	X_MSGBUF	0
67064b0504Schristos 	{ .n_name = "_msgbufp" },
68064b0504Schristos 	{ .n_name = NULL },
6961f28255Scgd };
7061f28255Scgd 
719f61665bSchristos static const char *radix;
729f61665bSchristos 
73baa8e84bSjoerg __dead static void	usage(void);
7461f28255Scgd 
757b442030Scgd #define	KREAD(addr, var) \
767b442030Scgd 	kvm_read(kd, addr, &var, sizeof(var)) != sizeof(var)
77a1d2abcaSchristos 
78a1d2abcaSchristos static const char *
fmtydhmsf(char * b,size_t l,intmax_t t,long nsec,int ht)792f9f119bSkre fmtydhmsf(char *b, size_t l, intmax_t t, long nsec, int ht)
80a1d2abcaSchristos {
813d4a88b5Skre 	intmax_t s, m, h;
82a1d2abcaSchristos 	int z;
830d9f7721Skre 	int prec;
84a1d2abcaSchristos 	size_t o;
85a1d2abcaSchristos 
86a1d2abcaSchristos 	s = t % 60;
87a1d2abcaSchristos 	t /= 60;
88a1d2abcaSchristos 
89a1d2abcaSchristos 	m = t % 60;
90a1d2abcaSchristos 	t /= 60;
91a1d2abcaSchristos 
929f61665bSchristos 	h = t;
93a1d2abcaSchristos 
94a1d2abcaSchristos 	z = 0;
95a1d2abcaSchristos 	o = 0;
96a1d2abcaSchristos 
97a1d2abcaSchristos #define APPENDFMT(fmt, ...)  \
98a1d2abcaSchristos     do { \
99a1d2abcaSchristos 	    z = snprintf(b + o, l - o, fmt, __VA_ARGS__); \
100a1d2abcaSchristos 	    if (z == -1) \
101a1d2abcaSchristos 		    return b; \
102a1d2abcaSchristos 	    o += (size_t)z; \
103a1d2abcaSchristos 	    if (o >= l) \
104a1d2abcaSchristos 		    return b; \
105a1d2abcaSchristos     } while (/*CONSTCOND*/0)
106a1d2abcaSchristos 
107a1d2abcaSchristos #define APPEND(a) \
108a1d2abcaSchristos     do if (a) \
1090d9f7721Skre 	APPENDFMT("%jd%c", a, toupper((unsigned char)__STRING(a)[0])); \
110a1d2abcaSchristos     while (/*CONSTCOND*/0)
1110d9f7721Skre #define APPENDS(a, pr, ms) \
1120d9f7721Skre     APPENDFMT("%jd%s%.*ld%c", a, radix, pr, ms, \
113a1d2abcaSchristos 	toupper((unsigned char)__STRING(a)[0]))
114a1d2abcaSchristos 
115a1d2abcaSchristos 	APPENDFMT("%s", "P");
116a1d2abcaSchristos 	APPENDFMT("%s", "T");
117a1d2abcaSchristos 	APPEND(h);
118a1d2abcaSchristos 	APPEND(m);
119a1d2abcaSchristos 	if (nsec)
1200d9f7721Skre 		nsec = (nsec + 500000) / 1000000;	/* now milliseconds */
1210d9f7721Skre 	prec = 3;
1222f9f119bSkre 	if (nsec && ht == 2) {
1230d9f7721Skre 		while (prec > 0 && (nsec % 10) == 0)
1240d9f7721Skre 			--prec, nsec /= 10;
1252f9f119bSkre 	}
1262f9f119bSkre 	if (nsec || ht > 2)
1270d9f7721Skre 		APPENDS(s, prec, nsec);
128a1d2abcaSchristos 	else
129a1d2abcaSchristos 		APPEND(s);
130a1d2abcaSchristos 	return b;
131a1d2abcaSchristos }
132a1d2abcaSchristos 
133a1d2abcaSchristos static void
pnsec(long nsec,long fsec,int scale)134a1d2abcaSchristos pnsec(long nsec, long fsec, int scale)
135a1d2abcaSchristos {
136a1d2abcaSchristos 	if (scale > 6)
137a1d2abcaSchristos 		printf("%6.6ld", (nsec + 499) / 1000);
138a1d2abcaSchristos 	else
139a1d2abcaSchristos 		printf("%*.*ld%.*s", scale, scale, fsec, 6 - scale, "000000");
140a1d2abcaSchristos }
141857f572eSdsl #endif
1427b442030Scgd 
1437b442030Scgd int
main(int argc,char * argv[])144907def68Ssimonb main(int argc, char *argv[])
14561f28255Scgd {
146a7d9e1f9Ssimonb 	struct kern_msgbuf cur;
147db02d1fbSchristos 	int ch, newl, log, i;
148eb7145dcSrin 	size_t size;
14973dfacb5Ssimonb 	char *p, *bufdata;
1507b442030Scgd 	char buf[5];
15173dfacb5Ssimonb #ifndef SMALL
152eb7145dcSrin 	size_t tstamp;
15382dbd18cSrin 	char tbuf[64];
154db02d1fbSchristos 	char *memf, *nlistf;
1557008793dSkre 	struct timespec boottime;
1562fef76cbSchristos 	struct timespec lasttime;
1572fef76cbSchristos 	intmax_t sec;
158329132e2Skre 	long nsec, fsec;
159329132e2Skre 	int scale;
1602fef76cbSchristos 	int deltas, quiet, humantime;
161475a6226Stsutsui 	bool frac, postts;
162db02d1fbSchristos 
163db02d1fbSchristos 	static const int bmib[] = { CTL_KERN, KERN_BOOTTIME };
164db02d1fbSchristos 	size = sizeof(boottime);
165db02d1fbSchristos 
1669f61665bSchristos 	(void)setlocale(LC_ALL, "");
1679f61665bSchristos 	radix = nl_langinfo(RADIXCHAR);
1689f61665bSchristos 	if (radix == NULL)
1699f61665bSchristos 		radix = ".";	/* could also select "," */
1709f61665bSchristos 
171db02d1fbSchristos 	boottime.tv_sec = 0;
1727008793dSkre 	boottime.tv_nsec = 0;
1732fef76cbSchristos 	lasttime.tv_sec = 0;
1742fef76cbSchristos 	lasttime.tv_nsec = 0;
1752fef76cbSchristos 	deltas = quiet = humantime = 0;
176db02d1fbSchristos 
177db02d1fbSchristos 	(void)sysctl(bmib, 2, &boottime, &size, NULL, 0);
178db02d1fbSchristos 
1797b442030Scgd 	memf = nlistf = NULL;
1802fef76cbSchristos 	while ((ch = getopt(argc, argv, "dM:N:tT")) != -1)
18161f28255Scgd 		switch(ch) {
1822fef76cbSchristos 		case 'd':
1832fef76cbSchristos 			deltas = 1;
1842fef76cbSchristos 			break;
18561f28255Scgd 		case 'M':
1867b442030Scgd 			memf = optarg;
18761f28255Scgd 			break;
18861f28255Scgd 		case 'N':
1897b442030Scgd 			nlistf = optarg;
19061f28255Scgd 			break;
191db02d1fbSchristos 		case 't':
1922fef76cbSchristos 			quiet = 1;
1932fef76cbSchristos 			break;
1942fef76cbSchristos 		case 'T':
195a1d2abcaSchristos 			humantime++;
196db02d1fbSchristos 			break;
19761f28255Scgd 		case '?':
19861f28255Scgd 		default:
19961f28255Scgd 			usage();
20061f28255Scgd 		}
20161f28255Scgd 	argc -= optind;
20261f28255Scgd 	argv += optind;
2032fef76cbSchristos 	if (quiet && humantime)
2042fef76cbSchristos 		err(EXIT_FAILURE, "-t cannot be used with -T");
20561f28255Scgd 
206643cb3c3Ssimonb 	if (memf == NULL) {
20773dfacb5Ssimonb #endif
208db02d1fbSchristos 		static const int mmib[2] = { CTL_KERN, KERN_MSGBUF };
20961f28255Scgd 
210db02d1fbSchristos 		if (sysctl(mmib, 2, NULL, &size, NULL, 0) == -1 ||
211857f572eSdsl 		    (bufdata = malloc(size)) == NULL ||
212db02d1fbSchristos 		    sysctl(mmib, 2, bufdata, &size, NULL, 0) == -1)
213a7d9e1f9Ssimonb 			err(1, "can't get msgbuf");
214a7d9e1f9Ssimonb 
215a7d9e1f9Ssimonb 		/* make a dummy struct msgbuf for the display logic */
216857f572eSdsl 		cur.msg_bufx = 0;
217857f572eSdsl 		cur.msg_bufs = size;
21873dfacb5Ssimonb #ifndef SMALL
219a7d9e1f9Ssimonb 	} else {
220a7d9e1f9Ssimonb 		kvm_t *kd;
221a7d9e1f9Ssimonb 		struct kern_msgbuf *bufp;
222a7d9e1f9Ssimonb 
223a7d9e1f9Ssimonb 		/*
224a7d9e1f9Ssimonb 		 * Read in message buffer header and data, and do sanity
225a7d9e1f9Ssimonb 		 * checks.
226a7d9e1f9Ssimonb 		 */
227a7d9e1f9Ssimonb 		kd = kvm_open(nlistf, memf, NULL, O_RDONLY, "dmesg");
228a7d9e1f9Ssimonb 		if (kd == NULL)
2297b442030Scgd 			exit (1);
2307b442030Scgd 		if (kvm_nlist(kd, nl) == -1)
2317b442030Scgd 			errx(1, "kvm_nlist: %s", kvm_geterr(kd));
2327b442030Scgd 		if (nl[X_MSGBUF].n_type == 0)
233a7d9e1f9Ssimonb 			errx(1, "%s: msgbufp not found", nlistf ? nlistf :
234a7d9e1f9Ssimonb 			    "namelist");
235f5c4107dSmjacob 		if (KREAD(nl[X_MSGBUF].n_value, bufp))
2365f4e3656Slukem 			errx(1, "kvm_read: %s (0x%lx)", kvm_geterr(kd),
237f5c4107dSmjacob 			    nl[X_MSGBUF].n_value);
238a7d9e1f9Ssimonb 		if (kvm_read(kd, (long)bufp, &cur,
239a7d9e1f9Ssimonb 		    offsetof(struct kern_msgbuf, msg_bufc)) !=
240a7d9e1f9Ssimonb 		    offsetof(struct kern_msgbuf, msg_bufc))
2415f4e3656Slukem 			errx(1, "kvm_read: %s (0x%lx)", kvm_geterr(kd),
2425f4e3656Slukem 			    (unsigned long)bufp);
24361f28255Scgd 		if (cur.msg_magic != MSG_MAGIC)
2447b442030Scgd 			errx(1, "magic number incorrect");
24571af424fSleo 		bufdata = malloc(cur.msg_bufs);
24671af424fSleo 		if (bufdata == NULL)
24771af424fSleo 			errx(1, "couldn't allocate space for buffer data");
24871af424fSleo 		if (kvm_read(kd, (long)&bufp->msg_bufc, bufdata,
24971af424fSleo 		    cur.msg_bufs) != cur.msg_bufs)
25071af424fSleo 			errx(1, "kvm_read: %s", kvm_geterr(kd));
25171af424fSleo 		kvm_close(kd);
25271af424fSleo 		if (cur.msg_bufx >= cur.msg_bufs)
25361f28255Scgd 			cur.msg_bufx = 0;
254a7d9e1f9Ssimonb 	}
25573dfacb5Ssimonb #endif
25661f28255Scgd 
25761f28255Scgd 	/*
258c6e5d311Senami 	 * The message buffer is circular; start at the write pointer
259c6e5d311Senami 	 * (which points the oldest character), and go to the write
260c6e5d311Senami 	 * pointer - 1 (which points the newest character).  I.e, loop
261c6e5d311Senami 	 * over cur.msg_bufs times.  Unused area is skipped since it
262c6e5d311Senami 	 * contains nul.
26361f28255Scgd 	 */
264329132e2Skre #ifndef SMALL
265329132e2Skre 	frac = false;
266475a6226Stsutsui 	postts = false;
267eb7145dcSrin 	tstamp = 0;
268329132e2Skre 	scale = 0;
269329132e2Skre #endif
270eb7145dcSrin 	for (newl = 1, log = i = 0, p = bufdata + cur.msg_bufx;
271c6e5d311Senami 	    i < cur.msg_bufs; i++, p++) {
272329132e2Skre 
273857f572eSdsl #ifndef SMALL
27471af424fSleo 		if (p == bufdata + cur.msg_bufs)
27571af424fSleo 			p = bufdata;
276db02d1fbSchristos #define ADDC(c)								\
277329132e2Skre     do {								\
27882dbd18cSrin 	if (tstamp < sizeof(tbuf) - 1)					\
279db02d1fbSchristos 		tbuf[tstamp++] = (c);					\
28082dbd18cSrin 	else {								\
28182dbd18cSrin 		/* Cannot be a timestamp. */				\
28282dbd18cSrin 		tstamp = 0;						\
28382dbd18cSrin 		tbuf[sizeof(tbuf) - 1] = '\0';				\
28482dbd18cSrin 		goto not_tstamp;					\
28582dbd18cSrin 	}								\
286329132e2Skre 	if (frac)							\
287329132e2Skre 		scale++;						\
288d67befb6Srin     } while (0)
2892a3cf2bfSrin #define	PRTBUF()							\
2902a3cf2bfSrin     for (char *_p = tbuf; *_p != '\0'; _p++) {				\
2912a3cf2bfSrin 	(void)vis(buf, *_p, VIS_NOSLASH, 0);				\
2922a3cf2bfSrin 	if (buf[1] == 0)						\
2932a3cf2bfSrin 		(void)putchar(buf[0]);					\
2942a3cf2bfSrin 	else								\
2952a3cf2bfSrin 		(void)printf("%s", buf);				\
2962a3cf2bfSrin     }
297857f572eSdsl #endif
29861f28255Scgd 		ch = *p;
2996d9827c8Schristos 		if (ch == '\0')
3006d9827c8Schristos 			continue;
30161f28255Scgd 		/* Skip "\n<.*>" syslog sequences. */
302db02d1fbSchristos 		/* Gather timestamp sequences */
303db02d1fbSchristos 		if (newl) {
304329132e2Skre #ifndef SMALL
305329132e2Skre 			int j;
306329132e2Skre #endif
307329132e2Skre 
308db02d1fbSchristos 			switch (ch) {
309329132e2Skre #ifndef SMALL
31043729d11Skre 			case '[':
311329132e2Skre 				frac = false;
312329132e2Skre 				scale = 0;
313db02d1fbSchristos 				ADDC(ch);
314db02d1fbSchristos 				continue;
31543729d11Skre #endif
316db02d1fbSchristos 			case '<':
317db02d1fbSchristos 				log = 1;
318db02d1fbSchristos 				continue;
319db02d1fbSchristos 			case '>':
320eb23b853Schristos 				log = 0;
321db02d1fbSchristos 				continue;
322329132e2Skre #ifndef SMALL
32343729d11Skre 			case ']':
32482dbd18cSrin 				if (tstamp == 0)
32582dbd18cSrin 					goto prchar;
326329132e2Skre 				frac = false;
327db02d1fbSchristos 				ADDC(ch);
328db02d1fbSchristos 				ADDC('\0');
329db02d1fbSchristos 				tstamp = 0;
330329132e2Skre 				sec = fsec = 0;
331329132e2Skre 				switch (sscanf(tbuf, "[%jd.%ld]", &sec, &fsec)){
332329132e2Skre 				case 0:
33382dbd18cSrin  not_tstamp:				/* not a timestamp */
3342a3cf2bfSrin 					PRTBUF();
335329132e2Skre 					continue;
336329132e2Skre 				case 1:
3372a3cf2bfSrin 					fsec = 0; /* XXX PRTBUF()? */
338329132e2Skre 					break;
339329132e2Skre 				case 2:
340329132e2Skre 					break;
3412a3cf2bfSrin 				case EOF:
342329132e2Skre 				default:
343329132e2Skre 					/* Help */
344329132e2Skre 					continue;
345329132e2Skre 				}
346*422de7d1Srin 				postts = true;
347329132e2Skre 
348329132e2Skre 				for (nsec = fsec, j = 9 - scale; --j >= 0; )
349329132e2Skre 					nsec *= 10;
3502fef76cbSchristos 				if (!quiet || deltas)
3512fef76cbSchristos 					printf("[");
352a1d2abcaSchristos 				if (humantime == 1) {
3532fef76cbSchristos 					time_t t;
3542fef76cbSchristos 					struct tm tm;
355329132e2Skre 
356db02d1fbSchristos 					t = boottime.tv_sec + sec;
3577008793dSkre 					if (nsec + boottime.tv_nsec >=
3587008793dSkre 					    ( 1L		/* 1 second */
3597008793dSkre 						 * 1000L	/* ms */
3607008793dSkre 						 * 1000L	/* us */
3617008793dSkre 						 * 1000L	/* ns */ ))
3627008793dSkre 							t++;
3637008793dSkre 
364db02d1fbSchristos 					if (localtime_r(&t, &tm) != NULL) {
36582dbd18cSrin 						strftime(tbuf, sizeof(tbuf),
3662fef76cbSchristos 						    "%a %b %e %H:%M:%S %Z %Y",
367db02d1fbSchristos 						    &tm);
368db02d1fbSchristos 						printf("%s", tbuf);
369db02d1fbSchristos 					}
370a1d2abcaSchristos 				} else if (humantime > 1) {
371a1d2abcaSchristos 					const char *fp = fmtydhmsf(tbuf,
37282dbd18cSrin 					    sizeof(tbuf), sec, fsec, humantime);
373a1d2abcaSchristos 					if (fp) {
374a1d2abcaSchristos 						printf("%s", fp);
375a1d2abcaSchristos 					}
3762fef76cbSchristos 				} else if (!quiet) {
3774cf82913Skre 					printf(" %5jd%s", sec, radix);
378a1d2abcaSchristos 					pnsec(nsec, fsec, scale);
3792fef76cbSchristos 				}
3802fef76cbSchristos 				if (deltas) {
3812fef76cbSchristos 					struct timespec nt = { sec, nsec };
3822fef76cbSchristos 					struct timespec dt;
383329132e2Skre 
3842fef76cbSchristos 					timespecsub(&nt, &lasttime, &dt);
3852fef76cbSchristos 					if (humantime || !quiet)
3862fef76cbSchristos 						printf(" ");
3874cf82913Skre 					printf("<% 4jd%s%6.6ld>",
3884cf82913Skre 					    (intmax_t)dt.tv_sec, radix,
3894cf82913Skre 					    (dt.tv_nsec+499) / 1000);
3902fef76cbSchristos 					lasttime = nt;
3912fef76cbSchristos 				}
3922fef76cbSchristos 				if (!quiet || deltas)
3932fef76cbSchristos 					printf("] ");
394db02d1fbSchristos 				continue;
39543729d11Skre #endif
396db02d1fbSchristos 			case ' ':
3976b4ce10fSkre #ifndef SMALL
398475a6226Stsutsui 				if (!tstamp && postts) {
399475a6226Stsutsui 					postts = false;
400db02d1fbSchristos 					continue;
401475a6226Stsutsui 				}
402eb7145dcSrin #endif
403db02d1fbSchristos 				/*FALLTHROUGH*/
404db02d1fbSchristos 			default:
40543729d11Skre #ifndef SMALL
406db02d1fbSchristos 				if (tstamp) {
407db02d1fbSchristos 					ADDC(ch);
408329132e2Skre 					if (ch == '.')
409329132e2Skre 						frac = true;
41061f28255Scgd 					continue;
41161f28255Scgd 				}
41282dbd18cSrin  prchar:
41343729d11Skre #endif
414db02d1fbSchristos 				if (log)
41561f28255Scgd 					continue;
416db02d1fbSchristos 				break;
417db02d1fbSchristos 			}
41861f28255Scgd 		}
4197b442030Scgd 		newl = ch == '\n';
4201225b610Saugustss 		(void)vis(buf, ch, VIS_NOSLASH, 0);
421857f572eSdsl #ifndef SMALL
4227b442030Scgd 		if (buf[1] == 0)
4237b442030Scgd 			(void)putchar(buf[0]);
4247b442030Scgd 		else
425857f572eSdsl #endif
4267b442030Scgd 			(void)printf("%s", buf);
42771af424fSleo 	}
4282a3cf2bfSrin #ifndef SMALL
4292a3cf2bfSrin 	/* non-terminated [.*] */
4302a3cf2bfSrin 	if (tstamp) {
4312a3cf2bfSrin 		ADDC('\0');
4322a3cf2bfSrin 		PRTBUF();
4332a3cf2bfSrin 	}
4342a3cf2bfSrin #endif
43561f28255Scgd 	if (!newl)
43661f28255Scgd 		(void)putchar('\n');
437db02d1fbSchristos 	return EXIT_SUCCESS;
43861f28255Scgd }
43961f28255Scgd 
440857f572eSdsl #ifndef SMALL
441baa8e84bSjoerg static void
usage(void)442907def68Ssimonb usage(void)
44361f28255Scgd {
4448c389fd0Senami 
445ba701a99Swiz 	(void)fprintf(stderr, "Usage: %s [-dTt] [-M core] [-N system]\n",
446db02d1fbSchristos 		getprogname());
447db02d1fbSchristos 	exit(EXIT_FAILURE);
44861f28255Scgd }
449857f572eSdsl #endif
450