hexdump.c revision 163858
1/*-
2 * Copyright (c) 1986, 1988, 1991, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 4. Neither the name of the University nor the names of its contributors
19 *    may be used to endorse or promote products derived from this software
20 *    without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 *	@(#)subr_prf.c	8.3 (Berkeley) 1/21/94
35 */
36
37#include <sys/cdefs.h>
38__FBSDID("$FreeBSD: head/sys/kern/subr_prf.c 163858 2006-11-01 04:54:51Z jb $");
39
40#include "opt_ddb.h"
41
42#include <sys/param.h>
43#include <sys/systm.h>
44#include <sys/lock.h>
45#include <sys/kdb.h>
46#include <sys/mutex.h>
47#include <sys/sx.h>
48#include <sys/kernel.h>
49#include <sys/msgbuf.h>
50#include <sys/malloc.h>
51#include <sys/proc.h>
52#include <sys/stddef.h>
53#include <sys/sysctl.h>
54#include <sys/tty.h>
55#include <sys/syslog.h>
56#include <sys/cons.h>
57#include <sys/uio.h>
58#include <sys/ctype.h>
59
60#ifdef DDB
61#include <ddb/ddb.h>
62#endif
63
64/*
65 * Note that stdarg.h and the ANSI style va_start macro is used for both
66 * ANSI and traditional C compilers.
67 */
68#include <machine/stdarg.h>
69
70#define TOCONS	0x01
71#define TOTTY	0x02
72#define TOLOG	0x04
73
74/* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */
75#define MAXNBUF	(sizeof(intmax_t) * NBBY + 1)
76
77struct putchar_arg {
78	int	flags;
79	int	pri;
80	struct	tty *tty;
81	char	*p_bufr;
82	size_t	n_bufr;
83	char	*p_next;
84	size_t	remain;
85};
86
87struct snprintf_arg {
88	char	*str;
89	size_t	remain;
90};
91
92extern	int log_open;
93
94static void  msglogchar(int c, int pri);
95static void  putchar(int ch, void *arg);
96static char *ksprintn(char *nbuf, uintmax_t num, int base, int *len, int upper);
97static void  snprintf_func(int ch, void *arg);
98
99static int msgbufmapped;		/* Set when safe to use msgbuf */
100int msgbuftrigger;
101
102static int      log_console_output = 1;
103TUNABLE_INT("kern.log_console_output", &log_console_output);
104SYSCTL_INT(_kern, OID_AUTO, log_console_output, CTLFLAG_RW,
105    &log_console_output, 0, "Duplicate console output to the syslog.");
106
107static int	always_console_output = 0;
108TUNABLE_INT("kern.always_console_output", &always_console_output);
109SYSCTL_INT(_kern, OID_AUTO, always_console_output, CTLFLAG_RW,
110    &always_console_output, 0, "Always output to console despite TIOCCONS.");
111
112/*
113 * Warn that a system table is full.
114 */
115void
116tablefull(const char *tab)
117{
118
119	log(LOG_ERR, "%s: table is full\n", tab);
120}
121
122/*
123 * Uprintf prints to the controlling terminal for the current process.
124 */
125int
126uprintf(const char *fmt, ...)
127{
128	struct thread *td = curthread;
129	struct proc *p = td->td_proc;
130	va_list ap;
131	struct putchar_arg pca;
132	int retval;
133
134	if (td == NULL || td == PCPU_GET(idlethread))
135		return (0);
136
137	mtx_lock(&Giant);
138	p = td->td_proc;
139	PROC_LOCK(p);
140	if ((p->p_flag & P_CONTROLT) == 0) {
141		PROC_UNLOCK(p);
142		retval = 0;
143		goto out;
144	}
145	SESS_LOCK(p->p_session);
146	pca.tty = p->p_session->s_ttyp;
147	SESS_UNLOCK(p->p_session);
148	PROC_UNLOCK(p);
149	if (pca.tty == NULL) {
150		retval = 0;
151		goto out;
152	}
153	pca.flags = TOTTY;
154	va_start(ap, fmt);
155	retval = kvprintf(fmt, putchar, &pca, 10, ap);
156	va_end(ap);
157out:
158	mtx_unlock(&Giant);
159	return (retval);
160}
161
162/*
163 * tprintf prints on the controlling terminal associated with the given
164 * session, possibly to the log as well.
165 */
166void
167tprintf(struct proc *p, int pri, const char *fmt, ...)
168{
169	struct tty *tp = NULL;
170	int flags = 0;
171	va_list ap;
172	struct putchar_arg pca;
173	struct session *sess = NULL;
174
175	mtx_lock(&Giant);
176	if (pri != -1)
177		flags |= TOLOG;
178	if (p != NULL) {
179		PROC_LOCK(p);
180		if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
181			sess = p->p_session;
182			SESS_LOCK(sess);
183			PROC_UNLOCK(p);
184			SESSHOLD(sess);
185			tp = sess->s_ttyp;
186			SESS_UNLOCK(sess);
187			if (ttycheckoutq(tp, 0))
188				flags |= TOTTY;
189			else
190				tp = NULL;
191		} else
192			PROC_UNLOCK(p);
193	}
194	pca.pri = pri;
195	pca.tty = tp;
196	pca.flags = flags;
197	va_start(ap, fmt);
198	kvprintf(fmt, putchar, &pca, 10, ap);
199	va_end(ap);
200	if (sess != NULL)
201		SESSRELE(sess);
202	msgbuftrigger = 1;
203	mtx_unlock(&Giant);
204}
205
206/*
207 * Ttyprintf displays a message on a tty; it should be used only by
208 * the tty driver, or anything that knows the underlying tty will not
209 * be revoke(2)'d away.  Other callers should use tprintf.
210 */
211int
212ttyprintf(struct tty *tp, const char *fmt, ...)
213{
214	va_list ap;
215	struct putchar_arg pca;
216	int retval;
217
218	va_start(ap, fmt);
219	pca.tty = tp;
220	pca.flags = TOTTY;
221	retval = kvprintf(fmt, putchar, &pca, 10, ap);
222	va_end(ap);
223	return (retval);
224}
225
226/*
227 * Log writes to the log buffer, and guarantees not to sleep (so can be
228 * called by interrupt routines).  If there is no process reading the
229 * log yet, it writes to the console also.
230 */
231void
232log(int level, const char *fmt, ...)
233{
234	va_list ap;
235	struct putchar_arg pca;
236
237	pca.tty = NULL;
238	pca.pri = level;
239	pca.flags = log_open ? TOLOG : TOCONS;
240	pca.p_bufr = NULL;
241
242	va_start(ap, fmt);
243	kvprintf(fmt, putchar, &pca, 10, ap);
244	va_end(ap);
245
246	msgbuftrigger = 1;
247}
248
249#define CONSCHUNK 128
250
251void
252log_console(struct uio *uio)
253{
254	int c, i, error, nl;
255	char *consbuffer;
256	int pri;
257
258	if (!log_console_output)
259		return;
260
261	pri = LOG_INFO | LOG_CONSOLE;
262	uio = cloneuio(uio);
263	consbuffer = malloc(CONSCHUNK, M_TEMP, M_WAITOK);
264
265	nl = 0;
266	while (uio->uio_resid > 0) {
267		c = imin(uio->uio_resid, CONSCHUNK);
268		error = uiomove(consbuffer, c, uio);
269		if (error != 0)
270			break;
271		for (i = 0; i < c; i++) {
272			msglogchar(consbuffer[i], pri);
273			if (consbuffer[i] == '\n')
274				nl = 1;
275			else
276				nl = 0;
277		}
278	}
279	if (!nl)
280		msglogchar('\n', pri);
281	msgbuftrigger = 1;
282	free(uio, M_IOV);
283	free(consbuffer, M_TEMP);
284	return;
285}
286
287int
288printf(const char *fmt, ...)
289{
290	va_list ap;
291	struct putchar_arg pca;
292	int retval;
293
294	critical_enter();
295
296	va_start(ap, fmt);
297	pca.tty = NULL;
298	pca.flags = TOCONS | TOLOG;
299	pca.pri = -1;
300	pca.p_bufr = (char *) PCPU_PTR(cons_bufr);
301	pca.p_next = pca.p_bufr;
302	pca.n_bufr = PCPU_CONS_BUFR;
303	pca.remain = PCPU_CONS_BUFR;
304	*pca.p_next = '\0';
305
306	retval = kvprintf(fmt, putchar, &pca, 10, ap);
307	va_end(ap);
308
309	/* Write any buffered console output: */
310	if (*pca.p_bufr != '\0')
311		cnputs(pca.p_bufr);
312
313	if (!panicstr)
314		msgbuftrigger = 1;
315
316	critical_exit();
317
318	return (retval);
319}
320
321int
322vprintf(const char *fmt, va_list ap)
323{
324	struct putchar_arg pca;
325	int retval;
326
327	critical_enter();
328
329	pca.tty = NULL;
330	pca.flags = TOCONS | TOLOG;
331	pca.pri = -1;
332	pca.p_bufr = (char *) PCPU_PTR(cons_bufr);
333	pca.p_next = pca.p_bufr;
334	pca.n_bufr = PCPU_CONS_BUFR;
335	pca.remain = PCPU_CONS_BUFR;
336	*pca.p_next = '\0';
337
338	retval = kvprintf(fmt, putchar, &pca, 10, ap);
339
340	/* Write any buffered console output: */
341	if (*pca.p_bufr != '\0')
342		cnputs(pca.p_bufr);
343
344	if (!panicstr)
345		msgbuftrigger = 1;
346
347	critical_exit();
348
349	return (retval);
350}
351
352static void
353putcons(int c, struct putchar_arg *ap)
354{
355	/* Check if no console output buffer was provided. */
356	if (ap->p_bufr == NULL)
357		/* Output direct to the console. */
358		cnputc(c);
359	else {
360		/* Buffer the character: */
361		if (c == '\n') {
362			*ap->p_next++ = '\r';
363			ap->remain--;
364		}
365		*ap->p_next++ = c;
366		ap->remain--;
367
368		/* Always leave the buffer zero terminated. */
369		*ap->p_next = '\0';
370
371		/* Check if the buffer needs to be flushed. */
372		if (ap->remain < 3 || c == '\n') {
373			cnputs(ap->p_bufr);
374			ap->p_next = ap->p_bufr;
375			ap->remain = ap->n_bufr;
376			*ap->p_next = '\0';
377		}
378	}
379}
380
381/*
382 * Print a character on console or users terminal.  If destination is
383 * the console then the last bunch of characters are saved in msgbuf for
384 * inspection later.
385 */
386static void
387putchar(int c, void *arg)
388{
389	struct putchar_arg *ap = (struct putchar_arg*) arg;
390	struct tty *tp = ap->tty;
391	int flags = ap->flags;
392
393	/* Don't use the tty code after a panic or while in ddb. */
394	if (kdb_active) {
395		if (c != '\0')
396			cnputc(c);
397	} else if (panicstr || ((flags & TOCONS) && constty == NULL)) {
398		if (c != '\0')
399			putcons(c, ap);
400	} else {
401		if ((flags & TOTTY) && tp != NULL)
402			tputchar(c, tp);
403		if (flags & TOCONS) {
404			if (constty != NULL)
405				msgbuf_addchar(&consmsgbuf, c);
406			if (always_console_output && c != '\0')
407				putcons(c, ap);
408		}
409	}
410	if ((flags & TOLOG))
411		msglogchar(c, ap->pri);
412}
413
414/*
415 * Scaled down version of sprintf(3).
416 */
417int
418sprintf(char *buf, const char *cfmt, ...)
419{
420	int retval;
421	va_list ap;
422
423	va_start(ap, cfmt);
424	retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
425	buf[retval] = '\0';
426	va_end(ap);
427	return (retval);
428}
429
430/*
431 * Scaled down version of vsprintf(3).
432 */
433int
434vsprintf(char *buf, const char *cfmt, va_list ap)
435{
436	int retval;
437
438	retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
439	buf[retval] = '\0';
440	return (retval);
441}
442
443/*
444 * Scaled down version of snprintf(3).
445 */
446int
447snprintf(char *str, size_t size, const char *format, ...)
448{
449	int retval;
450	va_list ap;
451
452	va_start(ap, format);
453	retval = vsnprintf(str, size, format, ap);
454	va_end(ap);
455	return(retval);
456}
457
458/*
459 * Scaled down version of vsnprintf(3).
460 */
461int
462vsnprintf(char *str, size_t size, const char *format, va_list ap)
463{
464	struct snprintf_arg info;
465	int retval;
466
467	info.str = str;
468	info.remain = size;
469	retval = kvprintf(format, snprintf_func, &info, 10, ap);
470	if (info.remain >= 1)
471		*info.str++ = '\0';
472	return (retval);
473}
474
475/*
476 * Kernel version which takes radix argument vsnprintf(3).
477 */
478int
479vsnrprintf(char *str, size_t size, int radix, const char *format, va_list ap)
480{
481	struct snprintf_arg info;
482	int retval;
483
484	info.str = str;
485	info.remain = size;
486	retval = kvprintf(format, snprintf_func, &info, radix, ap);
487	if (info.remain >= 1)
488		*info.str++ = '\0';
489	return (retval);
490}
491
492static void
493snprintf_func(int ch, void *arg)
494{
495	struct snprintf_arg *const info = arg;
496
497	if (info->remain >= 2) {
498		*info->str++ = ch;
499		info->remain--;
500	}
501}
502
503/*
504 * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
505 * order; return an optional length and a pointer to the last character
506 * written in the buffer (i.e., the first character of the string).
507 * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
508 */
509static char *
510ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
511{
512	char *p, c;
513
514	p = nbuf;
515	*p = '\0';
516	do {
517		c = hex2ascii(num % base);
518		*++p = upper ? toupper(c) : c;
519	} while (num /= base);
520	if (lenp)
521		*lenp = p - nbuf;
522	return (p);
523}
524
525/*
526 * Scaled down version of printf(3).
527 *
528 * Two additional formats:
529 *
530 * The format %b is supported to decode error registers.
531 * Its usage is:
532 *
533 *	printf("reg=%b\n", regval, "<base><arg>*");
534 *
535 * where <base> is the output base expressed as a control character, e.g.
536 * \10 gives octal; \20 gives hex.  Each arg is a sequence of characters,
537 * the first of which gives the bit number to be inspected (origin 1), and
538 * the next characters (up to a control character, i.e. a character <= 32),
539 * give the name of the register.  Thus:
540 *
541 *	kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
542 *
543 * would produce output:
544 *
545 *	reg=3<BITTWO,BITONE>
546 *
547 * XXX:  %D  -- Hexdump, takes pointer and separator string:
548 *		("%6D", ptr, ":")   -> XX:XX:XX:XX:XX:XX
549 *		("%*D", len, ptr, " " -> XX XX XX XX ...
550 */
551int
552kvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap)
553{
554#define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; }
555	char nbuf[MAXNBUF];
556	char *d;
557	const char *p, *percent, *q;
558	u_char *up;
559	int ch, n;
560	uintmax_t num;
561	int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
562	int cflag, hflag, jflag, tflag, zflag;
563	int dwidth, upper;
564	char padc;
565	int stop = 0, retval = 0;
566
567	num = 0;
568	if (!func)
569		d = (char *) arg;
570	else
571		d = NULL;
572
573	if (fmt == NULL)
574		fmt = "(fmt null)\n";
575
576	if (radix < 2 || radix > 36)
577		radix = 10;
578
579	for (;;) {
580		padc = ' ';
581		width = 0;
582		while ((ch = (u_char)*fmt++) != '%' || stop) {
583			if (ch == '\0')
584				return (retval);
585			PCHAR(ch);
586		}
587		percent = fmt - 1;
588		qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
589		sign = 0; dot = 0; dwidth = 0; upper = 0;
590		cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
591reswitch:	switch (ch = (u_char)*fmt++) {
592		case '.':
593			dot = 1;
594			goto reswitch;
595		case '#':
596			sharpflag = 1;
597			goto reswitch;
598		case '+':
599			sign = 1;
600			goto reswitch;
601		case '-':
602			ladjust = 1;
603			goto reswitch;
604		case '%':
605			PCHAR(ch);
606			break;
607		case '*':
608			if (!dot) {
609				width = va_arg(ap, int);
610				if (width < 0) {
611					ladjust = !ladjust;
612					width = -width;
613				}
614			} else {
615				dwidth = va_arg(ap, int);
616			}
617			goto reswitch;
618		case '0':
619			if (!dot) {
620				padc = '0';
621				goto reswitch;
622			}
623		case '1': case '2': case '3': case '4':
624		case '5': case '6': case '7': case '8': case '9':
625				for (n = 0;; ++fmt) {
626					n = n * 10 + ch - '0';
627					ch = *fmt;
628					if (ch < '0' || ch > '9')
629						break;
630				}
631			if (dot)
632				dwidth = n;
633			else
634				width = n;
635			goto reswitch;
636		case 'b':
637			num = (u_int)va_arg(ap, int);
638			p = va_arg(ap, char *);
639			for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;)
640				PCHAR(*q--);
641
642			if (num == 0)
643				break;
644
645			for (tmp = 0; *p;) {
646				n = *p++;
647				if (num & (1 << (n - 1))) {
648					PCHAR(tmp ? ',' : '<');
649					for (; (n = *p) > ' '; ++p)
650						PCHAR(n);
651					tmp = 1;
652				} else
653					for (; *p > ' '; ++p)
654						continue;
655			}
656			if (tmp)
657				PCHAR('>');
658			break;
659		case 'c':
660			PCHAR(va_arg(ap, int));
661			break;
662		case 'D':
663			up = va_arg(ap, u_char *);
664			p = va_arg(ap, char *);
665			if (!width)
666				width = 16;
667			while(width--) {
668				PCHAR(hex2ascii(*up >> 4));
669				PCHAR(hex2ascii(*up & 0x0f));
670				up++;
671				if (width)
672					for (q=p;*q;q++)
673						PCHAR(*q);
674			}
675			break;
676		case 'd':
677		case 'i':
678			base = 10;
679			sign = 1;
680			goto handle_sign;
681		case 'h':
682			if (hflag) {
683				hflag = 0;
684				cflag = 1;
685			} else
686				hflag = 1;
687			goto reswitch;
688		case 'j':
689			jflag = 1;
690			goto reswitch;
691		case 'l':
692			if (lflag) {
693				lflag = 0;
694				qflag = 1;
695			} else
696				lflag = 1;
697			goto reswitch;
698		case 'n':
699			if (jflag)
700				*(va_arg(ap, intmax_t *)) = retval;
701			else if (qflag)
702				*(va_arg(ap, quad_t *)) = retval;
703			else if (lflag)
704				*(va_arg(ap, long *)) = retval;
705			else if (zflag)
706				*(va_arg(ap, size_t *)) = retval;
707			else if (hflag)
708				*(va_arg(ap, short *)) = retval;
709			else if (cflag)
710				*(va_arg(ap, char *)) = retval;
711			else
712				*(va_arg(ap, int *)) = retval;
713			break;
714		case 'o':
715			base = 8;
716			goto handle_nosign;
717		case 'p':
718			base = 16;
719			sharpflag = (width == 0);
720			sign = 0;
721			num = (uintptr_t)va_arg(ap, void *);
722			goto number;
723		case 'q':
724			qflag = 1;
725			goto reswitch;
726		case 'r':
727			base = radix;
728			if (sign)
729				goto handle_sign;
730			goto handle_nosign;
731		case 's':
732			p = va_arg(ap, char *);
733			if (p == NULL)
734				p = "(null)";
735			if (!dot)
736				n = strlen (p);
737			else
738				for (n = 0; n < dwidth && p[n]; n++)
739					continue;
740
741			width -= n;
742
743			if (!ladjust && width > 0)
744				while (width--)
745					PCHAR(padc);
746			while (n--)
747				PCHAR(*p++);
748			if (ladjust && width > 0)
749				while (width--)
750					PCHAR(padc);
751			break;
752		case 't':
753			tflag = 1;
754			goto reswitch;
755		case 'u':
756			base = 10;
757			goto handle_nosign;
758		case 'X':
759			upper = 1;
760		case 'x':
761			base = 16;
762			goto handle_nosign;
763		case 'y':
764			base = 16;
765			sign = 1;
766			goto handle_sign;
767		case 'z':
768			zflag = 1;
769			goto reswitch;
770handle_nosign:
771			sign = 0;
772			if (jflag)
773				num = va_arg(ap, uintmax_t);
774			else if (qflag)
775				num = va_arg(ap, u_quad_t);
776			else if (tflag)
777				num = va_arg(ap, ptrdiff_t);
778			else if (lflag)
779				num = va_arg(ap, u_long);
780			else if (zflag)
781				num = va_arg(ap, size_t);
782			else if (hflag)
783				num = (u_short)va_arg(ap, int);
784			else if (cflag)
785				num = (u_char)va_arg(ap, int);
786			else
787				num = va_arg(ap, u_int);
788			goto number;
789handle_sign:
790			if (jflag)
791				num = va_arg(ap, intmax_t);
792			else if (qflag)
793				num = va_arg(ap, quad_t);
794			else if (tflag)
795				num = va_arg(ap, ptrdiff_t);
796			else if (lflag)
797				num = va_arg(ap, long);
798			else if (zflag)
799				num = va_arg(ap, size_t);
800			else if (hflag)
801				num = (short)va_arg(ap, int);
802			else if (cflag)
803				num = (char)va_arg(ap, int);
804			else
805				num = va_arg(ap, int);
806number:
807			if (sign && (intmax_t)num < 0) {
808				neg = 1;
809				num = -(intmax_t)num;
810			}
811			p = ksprintn(nbuf, num, base, &tmp, upper);
812			if (sharpflag && num != 0) {
813				if (base == 8)
814					tmp++;
815				else if (base == 16)
816					tmp += 2;
817			}
818			if (neg)
819				tmp++;
820
821			if (!ladjust && padc != '0' && width
822			    && (width -= tmp) > 0)
823				while (width--)
824					PCHAR(padc);
825			if (neg)
826				PCHAR('-');
827			if (sharpflag && num != 0) {
828				if (base == 8) {
829					PCHAR('0');
830				} else if (base == 16) {
831					PCHAR('0');
832					PCHAR('x');
833				}
834			}
835			if (!ladjust && width && (width -= tmp) > 0)
836				while (width--)
837					PCHAR(padc);
838
839			while (*p)
840				PCHAR(*p--);
841
842			if (ladjust && width && (width -= tmp) > 0)
843				while (width--)
844					PCHAR(padc);
845
846			break;
847		default:
848			while (percent < fmt)
849				PCHAR(*percent++);
850			/*
851			 * Since we ignore an formatting argument it is no
852			 * longer safe to obey the remaining formatting
853			 * arguments as the arguments will no longer match
854			 * the format specs.
855			 */
856			stop = 1;
857			break;
858		}
859	}
860#undef PCHAR
861}
862
863/*
864 * Put character in log buffer with a particular priority.
865 */
866static void
867msglogchar(int c, int pri)
868{
869	static int lastpri = -1;
870	static int dangling;
871	char nbuf[MAXNBUF];
872	char *p;
873
874	if (!msgbufmapped)
875		return;
876	if (c == '\0' || c == '\r')
877		return;
878	if (pri != -1 && pri != lastpri) {
879		if (dangling) {
880			msgbuf_addchar(msgbufp, '\n');
881			dangling = 0;
882		}
883		msgbuf_addchar(msgbufp, '<');
884		for (p = ksprintn(nbuf, (uintmax_t)pri, 10, NULL, 0); *p;)
885			msgbuf_addchar(msgbufp, *p--);
886		msgbuf_addchar(msgbufp, '>');
887		lastpri = pri;
888	}
889	msgbuf_addchar(msgbufp, c);
890	if (c == '\n') {
891		dangling = 0;
892		lastpri = -1;
893	} else {
894		dangling = 1;
895	}
896}
897
898void
899msgbufinit(void *ptr, int size)
900{
901	char *cp;
902	static struct msgbuf *oldp = NULL;
903
904	size -= sizeof(*msgbufp);
905	cp = (char *)ptr;
906	msgbufp = (struct msgbuf *)(cp + size);
907	msgbuf_reinit(msgbufp, cp, size);
908	if (msgbufmapped && oldp != msgbufp)
909		msgbuf_copy(oldp, msgbufp);
910	msgbufmapped = 1;
911	oldp = msgbufp;
912}
913
914static int unprivileged_read_msgbuf = 1;
915SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_read_msgbuf,
916    CTLFLAG_RW, &unprivileged_read_msgbuf, 0,
917    "Unprivileged processes may read the kernel message buffer");
918
919/* Sysctls for accessing/clearing the msgbuf */
920static int
921sysctl_kern_msgbuf(SYSCTL_HANDLER_ARGS)
922{
923	char buf[128];
924	u_int seq;
925	int error, len;
926
927	if (!unprivileged_read_msgbuf) {
928		error = suser(req->td);
929		if (error)
930			return (error);
931	}
932
933	/* Read the whole buffer, one chunk at a time. */
934	msgbuf_peekbytes(msgbufp, NULL, 0, &seq);
935	while ((len = msgbuf_peekbytes(msgbufp, buf, sizeof(buf), &seq)) > 0) {
936		error = sysctl_handle_opaque(oidp, buf, len, req);
937		if (error)
938			return (error);
939	}
940	return (0);
941}
942
943SYSCTL_PROC(_kern, OID_AUTO, msgbuf, CTLTYPE_STRING | CTLFLAG_RD,
944    0, 0, sysctl_kern_msgbuf, "A", "Contents of kernel message buffer");
945
946static int msgbuf_clearflag;
947
948static int
949sysctl_kern_msgbuf_clear(SYSCTL_HANDLER_ARGS)
950{
951	int error;
952	error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
953	if (!error && req->newptr) {
954		msgbuf_clear(msgbufp);
955		msgbuf_clearflag = 0;
956	}
957	return (error);
958}
959
960SYSCTL_PROC(_kern, OID_AUTO, msgbuf_clear,
961    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE, &msgbuf_clearflag, 0,
962    sysctl_kern_msgbuf_clear, "I", "Clear kernel message buffer");
963
964#ifdef DDB
965
966DB_SHOW_COMMAND(msgbuf, db_show_msgbuf)
967{
968	int i, j;
969
970	if (!msgbufmapped) {
971		db_printf("msgbuf not mapped yet\n");
972		return;
973	}
974	db_printf("msgbufp = %p\n", msgbufp);
975	db_printf("magic = %x, size = %d, r= %u, w = %u, ptr = %p, cksum= %u\n",
976	    msgbufp->msg_magic, msgbufp->msg_size, msgbufp->msg_rseq,
977	    msgbufp->msg_wseq, msgbufp->msg_ptr, msgbufp->msg_cksum);
978	for (i = 0; i < msgbufp->msg_size && !db_pager_quit; i++) {
979		j = MSGBUF_SEQ_TO_POS(msgbufp, i + msgbufp->msg_rseq);
980		db_printf("%c", msgbufp->msg_ptr[j]);
981	}
982	db_printf("\n");
983}
984
985#endif /* DDB */
986
987void
988hexdump(const void *ptr, int length, const char *hdr, int flags)
989{
990	int i, j, k;
991	int cols;
992	const unsigned char *cp;
993	char delim;
994
995	if ((flags & HD_DELIM_MASK) != 0)
996		delim = (flags & HD_DELIM_MASK) >> 8;
997	else
998		delim = ' ';
999
1000	if ((flags & HD_COLUMN_MASK) != 0)
1001		cols = flags & HD_COLUMN_MASK;
1002	else
1003		cols = 16;
1004
1005	cp = ptr;
1006	for (i = 0; i < length; i+= cols) {
1007		if (hdr != NULL)
1008			printf("%s", hdr);
1009
1010		if ((flags & HD_OMIT_COUNT) == 0)
1011			printf("%04x  ", i);
1012
1013		if ((flags & HD_OMIT_HEX) == 0) {
1014			for (j = 0; j < cols; j++) {
1015				k = i + j;
1016				if (k < length)
1017					printf("%c%02x", delim, cp[k]);
1018				else
1019					printf("   ");
1020			}
1021		}
1022
1023		if ((flags & HD_OMIT_CHARS) == 0) {
1024			printf("  |");
1025			for (j = 0; j < cols; j++) {
1026				k = i + j;
1027				if (k >= length)
1028					printf(" ");
1029				else if (cp[k] >= ' ' && cp[k] <= '~')
1030					printf("%c", cp[k]);
1031				else
1032					printf(".");
1033			}
1034			printf("|");
1035		}
1036		printf("\n");
1037	}
1038}
1039
1040