hexdump.c revision 164760
152419Sjulian/*-
252419Sjulian * Copyright (c) 1986, 1988, 1991, 1993
352419Sjulian *	The Regents of the University of California.  All rights reserved.
452419Sjulian * (c) UNIX System Laboratories, Inc.
552419Sjulian * All or some portions of this file are derived from material licensed
652419Sjulian * to the University of California by American Telephone and Telegraph
752419Sjulian * Co. or Unix System Laboratories, Inc. and are reproduced herein with
852419Sjulian * the permission of UNIX System Laboratories, Inc.
952419Sjulian *
1052419Sjulian * Redistribution and use in source and binary forms, with or without
1152419Sjulian * modification, are permitted provided that the following conditions
1252419Sjulian * are met:
1352419Sjulian * 1. Redistributions of source code must retain the above copyright
1452419Sjulian *    notice, this list of conditions and the following disclaimer.
1552419Sjulian * 2. Redistributions in binary form must reproduce the above copyright
1652419Sjulian *    notice, this list of conditions and the following disclaimer in the
1752419Sjulian *    documentation and/or other materials provided with the distribution.
1852419Sjulian * 4. Neither the name of the University nor the names of its contributors
1952419Sjulian *    may be used to endorse or promote products derived from this software
2052419Sjulian *    without specific prior written permission.
2152419Sjulian *
2252419Sjulian * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2352419Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2452419Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2552419Sjulian * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2652419Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2752419Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2852419Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2952419Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3052419Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3152419Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3252419Sjulian * SUCH DAMAGE.
3352419Sjulian *
3452419Sjulian *	@(#)subr_prf.c	8.3 (Berkeley) 1/21/94
3552419Sjulian */
3652419Sjulian
3752419Sjulian#include <sys/cdefs.h>
3852419Sjulian__FBSDID("$FreeBSD: head/sys/kern/subr_prf.c 164760 2006-11-30 04:17:05Z jb $");
3952419Sjulian
40158882Sglebius#include "opt_ddb.h"
41158882Sglebius#include "opt_printf.h"
42158882Sglebius
43158882Sglebius#include <sys/param.h>
44158882Sglebius#include <sys/systm.h>
4552419Sjulian#include <sys/lock.h>
4652419Sjulian#include <sys/kdb.h>
4752419Sjulian#include <sys/mutex.h>
4852419Sjulian#include <sys/sx.h>
4952419Sjulian#include <sys/kernel.h>
5052419Sjulian#include <sys/msgbuf.h>
5152419Sjulian#include <sys/malloc.h>
5252419Sjulian#include <sys/priv.h>
5352419Sjulian#include <sys/proc.h>
5452419Sjulian#include <sys/stddef.h>
55125011Sru#include <sys/sysctl.h>
56160423Sstefanf#include <sys/tty.h>
5752419Sjulian#include <sys/syslog.h>
5852419Sjulian#include <sys/cons.h>
5952419Sjulian#include <sys/uio.h>
6052419Sjulian#include <sys/ctype.h>
6152419Sjulian
6252419Sjulian#ifdef DDB
6352419Sjulian#include <ddb/ddb.h>
6452419Sjulian#endif
6552419Sjulian
6652419Sjulian/*
6752419Sjulian * Note that stdarg.h and the ANSI style va_start macro is used for both
6852419Sjulian * ANSI and traditional C compilers.
6952419Sjulian */
7052419Sjulian#include <machine/stdarg.h>
7152419Sjulian
7252419Sjulian#define TOCONS	0x01
7352419Sjulian#define TOTTY	0x02
74160002Sglebius#define TOLOG	0x04
7552419Sjulian
7652419Sjulian/* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */
7752419Sjulian#define MAXNBUF	(sizeof(intmax_t) * NBBY + 1)
7852419Sjulian
7952419Sjulianstruct putchar_arg {
8052419Sjulian	int	flags;
8152419Sjulian	int	pri;
8252419Sjulian	struct	tty *tty;
8352419Sjulian	char	*p_bufr;
8452419Sjulian	size_t	n_bufr;
8552419Sjulian	char	*p_next;
86160002Sglebius	size_t	remain;
8752419Sjulian};
8852419Sjulian
8952419Sjulianstruct snprintf_arg {
9052419Sjulian	char	*str;
9152419Sjulian	size_t	remain;
9252419Sjulian};
9352419Sjulian
9452419Sjulianextern	int log_open;
9552419Sjulian
9652419Sjulianstatic void  msglogchar(int c, int pri);
9752419Sjulianstatic void  putchar(int ch, void *arg);
9852419Sjulianstatic char *ksprintn(char *nbuf, uintmax_t num, int base, int *len, int upper);
99160002Sglebiusstatic void  snprintf_func(int ch, void *arg);
10052419Sjulian
10152419Sjulianstatic 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 == PCPU_GET(idlethread))
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	/* Write any buffered console output: */
318	if (*pca.p_bufr != '\0')
319		cnputs(pca.p_bufr);
320
321	if (!panicstr)
322		msgbuftrigger = 1;
323
324	return (retval);
325}
326
327int
328vprintf(const char *fmt, va_list ap)
329{
330	struct putchar_arg pca;
331	int retval;
332#ifdef PRINTF_BUFR_SIZE
333	char bufr[PRINTF_BUFR_SIZE];
334#endif
335
336	pca.tty = NULL;
337	pca.flags = TOCONS | TOLOG;
338	pca.pri = -1;
339#ifdef PRINTF_BUFR_SIZE
340	pca.p_bufr = bufr;
341	pca.p_next = pca.p_bufr;
342	pca.n_bufr = sizeof(bufr);
343	pca.remain = sizeof(bufr);
344	*pca.p_next = '\0';
345#else
346	/* Don't buffer console output. */
347	pca.p_bufr = NULL;
348#endif
349
350	retval = kvprintf(fmt, putchar, &pca, 10, ap);
351
352	/* Write any buffered console output: */
353	if (*pca.p_bufr != '\0')
354		cnputs(pca.p_bufr);
355
356	if (!panicstr)
357		msgbuftrigger = 1;
358
359	return (retval);
360}
361
362static void
363putcons(int c, struct putchar_arg *ap)
364{
365	/* Check if no console output buffer was provided. */
366	if (ap->p_bufr == NULL)
367		/* Output direct to the console. */
368		cnputc(c);
369	else {
370		/* Buffer the character: */
371		if (c == '\n') {
372			*ap->p_next++ = '\r';
373			ap->remain--;
374		}
375		*ap->p_next++ = c;
376		ap->remain--;
377
378		/* Always leave the buffer zero terminated. */
379		*ap->p_next = '\0';
380
381		/* Check if the buffer needs to be flushed. */
382		if (ap->remain < 3 || c == '\n') {
383			cnputs(ap->p_bufr);
384			ap->p_next = ap->p_bufr;
385			ap->remain = ap->n_bufr;
386			*ap->p_next = '\0';
387		}
388	}
389}
390
391/*
392 * Print a character on console or users terminal.  If destination is
393 * the console then the last bunch of characters are saved in msgbuf for
394 * inspection later.
395 */
396static void
397putchar(int c, void *arg)
398{
399	struct putchar_arg *ap = (struct putchar_arg*) arg;
400	struct tty *tp = ap->tty;
401	int flags = ap->flags;
402
403	/* Don't use the tty code after a panic or while in ddb. */
404	if (kdb_active) {
405		if (c != '\0')
406			cnputc(c);
407	} else if (panicstr || ((flags & TOCONS) && constty == NULL)) {
408		if (c != '\0')
409			putcons(c, ap);
410	} else {
411		if ((flags & TOTTY) && tp != NULL)
412			tputchar(c, tp);
413		if (flags & TOCONS) {
414			if (constty != NULL)
415				msgbuf_addchar(&consmsgbuf, c);
416			if (always_console_output && c != '\0')
417				putcons(c, ap);
418		}
419	}
420	if ((flags & TOLOG))
421		msglogchar(c, ap->pri);
422}
423
424/*
425 * Scaled down version of sprintf(3).
426 */
427int
428sprintf(char *buf, const char *cfmt, ...)
429{
430	int retval;
431	va_list ap;
432
433	va_start(ap, cfmt);
434	retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
435	buf[retval] = '\0';
436	va_end(ap);
437	return (retval);
438}
439
440/*
441 * Scaled down version of vsprintf(3).
442 */
443int
444vsprintf(char *buf, const char *cfmt, va_list ap)
445{
446	int retval;
447
448	retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
449	buf[retval] = '\0';
450	return (retval);
451}
452
453/*
454 * Scaled down version of snprintf(3).
455 */
456int
457snprintf(char *str, size_t size, const char *format, ...)
458{
459	int retval;
460	va_list ap;
461
462	va_start(ap, format);
463	retval = vsnprintf(str, size, format, ap);
464	va_end(ap);
465	return(retval);
466}
467
468/*
469 * Scaled down version of vsnprintf(3).
470 */
471int
472vsnprintf(char *str, size_t size, const char *format, va_list ap)
473{
474	struct snprintf_arg info;
475	int retval;
476
477	info.str = str;
478	info.remain = size;
479	retval = kvprintf(format, snprintf_func, &info, 10, ap);
480	if (info.remain >= 1)
481		*info.str++ = '\0';
482	return (retval);
483}
484
485/*
486 * Kernel version which takes radix argument vsnprintf(3).
487 */
488int
489vsnrprintf(char *str, size_t size, int radix, const char *format, va_list ap)
490{
491	struct snprintf_arg info;
492	int retval;
493
494	info.str = str;
495	info.remain = size;
496	retval = kvprintf(format, snprintf_func, &info, radix, ap);
497	if (info.remain >= 1)
498		*info.str++ = '\0';
499	return (retval);
500}
501
502static void
503snprintf_func(int ch, void *arg)
504{
505	struct snprintf_arg *const info = arg;
506
507	if (info->remain >= 2) {
508		*info->str++ = ch;
509		info->remain--;
510	}
511}
512
513/*
514 * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
515 * order; return an optional length and a pointer to the last character
516 * written in the buffer (i.e., the first character of the string).
517 * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
518 */
519static char *
520ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
521{
522	char *p, c;
523
524	p = nbuf;
525	*p = '\0';
526	do {
527		c = hex2ascii(num % base);
528		*++p = upper ? toupper(c) : c;
529	} while (num /= base);
530	if (lenp)
531		*lenp = p - nbuf;
532	return (p);
533}
534
535/*
536 * Scaled down version of printf(3).
537 *
538 * Two additional formats:
539 *
540 * The format %b is supported to decode error registers.
541 * Its usage is:
542 *
543 *	printf("reg=%b\n", regval, "<base><arg>*");
544 *
545 * where <base> is the output base expressed as a control character, e.g.
546 * \10 gives octal; \20 gives hex.  Each arg is a sequence of characters,
547 * the first of which gives the bit number to be inspected (origin 1), and
548 * the next characters (up to a control character, i.e. a character <= 32),
549 * give the name of the register.  Thus:
550 *
551 *	kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
552 *
553 * would produce output:
554 *
555 *	reg=3<BITTWO,BITONE>
556 *
557 * XXX:  %D  -- Hexdump, takes pointer and separator string:
558 *		("%6D", ptr, ":")   -> XX:XX:XX:XX:XX:XX
559 *		("%*D", len, ptr, " " -> XX XX XX XX ...
560 */
561int
562kvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap)
563{
564#define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; }
565	char nbuf[MAXNBUF];
566	char *d;
567	const char *p, *percent, *q;
568	u_char *up;
569	int ch, n;
570	uintmax_t num;
571	int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
572	int cflag, hflag, jflag, tflag, zflag;
573	int dwidth, upper;
574	char padc;
575	int stop = 0, retval = 0;
576
577	num = 0;
578	if (!func)
579		d = (char *) arg;
580	else
581		d = NULL;
582
583	if (fmt == NULL)
584		fmt = "(fmt null)\n";
585
586	if (radix < 2 || radix > 36)
587		radix = 10;
588
589	for (;;) {
590		padc = ' ';
591		width = 0;
592		while ((ch = (u_char)*fmt++) != '%' || stop) {
593			if (ch == '\0')
594				return (retval);
595			PCHAR(ch);
596		}
597		percent = fmt - 1;
598		qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
599		sign = 0; dot = 0; dwidth = 0; upper = 0;
600		cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
601reswitch:	switch (ch = (u_char)*fmt++) {
602		case '.':
603			dot = 1;
604			goto reswitch;
605		case '#':
606			sharpflag = 1;
607			goto reswitch;
608		case '+':
609			sign = 1;
610			goto reswitch;
611		case '-':
612			ladjust = 1;
613			goto reswitch;
614		case '%':
615			PCHAR(ch);
616			break;
617		case '*':
618			if (!dot) {
619				width = va_arg(ap, int);
620				if (width < 0) {
621					ladjust = !ladjust;
622					width = -width;
623				}
624			} else {
625				dwidth = va_arg(ap, int);
626			}
627			goto reswitch;
628		case '0':
629			if (!dot) {
630				padc = '0';
631				goto reswitch;
632			}
633		case '1': case '2': case '3': case '4':
634		case '5': case '6': case '7': case '8': case '9':
635				for (n = 0;; ++fmt) {
636					n = n * 10 + ch - '0';
637					ch = *fmt;
638					if (ch < '0' || ch > '9')
639						break;
640				}
641			if (dot)
642				dwidth = n;
643			else
644				width = n;
645			goto reswitch;
646		case 'b':
647			num = (u_int)va_arg(ap, int);
648			p = va_arg(ap, char *);
649			for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;)
650				PCHAR(*q--);
651
652			if (num == 0)
653				break;
654
655			for (tmp = 0; *p;) {
656				n = *p++;
657				if (num & (1 << (n - 1))) {
658					PCHAR(tmp ? ',' : '<');
659					for (; (n = *p) > ' '; ++p)
660						PCHAR(n);
661					tmp = 1;
662				} else
663					for (; *p > ' '; ++p)
664						continue;
665			}
666			if (tmp)
667				PCHAR('>');
668			break;
669		case 'c':
670			PCHAR(va_arg(ap, int));
671			break;
672		case 'D':
673			up = va_arg(ap, u_char *);
674			p = va_arg(ap, char *);
675			if (!width)
676				width = 16;
677			while(width--) {
678				PCHAR(hex2ascii(*up >> 4));
679				PCHAR(hex2ascii(*up & 0x0f));
680				up++;
681				if (width)
682					for (q=p;*q;q++)
683						PCHAR(*q);
684			}
685			break;
686		case 'd':
687		case 'i':
688			base = 10;
689			sign = 1;
690			goto handle_sign;
691		case 'h':
692			if (hflag) {
693				hflag = 0;
694				cflag = 1;
695			} else
696				hflag = 1;
697			goto reswitch;
698		case 'j':
699			jflag = 1;
700			goto reswitch;
701		case 'l':
702			if (lflag) {
703				lflag = 0;
704				qflag = 1;
705			} else
706				lflag = 1;
707			goto reswitch;
708		case 'n':
709			if (jflag)
710				*(va_arg(ap, intmax_t *)) = retval;
711			else if (qflag)
712				*(va_arg(ap, quad_t *)) = retval;
713			else if (lflag)
714				*(va_arg(ap, long *)) = retval;
715			else if (zflag)
716				*(va_arg(ap, size_t *)) = retval;
717			else if (hflag)
718				*(va_arg(ap, short *)) = retval;
719			else if (cflag)
720				*(va_arg(ap, char *)) = retval;
721			else
722				*(va_arg(ap, int *)) = retval;
723			break;
724		case 'o':
725			base = 8;
726			goto handle_nosign;
727		case 'p':
728			base = 16;
729			sharpflag = (width == 0);
730			sign = 0;
731			num = (uintptr_t)va_arg(ap, void *);
732			goto number;
733		case 'q':
734			qflag = 1;
735			goto reswitch;
736		case 'r':
737			base = radix;
738			if (sign)
739				goto handle_sign;
740			goto handle_nosign;
741		case 's':
742			p = va_arg(ap, char *);
743			if (p == NULL)
744				p = "(null)";
745			if (!dot)
746				n = strlen (p);
747			else
748				for (n = 0; n < dwidth && p[n]; n++)
749					continue;
750
751			width -= n;
752
753			if (!ladjust && width > 0)
754				while (width--)
755					PCHAR(padc);
756			while (n--)
757				PCHAR(*p++);
758			if (ladjust && width > 0)
759				while (width--)
760					PCHAR(padc);
761			break;
762		case 't':
763			tflag = 1;
764			goto reswitch;
765		case 'u':
766			base = 10;
767			goto handle_nosign;
768		case 'X':
769			upper = 1;
770		case 'x':
771			base = 16;
772			goto handle_nosign;
773		case 'y':
774			base = 16;
775			sign = 1;
776			goto handle_sign;
777		case 'z':
778			zflag = 1;
779			goto reswitch;
780handle_nosign:
781			sign = 0;
782			if (jflag)
783				num = va_arg(ap, uintmax_t);
784			else if (qflag)
785				num = va_arg(ap, u_quad_t);
786			else if (tflag)
787				num = va_arg(ap, ptrdiff_t);
788			else if (lflag)
789				num = va_arg(ap, u_long);
790			else if (zflag)
791				num = va_arg(ap, size_t);
792			else if (hflag)
793				num = (u_short)va_arg(ap, int);
794			else if (cflag)
795				num = (u_char)va_arg(ap, int);
796			else
797				num = va_arg(ap, u_int);
798			goto number;
799handle_sign:
800			if (jflag)
801				num = va_arg(ap, intmax_t);
802			else if (qflag)
803				num = va_arg(ap, quad_t);
804			else if (tflag)
805				num = va_arg(ap, ptrdiff_t);
806			else if (lflag)
807				num = va_arg(ap, long);
808			else if (zflag)
809				num = va_arg(ap, size_t);
810			else if (hflag)
811				num = (short)va_arg(ap, int);
812			else if (cflag)
813				num = (char)va_arg(ap, int);
814			else
815				num = va_arg(ap, int);
816number:
817			if (sign && (intmax_t)num < 0) {
818				neg = 1;
819				num = -(intmax_t)num;
820			}
821			p = ksprintn(nbuf, num, base, &tmp, upper);
822			if (sharpflag && num != 0) {
823				if (base == 8)
824					tmp++;
825				else if (base == 16)
826					tmp += 2;
827			}
828			if (neg)
829				tmp++;
830
831			if (!ladjust && padc != '0' && width
832			    && (width -= tmp) > 0)
833				while (width--)
834					PCHAR(padc);
835			if (neg)
836				PCHAR('-');
837			if (sharpflag && num != 0) {
838				if (base == 8) {
839					PCHAR('0');
840				} else if (base == 16) {
841					PCHAR('0');
842					PCHAR('x');
843				}
844			}
845			if (!ladjust && width && (width -= tmp) > 0)
846				while (width--)
847					PCHAR(padc);
848
849			while (*p)
850				PCHAR(*p--);
851
852			if (ladjust && width && (width -= tmp) > 0)
853				while (width--)
854					PCHAR(padc);
855
856			break;
857		default:
858			while (percent < fmt)
859				PCHAR(*percent++);
860			/*
861			 * Since we ignore an formatting argument it is no
862			 * longer safe to obey the remaining formatting
863			 * arguments as the arguments will no longer match
864			 * the format specs.
865			 */
866			stop = 1;
867			break;
868		}
869	}
870#undef PCHAR
871}
872
873/*
874 * Put character in log buffer with a particular priority.
875 */
876static void
877msglogchar(int c, int pri)
878{
879	static int lastpri = -1;
880	static int dangling;
881	char nbuf[MAXNBUF];
882	char *p;
883
884	if (!msgbufmapped)
885		return;
886	if (c == '\0' || c == '\r')
887		return;
888	if (pri != -1 && pri != lastpri) {
889		if (dangling) {
890			msgbuf_addchar(msgbufp, '\n');
891			dangling = 0;
892		}
893		msgbuf_addchar(msgbufp, '<');
894		for (p = ksprintn(nbuf, (uintmax_t)pri, 10, NULL, 0); *p;)
895			msgbuf_addchar(msgbufp, *p--);
896		msgbuf_addchar(msgbufp, '>');
897		lastpri = pri;
898	}
899	msgbuf_addchar(msgbufp, c);
900	if (c == '\n') {
901		dangling = 0;
902		lastpri = -1;
903	} else {
904		dangling = 1;
905	}
906}
907
908void
909msgbufinit(void *ptr, int size)
910{
911	char *cp;
912	static struct msgbuf *oldp = NULL;
913
914	size -= sizeof(*msgbufp);
915	cp = (char *)ptr;
916	msgbufp = (struct msgbuf *)(cp + size);
917	msgbuf_reinit(msgbufp, cp, size);
918	if (msgbufmapped && oldp != msgbufp)
919		msgbuf_copy(oldp, msgbufp);
920	msgbufmapped = 1;
921	oldp = msgbufp;
922}
923
924static int unprivileged_read_msgbuf = 1;
925SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_read_msgbuf,
926    CTLFLAG_RW, &unprivileged_read_msgbuf, 0,
927    "Unprivileged processes may read the kernel message buffer");
928
929/* Sysctls for accessing/clearing the msgbuf */
930static int
931sysctl_kern_msgbuf(SYSCTL_HANDLER_ARGS)
932{
933	char buf[128];
934	u_int seq;
935	int error, len;
936
937	if (!unprivileged_read_msgbuf) {
938		error = priv_check(req->td, PRIV_MSGBUF);
939		if (error)
940			return (error);
941	}
942
943	/* Read the whole buffer, one chunk at a time. */
944	msgbuf_peekbytes(msgbufp, NULL, 0, &seq);
945	while ((len = msgbuf_peekbytes(msgbufp, buf, sizeof(buf), &seq)) > 0) {
946		error = sysctl_handle_opaque(oidp, buf, len, req);
947		if (error)
948			return (error);
949	}
950	return (0);
951}
952
953SYSCTL_PROC(_kern, OID_AUTO, msgbuf, CTLTYPE_STRING | CTLFLAG_RD,
954    0, 0, sysctl_kern_msgbuf, "A", "Contents of kernel message buffer");
955
956static int msgbuf_clearflag;
957
958static int
959sysctl_kern_msgbuf_clear(SYSCTL_HANDLER_ARGS)
960{
961	int error;
962	error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
963	if (!error && req->newptr) {
964		msgbuf_clear(msgbufp);
965		msgbuf_clearflag = 0;
966	}
967	return (error);
968}
969
970SYSCTL_PROC(_kern, OID_AUTO, msgbuf_clear,
971    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE, &msgbuf_clearflag, 0,
972    sysctl_kern_msgbuf_clear, "I", "Clear kernel message buffer");
973
974#ifdef DDB
975
976DB_SHOW_COMMAND(msgbuf, db_show_msgbuf)
977{
978	int i, j;
979
980	if (!msgbufmapped) {
981		db_printf("msgbuf not mapped yet\n");
982		return;
983	}
984	db_printf("msgbufp = %p\n", msgbufp);
985	db_printf("magic = %x, size = %d, r= %u, w = %u, ptr = %p, cksum= %u\n",
986	    msgbufp->msg_magic, msgbufp->msg_size, msgbufp->msg_rseq,
987	    msgbufp->msg_wseq, msgbufp->msg_ptr, msgbufp->msg_cksum);
988	for (i = 0; i < msgbufp->msg_size && !db_pager_quit; i++) {
989		j = MSGBUF_SEQ_TO_POS(msgbufp, i + msgbufp->msg_rseq);
990		db_printf("%c", msgbufp->msg_ptr[j]);
991	}
992	db_printf("\n");
993}
994
995#endif /* DDB */
996
997void
998hexdump(const void *ptr, int length, const char *hdr, int flags)
999{
1000	int i, j, k;
1001	int cols;
1002	const unsigned char *cp;
1003	char delim;
1004
1005	if ((flags & HD_DELIM_MASK) != 0)
1006		delim = (flags & HD_DELIM_MASK) >> 8;
1007	else
1008		delim = ' ';
1009
1010	if ((flags & HD_COLUMN_MASK) != 0)
1011		cols = flags & HD_COLUMN_MASK;
1012	else
1013		cols = 16;
1014
1015	cp = ptr;
1016	for (i = 0; i < length; i+= cols) {
1017		if (hdr != NULL)
1018			printf("%s", hdr);
1019
1020		if ((flags & HD_OMIT_COUNT) == 0)
1021			printf("%04x  ", i);
1022
1023		if ((flags & HD_OMIT_HEX) == 0) {
1024			for (j = 0; j < cols; j++) {
1025				k = i + j;
1026				if (k < length)
1027					printf("%c%02x", delim, cp[k]);
1028				else
1029					printf("   ");
1030			}
1031		}
1032
1033		if ((flags & HD_OMIT_CHARS) == 0) {
1034			printf("  |");
1035			for (j = 0; j < cols; j++) {
1036				k = i + j;
1037				if (k >= length)
1038					printf(" ");
1039				else if (cp[k] >= ' ' && cp[k] <= '~')
1040					printf("%c", cp[k]);
1041				else
1042					printf(".");
1043			}
1044			printf("|");
1045		}
1046		printf("\n");
1047	}
1048}
1049
1050