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