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