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: stable/11/sys/kern/subr_prf.c 339446 2018-10-20 16:20:36Z jamie $");
39
40#ifdef _KERNEL
41#include "opt_ddb.h"
42#include "opt_printf.h"
43#endif  /* _KERNEL */
44
45#include <sys/param.h>
46#ifdef _KERNEL
47#include <sys/systm.h>
48#include <sys/lock.h>
49#include <sys/kdb.h>
50#include <sys/mutex.h>
51#include <sys/sx.h>
52#include <sys/kernel.h>
53#include <sys/msgbuf.h>
54#include <sys/malloc.h>
55#include <sys/priv.h>
56#include <sys/proc.h>
57#include <sys/stddef.h>
58#include <sys/sysctl.h>
59#include <sys/tty.h>
60#include <sys/syslog.h>
61#include <sys/cons.h>
62#include <sys/uio.h>
63#endif
64#include <sys/ctype.h>
65#include <sys/sbuf.h>
66
67#ifdef DDB
68#include <ddb/ddb.h>
69#endif
70
71/*
72 * Note that stdarg.h and the ANSI style va_start macro is used for both
73 * ANSI and traditional C compilers.
74 */
75#ifdef _KERNEL
76#include <machine/stdarg.h>
77#else
78#include <stdarg.h>
79#endif
80
81/*
82 * This is needed for sbuf_putbuf() when compiled into userland.  Due to the
83 * shared nature of this file, it's the only place to put it.
84 */
85#ifndef _KERNEL
86#include <stdio.h>
87#endif
88
89#ifdef _KERNEL
90
91#define TOCONS	0x01
92#define TOTTY	0x02
93#define TOLOG	0x04
94
95/* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */
96#define MAXNBUF	(sizeof(intmax_t) * NBBY + 1)
97
98struct putchar_arg {
99	int	flags;
100	int	pri;
101	struct	tty *tty;
102	char	*p_bufr;
103	size_t	n_bufr;
104	char	*p_next;
105	size_t	remain;
106};
107
108struct snprintf_arg {
109	char	*str;
110	size_t	remain;
111};
112
113extern	int log_open;
114
115static void  msglogchar(int c, int pri);
116static void  msglogstr(char *str, int pri, int filter_cr);
117static void  putchar(int ch, void *arg);
118static char *ksprintn(char *nbuf, uintmax_t num, int base, int *len, int upper);
119static void  snprintf_func(int ch, void *arg);
120
121static bool msgbufmapped;		/* Set when safe to use msgbuf */
122int msgbuftrigger;
123
124#ifndef BOOT_TAG_SZ
125#define	BOOT_TAG_SZ	32
126#endif
127#ifndef BOOT_TAG
128/* Tag used to mark the start of a boot in dmesg */
129#define	BOOT_TAG	""
130#endif
131
132static char current_boot_tag[BOOT_TAG_SZ + 1] = BOOT_TAG;
133SYSCTL_STRING(_kern, OID_AUTO, boot_tag, CTLFLAG_RDTUN | CTLFLAG_NOFETCH,
134    current_boot_tag, 0, "Tag added to dmesg at start of boot");
135
136static int log_console_output = 1;
137SYSCTL_INT(_kern, OID_AUTO, log_console_output, CTLFLAG_RWTUN,
138    &log_console_output, 0, "Duplicate console output to the syslog");
139
140/*
141 * See the comment in log_console() below for more explanation of this.
142 */
143static int log_console_add_linefeed;
144SYSCTL_INT(_kern, OID_AUTO, log_console_add_linefeed, CTLFLAG_RWTUN,
145    &log_console_add_linefeed, 0, "log_console() adds extra newlines");
146
147static int always_console_output;
148SYSCTL_INT(_kern, OID_AUTO, always_console_output, CTLFLAG_RWTUN,
149    &always_console_output, 0, "Always output to console despite TIOCCONS");
150
151/*
152 * Warn that a system table is full.
153 */
154void
155tablefull(const char *tab)
156{
157
158	log(LOG_ERR, "%s: table is full\n", tab);
159}
160
161/*
162 * Uprintf prints to the controlling terminal for the current process.
163 */
164int
165uprintf(const char *fmt, ...)
166{
167	va_list ap;
168	struct putchar_arg pca;
169	struct proc *p;
170	struct thread *td;
171	int retval;
172
173	td = curthread;
174	if (TD_IS_IDLETHREAD(td))
175		return (0);
176
177	sx_slock(&proctree_lock);
178	p = td->td_proc;
179	PROC_LOCK(p);
180	if ((p->p_flag & P_CONTROLT) == 0) {
181		PROC_UNLOCK(p);
182		sx_sunlock(&proctree_lock);
183		return (0);
184	}
185	SESS_LOCK(p->p_session);
186	pca.tty = p->p_session->s_ttyp;
187	SESS_UNLOCK(p->p_session);
188	PROC_UNLOCK(p);
189	if (pca.tty == NULL) {
190		sx_sunlock(&proctree_lock);
191		return (0);
192	}
193	pca.flags = TOTTY;
194	pca.p_bufr = NULL;
195	va_start(ap, fmt);
196	tty_lock(pca.tty);
197	sx_sunlock(&proctree_lock);
198	retval = kvprintf(fmt, putchar, &pca, 10, ap);
199	tty_unlock(pca.tty);
200	va_end(ap);
201	return (retval);
202}
203
204/*
205 * tprintf and vtprintf print on the controlling terminal associated with the
206 * given session, possibly to the log as well.
207 */
208void
209tprintf(struct proc *p, int pri, const char *fmt, ...)
210{
211	va_list ap;
212
213	va_start(ap, fmt);
214	vtprintf(p, pri, fmt, ap);
215	va_end(ap);
216}
217
218void
219vtprintf(struct proc *p, int pri, const char *fmt, va_list ap)
220{
221	struct tty *tp = NULL;
222	int flags = 0;
223	struct putchar_arg pca;
224	struct session *sess = NULL;
225
226	sx_slock(&proctree_lock);
227	if (pri != -1)
228		flags |= TOLOG;
229	if (p != NULL) {
230		PROC_LOCK(p);
231		if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
232			sess = p->p_session;
233			sess_hold(sess);
234			PROC_UNLOCK(p);
235			tp = sess->s_ttyp;
236			if (tp != NULL && tty_checkoutq(tp))
237				flags |= TOTTY;
238			else
239				tp = NULL;
240		} else
241			PROC_UNLOCK(p);
242	}
243	pca.pri = pri;
244	pca.tty = tp;
245	pca.flags = flags;
246	pca.p_bufr = NULL;
247	if (pca.tty != NULL)
248		tty_lock(pca.tty);
249	sx_sunlock(&proctree_lock);
250	kvprintf(fmt, putchar, &pca, 10, ap);
251	if (pca.tty != NULL)
252		tty_unlock(pca.tty);
253	if (sess != NULL)
254		sess_release(sess);
255	msgbuftrigger = 1;
256}
257
258/*
259 * Ttyprintf displays a message on a tty; it should be used only by
260 * the tty driver, or anything that knows the underlying tty will not
261 * be revoke(2)'d away.  Other callers should use tprintf.
262 */
263int
264ttyprintf(struct tty *tp, const char *fmt, ...)
265{
266	va_list ap;
267	struct putchar_arg pca;
268	int retval;
269
270	va_start(ap, fmt);
271	pca.tty = tp;
272	pca.flags = TOTTY;
273	pca.p_bufr = NULL;
274	retval = kvprintf(fmt, putchar, &pca, 10, ap);
275	va_end(ap);
276	return (retval);
277}
278
279static int
280_vprintf(int level, int flags, const char *fmt, va_list ap)
281{
282	struct putchar_arg pca;
283	int retval;
284#ifdef PRINTF_BUFR_SIZE
285	char bufr[PRINTF_BUFR_SIZE];
286#endif
287
288	pca.tty = NULL;
289	pca.pri = level;
290	pca.flags = flags;
291#ifdef PRINTF_BUFR_SIZE
292	pca.p_bufr = bufr;
293	pca.p_next = pca.p_bufr;
294	pca.n_bufr = sizeof(bufr);
295	pca.remain = sizeof(bufr);
296	*pca.p_next = '\0';
297#else
298	/* Don't buffer console output. */
299	pca.p_bufr = NULL;
300#endif
301
302	retval = kvprintf(fmt, putchar, &pca, 10, ap);
303
304#ifdef PRINTF_BUFR_SIZE
305	/* Write any buffered console/log output: */
306	if (*pca.p_bufr != '\0') {
307		if (pca.flags & TOLOG)
308			msglogstr(pca.p_bufr, level, /*filter_cr*/1);
309
310		if (pca.flags & TOCONS)
311			cnputs(pca.p_bufr);
312	}
313#endif
314
315	return (retval);
316}
317
318/*
319 * Log writes to the log buffer, and guarantees not to sleep (so can be
320 * called by interrupt routines).  If there is no process reading the
321 * log yet, it writes to the console also.
322 */
323void
324log(int level, const char *fmt, ...)
325{
326	va_list ap;
327
328	va_start(ap, fmt);
329	vlog(level, fmt, ap);
330	va_end(ap);
331}
332
333void
334vlog(int level, const char *fmt, va_list ap)
335{
336
337	(void)_vprintf(level, log_open ? TOLOG : TOCONS | TOLOG, fmt, ap);
338	msgbuftrigger = 1;
339}
340
341#define CONSCHUNK 128
342
343void
344log_console(struct uio *uio)
345{
346	int c, error, nl;
347	char *consbuffer;
348	int pri;
349
350	if (!log_console_output)
351		return;
352
353	pri = LOG_INFO | LOG_CONSOLE;
354	uio = cloneuio(uio);
355	consbuffer = malloc(CONSCHUNK, M_TEMP, M_WAITOK);
356
357	nl = 0;
358	while (uio->uio_resid > 0) {
359		c = imin(uio->uio_resid, CONSCHUNK - 1);
360		error = uiomove(consbuffer, c, uio);
361		if (error != 0)
362			break;
363		/* Make sure we're NUL-terminated */
364		consbuffer[c] = '\0';
365		if (consbuffer[c - 1] == '\n')
366			nl = 1;
367		else
368			nl = 0;
369		msglogstr(consbuffer, pri, /*filter_cr*/ 1);
370	}
371	/*
372	 * The previous behavior in log_console() is preserved when
373	 * log_console_add_linefeed is non-zero.  For that behavior, if an
374	 * individual console write came in that was not terminated with a
375	 * line feed, it would add a line feed.
376	 *
377	 * This results in different data in the message buffer than
378	 * appears on the system console (which doesn't add extra line feed
379	 * characters).
380	 *
381	 * A number of programs and rc scripts write a line feed, or a period
382	 * and a line feed when they have completed their operation.  On
383	 * the console, this looks seamless, but when displayed with
384	 * 'dmesg -a', you wind up with output that looks like this:
385	 *
386	 * Updating motd:
387	 * .
388	 *
389	 * On the console, it looks like this:
390	 * Updating motd:.
391	 *
392	 * We could add logic to detect that situation, or just not insert
393	 * the extra newlines.  Set the kern.log_console_add_linefeed
394	 * sysctl/tunable variable to get the old behavior.
395	 */
396	if (!nl && log_console_add_linefeed) {
397		consbuffer[0] = '\n';
398		consbuffer[1] = '\0';
399		msglogstr(consbuffer, pri, /*filter_cr*/ 1);
400	}
401	msgbuftrigger = 1;
402	free(uio, M_IOV);
403	free(consbuffer, M_TEMP);
404}
405
406int
407printf(const char *fmt, ...)
408{
409	va_list ap;
410	int retval;
411
412	va_start(ap, fmt);
413	retval = vprintf(fmt, ap);
414	va_end(ap);
415
416	return (retval);
417}
418
419int
420vprintf(const char *fmt, va_list ap)
421{
422	int retval;
423
424	retval = _vprintf(-1, TOCONS | TOLOG, fmt, ap);
425
426	if (!panicstr)
427		msgbuftrigger = 1;
428
429	return (retval);
430}
431
432static void
433prf_putbuf(char *bufr, int flags, int pri)
434{
435
436	if (flags & TOLOG)
437		msglogstr(bufr, pri, /*filter_cr*/1);
438
439	if (flags & TOCONS) {
440		if ((panicstr == NULL) && (constty != NULL))
441			msgbuf_addstr(&consmsgbuf, -1,
442			    bufr, /*filter_cr*/ 0);
443
444		if ((constty == NULL) ||(always_console_output))
445			cnputs(bufr);
446	}
447}
448
449static void
450putbuf(int c, struct putchar_arg *ap)
451{
452	/* Check if no console output buffer was provided. */
453	if (ap->p_bufr == NULL) {
454		/* Output direct to the console. */
455		if (ap->flags & TOCONS)
456			cnputc(c);
457
458		if (ap->flags & TOLOG)
459			msglogchar(c, ap->pri);
460	} else {
461		/* Buffer the character: */
462		*ap->p_next++ = c;
463		ap->remain--;
464
465		/* Always leave the buffer zero terminated. */
466		*ap->p_next = '\0';
467
468		/* Check if the buffer needs to be flushed. */
469		if (ap->remain == 2 || c == '\n') {
470			prf_putbuf(ap->p_bufr, ap->flags, ap->pri);
471
472			ap->p_next = ap->p_bufr;
473			ap->remain = ap->n_bufr;
474			*ap->p_next = '\0';
475		}
476
477		/*
478		 * Since we fill the buffer up one character at a time,
479		 * this should not happen.  We should always catch it when
480		 * ap->remain == 2 (if not sooner due to a newline), flush
481		 * the buffer and move on.  One way this could happen is
482		 * if someone sets PRINTF_BUFR_SIZE to 1 or something
483		 * similarly silly.
484		 */
485		KASSERT(ap->remain > 2, ("Bad buffer logic, remain = %zd",
486		    ap->remain));
487	}
488}
489
490/*
491 * Print a character on console or users terminal.  If destination is
492 * the console then the last bunch of characters are saved in msgbuf for
493 * inspection later.
494 */
495static void
496putchar(int c, void *arg)
497{
498	struct putchar_arg *ap = (struct putchar_arg*) arg;
499	struct tty *tp = ap->tty;
500	int flags = ap->flags;
501
502	/* Don't use the tty code after a panic or while in ddb. */
503	if (kdb_active) {
504		if (c != '\0')
505			cnputc(c);
506		return;
507	}
508
509	if ((flags & TOTTY) && tp != NULL && panicstr == NULL)
510		tty_putchar(tp, c);
511
512	if ((flags & (TOCONS | TOLOG)) && c != '\0')
513		putbuf(c, ap);
514}
515
516/*
517 * Scaled down version of sprintf(3).
518 */
519int
520sprintf(char *buf, const char *cfmt, ...)
521{
522	int retval;
523	va_list ap;
524
525	va_start(ap, cfmt);
526	retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
527	buf[retval] = '\0';
528	va_end(ap);
529	return (retval);
530}
531
532/*
533 * Scaled down version of vsprintf(3).
534 */
535int
536vsprintf(char *buf, const char *cfmt, va_list ap)
537{
538	int retval;
539
540	retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
541	buf[retval] = '\0';
542	return (retval);
543}
544
545/*
546 * Scaled down version of snprintf(3).
547 */
548int
549snprintf(char *str, size_t size, const char *format, ...)
550{
551	int retval;
552	va_list ap;
553
554	va_start(ap, format);
555	retval = vsnprintf(str, size, format, ap);
556	va_end(ap);
557	return(retval);
558}
559
560/*
561 * Scaled down version of vsnprintf(3).
562 */
563int
564vsnprintf(char *str, size_t size, const char *format, va_list ap)
565{
566	struct snprintf_arg info;
567	int retval;
568
569	info.str = str;
570	info.remain = size;
571	retval = kvprintf(format, snprintf_func, &info, 10, ap);
572	if (info.remain >= 1)
573		*info.str++ = '\0';
574	return (retval);
575}
576
577/*
578 * Kernel version which takes radix argument vsnprintf(3).
579 */
580int
581vsnrprintf(char *str, size_t size, int radix, const char *format, va_list ap)
582{
583	struct snprintf_arg info;
584	int retval;
585
586	info.str = str;
587	info.remain = size;
588	retval = kvprintf(format, snprintf_func, &info, radix, ap);
589	if (info.remain >= 1)
590		*info.str++ = '\0';
591	return (retval);
592}
593
594static void
595snprintf_func(int ch, void *arg)
596{
597	struct snprintf_arg *const info = arg;
598
599	if (info->remain >= 2) {
600		*info->str++ = ch;
601		info->remain--;
602	}
603}
604
605/*
606 * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
607 * order; return an optional length and a pointer to the last character
608 * written in the buffer (i.e., the first character of the string).
609 * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
610 */
611static char *
612ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
613{
614	char *p, c;
615
616	p = nbuf;
617	*p = '\0';
618	do {
619		c = hex2ascii(num % base);
620		*++p = upper ? toupper(c) : c;
621	} while (num /= base);
622	if (lenp)
623		*lenp = p - nbuf;
624	return (p);
625}
626
627/*
628 * Scaled down version of printf(3).
629 *
630 * Two additional formats:
631 *
632 * The format %b is supported to decode error registers.
633 * Its usage is:
634 *
635 *	printf("reg=%b\n", regval, "<base><arg>*");
636 *
637 * where <base> is the output base expressed as a control character, e.g.
638 * \10 gives octal; \20 gives hex.  Each arg is a sequence of characters,
639 * the first of which gives the bit number to be inspected (origin 1), and
640 * the next characters (up to a control character, i.e. a character <= 32),
641 * give the name of the register.  Thus:
642 *
643 *	kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE");
644 *
645 * would produce output:
646 *
647 *	reg=3<BITTWO,BITONE>
648 *
649 * XXX:  %D  -- Hexdump, takes pointer and separator string:
650 *		("%6D", ptr, ":")   -> XX:XX:XX:XX:XX:XX
651 *		("%*D", len, ptr, " " -> XX XX XX XX ...
652 */
653int
654kvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap)
655{
656#define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; }
657	char nbuf[MAXNBUF];
658	char *d;
659	const char *p, *percent, *q;
660	u_char *up;
661	int ch, n;
662	uintmax_t num;
663	int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
664	int cflag, hflag, jflag, tflag, zflag;
665	int dwidth, upper;
666	char padc;
667	int stop = 0, retval = 0;
668
669	num = 0;
670	if (!func)
671		d = (char *) arg;
672	else
673		d = NULL;
674
675	if (fmt == NULL)
676		fmt = "(fmt null)\n";
677
678	if (radix < 2 || radix > 36)
679		radix = 10;
680
681	for (;;) {
682		padc = ' ';
683		width = 0;
684		while ((ch = (u_char)*fmt++) != '%' || stop) {
685			if (ch == '\0')
686				return (retval);
687			PCHAR(ch);
688		}
689		percent = fmt - 1;
690		qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
691		sign = 0; dot = 0; dwidth = 0; upper = 0;
692		cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
693reswitch:	switch (ch = (u_char)*fmt++) {
694		case '.':
695			dot = 1;
696			goto reswitch;
697		case '#':
698			sharpflag = 1;
699			goto reswitch;
700		case '+':
701			sign = 1;
702			goto reswitch;
703		case '-':
704			ladjust = 1;
705			goto reswitch;
706		case '%':
707			PCHAR(ch);
708			break;
709		case '*':
710			if (!dot) {
711				width = va_arg(ap, int);
712				if (width < 0) {
713					ladjust = !ladjust;
714					width = -width;
715				}
716			} else {
717				dwidth = va_arg(ap, int);
718			}
719			goto reswitch;
720		case '0':
721			if (!dot) {
722				padc = '0';
723				goto reswitch;
724			}
725			/* FALLTHROUGH */
726		case '1': case '2': case '3': case '4':
727		case '5': case '6': case '7': case '8': case '9':
728				for (n = 0;; ++fmt) {
729					n = n * 10 + ch - '0';
730					ch = *fmt;
731					if (ch < '0' || ch > '9')
732						break;
733				}
734			if (dot)
735				dwidth = n;
736			else
737				width = n;
738			goto reswitch;
739		case 'b':
740			num = (u_int)va_arg(ap, int);
741			p = va_arg(ap, char *);
742			for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;)
743				PCHAR(*q--);
744
745			if (num == 0)
746				break;
747
748			for (tmp = 0; *p;) {
749				n = *p++;
750				if (num & (1 << (n - 1))) {
751					PCHAR(tmp ? ',' : '<');
752					for (; (n = *p) > ' '; ++p)
753						PCHAR(n);
754					tmp = 1;
755				} else
756					for (; *p > ' '; ++p)
757						continue;
758			}
759			if (tmp)
760				PCHAR('>');
761			break;
762		case 'c':
763			width -= 1;
764
765			if (!ladjust && width > 0)
766				while (width--)
767					PCHAR(padc);
768			PCHAR(va_arg(ap, int));
769			if (ladjust && width > 0)
770				while (width--)
771					PCHAR(padc);
772			break;
773		case 'D':
774			up = va_arg(ap, u_char *);
775			p = va_arg(ap, char *);
776			if (!width)
777				width = 16;
778			while(width--) {
779				PCHAR(hex2ascii(*up >> 4));
780				PCHAR(hex2ascii(*up & 0x0f));
781				up++;
782				if (width)
783					for (q=p;*q;q++)
784						PCHAR(*q);
785			}
786			break;
787		case 'd':
788		case 'i':
789			base = 10;
790			sign = 1;
791			goto handle_sign;
792		case 'h':
793			if (hflag) {
794				hflag = 0;
795				cflag = 1;
796			} else
797				hflag = 1;
798			goto reswitch;
799		case 'j':
800			jflag = 1;
801			goto reswitch;
802		case 'l':
803			if (lflag) {
804				lflag = 0;
805				qflag = 1;
806			} else
807				lflag = 1;
808			goto reswitch;
809		case 'n':
810			if (jflag)
811				*(va_arg(ap, intmax_t *)) = retval;
812			else if (qflag)
813				*(va_arg(ap, quad_t *)) = retval;
814			else if (lflag)
815				*(va_arg(ap, long *)) = retval;
816			else if (zflag)
817				*(va_arg(ap, size_t *)) = retval;
818			else if (hflag)
819				*(va_arg(ap, short *)) = retval;
820			else if (cflag)
821				*(va_arg(ap, char *)) = retval;
822			else
823				*(va_arg(ap, int *)) = retval;
824			break;
825		case 'o':
826			base = 8;
827			goto handle_nosign;
828		case 'p':
829			base = 16;
830			sharpflag = (width == 0);
831			sign = 0;
832			num = (uintptr_t)va_arg(ap, void *);
833			goto number;
834		case 'q':
835			qflag = 1;
836			goto reswitch;
837		case 'r':
838			base = radix;
839			if (sign)
840				goto handle_sign;
841			goto handle_nosign;
842		case 's':
843			p = va_arg(ap, char *);
844			if (p == NULL)
845				p = "(null)";
846			if (!dot)
847				n = strlen (p);
848			else
849				for (n = 0; n < dwidth && p[n]; n++)
850					continue;
851
852			width -= n;
853
854			if (!ladjust && width > 0)
855				while (width--)
856					PCHAR(padc);
857			while (n--)
858				PCHAR(*p++);
859			if (ladjust && width > 0)
860				while (width--)
861					PCHAR(padc);
862			break;
863		case 't':
864			tflag = 1;
865			goto reswitch;
866		case 'u':
867			base = 10;
868			goto handle_nosign;
869		case 'X':
870			upper = 1;
871		case 'x':
872			base = 16;
873			goto handle_nosign;
874		case 'y':
875			base = 16;
876			sign = 1;
877			goto handle_sign;
878		case 'z':
879			zflag = 1;
880			goto reswitch;
881handle_nosign:
882			sign = 0;
883			if (jflag)
884				num = va_arg(ap, uintmax_t);
885			else if (qflag)
886				num = va_arg(ap, u_quad_t);
887			else if (tflag)
888				num = va_arg(ap, ptrdiff_t);
889			else if (lflag)
890				num = va_arg(ap, u_long);
891			else if (zflag)
892				num = va_arg(ap, size_t);
893			else if (hflag)
894				num = (u_short)va_arg(ap, int);
895			else if (cflag)
896				num = (u_char)va_arg(ap, int);
897			else
898				num = va_arg(ap, u_int);
899			goto number;
900handle_sign:
901			if (jflag)
902				num = va_arg(ap, intmax_t);
903			else if (qflag)
904				num = va_arg(ap, quad_t);
905			else if (tflag)
906				num = va_arg(ap, ptrdiff_t);
907			else if (lflag)
908				num = va_arg(ap, long);
909			else if (zflag)
910				num = va_arg(ap, ssize_t);
911			else if (hflag)
912				num = (short)va_arg(ap, int);
913			else if (cflag)
914				num = (char)va_arg(ap, int);
915			else
916				num = va_arg(ap, int);
917number:
918			if (sign && (intmax_t)num < 0) {
919				neg = 1;
920				num = -(intmax_t)num;
921			}
922			p = ksprintn(nbuf, num, base, &n, upper);
923			tmp = 0;
924			if (sharpflag && num != 0) {
925				if (base == 8)
926					tmp++;
927				else if (base == 16)
928					tmp += 2;
929			}
930			if (neg)
931				tmp++;
932
933			if (!ladjust && padc == '0')
934				dwidth = width - tmp;
935			width -= tmp + imax(dwidth, n);
936			dwidth -= n;
937			if (!ladjust)
938				while (width-- > 0)
939					PCHAR(' ');
940			if (neg)
941				PCHAR('-');
942			if (sharpflag && num != 0) {
943				if (base == 8) {
944					PCHAR('0');
945				} else if (base == 16) {
946					PCHAR('0');
947					PCHAR('x');
948				}
949			}
950			while (dwidth-- > 0)
951				PCHAR('0');
952
953			while (*p)
954				PCHAR(*p--);
955
956			if (ladjust)
957				while (width-- > 0)
958					PCHAR(' ');
959
960			break;
961		default:
962			while (percent < fmt)
963				PCHAR(*percent++);
964			/*
965			 * Since we ignore a formatting argument it is no
966			 * longer safe to obey the remaining formatting
967			 * arguments as the arguments will no longer match
968			 * the format specs.
969			 */
970			stop = 1;
971			break;
972		}
973	}
974#undef PCHAR
975}
976
977/*
978 * Put character in log buffer with a particular priority.
979 */
980static void
981msglogchar(int c, int pri)
982{
983	static int lastpri = -1;
984	static int dangling;
985	char nbuf[MAXNBUF];
986	char *p;
987
988	if (!msgbufmapped)
989		return;
990	if (c == '\0' || c == '\r')
991		return;
992	if (pri != -1 && pri != lastpri) {
993		if (dangling) {
994			msgbuf_addchar(msgbufp, '\n');
995			dangling = 0;
996		}
997		msgbuf_addchar(msgbufp, '<');
998		for (p = ksprintn(nbuf, (uintmax_t)pri, 10, NULL, 0); *p;)
999			msgbuf_addchar(msgbufp, *p--);
1000		msgbuf_addchar(msgbufp, '>');
1001		lastpri = pri;
1002	}
1003	msgbuf_addchar(msgbufp, c);
1004	if (c == '\n') {
1005		dangling = 0;
1006		lastpri = -1;
1007	} else {
1008		dangling = 1;
1009	}
1010}
1011
1012static void
1013msglogstr(char *str, int pri, int filter_cr)
1014{
1015	if (!msgbufmapped)
1016		return;
1017
1018	msgbuf_addstr(msgbufp, pri, str, filter_cr);
1019}
1020
1021void
1022msgbufinit(void *ptr, int size)
1023{
1024	char *cp;
1025	static struct msgbuf *oldp = NULL;
1026	bool print_boot_tag;
1027
1028	size -= sizeof(*msgbufp);
1029	cp = (char *)ptr;
1030	print_boot_tag = !msgbufmapped;
1031	/* Attempt to fetch kern.boot_tag tunable on first mapping */
1032	if (!msgbufmapped)
1033		TUNABLE_STR_FETCH("kern.boot_tag", current_boot_tag,
1034		    sizeof(current_boot_tag));
1035	msgbufp = (struct msgbuf *)(cp + size);
1036	msgbuf_reinit(msgbufp, cp, size);
1037	if (msgbufmapped && oldp != msgbufp)
1038		msgbuf_copy(oldp, msgbufp);
1039	msgbufmapped = true;
1040	if (print_boot_tag && *current_boot_tag != '\0')
1041		printf("%s\n", current_boot_tag);
1042	oldp = msgbufp;
1043}
1044
1045/* Sysctls for accessing/clearing the msgbuf */
1046static int
1047sysctl_kern_msgbuf(SYSCTL_HANDLER_ARGS)
1048{
1049	char buf[128];
1050	u_int seq;
1051	int error, len;
1052
1053	error = priv_check(req->td, PRIV_MSGBUF);
1054	if (error)
1055		return (error);
1056
1057	/* Read the whole buffer, one chunk at a time. */
1058	mtx_lock(&msgbuf_lock);
1059	msgbuf_peekbytes(msgbufp, NULL, 0, &seq);
1060	for (;;) {
1061		len = msgbuf_peekbytes(msgbufp, buf, sizeof(buf), &seq);
1062		mtx_unlock(&msgbuf_lock);
1063		if (len == 0)
1064			return (SYSCTL_OUT(req, "", 1)); /* add nulterm */
1065
1066		error = sysctl_handle_opaque(oidp, buf, len, req);
1067		if (error)
1068			return (error);
1069
1070		mtx_lock(&msgbuf_lock);
1071	}
1072}
1073
1074SYSCTL_PROC(_kern, OID_AUTO, msgbuf,
1075    CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
1076    NULL, 0, sysctl_kern_msgbuf, "A", "Contents of kernel message buffer");
1077
1078static int msgbuf_clearflag;
1079
1080static int
1081sysctl_kern_msgbuf_clear(SYSCTL_HANDLER_ARGS)
1082{
1083	int error;
1084	error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
1085	if (!error && req->newptr) {
1086		mtx_lock(&msgbuf_lock);
1087		msgbuf_clear(msgbufp);
1088		mtx_unlock(&msgbuf_lock);
1089		msgbuf_clearflag = 0;
1090	}
1091	return (error);
1092}
1093
1094SYSCTL_PROC(_kern, OID_AUTO, msgbuf_clear,
1095    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE | CTLFLAG_MPSAFE,
1096    &msgbuf_clearflag, 0, sysctl_kern_msgbuf_clear, "I",
1097    "Clear kernel message buffer");
1098
1099#ifdef DDB
1100
1101DB_SHOW_COMMAND(msgbuf, db_show_msgbuf)
1102{
1103	int i, j;
1104
1105	if (!msgbufmapped) {
1106		db_printf("msgbuf not mapped yet\n");
1107		return;
1108	}
1109	db_printf("msgbufp = %p\n", msgbufp);
1110	db_printf("magic = %x, size = %d, r= %u, w = %u, ptr = %p, cksum= %u\n",
1111	    msgbufp->msg_magic, msgbufp->msg_size, msgbufp->msg_rseq,
1112	    msgbufp->msg_wseq, msgbufp->msg_ptr, msgbufp->msg_cksum);
1113	for (i = 0; i < msgbufp->msg_size && !db_pager_quit; i++) {
1114		j = MSGBUF_SEQ_TO_POS(msgbufp, i + msgbufp->msg_rseq);
1115		db_printf("%c", msgbufp->msg_ptr[j]);
1116	}
1117	db_printf("\n");
1118}
1119
1120#endif /* DDB */
1121
1122void
1123hexdump(const void *ptr, int length, const char *hdr, int flags)
1124{
1125	int i, j, k;
1126	int cols;
1127	const unsigned char *cp;
1128	char delim;
1129
1130	if ((flags & HD_DELIM_MASK) != 0)
1131		delim = (flags & HD_DELIM_MASK) >> 8;
1132	else
1133		delim = ' ';
1134
1135	if ((flags & HD_COLUMN_MASK) != 0)
1136		cols = flags & HD_COLUMN_MASK;
1137	else
1138		cols = 16;
1139
1140	cp = ptr;
1141	for (i = 0; i < length; i+= cols) {
1142		if (hdr != NULL)
1143			printf("%s", hdr);
1144
1145		if ((flags & HD_OMIT_COUNT) == 0)
1146			printf("%04x  ", i);
1147
1148		if ((flags & HD_OMIT_HEX) == 0) {
1149			for (j = 0; j < cols; j++) {
1150				k = i + j;
1151				if (k < length)
1152					printf("%c%02x", delim, cp[k]);
1153				else
1154					printf("   ");
1155			}
1156		}
1157
1158		if ((flags & HD_OMIT_CHARS) == 0) {
1159			printf("  |");
1160			for (j = 0; j < cols; j++) {
1161				k = i + j;
1162				if (k >= length)
1163					printf(" ");
1164				else if (cp[k] >= ' ' && cp[k] <= '~')
1165					printf("%c", cp[k]);
1166				else
1167					printf(".");
1168			}
1169			printf("|");
1170		}
1171		printf("\n");
1172	}
1173}
1174#endif /* _KERNEL */
1175
1176void
1177sbuf_hexdump(struct sbuf *sb, const void *ptr, int length, const char *hdr,
1178	     int flags)
1179{
1180	int i, j, k;
1181	int cols;
1182	const unsigned char *cp;
1183	char delim;
1184
1185	if ((flags & HD_DELIM_MASK) != 0)
1186		delim = (flags & HD_DELIM_MASK) >> 8;
1187	else
1188		delim = ' ';
1189
1190	if ((flags & HD_COLUMN_MASK) != 0)
1191		cols = flags & HD_COLUMN_MASK;
1192	else
1193		cols = 16;
1194
1195	cp = ptr;
1196	for (i = 0; i < length; i+= cols) {
1197		if (hdr != NULL)
1198			sbuf_printf(sb, "%s", hdr);
1199
1200		if ((flags & HD_OMIT_COUNT) == 0)
1201			sbuf_printf(sb, "%04x  ", i);
1202
1203		if ((flags & HD_OMIT_HEX) == 0) {
1204			for (j = 0; j < cols; j++) {
1205				k = i + j;
1206				if (k < length)
1207					sbuf_printf(sb, "%c%02x", delim, cp[k]);
1208				else
1209					sbuf_printf(sb, "   ");
1210			}
1211		}
1212
1213		if ((flags & HD_OMIT_CHARS) == 0) {
1214			sbuf_printf(sb, "  |");
1215			for (j = 0; j < cols; j++) {
1216				k = i + j;
1217				if (k >= length)
1218					sbuf_printf(sb, " ");
1219				else if (cp[k] >= ' ' && cp[k] <= '~')
1220					sbuf_printf(sb, "%c", cp[k]);
1221				else
1222					sbuf_printf(sb, ".");
1223			}
1224			sbuf_printf(sb, "|");
1225		}
1226		sbuf_printf(sb, "\n");
1227	}
1228}
1229
1230#ifdef _KERNEL
1231void
1232counted_warning(unsigned *counter, const char *msg)
1233{
1234	struct thread *td;
1235	unsigned c;
1236
1237	for (;;) {
1238		c = *counter;
1239		if (c == 0)
1240			break;
1241		if (atomic_cmpset_int(counter, c, c - 1)) {
1242			td = curthread;
1243			log(LOG_INFO, "pid %d (%s) %s%s\n",
1244			    td->td_proc->p_pid, td->td_name, msg,
1245			    c > 1 ? "" : " - not logging anymore");
1246			break;
1247		}
1248	}
1249}
1250#endif
1251
1252#ifdef _KERNEL
1253void
1254sbuf_putbuf(struct sbuf *sb)
1255{
1256
1257	prf_putbuf(sbuf_data(sb), TOLOG | TOCONS, -1);
1258}
1259#else
1260void
1261sbuf_putbuf(struct sbuf *sb)
1262{
1263
1264	printf("%s", sbuf_data(sb));
1265}
1266#endif
1267