hexdump.c revision 164033
1233237Sjkim/*-
2233237Sjkim * Copyright (c) 1986, 1988, 1991, 1993
3233237Sjkim *	The Regents of the University of California.  All rights reserved.
4233237Sjkim * (c) UNIX System Laboratories, Inc.
5233237Sjkim * All or some portions of this file are derived from material licensed
6233237Sjkim * to the University of California by American Telephone and Telegraph
7233237Sjkim * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8233237Sjkim * the permission of UNIX System Laboratories, Inc.
9245582Sjkim *
10233237Sjkim * Redistribution and use in source and binary forms, with or without
11233237Sjkim * modification, are permitted provided that the following conditions
12233237Sjkim * are met:
13233237Sjkim * 1. Redistributions of source code must retain the above copyright
14233237Sjkim *    notice, this list of conditions and the following disclaimer.
15233237Sjkim * 2. Redistributions in binary form must reproduce the above copyright
16233237Sjkim *    notice, this list of conditions and the following disclaimer in the
17233237Sjkim *    documentation and/or other materials provided with the distribution.
18233237Sjkim * 4. Neither the name of the University nor the names of its contributors
19233237Sjkim *    may be used to endorse or promote products derived from this software
20233237Sjkim *    without specific prior written permission.
21233237Sjkim *
22233237Sjkim * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23233237Sjkim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24233237Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25233237Sjkim * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26233237Sjkim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27233237Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28233237Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29233237Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30233237Sjkim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31233237Sjkim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32233237Sjkim * SUCH DAMAGE.
33233237Sjkim *
34233237Sjkim *	@(#)subr_prf.c	8.3 (Berkeley) 1/21/94
35233237Sjkim */
36233237Sjkim
37233237Sjkim#include <sys/cdefs.h>
38233237Sjkim__FBSDID("$FreeBSD: head/sys/kern/subr_prf.c 164033 2006-11-06 13:42:10Z rwatson $");
39233237Sjkim
40233237Sjkim#include "opt_ddb.h"
41233237Sjkim
42233237Sjkim#include <sys/param.h>
43233237Sjkim#include <sys/systm.h>
44233237Sjkim#include <sys/lock.h>
45233250Sjkim#include <sys/kdb.h>
46233250Sjkim#include <sys/mutex.h>
47233237Sjkim#include <sys/sx.h>
48233237Sjkim#include <sys/kernel.h>
49233237Sjkim#include <sys/msgbuf.h>
50233237Sjkim#include <sys/malloc.h>
51233237Sjkim#include <sys/priv.h>
52233237Sjkim#include <sys/proc.h>
53233237Sjkim#include <sys/stddef.h>
54233237Sjkim#include <sys/sysctl.h>
55233237Sjkim#include <sys/tty.h>
56233237Sjkim#include <sys/syslog.h>
57233237Sjkim#include <sys/cons.h>
58233237Sjkim#include <sys/uio.h>
59233237Sjkim#include <sys/ctype.h>
60233237Sjkim
61233237Sjkim#ifdef DDB
62233237Sjkim#include <ddb/ddb.h>
63233237Sjkim#endif
64233237Sjkim
65233237Sjkim/*
66233237Sjkim * Note that stdarg.h and the ANSI style va_start macro is used for both
67233237Sjkim * ANSI and traditional C compilers.
68233237Sjkim */
69233237Sjkim#include <machine/stdarg.h>
70233237Sjkim
71233237Sjkim#define TOCONS	0x01
72233237Sjkim#define TOTTY	0x02
73233237Sjkim#define TOLOG	0x04
74233237Sjkim
75233237Sjkim/* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */
76233237Sjkim#define MAXNBUF	(sizeof(intmax_t) * NBBY + 1)
77233237Sjkim
78233237Sjkimstruct putchar_arg {
79233237Sjkim	int	flags;
80233237Sjkim	int	pri;
81233237Sjkim	struct	tty *tty;
82233237Sjkim	char	*p_bufr;
83233237Sjkim	size_t	n_bufr;
84233237Sjkim	char	*p_next;
85233237Sjkim	size_t	remain;
86233237Sjkim};
87233237Sjkim
88233237Sjkimstruct snprintf_arg {
89233237Sjkim	char	*str;
90233237Sjkim	size_t	remain;
91233237Sjkim};
92233237Sjkim
93233237Sjkimextern	int log_open;
94233237Sjkim
95233237Sjkimstatic void  msglogchar(int c, int pri);
96233237Sjkimstatic void  putchar(int ch, void *arg);
97233237Sjkimstatic char *ksprintn(char *nbuf, uintmax_t num, int base, int *len, int upper);
98233237Sjkimstatic void  snprintf_func(int ch, void *arg);
99233237Sjkim
100233237Sjkimstatic int msgbufmapped;		/* Set when safe to use msgbuf */
101233237Sjkimint msgbuftrigger;
102233237Sjkim
103233237Sjkimstatic int      log_console_output = 1;
104233237SjkimTUNABLE_INT("kern.log_console_output", &log_console_output);
105233237SjkimSYSCTL_INT(_kern, OID_AUTO, log_console_output, CTLFLAG_RW,
106233237Sjkim    &log_console_output, 0, "Duplicate console output to the syslog.");
107233237Sjkim
108233237Sjkimstatic int	always_console_output = 0;
109233237SjkimTUNABLE_INT("kern.always_console_output", &always_console_output);
110233237SjkimSYSCTL_INT(_kern, OID_AUTO, always_console_output, CTLFLAG_RW,
111233237Sjkim    &always_console_output, 0, "Always output to console despite TIOCCONS.");
112233237Sjkim
113233237Sjkim/*
114233237Sjkim * Warn that a system table is full.
115233237Sjkim */
116233237Sjkimvoid
117233237Sjkimtablefull(const char *tab)
118233237Sjkim{
119233237Sjkim
120233237Sjkim	log(LOG_ERR, "%s: table is full\n", tab);
121233237Sjkim}
122233237Sjkim
123233237Sjkim/*
124233237Sjkim * Uprintf prints to the controlling terminal for the current process.
125233237Sjkim */
126233237Sjkimint
127233237Sjkimuprintf(const char *fmt, ...)
128233237Sjkim{
129233237Sjkim	struct thread *td = curthread;
130233237Sjkim	struct proc *p = td->td_proc;
131233237Sjkim	va_list ap;
132233237Sjkim	struct putchar_arg pca;
133233237Sjkim	int retval;
134233237Sjkim
135233237Sjkim	if (td == NULL || td == PCPU_GET(idlethread))
136233237Sjkim		return (0);
137233237Sjkim
138233237Sjkim	mtx_lock(&Giant);
139233237Sjkim	p = td->td_proc;
140233237Sjkim	PROC_LOCK(p);
141233237Sjkim	if ((p->p_flag & P_CONTROLT) == 0) {
142233237Sjkim		PROC_UNLOCK(p);
143233237Sjkim		retval = 0;
144233237Sjkim		goto out;
145233237Sjkim	}
146233237Sjkim	SESS_LOCK(p->p_session);
147233237Sjkim	pca.tty = p->p_session->s_ttyp;
148233237Sjkim	SESS_UNLOCK(p->p_session);
149233237Sjkim	PROC_UNLOCK(p);
150233237Sjkim	if (pca.tty == NULL) {
151233237Sjkim		retval = 0;
152233237Sjkim		goto out;
153233237Sjkim	}
154233237Sjkim	pca.flags = TOTTY;
155233237Sjkim	va_start(ap, fmt);
156233237Sjkim	retval = kvprintf(fmt, putchar, &pca, 10, ap);
157233237Sjkim	va_end(ap);
158233237Sjkimout:
159233237Sjkim	mtx_unlock(&Giant);
160233237Sjkim	return (retval);
161233237Sjkim}
162233237Sjkim
163233237Sjkim/*
164233237Sjkim * tprintf prints on the controlling terminal associated with the given
165233237Sjkim * session, possibly to the log as well.
166233237Sjkim */
167233237Sjkimvoid
168233237Sjkimtprintf(struct proc *p, int pri, const char *fmt, ...)
169233237Sjkim{
170233237Sjkim	struct tty *tp = NULL;
171233237Sjkim	int flags = 0;
172233237Sjkim	va_list ap;
173233237Sjkim	struct putchar_arg pca;
174233237Sjkim	struct session *sess = NULL;
175233237Sjkim
176233237Sjkim	mtx_lock(&Giant);
177233237Sjkim	if (pri != -1)
178233237Sjkim		flags |= TOLOG;
179233237Sjkim	if (p != NULL) {
180233237Sjkim		PROC_LOCK(p);
181233237Sjkim		if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
182233237Sjkim			sess = p->p_session;
183233237Sjkim			SESS_LOCK(sess);
184233237Sjkim			PROC_UNLOCK(p);
185233237Sjkim			SESSHOLD(sess);
186233237Sjkim			tp = sess->s_ttyp;
187233237Sjkim			SESS_UNLOCK(sess);
188233237Sjkim			if (ttycheckoutq(tp, 0))
189233237Sjkim				flags |= TOTTY;
190233237Sjkim			else
191233237Sjkim				tp = NULL;
192233237Sjkim		} else
193233237Sjkim			PROC_UNLOCK(p);
194233237Sjkim	}
195233237Sjkim	pca.pri = pri;
196233237Sjkim	pca.tty = tp;
197233237Sjkim	pca.flags = flags;
198233237Sjkim	va_start(ap, fmt);
199233237Sjkim	kvprintf(fmt, putchar, &pca, 10, ap);
200233237Sjkim	va_end(ap);
201233237Sjkim	if (sess != NULL)
202233237Sjkim		SESSRELE(sess);
203233237Sjkim	msgbuftrigger = 1;
204233237Sjkim	mtx_unlock(&Giant);
205233237Sjkim}
206233237Sjkim
207233237Sjkim/*
208233237Sjkim * Ttyprintf displays a message on a tty; it should be used only by
209233237Sjkim * the tty driver, or anything that knows the underlying tty will not
210233237Sjkim * be revoke(2)'d away.  Other callers should use tprintf.
211233237Sjkim */
212233237Sjkimint
213233237Sjkimttyprintf(struct tty *tp, const char *fmt, ...)
214233237Sjkim{
215233237Sjkim	va_list ap;
216233237Sjkim	struct putchar_arg pca;
217233237Sjkim	int retval;
218233237Sjkim
219233237Sjkim	va_start(ap, fmt);
220233237Sjkim	pca.tty = tp;
221233237Sjkim	pca.flags = TOTTY;
222233237Sjkim	retval = kvprintf(fmt, putchar, &pca, 10, ap);
223233237Sjkim	va_end(ap);
224233237Sjkim	return (retval);
225233237Sjkim}
226233237Sjkim
227233237Sjkim/*
228233237Sjkim * Log writes to the log buffer, and guarantees not to sleep (so can be
229233237Sjkim * called by interrupt routines).  If there is no process reading the
230233237Sjkim * log yet, it writes to the console also.
231233237Sjkim */
232233237Sjkimvoid
233233237Sjkimlog(int level, const char *fmt, ...)
234233237Sjkim{
235233237Sjkim	va_list ap;
236233237Sjkim	struct putchar_arg pca;
237233237Sjkim
238233237Sjkim	pca.tty = NULL;
239233237Sjkim	pca.pri = level;
240233237Sjkim	pca.flags = log_open ? TOLOG : TOCONS;
241233237Sjkim	pca.p_bufr = NULL;
242233237Sjkim
243233237Sjkim	va_start(ap, fmt);
244233237Sjkim	kvprintf(fmt, putchar, &pca, 10, ap);
245233237Sjkim	va_end(ap);
246233237Sjkim
247233237Sjkim	msgbuftrigger = 1;
248233237Sjkim}
249233237Sjkim
250233237Sjkim#define CONSCHUNK 128
251233237Sjkim
252233237Sjkimvoid
253233237Sjkimlog_console(struct uio *uio)
254233237Sjkim{
255233237Sjkim	int c, i, error, nl;
256233237Sjkim	char *consbuffer;
257233237Sjkim	int pri;
258233237Sjkim
259233237Sjkim	if (!log_console_output)
260233237Sjkim		return;
261233237Sjkim
262233237Sjkim	pri = LOG_INFO | LOG_CONSOLE;
263233237Sjkim	uio = cloneuio(uio);
264233237Sjkim	consbuffer = malloc(CONSCHUNK, M_TEMP, M_WAITOK);
265233237Sjkim
266233237Sjkim	nl = 0;
267233237Sjkim	while (uio->uio_resid > 0) {
268233237Sjkim		c = imin(uio->uio_resid, CONSCHUNK);
269233237Sjkim		error = uiomove(consbuffer, c, uio);
270233237Sjkim		if (error != 0)
271233237Sjkim			break;
272233237Sjkim		for (i = 0; i < c; i++) {
273233237Sjkim			msglogchar(consbuffer[i], pri);
274233237Sjkim			if (consbuffer[i] == '\n')
275233237Sjkim				nl = 1;
276233237Sjkim			else
277233237Sjkim				nl = 0;
278233237Sjkim		}
279233237Sjkim	}
280233237Sjkim	if (!nl)
281233237Sjkim		msglogchar('\n', pri);
282233237Sjkim	msgbuftrigger = 1;
283233237Sjkim	free(uio, M_IOV);
284233237Sjkim	free(consbuffer, M_TEMP);
285	return;
286}
287
288int
289printf(const char *fmt, ...)
290{
291	va_list ap;
292	struct putchar_arg pca;
293	int retval;
294
295	critical_enter();
296
297	va_start(ap, fmt);
298	pca.tty = NULL;
299	pca.flags = TOCONS | TOLOG;
300	pca.pri = -1;
301	pca.p_bufr = (char *) PCPU_PTR(cons_bufr);
302	pca.p_next = pca.p_bufr;
303	pca.n_bufr = PCPU_CONS_BUFR;
304	pca.remain = PCPU_CONS_BUFR;
305	*pca.p_next = '\0';
306
307	retval = kvprintf(fmt, putchar, &pca, 10, ap);
308	va_end(ap);
309
310	/* Write any buffered console output: */
311	if (*pca.p_bufr != '\0')
312		cnputs(pca.p_bufr);
313
314	if (!panicstr)
315		msgbuftrigger = 1;
316
317	critical_exit();
318
319	return (retval);
320}
321
322int
323vprintf(const char *fmt, va_list ap)
324{
325	struct putchar_arg pca;
326	int retval;
327
328	critical_enter();
329
330	pca.tty = NULL;
331	pca.flags = TOCONS | TOLOG;
332	pca.pri = -1;
333	pca.p_bufr = (char *) PCPU_PTR(cons_bufr);
334	pca.p_next = pca.p_bufr;
335	pca.n_bufr = PCPU_CONS_BUFR;
336	pca.remain = PCPU_CONS_BUFR;
337	*pca.p_next = '\0';
338
339	retval = kvprintf(fmt, putchar, &pca, 10, ap);
340
341	/* Write any buffered console output: */
342	if (*pca.p_bufr != '\0')
343		cnputs(pca.p_bufr);
344
345	if (!panicstr)
346		msgbuftrigger = 1;
347
348	critical_exit();
349
350	return (retval);
351}
352
353static void
354putcons(int c, struct putchar_arg *ap)
355{
356	/* Check if no console output buffer was provided. */
357	if (ap->p_bufr == NULL)
358		/* Output direct to the console. */
359		cnputc(c);
360	else {
361		/* Buffer the character: */
362		if (c == '\n') {
363			*ap->p_next++ = '\r';
364			ap->remain--;
365		}
366		*ap->p_next++ = c;
367		ap->remain--;
368
369		/* Always leave the buffer zero terminated. */
370		*ap->p_next = '\0';
371
372		/* Check if the buffer needs to be flushed. */
373		if (ap->remain < 3 || c == '\n') {
374			cnputs(ap->p_bufr);
375			ap->p_next = ap->p_bufr;
376			ap->remain = ap->n_bufr;
377			*ap->p_next = '\0';
378		}
379	}
380}
381
382/*
383 * Print a character on console or users terminal.  If destination is
384 * the console then the last bunch of characters are saved in msgbuf for
385 * inspection later.
386 */
387static void
388putchar(int c, void *arg)
389{
390	struct putchar_arg *ap = (struct putchar_arg*) arg;
391	struct tty *tp = ap->tty;
392	int flags = ap->flags;
393
394	/* Don't use the tty code after a panic or while in ddb. */
395	if (kdb_active) {
396		if (c != '\0')
397			cnputc(c);
398	} else if (panicstr || ((flags & TOCONS) && constty == NULL)) {
399		if (c != '\0')
400			putcons(c, ap);
401	} else {
402		if ((flags & TOTTY) && tp != NULL)
403			tputchar(c, tp);
404		if (flags & TOCONS) {
405			if (constty != NULL)
406				msgbuf_addchar(&consmsgbuf, c);
407			if (always_console_output && c != '\0')
408				putcons(c, ap);
409		}
410	}
411	if ((flags & TOLOG))
412		msglogchar(c, ap->pri);
413}
414
415/*
416 * Scaled down version of sprintf(3).
417 */
418int
419sprintf(char *buf, const char *cfmt, ...)
420{
421	int retval;
422	va_list ap;
423
424	va_start(ap, cfmt);
425	retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
426	buf[retval] = '\0';
427	va_end(ap);
428	return (retval);
429}
430
431/*
432 * Scaled down version of vsprintf(3).
433 */
434int
435vsprintf(char *buf, const char *cfmt, va_list ap)
436{
437	int retval;
438
439	retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
440	buf[retval] = '\0';
441	return (retval);
442}
443
444/*
445 * Scaled down version of snprintf(3).
446 */
447int
448snprintf(char *str, size_t size, const char *format, ...)
449{
450	int retval;
451	va_list ap;
452
453	va_start(ap, format);
454	retval = vsnprintf(str, size, format, ap);
455	va_end(ap);
456	return(retval);
457}
458
459/*
460 * Scaled down version of vsnprintf(3).
461 */
462int
463vsnprintf(char *str, size_t size, const char *format, va_list ap)
464{
465	struct snprintf_arg info;
466	int retval;
467
468	info.str = str;
469	info.remain = size;
470	retval = kvprintf(format, snprintf_func, &info, 10, ap);
471	if (info.remain >= 1)
472		*info.str++ = '\0';
473	return (retval);
474}
475
476/*
477 * Kernel version which takes radix argument vsnprintf(3).
478 */
479int
480vsnrprintf(char *str, size_t size, int radix, const char *format, va_list ap)
481{
482	struct snprintf_arg info;
483	int retval;
484
485	info.str = str;
486	info.remain = size;
487	retval = kvprintf(format, snprintf_func, &info, radix, ap);
488	if (info.remain >= 1)
489		*info.str++ = '\0';
490	return (retval);
491}
492
493static void
494snprintf_func(int ch, void *arg)
495{
496	struct snprintf_arg *const info = arg;
497
498	if (info->remain >= 2) {
499		*info->str++ = ch;
500		info->remain--;
501	}
502}
503
504/*
505 * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
506 * order; return an optional length and a pointer to the last character
507 * written in the buffer (i.e., the first character of the string).
508 * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
509 */
510static char *
511ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
512{
513	char *p, c;
514
515	p = nbuf;
516	*p = '\0';
517	do {
518		c = hex2ascii(num % base);
519		*++p = upper ? toupper(c) : c;
520	} while (num /= base);
521	if (lenp)
522		*lenp = p - nbuf;
523	return (p);
524}
525
526/*
527 * Scaled down version of printf(3).
528 *
529 * Two additional formats:
530 *
531 * The format %b is supported to decode error registers.
532 * Its usage is:
533 *
534 *	printf("reg=%b\n", regval, "<base><arg>*");
535 *
536 * where <base> is the output base expressed as a control character, e.g.
537 * \10 gives octal; \20 gives hex.  Each arg is a sequence of characters,
538 * the first of which gives the bit number to be inspected (origin 1), and
539 * the next characters (up to a control character, i.e. a character <= 32),
540 * give the name of the register.  Thus:
541 *
542 *	kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
543 *
544 * would produce output:
545 *
546 *	reg=3<BITTWO,BITONE>
547 *
548 * XXX:  %D  -- Hexdump, takes pointer and separator string:
549 *		("%6D", ptr, ":")   -> XX:XX:XX:XX:XX:XX
550 *		("%*D", len, ptr, " " -> XX XX XX XX ...
551 */
552int
553kvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap)
554{
555#define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; }
556	char nbuf[MAXNBUF];
557	char *d;
558	const char *p, *percent, *q;
559	u_char *up;
560	int ch, n;
561	uintmax_t num;
562	int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
563	int cflag, hflag, jflag, tflag, zflag;
564	int dwidth, upper;
565	char padc;
566	int stop = 0, retval = 0;
567
568	num = 0;
569	if (!func)
570		d = (char *) arg;
571	else
572		d = NULL;
573
574	if (fmt == NULL)
575		fmt = "(fmt null)\n";
576
577	if (radix < 2 || radix > 36)
578		radix = 10;
579
580	for (;;) {
581		padc = ' ';
582		width = 0;
583		while ((ch = (u_char)*fmt++) != '%' || stop) {
584			if (ch == '\0')
585				return (retval);
586			PCHAR(ch);
587		}
588		percent = fmt - 1;
589		qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
590		sign = 0; dot = 0; dwidth = 0; upper = 0;
591		cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
592reswitch:	switch (ch = (u_char)*fmt++) {
593		case '.':
594			dot = 1;
595			goto reswitch;
596		case '#':
597			sharpflag = 1;
598			goto reswitch;
599		case '+':
600			sign = 1;
601			goto reswitch;
602		case '-':
603			ladjust = 1;
604			goto reswitch;
605		case '%':
606			PCHAR(ch);
607			break;
608		case '*':
609			if (!dot) {
610				width = va_arg(ap, int);
611				if (width < 0) {
612					ladjust = !ladjust;
613					width = -width;
614				}
615			} else {
616				dwidth = va_arg(ap, int);
617			}
618			goto reswitch;
619		case '0':
620			if (!dot) {
621				padc = '0';
622				goto reswitch;
623			}
624		case '1': case '2': case '3': case '4':
625		case '5': case '6': case '7': case '8': case '9':
626				for (n = 0;; ++fmt) {
627					n = n * 10 + ch - '0';
628					ch = *fmt;
629					if (ch < '0' || ch > '9')
630						break;
631				}
632			if (dot)
633				dwidth = n;
634			else
635				width = n;
636			goto reswitch;
637		case 'b':
638			num = (u_int)va_arg(ap, int);
639			p = va_arg(ap, char *);
640			for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;)
641				PCHAR(*q--);
642
643			if (num == 0)
644				break;
645
646			for (tmp = 0; *p;) {
647				n = *p++;
648				if (num & (1 << (n - 1))) {
649					PCHAR(tmp ? ',' : '<');
650					for (; (n = *p) > ' '; ++p)
651						PCHAR(n);
652					tmp = 1;
653				} else
654					for (; *p > ' '; ++p)
655						continue;
656			}
657			if (tmp)
658				PCHAR('>');
659			break;
660		case 'c':
661			PCHAR(va_arg(ap, int));
662			break;
663		case 'D':
664			up = va_arg(ap, u_char *);
665			p = va_arg(ap, char *);
666			if (!width)
667				width = 16;
668			while(width--) {
669				PCHAR(hex2ascii(*up >> 4));
670				PCHAR(hex2ascii(*up & 0x0f));
671				up++;
672				if (width)
673					for (q=p;*q;q++)
674						PCHAR(*q);
675			}
676			break;
677		case 'd':
678		case 'i':
679			base = 10;
680			sign = 1;
681			goto handle_sign;
682		case 'h':
683			if (hflag) {
684				hflag = 0;
685				cflag = 1;
686			} else
687				hflag = 1;
688			goto reswitch;
689		case 'j':
690			jflag = 1;
691			goto reswitch;
692		case 'l':
693			if (lflag) {
694				lflag = 0;
695				qflag = 1;
696			} else
697				lflag = 1;
698			goto reswitch;
699		case 'n':
700			if (jflag)
701				*(va_arg(ap, intmax_t *)) = retval;
702			else if (qflag)
703				*(va_arg(ap, quad_t *)) = retval;
704			else if (lflag)
705				*(va_arg(ap, long *)) = retval;
706			else if (zflag)
707				*(va_arg(ap, size_t *)) = retval;
708			else if (hflag)
709				*(va_arg(ap, short *)) = retval;
710			else if (cflag)
711				*(va_arg(ap, char *)) = retval;
712			else
713				*(va_arg(ap, int *)) = retval;
714			break;
715		case 'o':
716			base = 8;
717			goto handle_nosign;
718		case 'p':
719			base = 16;
720			sharpflag = (width == 0);
721			sign = 0;
722			num = (uintptr_t)va_arg(ap, void *);
723			goto number;
724		case 'q':
725			qflag = 1;
726			goto reswitch;
727		case 'r':
728			base = radix;
729			if (sign)
730				goto handle_sign;
731			goto handle_nosign;
732		case 's':
733			p = va_arg(ap, char *);
734			if (p == NULL)
735				p = "(null)";
736			if (!dot)
737				n = strlen (p);
738			else
739				for (n = 0; n < dwidth && p[n]; n++)
740					continue;
741
742			width -= n;
743
744			if (!ladjust && width > 0)
745				while (width--)
746					PCHAR(padc);
747			while (n--)
748				PCHAR(*p++);
749			if (ladjust && width > 0)
750				while (width--)
751					PCHAR(padc);
752			break;
753		case 't':
754			tflag = 1;
755			goto reswitch;
756		case 'u':
757			base = 10;
758			goto handle_nosign;
759		case 'X':
760			upper = 1;
761		case 'x':
762			base = 16;
763			goto handle_nosign;
764		case 'y':
765			base = 16;
766			sign = 1;
767			goto handle_sign;
768		case 'z':
769			zflag = 1;
770			goto reswitch;
771handle_nosign:
772			sign = 0;
773			if (jflag)
774				num = va_arg(ap, uintmax_t);
775			else if (qflag)
776				num = va_arg(ap, u_quad_t);
777			else if (tflag)
778				num = va_arg(ap, ptrdiff_t);
779			else if (lflag)
780				num = va_arg(ap, u_long);
781			else if (zflag)
782				num = va_arg(ap, size_t);
783			else if (hflag)
784				num = (u_short)va_arg(ap, int);
785			else if (cflag)
786				num = (u_char)va_arg(ap, int);
787			else
788				num = va_arg(ap, u_int);
789			goto number;
790handle_sign:
791			if (jflag)
792				num = va_arg(ap, intmax_t);
793			else if (qflag)
794				num = va_arg(ap, quad_t);
795			else if (tflag)
796				num = va_arg(ap, ptrdiff_t);
797			else if (lflag)
798				num = va_arg(ap, long);
799			else if (zflag)
800				num = va_arg(ap, size_t);
801			else if (hflag)
802				num = (short)va_arg(ap, int);
803			else if (cflag)
804				num = (char)va_arg(ap, int);
805			else
806				num = va_arg(ap, int);
807number:
808			if (sign && (intmax_t)num < 0) {
809				neg = 1;
810				num = -(intmax_t)num;
811			}
812			p = ksprintn(nbuf, num, base, &tmp, upper);
813			if (sharpflag && num != 0) {
814				if (base == 8)
815					tmp++;
816				else if (base == 16)
817					tmp += 2;
818			}
819			if (neg)
820				tmp++;
821
822			if (!ladjust && padc != '0' && width
823			    && (width -= tmp) > 0)
824				while (width--)
825					PCHAR(padc);
826			if (neg)
827				PCHAR('-');
828			if (sharpflag && num != 0) {
829				if (base == 8) {
830					PCHAR('0');
831				} else if (base == 16) {
832					PCHAR('0');
833					PCHAR('x');
834				}
835			}
836			if (!ladjust && width && (width -= tmp) > 0)
837				while (width--)
838					PCHAR(padc);
839
840			while (*p)
841				PCHAR(*p--);
842
843			if (ladjust && width && (width -= tmp) > 0)
844				while (width--)
845					PCHAR(padc);
846
847			break;
848		default:
849			while (percent < fmt)
850				PCHAR(*percent++);
851			/*
852			 * Since we ignore an formatting argument it is no
853			 * longer safe to obey the remaining formatting
854			 * arguments as the arguments will no longer match
855			 * the format specs.
856			 */
857			stop = 1;
858			break;
859		}
860	}
861#undef PCHAR
862}
863
864/*
865 * Put character in log buffer with a particular priority.
866 */
867static void
868msglogchar(int c, int pri)
869{
870	static int lastpri = -1;
871	static int dangling;
872	char nbuf[MAXNBUF];
873	char *p;
874
875	if (!msgbufmapped)
876		return;
877	if (c == '\0' || c == '\r')
878		return;
879	if (pri != -1 && pri != lastpri) {
880		if (dangling) {
881			msgbuf_addchar(msgbufp, '\n');
882			dangling = 0;
883		}
884		msgbuf_addchar(msgbufp, '<');
885		for (p = ksprintn(nbuf, (uintmax_t)pri, 10, NULL, 0); *p;)
886			msgbuf_addchar(msgbufp, *p--);
887		msgbuf_addchar(msgbufp, '>');
888		lastpri = pri;
889	}
890	msgbuf_addchar(msgbufp, c);
891	if (c == '\n') {
892		dangling = 0;
893		lastpri = -1;
894	} else {
895		dangling = 1;
896	}
897}
898
899void
900msgbufinit(void *ptr, int size)
901{
902	char *cp;
903	static struct msgbuf *oldp = NULL;
904
905	size -= sizeof(*msgbufp);
906	cp = (char *)ptr;
907	msgbufp = (struct msgbuf *)(cp + size);
908	msgbuf_reinit(msgbufp, cp, size);
909	if (msgbufmapped && oldp != msgbufp)
910		msgbuf_copy(oldp, msgbufp);
911	msgbufmapped = 1;
912	oldp = msgbufp;
913}
914
915static int unprivileged_read_msgbuf = 1;
916SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_read_msgbuf,
917    CTLFLAG_RW, &unprivileged_read_msgbuf, 0,
918    "Unprivileged processes may read the kernel message buffer");
919
920/* Sysctls for accessing/clearing the msgbuf */
921static int
922sysctl_kern_msgbuf(SYSCTL_HANDLER_ARGS)
923{
924	char buf[128];
925	u_int seq;
926	int error, len;
927
928	if (!unprivileged_read_msgbuf) {
929		error = priv_check(req->td, PRIV_MSGBUF);
930		if (error)
931			return (error);
932	}
933
934	/* Read the whole buffer, one chunk at a time. */
935	msgbuf_peekbytes(msgbufp, NULL, 0, &seq);
936	while ((len = msgbuf_peekbytes(msgbufp, buf, sizeof(buf), &seq)) > 0) {
937		error = sysctl_handle_opaque(oidp, buf, len, req);
938		if (error)
939			return (error);
940	}
941	return (0);
942}
943
944SYSCTL_PROC(_kern, OID_AUTO, msgbuf, CTLTYPE_STRING | CTLFLAG_RD,
945    0, 0, sysctl_kern_msgbuf, "A", "Contents of kernel message buffer");
946
947static int msgbuf_clearflag;
948
949static int
950sysctl_kern_msgbuf_clear(SYSCTL_HANDLER_ARGS)
951{
952	int error;
953	error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
954	if (!error && req->newptr) {
955		msgbuf_clear(msgbufp);
956		msgbuf_clearflag = 0;
957	}
958	return (error);
959}
960
961SYSCTL_PROC(_kern, OID_AUTO, msgbuf_clear,
962    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE, &msgbuf_clearflag, 0,
963    sysctl_kern_msgbuf_clear, "I", "Clear kernel message buffer");
964
965#ifdef DDB
966
967DB_SHOW_COMMAND(msgbuf, db_show_msgbuf)
968{
969	int i, j;
970
971	if (!msgbufmapped) {
972		db_printf("msgbuf not mapped yet\n");
973		return;
974	}
975	db_printf("msgbufp = %p\n", msgbufp);
976	db_printf("magic = %x, size = %d, r= %u, w = %u, ptr = %p, cksum= %u\n",
977	    msgbufp->msg_magic, msgbufp->msg_size, msgbufp->msg_rseq,
978	    msgbufp->msg_wseq, msgbufp->msg_ptr, msgbufp->msg_cksum);
979	for (i = 0; i < msgbufp->msg_size && !db_pager_quit; i++) {
980		j = MSGBUF_SEQ_TO_POS(msgbufp, i + msgbufp->msg_rseq);
981		db_printf("%c", msgbufp->msg_ptr[j]);
982	}
983	db_printf("\n");
984}
985
986#endif /* DDB */
987
988void
989hexdump(const void *ptr, int length, const char *hdr, int flags)
990{
991	int i, j, k;
992	int cols;
993	const unsigned char *cp;
994	char delim;
995
996	if ((flags & HD_DELIM_MASK) != 0)
997		delim = (flags & HD_DELIM_MASK) >> 8;
998	else
999		delim = ' ';
1000
1001	if ((flags & HD_COLUMN_MASK) != 0)
1002		cols = flags & HD_COLUMN_MASK;
1003	else
1004		cols = 16;
1005
1006	cp = ptr;
1007	for (i = 0; i < length; i+= cols) {
1008		if (hdr != NULL)
1009			printf("%s", hdr);
1010
1011		if ((flags & HD_OMIT_COUNT) == 0)
1012			printf("%04x  ", i);
1013
1014		if ((flags & HD_OMIT_HEX) == 0) {
1015			for (j = 0; j < cols; j++) {
1016				k = i + j;
1017				if (k < length)
1018					printf("%c%02x", delim, cp[k]);
1019				else
1020					printf("   ");
1021			}
1022		}
1023
1024		if ((flags & HD_OMIT_CHARS) == 0) {
1025			printf("  |");
1026			for (j = 0; j < cols; j++) {
1027				k = i + j;
1028				if (k >= length)
1029					printf(" ");
1030				else if (cp[k] >= ' ' && cp[k] <= '~')
1031					printf("%c", cp[k]);
1032				else
1033					printf(".");
1034			}
1035			printf("|");
1036		}
1037		printf("\n");
1038	}
1039}
1040
1041