xref: /freebsd/sys/kern/subr_prf.c (revision c4e929946ca6e5fa4f39b8966d21080bf164f2e8)
1df8bae1dSRodney W. Grimes /*-
2df8bae1dSRodney W. Grimes  * Copyright (c) 1986, 1988, 1991, 1993
3df8bae1dSRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
4df8bae1dSRodney W. Grimes  * (c) UNIX System Laboratories, Inc.
5df8bae1dSRodney W. Grimes  * All or some portions of this file are derived from material licensed
6df8bae1dSRodney W. Grimes  * to the University of California by American Telephone and Telegraph
7df8bae1dSRodney W. Grimes  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8df8bae1dSRodney W. Grimes  * the permission of UNIX System Laboratories, Inc.
9df8bae1dSRodney W. Grimes  *
10df8bae1dSRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
11df8bae1dSRodney W. Grimes  * modification, are permitted provided that the following conditions
12df8bae1dSRodney W. Grimes  * are met:
13df8bae1dSRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
14df8bae1dSRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
15df8bae1dSRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
16df8bae1dSRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
17df8bae1dSRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
1869a28758SEd Maste  * 3. Neither the name of the University nor the names of its contributors
19df8bae1dSRodney W. Grimes  *    may be used to endorse or promote products derived from this software
20df8bae1dSRodney W. Grimes  *    without specific prior written permission.
21df8bae1dSRodney W. Grimes  *
22df8bae1dSRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23df8bae1dSRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24df8bae1dSRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25df8bae1dSRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26df8bae1dSRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27df8bae1dSRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28df8bae1dSRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29df8bae1dSRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30df8bae1dSRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31df8bae1dSRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32df8bae1dSRodney W. Grimes  * SUCH DAMAGE.
33df8bae1dSRodney W. Grimes  *
34df8bae1dSRodney W. Grimes  *	@(#)subr_prf.c	8.3 (Berkeley) 1/21/94
35df8bae1dSRodney W. Grimes  */
36df8bae1dSRodney W. Grimes 
37677b542eSDavid E. O'Brien #include <sys/cdefs.h>
38677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$");
39677b542eSDavid E. O'Brien 
405672fac9SKenneth D. Merry #ifdef _KERNEL
413ae59505SPoul-Henning Kamp #include "opt_ddb.h"
42e0b65125SJohn Birrell #include "opt_printf.h"
435672fac9SKenneth D. Merry #endif  /* _KERNEL */
443ae59505SPoul-Henning Kamp 
45df8bae1dSRodney W. Grimes #include <sys/param.h>
465672fac9SKenneth D. Merry #ifdef _KERNEL
47df8bae1dSRodney W. Grimes #include <sys/systm.h>
48f591779bSSeigo Tanimura #include <sys/lock.h>
4982ebaee7SMarcel Moolenaar #include <sys/kdb.h>
50f591779bSSeigo Tanimura #include <sys/mutex.h>
51f591779bSSeigo Tanimura #include <sys/sx.h>
52e796e00dSPoul-Henning Kamp #include <sys/kernel.h>
53df8bae1dSRodney W. Grimes #include <sys/msgbuf.h>
54a1c995b6SPoul-Henning Kamp #include <sys/malloc.h>
55acd3428bSRobert Watson #include <sys/priv.h>
56df8bae1dSRodney W. Grimes #include <sys/proc.h>
572bb95458SMaxime Henrion #include <sys/stddef.h>
5858a24f79SPoul-Henning Kamp #include <sys/sysctl.h>
59df8bae1dSRodney W. Grimes #include <sys/tty.h>
60df8bae1dSRodney W. Grimes #include <sys/syslog.h>
61ce9edcf5SPoul-Henning Kamp #include <sys/cons.h>
62e2a09b26SPoul-Henning Kamp #include <sys/uio.h>
635672fac9SKenneth D. Merry #endif
640d84d9ebSJung-uk Kim #include <sys/ctype.h>
655672fac9SKenneth D. Merry #include <sys/sbuf.h>
66df8bae1dSRodney W. Grimes 
673ae59505SPoul-Henning Kamp #ifdef DDB
683ae59505SPoul-Henning Kamp #include <ddb/ddb.h>
693ae59505SPoul-Henning Kamp #endif
703ae59505SPoul-Henning Kamp 
71df8bae1dSRodney W. Grimes /*
72df8bae1dSRodney W. Grimes  * Note that stdarg.h and the ANSI style va_start macro is used for both
73df8bae1dSRodney W. Grimes  * ANSI and traditional C compilers.
74df8bae1dSRodney W. Grimes  */
7507f862a7SMarcel Moolenaar #ifdef _KERNEL
76df8bae1dSRodney W. Grimes #include <machine/stdarg.h>
7707f862a7SMarcel Moolenaar #else
7807f862a7SMarcel Moolenaar #include <stdarg.h>
79*c4e92994SJung-uk Kim #include <stdio.h>
8007f862a7SMarcel Moolenaar #endif
81df8bae1dSRodney W. Grimes 
825672fac9SKenneth D. Merry #ifdef _KERNEL
835672fac9SKenneth D. Merry 
84df8bae1dSRodney W. Grimes #define TOCONS	0x01
85df8bae1dSRodney W. Grimes #define TOTTY	0x02
86df8bae1dSRodney W. Grimes #define TOLOG	0x04
87df8bae1dSRodney W. Grimes 
8882941964SPeter Wemm /* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */
893b1f7e7dSDag-Erling Smørgrav #define MAXNBUF	(sizeof(intmax_t) * NBBY + 1)
90df8bae1dSRodney W. Grimes 
918245f3f5SArchie Cobbs struct putchar_arg {
928245f3f5SArchie Cobbs 	int	flags;
93e2a09b26SPoul-Henning Kamp 	int	pri;
948245f3f5SArchie Cobbs 	struct	tty *tty;
953d068827SJohn Birrell 	char	*p_bufr;
963d068827SJohn Birrell 	size_t	n_bufr;
973d068827SJohn Birrell 	char	*p_next;
983d068827SJohn Birrell 	size_t	remain;
998245f3f5SArchie Cobbs };
1008245f3f5SArchie Cobbs 
1018245f3f5SArchie Cobbs struct snprintf_arg {
1028245f3f5SArchie Cobbs 	char	*str;
1038245f3f5SArchie Cobbs 	size_t	remain;
1048245f3f5SArchie Cobbs };
1058245f3f5SArchie Cobbs 
106e2a09b26SPoul-Henning Kamp extern	int log_open;
107e2a09b26SPoul-Henning Kamp 
108e2a09b26SPoul-Henning Kamp static void  msglogchar(int c, int pri);
109d42a4eb5SKenneth D. Merry static void  msglogstr(char *str, int pri, int filter_cr);
1104d77a549SAlfred Perlstein static void  putchar(int ch, void *arg);
1110d84d9ebSJung-uk Kim static char *ksprintn(char *nbuf, uintmax_t num, int base, int *len, int upper);
1124d77a549SAlfred Perlstein static void  snprintf_func(int ch, void *arg);
113df8bae1dSRodney W. Grimes 
114e796e00dSPoul-Henning Kamp static int msgbufmapped;		/* Set when safe to use msgbuf */
115e2a09b26SPoul-Henning Kamp int msgbuftrigger;
116df8bae1dSRodney W. Grimes 
117dbe620d3SDavid Malone static int log_console_output = 1;
118af3b2549SHans Petter Selasky SYSCTL_INT(_kern, OID_AUTO, log_console_output, CTLFLAG_RWTUN,
119af3b2549SHans Petter Selasky     &log_console_output, 0, "Duplicate console output to the syslog");
1208e1b7974SBrian Feldman 
121d42a4eb5SKenneth D. Merry /*
122d42a4eb5SKenneth D. Merry  * See the comment in log_console() below for more explanation of this.
123d42a4eb5SKenneth D. Merry  */
124af3b2549SHans Petter Selasky static int log_console_add_linefeed;
125af3b2549SHans Petter Selasky SYSCTL_INT(_kern, OID_AUTO, log_console_add_linefeed, CTLFLAG_RWTUN,
126af3b2549SHans Petter Selasky     &log_console_add_linefeed, 0, "log_console() adds extra newlines");
127d42a4eb5SKenneth D. Merry 
128af3b2549SHans Petter Selasky static int always_console_output;
129af3b2549SHans Petter Selasky SYSCTL_INT(_kern, OID_AUTO, always_console_output, CTLFLAG_RWTUN,
130af3b2549SHans Petter Selasky     &always_console_output, 0, "Always output to console despite TIOCCONS");
131dbe620d3SDavid Malone 
132df8bae1dSRodney W. Grimes /*
133df8bae1dSRodney W. Grimes  * Warn that a system table is full.
134df8bae1dSRodney W. Grimes  */
135df8bae1dSRodney W. Grimes void
136e2a09b26SPoul-Henning Kamp tablefull(const char *tab)
137df8bae1dSRodney W. Grimes {
138df8bae1dSRodney W. Grimes 
139df8bae1dSRodney W. Grimes 	log(LOG_ERR, "%s: table is full\n", tab);
140df8bae1dSRodney W. Grimes }
141df8bae1dSRodney W. Grimes 
142df8bae1dSRodney W. Grimes /*
143df8bae1dSRodney W. Grimes  * Uprintf prints to the controlling terminal for the current process.
144df8bae1dSRodney W. Grimes  */
145f1550d9dSDoug Rabson int
146df8bae1dSRodney W. Grimes uprintf(const char *fmt, ...)
147df8bae1dSRodney W. Grimes {
148df8bae1dSRodney W. Grimes 	va_list ap;
149791d77e0SPoul-Henning Kamp 	struct putchar_arg pca;
150ff7b7d90SEd Schouten 	struct proc *p;
151ff7b7d90SEd Schouten 	struct thread *td;
152f591779bSSeigo Tanimura 	int retval;
153df8bae1dSRodney W. Grimes 
154ff7b7d90SEd Schouten 	td = curthread;
155ff7b7d90SEd Schouten 	if (TD_IS_IDLETHREAD(td))
156f591779bSSeigo Tanimura 		return (0);
157f591779bSSeigo Tanimura 
158bc093719SEd Schouten 	sx_slock(&proctree_lock);
159ff7b7d90SEd Schouten 	p = td->td_proc;
160f591779bSSeigo Tanimura 	PROC_LOCK(p);
161f591779bSSeigo Tanimura 	if ((p->p_flag & P_CONTROLT) == 0) {
162f591779bSSeigo Tanimura 		PROC_UNLOCK(p);
1638740a711SKonstantin Belousov 		sx_sunlock(&proctree_lock);
1648740a711SKonstantin Belousov 		return (0);
165f591779bSSeigo Tanimura 	}
166f591779bSSeigo Tanimura 	SESS_LOCK(p->p_session);
167791d77e0SPoul-Henning Kamp 	pca.tty = p->p_session->s_ttyp;
168f591779bSSeigo Tanimura 	SESS_UNLOCK(p->p_session);
169f591779bSSeigo Tanimura 	PROC_UNLOCK(p);
170329c75a7SRobert Watson 	if (pca.tty == NULL) {
1718740a711SKonstantin Belousov 		sx_sunlock(&proctree_lock);
1728740a711SKonstantin Belousov 		return (0);
173329c75a7SRobert Watson 	}
174791d77e0SPoul-Henning Kamp 	pca.flags = TOTTY;
1755e319c48SKenneth D. Merry 	pca.p_bufr = NULL;
176f591779bSSeigo Tanimura 	va_start(ap, fmt);
177bc093719SEd Schouten 	tty_lock(pca.tty);
1788740a711SKonstantin Belousov 	sx_sunlock(&proctree_lock);
179f1550d9dSDoug Rabson 	retval = kvprintf(fmt, putchar, &pca, 10, ap);
180bc093719SEd Schouten 	tty_unlock(pca.tty);
181df8bae1dSRodney W. Grimes 	va_end(ap);
18258a24f79SPoul-Henning Kamp 	return (retval);
183df8bae1dSRodney W. Grimes }
184df8bae1dSRodney W. Grimes 
185df8bae1dSRodney W. Grimes /*
18634c916c6SNavdeep Parhar  * tprintf and vtprintf print on the controlling terminal associated with the
18734c916c6SNavdeep Parhar  * given session, possibly to the log as well.
188df8bae1dSRodney W. Grimes  */
189a52585d7SPoul-Henning Kamp void
190a52585d7SPoul-Henning Kamp tprintf(struct proc *p, int pri, const char *fmt, ...)
191df8bae1dSRodney W. Grimes {
19234c916c6SNavdeep Parhar 	va_list ap;
19334c916c6SNavdeep Parhar 
19434c916c6SNavdeep Parhar 	va_start(ap, fmt);
19534c916c6SNavdeep Parhar 	vtprintf(p, pri, fmt, ap);
19634c916c6SNavdeep Parhar 	va_end(ap);
19734c916c6SNavdeep Parhar }
19834c916c6SNavdeep Parhar 
19934c916c6SNavdeep Parhar void
20034c916c6SNavdeep Parhar vtprintf(struct proc *p, int pri, const char *fmt, va_list ap)
20134c916c6SNavdeep Parhar {
202df8bae1dSRodney W. Grimes 	struct tty *tp = NULL;
203b5a2bad1SJohn Baldwin 	int flags = 0;
204791d77e0SPoul-Henning Kamp 	struct putchar_arg pca;
205b5a2bad1SJohn Baldwin 	struct session *sess = NULL;
206df8bae1dSRodney W. Grimes 
207bc093719SEd Schouten 	sx_slock(&proctree_lock);
208e2a09b26SPoul-Henning Kamp 	if (pri != -1)
209a52585d7SPoul-Henning Kamp 		flags |= TOLOG;
210f591779bSSeigo Tanimura 	if (p != NULL) {
211f591779bSSeigo Tanimura 		PROC_LOCK(p);
212f591779bSSeigo Tanimura 		if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
213b5a2bad1SJohn Baldwin 			sess = p->p_session;
214bc093719SEd Schouten 			sess_hold(sess);
215f591779bSSeigo Tanimura 			PROC_UNLOCK(p);
216b5a2bad1SJohn Baldwin 			tp = sess->s_ttyp;
217bc093719SEd Schouten 			if (tp != NULL && tty_checkoutq(tp))
218f591779bSSeigo Tanimura 				flags |= TOTTY;
219f591779bSSeigo Tanimura 			else
220f591779bSSeigo Tanimura 				tp = NULL;
221f591779bSSeigo Tanimura 		} else
222f591779bSSeigo Tanimura 			PROC_UNLOCK(p);
223a52585d7SPoul-Henning Kamp 	}
224e2a09b26SPoul-Henning Kamp 	pca.pri = pri;
225791d77e0SPoul-Henning Kamp 	pca.tty = tp;
226791d77e0SPoul-Henning Kamp 	pca.flags = flags;
2275e319c48SKenneth D. Merry 	pca.p_bufr = NULL;
228bc093719SEd Schouten 	if (pca.tty != NULL)
229bc093719SEd Schouten 		tty_lock(pca.tty);
2308740a711SKonstantin Belousov 	sx_sunlock(&proctree_lock);
23174f1af01SPoul-Henning Kamp 	kvprintf(fmt, putchar, &pca, 10, ap);
232bc093719SEd Schouten 	if (pca.tty != NULL)
233bc093719SEd Schouten 		tty_unlock(pca.tty);
234572b4402SPoul-Henning Kamp 	if (sess != NULL)
235bc093719SEd Schouten 		sess_release(sess);
236e2a09b26SPoul-Henning Kamp 	msgbuftrigger = 1;
237df8bae1dSRodney W. Grimes }
238df8bae1dSRodney W. Grimes 
239df8bae1dSRodney W. Grimes /*
240df8bae1dSRodney W. Grimes  * Ttyprintf displays a message on a tty; it should be used only by
241df8bae1dSRodney W. Grimes  * the tty driver, or anything that knows the underlying tty will not
242df8bae1dSRodney W. Grimes  * be revoke(2)'d away.  Other callers should use tprintf.
243df8bae1dSRodney W. Grimes  */
244f1550d9dSDoug Rabson int
245df8bae1dSRodney W. Grimes ttyprintf(struct tty *tp, const char *fmt, ...)
246df8bae1dSRodney W. Grimes {
247df8bae1dSRodney W. Grimes 	va_list ap;
248791d77e0SPoul-Henning Kamp 	struct putchar_arg pca;
249f1550d9dSDoug Rabson 	int retval;
250f1550d9dSDoug Rabson 
251df8bae1dSRodney W. Grimes 	va_start(ap, fmt);
252791d77e0SPoul-Henning Kamp 	pca.tty = tp;
253791d77e0SPoul-Henning Kamp 	pca.flags = TOTTY;
2545e319c48SKenneth D. Merry 	pca.p_bufr = NULL;
255f1550d9dSDoug Rabson 	retval = kvprintf(fmt, putchar, &pca, 10, ap);
256df8bae1dSRodney W. Grimes 	va_end(ap);
25758a24f79SPoul-Henning Kamp 	return (retval);
258df8bae1dSRodney W. Grimes }
259df8bae1dSRodney W. Grimes 
260ae8959ddSBryan Drewery static int
261ae8959ddSBryan Drewery _vprintf(int level, int flags, const char *fmt, va_list ap)
262df8bae1dSRodney W. Grimes {
263791d77e0SPoul-Henning Kamp 	struct putchar_arg pca;
264ae8959ddSBryan Drewery 	int retval;
265d42a4eb5SKenneth D. Merry #ifdef PRINTF_BUFR_SIZE
266d42a4eb5SKenneth D. Merry 	char bufr[PRINTF_BUFR_SIZE];
267d42a4eb5SKenneth D. Merry #endif
268e2a09b26SPoul-Henning Kamp 
269791d77e0SPoul-Henning Kamp 	pca.tty = NULL;
270e2a09b26SPoul-Henning Kamp 	pca.pri = level;
271ae8959ddSBryan Drewery 	pca.flags = flags;
272d42a4eb5SKenneth D. Merry #ifdef PRINTF_BUFR_SIZE
273d42a4eb5SKenneth D. Merry 	pca.p_bufr = bufr;
274d42a4eb5SKenneth D. Merry 	pca.p_next = pca.p_bufr;
275d42a4eb5SKenneth D. Merry 	pca.n_bufr = sizeof(bufr);
276d42a4eb5SKenneth D. Merry 	pca.remain = sizeof(bufr);
277d42a4eb5SKenneth D. Merry 	*pca.p_next = '\0';
278d42a4eb5SKenneth D. Merry #else
279ae8959ddSBryan Drewery 	/* Don't buffer console output. */
2803d068827SJohn Birrell 	pca.p_bufr = NULL;
281d42a4eb5SKenneth D. Merry #endif
282e2a09b26SPoul-Henning Kamp 
283ae8959ddSBryan Drewery 	retval = kvprintf(fmt, putchar, &pca, 10, ap);
284e2a09b26SPoul-Henning Kamp 
285d42a4eb5SKenneth D. Merry #ifdef PRINTF_BUFR_SIZE
286d42a4eb5SKenneth D. Merry 	/* Write any buffered console/log output: */
287d42a4eb5SKenneth D. Merry 	if (*pca.p_bufr != '\0') {
288d42a4eb5SKenneth D. Merry 		if (pca.flags & TOLOG)
289d42a4eb5SKenneth D. Merry 			msglogstr(pca.p_bufr, level, /*filter_cr*/1);
290d42a4eb5SKenneth D. Merry 
291d42a4eb5SKenneth D. Merry 		if (pca.flags & TOCONS)
292d42a4eb5SKenneth D. Merry 			cnputs(pca.p_bufr);
293d42a4eb5SKenneth D. Merry 	}
294d42a4eb5SKenneth D. Merry #endif
295ae8959ddSBryan Drewery 
296ae8959ddSBryan Drewery 	return (retval);
297ae8959ddSBryan Drewery }
298ae8959ddSBryan Drewery 
299ae8959ddSBryan Drewery /*
300ae8959ddSBryan Drewery  * Log writes to the log buffer, and guarantees not to sleep (so can be
301ae8959ddSBryan Drewery  * called by interrupt routines).  If there is no process reading the
302ae8959ddSBryan Drewery  * log yet, it writes to the console also.
303ae8959ddSBryan Drewery  */
304ae8959ddSBryan Drewery void
305ae8959ddSBryan Drewery log(int level, const char *fmt, ...)
306ae8959ddSBryan Drewery {
307ae8959ddSBryan Drewery 	va_list ap;
308ae8959ddSBryan Drewery 
309ae8959ddSBryan Drewery 	va_start(ap, fmt);
31007713ddeSMark Johnston 	vlog(level, fmt, ap);
311ae8959ddSBryan Drewery 	va_end(ap);
31207713ddeSMark Johnston }
313ae8959ddSBryan Drewery 
31407713ddeSMark Johnston void
31507713ddeSMark Johnston vlog(int level, const char *fmt, va_list ap)
31607713ddeSMark Johnston {
31707713ddeSMark Johnston 
31807713ddeSMark Johnston 	(void)_vprintf(level, log_open ? TOLOG : TOCONS | TOLOG, fmt, ap);
319b80e3b41SPoul-Henning Kamp 	msgbuftrigger = 1;
320df8bae1dSRodney W. Grimes }
321df8bae1dSRodney W. Grimes 
322e2a09b26SPoul-Henning Kamp #define CONSCHUNK 128
323e2a09b26SPoul-Henning Kamp 
324e2a09b26SPoul-Henning Kamp void
325e2a09b26SPoul-Henning Kamp log_console(struct uio *uio)
326df8bae1dSRodney W. Grimes {
327d42a4eb5SKenneth D. Merry 	int c, error, nl;
328e2a09b26SPoul-Henning Kamp 	char *consbuffer;
329e2a09b26SPoul-Henning Kamp 	int pri;
330df8bae1dSRodney W. Grimes 
331dbe620d3SDavid Malone 	if (!log_console_output)
332dbe620d3SDavid Malone 		return;
333dbe620d3SDavid Malone 
334e2a09b26SPoul-Henning Kamp 	pri = LOG_INFO | LOG_CONSOLE;
335552afd9cSPoul-Henning Kamp 	uio = cloneuio(uio);
336552afd9cSPoul-Henning Kamp 	consbuffer = malloc(CONSCHUNK, M_TEMP, M_WAITOK);
337e2a09b26SPoul-Henning Kamp 
3383a4d0c86SEd Schouten 	nl = 0;
339e2a09b26SPoul-Henning Kamp 	while (uio->uio_resid > 0) {
340d42a4eb5SKenneth D. Merry 		c = imin(uio->uio_resid, CONSCHUNK - 1);
341e2a09b26SPoul-Henning Kamp 		error = uiomove(consbuffer, c, uio);
342e2a09b26SPoul-Henning Kamp 		if (error != 0)
3432f9752e9SPoul-Henning Kamp 			break;
344d42a4eb5SKenneth D. Merry 		/* Make sure we're NUL-terminated */
345d42a4eb5SKenneth D. Merry 		consbuffer[c] = '\0';
346d42a4eb5SKenneth D. Merry 		if (consbuffer[c - 1] == '\n')
3473a4d0c86SEd Schouten 			nl = 1;
3483a4d0c86SEd Schouten 		else
3493a4d0c86SEd Schouten 			nl = 0;
350d42a4eb5SKenneth D. Merry 		msglogstr(consbuffer, pri, /*filter_cr*/ 1);
351e2a09b26SPoul-Henning Kamp 	}
352d42a4eb5SKenneth D. Merry 	/*
353d42a4eb5SKenneth D. Merry 	 * The previous behavior in log_console() is preserved when
354d42a4eb5SKenneth D. Merry 	 * log_console_add_linefeed is non-zero.  For that behavior, if an
355d42a4eb5SKenneth D. Merry 	 * individual console write came in that was not terminated with a
356d42a4eb5SKenneth D. Merry 	 * line feed, it would add a line feed.
357d42a4eb5SKenneth D. Merry 	 *
358d42a4eb5SKenneth D. Merry 	 * This results in different data in the message buffer than
359d42a4eb5SKenneth D. Merry 	 * appears on the system console (which doesn't add extra line feed
360d42a4eb5SKenneth D. Merry 	 * characters).
361d42a4eb5SKenneth D. Merry 	 *
362d42a4eb5SKenneth D. Merry 	 * A number of programs and rc scripts write a line feed, or a period
363d42a4eb5SKenneth D. Merry 	 * and a line feed when they have completed their operation.  On
364d42a4eb5SKenneth D. Merry 	 * the console, this looks seamless, but when displayed with
365d42a4eb5SKenneth D. Merry 	 * 'dmesg -a', you wind up with output that looks like this:
366d42a4eb5SKenneth D. Merry 	 *
367d42a4eb5SKenneth D. Merry 	 * Updating motd:
368d42a4eb5SKenneth D. Merry 	 * .
369d42a4eb5SKenneth D. Merry 	 *
370d42a4eb5SKenneth D. Merry 	 * On the console, it looks like this:
371d42a4eb5SKenneth D. Merry 	 * Updating motd:.
372d42a4eb5SKenneth D. Merry 	 *
373d42a4eb5SKenneth D. Merry 	 * We could add logic to detect that situation, or just not insert
374d42a4eb5SKenneth D. Merry 	 * the extra newlines.  Set the kern.log_console_add_linefeed
375d42a4eb5SKenneth D. Merry 	 * sysctl/tunable variable to get the old behavior.
376d42a4eb5SKenneth D. Merry 	 */
377d42a4eb5SKenneth D. Merry 	if (!nl && log_console_add_linefeed) {
378d42a4eb5SKenneth D. Merry 		consbuffer[0] = '\n';
379d42a4eb5SKenneth D. Merry 		consbuffer[1] = '\0';
380d42a4eb5SKenneth D. Merry 		msglogstr(consbuffer, pri, /*filter_cr*/ 1);
3813a4d0c86SEd Schouten 	}
382b80e3b41SPoul-Henning Kamp 	msgbuftrigger = 1;
383552afd9cSPoul-Henning Kamp 	free(uio, M_IOV);
384552afd9cSPoul-Henning Kamp 	free(consbuffer, M_TEMP);
385e2a09b26SPoul-Henning Kamp 	return;
386df8bae1dSRodney W. Grimes }
387df8bae1dSRodney W. Grimes 
3886ddbf1e2SGary Palmer int
389df8bae1dSRodney W. Grimes printf(const char *fmt, ...)
390df8bae1dSRodney W. Grimes {
391df8bae1dSRodney W. Grimes 	va_list ap;
39265ed8cbdSJustin T. Gibbs 	int retval;
3933d068827SJohn Birrell 
394df8bae1dSRodney W. Grimes 	va_start(ap, fmt);
39591c3cbfeSEd Schouten 	retval = vprintf(fmt, ap);
396df8bae1dSRodney W. Grimes 	va_end(ap);
3973d068827SJohn Birrell 
39858a24f79SPoul-Henning Kamp 	return (retval);
399df8bae1dSRodney W. Grimes }
400df8bae1dSRodney W. Grimes 
401f1550d9dSDoug Rabson int
402791d77e0SPoul-Henning Kamp vprintf(const char *fmt, va_list ap)
403791d77e0SPoul-Henning Kamp {
404f1550d9dSDoug Rabson 	int retval;
4053d068827SJohn Birrell 
406ae8959ddSBryan Drewery 	retval = _vprintf(-1, TOCONS | TOLOG, fmt, ap);
4073d068827SJohn Birrell 
408791d77e0SPoul-Henning Kamp 	if (!panicstr)
409b80e3b41SPoul-Henning Kamp 		msgbuftrigger = 1;
4103d068827SJohn Birrell 
41158a24f79SPoul-Henning Kamp 	return (retval);
412791d77e0SPoul-Henning Kamp }
413791d77e0SPoul-Henning Kamp 
4143d068827SJohn Birrell static void
415388f3ce6SScott Long prf_putbuf(char *bufr, int flags, int pri)
416388f3ce6SScott Long {
417388f3ce6SScott Long 
418388f3ce6SScott Long 	if (flags & TOLOG)
419388f3ce6SScott Long 		msglogstr(bufr, pri, /*filter_cr*/1);
420388f3ce6SScott Long 
421388f3ce6SScott Long 	if (flags & TOCONS) {
422388f3ce6SScott Long 		if ((panicstr == NULL) && (constty != NULL))
423388f3ce6SScott Long 			msgbuf_addstr(&consmsgbuf, -1,
424388f3ce6SScott Long 			    bufr, /*filter_cr*/ 0);
425388f3ce6SScott Long 
426388f3ce6SScott Long 		if ((constty == NULL) ||(always_console_output))
427388f3ce6SScott Long 			cnputs(bufr);
428388f3ce6SScott Long 	}
429388f3ce6SScott Long }
430388f3ce6SScott Long 
431388f3ce6SScott Long static void
432d42a4eb5SKenneth D. Merry putbuf(int c, struct putchar_arg *ap)
4333d068827SJohn Birrell {
4343d068827SJohn Birrell 	/* Check if no console output buffer was provided. */
435d42a4eb5SKenneth D. Merry 	if (ap->p_bufr == NULL) {
4363d068827SJohn Birrell 		/* Output direct to the console. */
437d42a4eb5SKenneth D. Merry 		if (ap->flags & TOCONS)
4383d068827SJohn Birrell 			cnputc(c);
439d42a4eb5SKenneth D. Merry 
440d42a4eb5SKenneth D. Merry 		if (ap->flags & TOLOG)
441d42a4eb5SKenneth D. Merry 			msglogchar(c, ap->pri);
442d42a4eb5SKenneth D. Merry 	} else {
4433d068827SJohn Birrell 		/* Buffer the character: */
4443d068827SJohn Birrell 		*ap->p_next++ = c;
4453d068827SJohn Birrell 		ap->remain--;
4463d068827SJohn Birrell 
4473d068827SJohn Birrell 		/* Always leave the buffer zero terminated. */
4483d068827SJohn Birrell 		*ap->p_next = '\0';
4493d068827SJohn Birrell 
4503d068827SJohn Birrell 		/* Check if the buffer needs to be flushed. */
451d42a4eb5SKenneth D. Merry 		if (ap->remain == 2 || c == '\n') {
452388f3ce6SScott Long 			prf_putbuf(ap->p_bufr, ap->flags, ap->pri);
453d42a4eb5SKenneth D. Merry 
4543d068827SJohn Birrell 			ap->p_next = ap->p_bufr;
4553d068827SJohn Birrell 			ap->remain = ap->n_bufr;
4563d068827SJohn Birrell 			*ap->p_next = '\0';
4573d068827SJohn Birrell 		}
458d42a4eb5SKenneth D. Merry 
459d42a4eb5SKenneth D. Merry 		/*
460d42a4eb5SKenneth D. Merry 		 * Since we fill the buffer up one character at a time,
461d42a4eb5SKenneth D. Merry 		 * this should not happen.  We should always catch it when
462d42a4eb5SKenneth D. Merry 		 * ap->remain == 2 (if not sooner due to a newline), flush
463d42a4eb5SKenneth D. Merry 		 * the buffer and move on.  One way this could happen is
464d42a4eb5SKenneth D. Merry 		 * if someone sets PRINTF_BUFR_SIZE to 1 or something
465d42a4eb5SKenneth D. Merry 		 * similarly silly.
466d42a4eb5SKenneth D. Merry 		 */
467d42a4eb5SKenneth D. Merry 		KASSERT(ap->remain > 2, ("Bad buffer logic, remain = %zd",
468d42a4eb5SKenneth D. Merry 		    ap->remain));
4693d068827SJohn Birrell 	}
4703d068827SJohn Birrell }
4713d068827SJohn Birrell 
472791d77e0SPoul-Henning Kamp /*
473791d77e0SPoul-Henning Kamp  * Print a character on console or users terminal.  If destination is
474e796e00dSPoul-Henning Kamp  * the console then the last bunch of characters are saved in msgbuf for
475791d77e0SPoul-Henning Kamp  * inspection later.
476791d77e0SPoul-Henning Kamp  */
477791d77e0SPoul-Henning Kamp static void
478791d77e0SPoul-Henning Kamp putchar(int c, void *arg)
479791d77e0SPoul-Henning Kamp {
480791d77e0SPoul-Henning Kamp 	struct putchar_arg *ap = (struct putchar_arg*) arg;
481791d77e0SPoul-Henning Kamp 	struct tty *tp = ap->tty;
4823d068827SJohn Birrell 	int flags = ap->flags;
483d29bf12fSIan Dowse 
484adef9265SIan Dowse 	/* Don't use the tty code after a panic or while in ddb. */
4853d068827SJohn Birrell 	if (kdb_active) {
486d29bf12fSIan Dowse 		if (c != '\0')
487d29bf12fSIan Dowse 			cnputc(c);
48880f1c58bSMarcel Moolenaar 		return;
48980f1c58bSMarcel Moolenaar 	}
49080f1c58bSMarcel Moolenaar 
49180f1c58bSMarcel Moolenaar 	if ((flags & TOTTY) && tp != NULL && panicstr == NULL)
492bc093719SEd Schouten 		tty_putchar(tp, c);
493d42a4eb5SKenneth D. Merry 
49480f1c58bSMarcel Moolenaar 	if ((flags & (TOCONS | TOLOG)) && c != '\0')
495d42a4eb5SKenneth D. Merry 		putbuf(c, ap);
496791d77e0SPoul-Henning Kamp }
497791d77e0SPoul-Henning Kamp 
498791d77e0SPoul-Henning Kamp /*
499791d77e0SPoul-Henning Kamp  * Scaled down version of sprintf(3).
500791d77e0SPoul-Henning Kamp  */
501791d77e0SPoul-Henning Kamp int
502791d77e0SPoul-Henning Kamp sprintf(char *buf, const char *cfmt, ...)
503791d77e0SPoul-Henning Kamp {
504791d77e0SPoul-Henning Kamp 	int retval;
505791d77e0SPoul-Henning Kamp 	va_list ap;
506791d77e0SPoul-Henning Kamp 
507791d77e0SPoul-Henning Kamp 	va_start(ap, cfmt);
508791d77e0SPoul-Henning Kamp 	retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
509fe96d47dSPoul-Henning Kamp 	buf[retval] = '\0';
510791d77e0SPoul-Henning Kamp 	va_end(ap);
51158a24f79SPoul-Henning Kamp 	return (retval);
512791d77e0SPoul-Henning Kamp }
513791d77e0SPoul-Henning Kamp 
514791d77e0SPoul-Henning Kamp /*
51599237364SAndrey A. Chernov  * Scaled down version of vsprintf(3).
51699237364SAndrey A. Chernov  */
51799237364SAndrey A. Chernov int
51899237364SAndrey A. Chernov vsprintf(char *buf, const char *cfmt, va_list ap)
51999237364SAndrey A. Chernov {
52099237364SAndrey A. Chernov 	int retval;
52199237364SAndrey A. Chernov 
52299237364SAndrey A. Chernov 	retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
52399237364SAndrey A. Chernov 	buf[retval] = '\0';
52458a24f79SPoul-Henning Kamp 	return (retval);
52599237364SAndrey A. Chernov }
52699237364SAndrey A. Chernov 
52799237364SAndrey A. Chernov /*
5288245f3f5SArchie Cobbs  * Scaled down version of snprintf(3).
5298245f3f5SArchie Cobbs  */
5308245f3f5SArchie Cobbs int
5318245f3f5SArchie Cobbs snprintf(char *str, size_t size, const char *format, ...)
5328245f3f5SArchie Cobbs {
5338245f3f5SArchie Cobbs 	int retval;
5348245f3f5SArchie Cobbs 	va_list ap;
5358245f3f5SArchie Cobbs 
5368245f3f5SArchie Cobbs 	va_start(ap, format);
5378245f3f5SArchie Cobbs 	retval = vsnprintf(str, size, format, ap);
5388245f3f5SArchie Cobbs 	va_end(ap);
5398245f3f5SArchie Cobbs 	return(retval);
5408245f3f5SArchie Cobbs }
5418245f3f5SArchie Cobbs 
5428245f3f5SArchie Cobbs /*
5438245f3f5SArchie Cobbs  * Scaled down version of vsnprintf(3).
5448245f3f5SArchie Cobbs  */
5458245f3f5SArchie Cobbs int
5468245f3f5SArchie Cobbs vsnprintf(char *str, size_t size, const char *format, va_list ap)
5478245f3f5SArchie Cobbs {
5488245f3f5SArchie Cobbs 	struct snprintf_arg info;
5498245f3f5SArchie Cobbs 	int retval;
5508245f3f5SArchie Cobbs 
5518245f3f5SArchie Cobbs 	info.str = str;
5528245f3f5SArchie Cobbs 	info.remain = size;
5538245f3f5SArchie Cobbs 	retval = kvprintf(format, snprintf_func, &info, 10, ap);
5548245f3f5SArchie Cobbs 	if (info.remain >= 1)
5558245f3f5SArchie Cobbs 		*info.str++ = '\0';
55658a24f79SPoul-Henning Kamp 	return (retval);
5578245f3f5SArchie Cobbs }
5588245f3f5SArchie Cobbs 
5598751a8c7SPoul-Henning Kamp /*
5608751a8c7SPoul-Henning Kamp  * Kernel version which takes radix argument vsnprintf(3).
5618751a8c7SPoul-Henning Kamp  */
5628751a8c7SPoul-Henning Kamp int
5638751a8c7SPoul-Henning Kamp vsnrprintf(char *str, size_t size, int radix, const char *format, va_list ap)
5648751a8c7SPoul-Henning Kamp {
5658751a8c7SPoul-Henning Kamp 	struct snprintf_arg info;
5668751a8c7SPoul-Henning Kamp 	int retval;
5678751a8c7SPoul-Henning Kamp 
5688751a8c7SPoul-Henning Kamp 	info.str = str;
5698751a8c7SPoul-Henning Kamp 	info.remain = size;
5708751a8c7SPoul-Henning Kamp 	retval = kvprintf(format, snprintf_func, &info, radix, ap);
5718751a8c7SPoul-Henning Kamp 	if (info.remain >= 1)
5728751a8c7SPoul-Henning Kamp 		*info.str++ = '\0';
5738751a8c7SPoul-Henning Kamp 	return (retval);
5748751a8c7SPoul-Henning Kamp }
5758751a8c7SPoul-Henning Kamp 
5768245f3f5SArchie Cobbs static void
5778245f3f5SArchie Cobbs snprintf_func(int ch, void *arg)
5788245f3f5SArchie Cobbs {
5798245f3f5SArchie Cobbs 	struct snprintf_arg *const info = arg;
5808245f3f5SArchie Cobbs 
5818245f3f5SArchie Cobbs 	if (info->remain >= 2) {
5828245f3f5SArchie Cobbs 		*info->str++ = ch;
5838245f3f5SArchie Cobbs 		info->remain--;
5848245f3f5SArchie Cobbs 	}
5858245f3f5SArchie Cobbs }
5868245f3f5SArchie Cobbs 
5878245f3f5SArchie Cobbs /*
58882941964SPeter Wemm  * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
58905292ba2SArchie Cobbs  * order; return an optional length and a pointer to the last character
59005292ba2SArchie Cobbs  * written in the buffer (i.e., the first character of the string).
59105292ba2SArchie Cobbs  * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
592791d77e0SPoul-Henning Kamp  */
593791d77e0SPoul-Henning Kamp static char *
5940d84d9ebSJung-uk Kim ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
59505292ba2SArchie Cobbs {
5960d84d9ebSJung-uk Kim 	char *p, c;
597791d77e0SPoul-Henning Kamp 
59805292ba2SArchie Cobbs 	p = nbuf;
599ad4f8dbdSArchie Cobbs 	*p = '\0';
600791d77e0SPoul-Henning Kamp 	do {
6010d84d9ebSJung-uk Kim 		c = hex2ascii(num % base);
6020d84d9ebSJung-uk Kim 		*++p = upper ? toupper(c) : c;
6033b1f7e7dSDag-Erling Smørgrav 	} while (num /= base);
6047d921a01SPeter Wemm 	if (lenp)
6057d921a01SPeter Wemm 		*lenp = p - nbuf;
6067d921a01SPeter Wemm 	return (p);
6077d921a01SPeter Wemm }
608791d77e0SPoul-Henning Kamp 
609df8bae1dSRodney W. Grimes /*
610df8bae1dSRodney W. Grimes  * Scaled down version of printf(3).
611df8bae1dSRodney W. Grimes  *
612df8bae1dSRodney W. Grimes  * Two additional formats:
613df8bae1dSRodney W. Grimes  *
614df8bae1dSRodney W. Grimes  * The format %b is supported to decode error registers.
615df8bae1dSRodney W. Grimes  * Its usage is:
616df8bae1dSRodney W. Grimes  *
617df8bae1dSRodney W. Grimes  *	printf("reg=%b\n", regval, "<base><arg>*");
618df8bae1dSRodney W. Grimes  *
619df8bae1dSRodney W. Grimes  * where <base> is the output base expressed as a control character, e.g.
620df8bae1dSRodney W. Grimes  * \10 gives octal; \20 gives hex.  Each arg is a sequence of characters,
621df8bae1dSRodney W. Grimes  * the first of which gives the bit number to be inspected (origin 1), and
622df8bae1dSRodney W. Grimes  * the next characters (up to a control character, i.e. a character <= 32),
623df8bae1dSRodney W. Grimes  * give the name of the register.  Thus:
624df8bae1dSRodney W. Grimes  *
625c5f282daSAlexey Dokuchaev  *	kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE");
626df8bae1dSRodney W. Grimes  *
627df8bae1dSRodney W. Grimes  * would produce output:
628df8bae1dSRodney W. Grimes  *
629df8bae1dSRodney W. Grimes  *	reg=3<BITTWO,BITONE>
630df8bae1dSRodney W. Grimes  *
631120f0783SPoul-Henning Kamp  * XXX:  %D  -- Hexdump, takes pointer and separator string:
632120f0783SPoul-Henning Kamp  *		("%6D", ptr, ":")   -> XX:XX:XX:XX:XX:XX
633120f0783SPoul-Henning Kamp  *		("%*D", len, ptr, " " -> XX XX XX XX ...
634df8bae1dSRodney W. Grimes  */
635791d77e0SPoul-Henning Kamp int
636791d77e0SPoul-Henning Kamp kvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap)
637df8bae1dSRodney W. Grimes {
638791d77e0SPoul-Henning Kamp #define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; }
639ad4f8dbdSArchie Cobbs 	char nbuf[MAXNBUF];
6403b1f7e7dSDag-Erling Smørgrav 	char *d;
6413b1f7e7dSDag-Erling Smørgrav 	const char *p, *percent, *q;
642120f0783SPoul-Henning Kamp 	u_char *up;
643791d77e0SPoul-Henning Kamp 	int ch, n;
6443b1f7e7dSDag-Erling Smørgrav 	uintmax_t num;
6457d921a01SPeter Wemm 	int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
64632869e71SNate Lawson 	int cflag, hflag, jflag, tflag, zflag;
6470d84d9ebSJung-uk Kim 	int dwidth, upper;
648df8bae1dSRodney W. Grimes 	char padc;
6491e7d2c47SPoul-Henning Kamp 	int stop = 0, retval = 0;
650791d77e0SPoul-Henning Kamp 
6513b1f7e7dSDag-Erling Smørgrav 	num = 0;
652fe96d47dSPoul-Henning Kamp 	if (!func)
653791d77e0SPoul-Henning Kamp 		d = (char *) arg;
654791d77e0SPoul-Henning Kamp 	else
655fe96d47dSPoul-Henning Kamp 		d = NULL;
6568f5067baSDavid Greenman 
6578f5067baSDavid Greenman 	if (fmt == NULL)
6582336b9d7SBruce Evans 		fmt = "(fmt null)\n";
659b4b2f81eSPoul-Henning Kamp 
660120f0783SPoul-Henning Kamp 	if (radix < 2 || radix > 36)
661b4b2f81eSPoul-Henning Kamp 		radix = 10;
662b4b2f81eSPoul-Henning Kamp 
663df8bae1dSRodney W. Grimes 	for (;;) {
664df8bae1dSRodney W. Grimes 		padc = ' ';
665df8bae1dSRodney W. Grimes 		width = 0;
6661e7d2c47SPoul-Henning Kamp 		while ((ch = (u_char)*fmt++) != '%' || stop) {
667df8bae1dSRodney W. Grimes 			if (ch == '\0')
66858a24f79SPoul-Henning Kamp 				return (retval);
669791d77e0SPoul-Henning Kamp 			PCHAR(ch);
670df8bae1dSRodney W. Grimes 		}
6713b1f7e7dSDag-Erling Smørgrav 		percent = fmt - 1;
6727d921a01SPeter Wemm 		qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
6730d84d9ebSJung-uk Kim 		sign = 0; dot = 0; dwidth = 0; upper = 0;
67432869e71SNate Lawson 		cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
675e0c95ed9SBruce Evans reswitch:	switch (ch = (u_char)*fmt++) {
6764830092aSPoul-Henning Kamp 		case '.':
6774830092aSPoul-Henning Kamp 			dot = 1;
6784830092aSPoul-Henning Kamp 			goto reswitch;
679791d77e0SPoul-Henning Kamp 		case '#':
680791d77e0SPoul-Henning Kamp 			sharpflag = 1;
681791d77e0SPoul-Henning Kamp 			goto reswitch;
682791d77e0SPoul-Henning Kamp 		case '+':
683791d77e0SPoul-Henning Kamp 			sign = 1;
684791d77e0SPoul-Henning Kamp 			goto reswitch;
685791d77e0SPoul-Henning Kamp 		case '-':
686791d77e0SPoul-Henning Kamp 			ladjust = 1;
687791d77e0SPoul-Henning Kamp 			goto reswitch;
688791d77e0SPoul-Henning Kamp 		case '%':
689791d77e0SPoul-Henning Kamp 			PCHAR(ch);
690791d77e0SPoul-Henning Kamp 			break;
691791d77e0SPoul-Henning Kamp 		case '*':
692ed71c342SPoul-Henning Kamp 			if (!dot) {
693791d77e0SPoul-Henning Kamp 				width = va_arg(ap, int);
694791d77e0SPoul-Henning Kamp 				if (width < 0) {
695791d77e0SPoul-Henning Kamp 					ladjust = !ladjust;
696791d77e0SPoul-Henning Kamp 					width = -width;
697791d77e0SPoul-Henning Kamp 				}
698ed71c342SPoul-Henning Kamp 			} else {
699ed71c342SPoul-Henning Kamp 				dwidth = va_arg(ap, int);
700ed71c342SPoul-Henning Kamp 			}
701791d77e0SPoul-Henning Kamp 			goto reswitch;
702df8bae1dSRodney W. Grimes 		case '0':
7034f20e4b1SPoul-Henning Kamp 			if (!dot) {
704df8bae1dSRodney W. Grimes 				padc = '0';
705df8bae1dSRodney W. Grimes 				goto reswitch;
7064f20e4b1SPoul-Henning Kamp 			}
707df8bae1dSRodney W. Grimes 		case '1': case '2': case '3': case '4':
708df8bae1dSRodney W. Grimes 		case '5': case '6': case '7': case '8': case '9':
7094f20e4b1SPoul-Henning Kamp 				for (n = 0;; ++fmt) {
7104f20e4b1SPoul-Henning Kamp 					n = n * 10 + ch - '0';
711df8bae1dSRodney W. Grimes 					ch = *fmt;
712df8bae1dSRodney W. Grimes 					if (ch < '0' || ch > '9')
713df8bae1dSRodney W. Grimes 						break;
714df8bae1dSRodney W. Grimes 				}
7154f20e4b1SPoul-Henning Kamp 			if (dot)
7164f20e4b1SPoul-Henning Kamp 				dwidth = n;
7174f20e4b1SPoul-Henning Kamp 			else
7184f20e4b1SPoul-Henning Kamp 				width = n;
719df8bae1dSRodney W. Grimes 			goto reswitch;
720df8bae1dSRodney W. Grimes 		case 'b':
721377a66bcSJohn Baldwin 			num = (u_int)va_arg(ap, int);
722df8bae1dSRodney W. Grimes 			p = va_arg(ap, char *);
7230d84d9ebSJung-uk Kim 			for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;)
724791d77e0SPoul-Henning Kamp 				PCHAR(*q--);
725df8bae1dSRodney W. Grimes 
7263b1f7e7dSDag-Erling Smørgrav 			if (num == 0)
727df8bae1dSRodney W. Grimes 				break;
728df8bae1dSRodney W. Grimes 
729797f2d22SPoul-Henning Kamp 			for (tmp = 0; *p;) {
730797f2d22SPoul-Henning Kamp 				n = *p++;
7313b1f7e7dSDag-Erling Smørgrav 				if (num & (1 << (n - 1))) {
732791d77e0SPoul-Henning Kamp 					PCHAR(tmp ? ',' : '<');
733df8bae1dSRodney W. Grimes 					for (; (n = *p) > ' '; ++p)
734791d77e0SPoul-Henning Kamp 						PCHAR(n);
735df8bae1dSRodney W. Grimes 					tmp = 1;
736df8bae1dSRodney W. Grimes 				} else
737df8bae1dSRodney W. Grimes 					for (; *p > ' '; ++p)
738df8bae1dSRodney W. Grimes 						continue;
739df8bae1dSRodney W. Grimes 			}
740df8bae1dSRodney W. Grimes 			if (tmp)
741791d77e0SPoul-Henning Kamp 				PCHAR('>');
742df8bae1dSRodney W. Grimes 			break;
743df8bae1dSRodney W. Grimes 		case 'c':
744dd6ea7f7SConrad Meyer 			width -= 1;
745dd6ea7f7SConrad Meyer 
746dd6ea7f7SConrad Meyer 			if (!ladjust && width > 0)
747dd6ea7f7SConrad Meyer 				while (width--)
748dd6ea7f7SConrad Meyer 					PCHAR(padc);
749791d77e0SPoul-Henning Kamp 			PCHAR(va_arg(ap, int));
750dd6ea7f7SConrad Meyer 			if (ladjust && width > 0)
751dd6ea7f7SConrad Meyer 				while (width--)
752dd6ea7f7SConrad Meyer 					PCHAR(padc);
753df8bae1dSRodney W. Grimes 			break;
754120f0783SPoul-Henning Kamp 		case 'D':
755120f0783SPoul-Henning Kamp 			up = va_arg(ap, u_char *);
756120f0783SPoul-Henning Kamp 			p = va_arg(ap, char *);
757120f0783SPoul-Henning Kamp 			if (!width)
758120f0783SPoul-Henning Kamp 				width = 16;
759120f0783SPoul-Henning Kamp 			while(width--) {
760120f0783SPoul-Henning Kamp 				PCHAR(hex2ascii(*up >> 4));
761120f0783SPoul-Henning Kamp 				PCHAR(hex2ascii(*up & 0x0f));
762120f0783SPoul-Henning Kamp 				up++;
763120f0783SPoul-Henning Kamp 				if (width)
764120f0783SPoul-Henning Kamp 					for (q=p;*q;q++)
765120f0783SPoul-Henning Kamp 						PCHAR(*q);
766120f0783SPoul-Henning Kamp 			}
767120f0783SPoul-Henning Kamp 			break;
768df8bae1dSRodney W. Grimes 		case 'd':
769e0b74464SWarner Losh 		case 'i':
770df8bae1dSRodney W. Grimes 			base = 10;
7713b1f7e7dSDag-Erling Smørgrav 			sign = 1;
7723b1f7e7dSDag-Erling Smørgrav 			goto handle_sign;
77332869e71SNate Lawson 		case 'h':
77432869e71SNate Lawson 			if (hflag) {
77532869e71SNate Lawson 				hflag = 0;
77632869e71SNate Lawson 				cflag = 1;
77732869e71SNate Lawson 			} else
77832869e71SNate Lawson 				hflag = 1;
77932869e71SNate Lawson 			goto reswitch;
7803b1f7e7dSDag-Erling Smørgrav 		case 'j':
7813b1f7e7dSDag-Erling Smørgrav 			jflag = 1;
7823b1f7e7dSDag-Erling Smørgrav 			goto reswitch;
783791d77e0SPoul-Henning Kamp 		case 'l':
784301ca4ffSBrian Feldman 			if (lflag) {
785301ca4ffSBrian Feldman 				lflag = 0;
786301ca4ffSBrian Feldman 				qflag = 1;
787301ca4ffSBrian Feldman 			} else
788791d77e0SPoul-Henning Kamp 				lflag = 1;
789791d77e0SPoul-Henning Kamp 			goto reswitch;
7903b1f7e7dSDag-Erling Smørgrav 		case 'n':
7913b1f7e7dSDag-Erling Smørgrav 			if (jflag)
7923b1f7e7dSDag-Erling Smørgrav 				*(va_arg(ap, intmax_t *)) = retval;
7933b1f7e7dSDag-Erling Smørgrav 			else if (qflag)
7943b1f7e7dSDag-Erling Smørgrav 				*(va_arg(ap, quad_t *)) = retval;
7957d921a01SPeter Wemm 			else if (lflag)
7963b1f7e7dSDag-Erling Smørgrav 				*(va_arg(ap, long *)) = retval;
7974578a2e6SMaxime Henrion 			else if (zflag)
7984578a2e6SMaxime Henrion 				*(va_arg(ap, size_t *)) = retval;
79932869e71SNate Lawson 			else if (hflag)
80032869e71SNate Lawson 				*(va_arg(ap, short *)) = retval;
80132869e71SNate Lawson 			else if (cflag)
80232869e71SNate Lawson 				*(va_arg(ap, char *)) = retval;
8037d921a01SPeter Wemm 			else
8043b1f7e7dSDag-Erling Smørgrav 				*(va_arg(ap, int *)) = retval;
8053b1f7e7dSDag-Erling Smørgrav 			break;
8063b1f7e7dSDag-Erling Smørgrav 		case 'o':
807df8bae1dSRodney W. Grimes 			base = 8;
8083b1f7e7dSDag-Erling Smørgrav 			goto handle_nosign;
80912d17f65SPoul-Henning Kamp 		case 'p':
81012d17f65SPoul-Henning Kamp 			base = 16;
811c41141b0SBruce Evans 			sharpflag = (width == 0);
8123b1f7e7dSDag-Erling Smørgrav 			sign = 0;
8133b1f7e7dSDag-Erling Smørgrav 			num = (uintptr_t)va_arg(ap, void *);
8143b1f7e7dSDag-Erling Smørgrav 			goto number;
8157d921a01SPeter Wemm 		case 'q':
8167d921a01SPeter Wemm 			qflag = 1;
8177d921a01SPeter Wemm 			goto reswitch;
818e0c38587SBruce Evans 		case 'r':
819e0c38587SBruce Evans 			base = radix;
8203b1f7e7dSDag-Erling Smørgrav 			if (sign)
8213b1f7e7dSDag-Erling Smørgrav 				goto handle_sign;
8223b1f7e7dSDag-Erling Smørgrav 			goto handle_nosign;
823791d77e0SPoul-Henning Kamp 		case 's':
824791d77e0SPoul-Henning Kamp 			p = va_arg(ap, char *);
825791d77e0SPoul-Henning Kamp 			if (p == NULL)
826791d77e0SPoul-Henning Kamp 				p = "(null)";
8274830092aSPoul-Henning Kamp 			if (!dot)
8284830092aSPoul-Henning Kamp 				n = strlen (p);
8294830092aSPoul-Henning Kamp 			else
8304f20e4b1SPoul-Henning Kamp 				for (n = 0; n < dwidth && p[n]; n++)
8314830092aSPoul-Henning Kamp 					continue;
8324f20e4b1SPoul-Henning Kamp 
8334830092aSPoul-Henning Kamp 			width -= n;
8344f20e4b1SPoul-Henning Kamp 
835791d77e0SPoul-Henning Kamp 			if (!ladjust && width > 0)
836791d77e0SPoul-Henning Kamp 				while (width--)
837791d77e0SPoul-Henning Kamp 					PCHAR(padc);
8384830092aSPoul-Henning Kamp 			while (n--)
839791d77e0SPoul-Henning Kamp 				PCHAR(*p++);
840791d77e0SPoul-Henning Kamp 			if (ladjust && width > 0)
841791d77e0SPoul-Henning Kamp 				while (width--)
842791d77e0SPoul-Henning Kamp 					PCHAR(padc);
843791d77e0SPoul-Henning Kamp 			break;
8442bb95458SMaxime Henrion 		case 't':
8452bb95458SMaxime Henrion 			tflag = 1;
8462bb95458SMaxime Henrion 			goto reswitch;
847f53dbe97SBruce Evans 		case 'u':
848f53dbe97SBruce Evans 			base = 10;
8493b1f7e7dSDag-Erling Smørgrav 			goto handle_nosign;
850aa998012SMike Smith 		case 'X':
8510d84d9ebSJung-uk Kim 			upper = 1;
8520d84d9ebSJung-uk Kim 		case 'x':
853df8bae1dSRodney W. Grimes 			base = 16;
8543b1f7e7dSDag-Erling Smørgrav 			goto handle_nosign;
8554578a2e6SMaxime Henrion 		case 'y':
856e0c38587SBruce Evans 			base = 16;
85785594430SJohn Baldwin 			sign = 1;
8583b1f7e7dSDag-Erling Smørgrav 			goto handle_sign;
8594578a2e6SMaxime Henrion 		case 'z':
8604578a2e6SMaxime Henrion 			zflag = 1;
8614578a2e6SMaxime Henrion 			goto reswitch;
8623b1f7e7dSDag-Erling Smørgrav handle_nosign:
8633b1f7e7dSDag-Erling Smørgrav 			sign = 0;
8643b1f7e7dSDag-Erling Smørgrav 			if (jflag)
8653b1f7e7dSDag-Erling Smørgrav 				num = va_arg(ap, uintmax_t);
8663b1f7e7dSDag-Erling Smørgrav 			else if (qflag)
8673b1f7e7dSDag-Erling Smørgrav 				num = va_arg(ap, u_quad_t);
8682bb95458SMaxime Henrion 			else if (tflag)
8692bb95458SMaxime Henrion 				num = va_arg(ap, ptrdiff_t);
8703b1f7e7dSDag-Erling Smørgrav 			else if (lflag)
8713b1f7e7dSDag-Erling Smørgrav 				num = va_arg(ap, u_long);
8724578a2e6SMaxime Henrion 			else if (zflag)
8734578a2e6SMaxime Henrion 				num = va_arg(ap, size_t);
87432869e71SNate Lawson 			else if (hflag)
87532869e71SNate Lawson 				num = (u_short)va_arg(ap, int);
87632869e71SNate Lawson 			else if (cflag)
87732869e71SNate Lawson 				num = (u_char)va_arg(ap, int);
8783b1f7e7dSDag-Erling Smørgrav 			else
8793b1f7e7dSDag-Erling Smørgrav 				num = va_arg(ap, u_int);
880e0c38587SBruce Evans 			goto number;
8813b1f7e7dSDag-Erling Smørgrav handle_sign:
8823b1f7e7dSDag-Erling Smørgrav 			if (jflag)
8833b1f7e7dSDag-Erling Smørgrav 				num = va_arg(ap, intmax_t);
8843b1f7e7dSDag-Erling Smørgrav 			else if (qflag)
8853b1f7e7dSDag-Erling Smørgrav 				num = va_arg(ap, quad_t);
8862bb95458SMaxime Henrion 			else if (tflag)
8872bb95458SMaxime Henrion 				num = va_arg(ap, ptrdiff_t);
8883b1f7e7dSDag-Erling Smørgrav 			else if (lflag)
8893b1f7e7dSDag-Erling Smørgrav 				num = va_arg(ap, long);
8904578a2e6SMaxime Henrion 			else if (zflag)
891e1088cdcSXin LI 				num = va_arg(ap, ssize_t);
89232869e71SNate Lawson 			else if (hflag)
89332869e71SNate Lawson 				num = (short)va_arg(ap, int);
89432869e71SNate Lawson 			else if (cflag)
89532869e71SNate Lawson 				num = (char)va_arg(ap, int);
8963b1f7e7dSDag-Erling Smørgrav 			else
8973b1f7e7dSDag-Erling Smørgrav 				num = va_arg(ap, int);
8987d921a01SPeter Wemm number:
8993b1f7e7dSDag-Erling Smørgrav 			if (sign && (intmax_t)num < 0) {
9007d921a01SPeter Wemm 				neg = 1;
9013b1f7e7dSDag-Erling Smørgrav 				num = -(intmax_t)num;
9027d921a01SPeter Wemm 			}
9034624e08aSJung-uk Kim 			p = ksprintn(nbuf, num, base, &n, upper);
9044624e08aSJung-uk Kim 			tmp = 0;
9053b1f7e7dSDag-Erling Smørgrav 			if (sharpflag && num != 0) {
906791d77e0SPoul-Henning Kamp 				if (base == 8)
907791d77e0SPoul-Henning Kamp 					tmp++;
908791d77e0SPoul-Henning Kamp 				else if (base == 16)
909791d77e0SPoul-Henning Kamp 					tmp += 2;
910791d77e0SPoul-Henning Kamp 			}
911791d77e0SPoul-Henning Kamp 			if (neg)
912791d77e0SPoul-Henning Kamp 				tmp++;
913791d77e0SPoul-Henning Kamp 
9144624e08aSJung-uk Kim 			if (!ladjust && padc == '0')
9154624e08aSJung-uk Kim 				dwidth = width - tmp;
9164a82f108SJung-uk Kim 			width -= tmp + imax(dwidth, n);
9174624e08aSJung-uk Kim 			dwidth -= n;
9184624e08aSJung-uk Kim 			if (!ladjust)
9194624e08aSJung-uk Kim 				while (width-- > 0)
9204624e08aSJung-uk Kim 					PCHAR(' ');
921791d77e0SPoul-Henning Kamp 			if (neg)
922791d77e0SPoul-Henning Kamp 				PCHAR('-');
9233b1f7e7dSDag-Erling Smørgrav 			if (sharpflag && num != 0) {
924791d77e0SPoul-Henning Kamp 				if (base == 8) {
925791d77e0SPoul-Henning Kamp 					PCHAR('0');
926791d77e0SPoul-Henning Kamp 				} else if (base == 16) {
927791d77e0SPoul-Henning Kamp 					PCHAR('0');
928791d77e0SPoul-Henning Kamp 					PCHAR('x');
929791d77e0SPoul-Henning Kamp 				}
930791d77e0SPoul-Henning Kamp 			}
9314624e08aSJung-uk Kim 			while (dwidth-- > 0)
9324624e08aSJung-uk Kim 				PCHAR('0');
933791d77e0SPoul-Henning Kamp 
934797f2d22SPoul-Henning Kamp 			while (*p)
935791d77e0SPoul-Henning Kamp 				PCHAR(*p--);
936791d77e0SPoul-Henning Kamp 
9374624e08aSJung-uk Kim 			if (ladjust)
9384624e08aSJung-uk Kim 				while (width-- > 0)
9394624e08aSJung-uk Kim 					PCHAR(' ');
940791d77e0SPoul-Henning Kamp 
941df8bae1dSRodney W. Grimes 			break;
942df8bae1dSRodney W. Grimes 		default:
9433b1f7e7dSDag-Erling Smørgrav 			while (percent < fmt)
9443b1f7e7dSDag-Erling Smørgrav 				PCHAR(*percent++);
9451e7d2c47SPoul-Henning Kamp 			/*
9462809a6dfSBryan Drewery 			 * Since we ignore a formatting argument it is no
9471e7d2c47SPoul-Henning Kamp 			 * longer safe to obey the remaining formatting
9481e7d2c47SPoul-Henning Kamp 			 * arguments as the arguments will no longer match
9491e7d2c47SPoul-Henning Kamp 			 * the format specs.
9501e7d2c47SPoul-Henning Kamp 			 */
9511e7d2c47SPoul-Henning Kamp 			stop = 1;
952791d77e0SPoul-Henning Kamp 			break;
953df8bae1dSRodney W. Grimes 		}
954df8bae1dSRodney W. Grimes 	}
955791d77e0SPoul-Henning Kamp #undef PCHAR
956df8bae1dSRodney W. Grimes }
957df8bae1dSRodney W. Grimes 
958df8bae1dSRodney W. Grimes /*
959e2a09b26SPoul-Henning Kamp  * Put character in log buffer with a particular priority.
960df8bae1dSRodney W. Grimes  */
961df8bae1dSRodney W. Grimes static void
962e2a09b26SPoul-Henning Kamp msglogchar(int c, int pri)
963e2a09b26SPoul-Henning Kamp {
964e2a09b26SPoul-Henning Kamp 	static int lastpri = -1;
965e2a09b26SPoul-Henning Kamp 	static int dangling;
966e2a09b26SPoul-Henning Kamp 	char nbuf[MAXNBUF];
967e2a09b26SPoul-Henning Kamp 	char *p;
968e2a09b26SPoul-Henning Kamp 
969e2a09b26SPoul-Henning Kamp 	if (!msgbufmapped)
970e2a09b26SPoul-Henning Kamp 		return;
971e2a09b26SPoul-Henning Kamp 	if (c == '\0' || c == '\r')
972e2a09b26SPoul-Henning Kamp 		return;
973e2a09b26SPoul-Henning Kamp 	if (pri != -1 && pri != lastpri) {
974e2a09b26SPoul-Henning Kamp 		if (dangling) {
9754784a469SIan Dowse 			msgbuf_addchar(msgbufp, '\n');
976e2a09b26SPoul-Henning Kamp 			dangling = 0;
977e2a09b26SPoul-Henning Kamp 		}
9784784a469SIan Dowse 		msgbuf_addchar(msgbufp, '<');
9790d84d9ebSJung-uk Kim 		for (p = ksprintn(nbuf, (uintmax_t)pri, 10, NULL, 0); *p;)
9804784a469SIan Dowse 			msgbuf_addchar(msgbufp, *p--);
9814784a469SIan Dowse 		msgbuf_addchar(msgbufp, '>');
982e2a09b26SPoul-Henning Kamp 		lastpri = pri;
983e2a09b26SPoul-Henning Kamp 	}
9844784a469SIan Dowse 	msgbuf_addchar(msgbufp, c);
985e2a09b26SPoul-Henning Kamp 	if (c == '\n') {
986e2a09b26SPoul-Henning Kamp 		dangling = 0;
987e2a09b26SPoul-Henning Kamp 		lastpri = -1;
988e2a09b26SPoul-Henning Kamp 	} else {
989e2a09b26SPoul-Henning Kamp 		dangling = 1;
990e2a09b26SPoul-Henning Kamp 	}
991e2a09b26SPoul-Henning Kamp }
992e2a09b26SPoul-Henning Kamp 
993d42a4eb5SKenneth D. Merry static void
994d42a4eb5SKenneth D. Merry msglogstr(char *str, int pri, int filter_cr)
995d42a4eb5SKenneth D. Merry {
996d42a4eb5SKenneth D. Merry 	if (!msgbufmapped)
997d42a4eb5SKenneth D. Merry 		return;
998d42a4eb5SKenneth D. Merry 
999d42a4eb5SKenneth D. Merry 	msgbuf_addstr(msgbufp, pri, str, filter_cr);
1000d42a4eb5SKenneth D. Merry }
1001d42a4eb5SKenneth D. Merry 
1002e796e00dSPoul-Henning Kamp void
100301ee4395SThomas Moestl msgbufinit(void *ptr, int size)
1004e796e00dSPoul-Henning Kamp {
1005e796e00dSPoul-Henning Kamp 	char *cp;
1006eb9d435aSJonathan Lemon 	static struct msgbuf *oldp = NULL;
1007e796e00dSPoul-Henning Kamp 
1008cca8f980SIan Dowse 	size -= sizeof(*msgbufp);
1009e796e00dSPoul-Henning Kamp 	cp = (char *)ptr;
1010cca8f980SIan Dowse 	msgbufp = (struct msgbuf *)(cp + size);
10114784a469SIan Dowse 	msgbuf_reinit(msgbufp, cp, size);
1012eb9d435aSJonathan Lemon 	if (msgbufmapped && oldp != msgbufp)
10134784a469SIan Dowse 		msgbuf_copy(oldp, msgbufp);
1014e796e00dSPoul-Henning Kamp 	msgbufmapped = 1;
1015eb9d435aSJonathan Lemon 	oldp = msgbufp;
1016e796e00dSPoul-Henning Kamp }
1017e796e00dSPoul-Henning Kamp 
10186f3933faSRobert Watson static int unprivileged_read_msgbuf = 1;
1019d0615c64SAndrew R. Reiter SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_read_msgbuf,
10206f3933faSRobert Watson     CTLFLAG_RW, &unprivileged_read_msgbuf, 0,
10216f3933faSRobert Watson     "Unprivileged processes may read the kernel message buffer");
10226f3933faSRobert Watson 
1023948d3d94SThomas Moestl /* Sysctls for accessing/clearing the msgbuf */
1024948d3d94SThomas Moestl static int
1025948d3d94SThomas Moestl sysctl_kern_msgbuf(SYSCTL_HANDLER_ARGS)
1026948d3d94SThomas Moestl {
10274784a469SIan Dowse 	char buf[128];
10284784a469SIan Dowse 	u_int seq;
10294784a469SIan Dowse 	int error, len;
1030948d3d94SThomas Moestl 
10316f3933faSRobert Watson 	if (!unprivileged_read_msgbuf) {
1032acd3428bSRobert Watson 		error = priv_check(req->td, PRIV_MSGBUF);
10336f3933faSRobert Watson 		if (error)
10346f3933faSRobert Watson 			return (error);
10356f3933faSRobert Watson 	}
10366f3933faSRobert Watson 
10374784a469SIan Dowse 	/* Read the whole buffer, one chunk at a time. */
1038ca1d2f65SEd Schouten 	mtx_lock(&msgbuf_lock);
10394784a469SIan Dowse 	msgbuf_peekbytes(msgbufp, NULL, 0, &seq);
1040ca1d2f65SEd Schouten 	for (;;) {
1041ca1d2f65SEd Schouten 		len = msgbuf_peekbytes(msgbufp, buf, sizeof(buf), &seq);
1042ca1d2f65SEd Schouten 		mtx_unlock(&msgbuf_lock);
1043ca1d2f65SEd Schouten 		if (len == 0)
1044e5197e3aSIan Lepore 			return (SYSCTL_OUT(req, "", 1)); /* add nulterm */
1045ca1d2f65SEd Schouten 
10464784a469SIan Dowse 		error = sysctl_handle_opaque(oidp, buf, len, req);
1047948d3d94SThomas Moestl 		if (error)
1048948d3d94SThomas Moestl 			return (error);
1049ca1d2f65SEd Schouten 
1050ca1d2f65SEd Schouten 		mtx_lock(&msgbuf_lock);
1051948d3d94SThomas Moestl 	}
1052948d3d94SThomas Moestl }
1053948d3d94SThomas Moestl 
1054ca1d2f65SEd Schouten SYSCTL_PROC(_kern, OID_AUTO, msgbuf,
1055ca1d2f65SEd Schouten     CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
10564592c621SWarner Losh     NULL, 0, sysctl_kern_msgbuf, "A", "Contents of kernel message buffer");
1057948d3d94SThomas Moestl 
10584784a469SIan Dowse static int msgbuf_clearflag;
1059948d3d94SThomas Moestl 
1060948d3d94SThomas Moestl static int
1061948d3d94SThomas Moestl sysctl_kern_msgbuf_clear(SYSCTL_HANDLER_ARGS)
1062948d3d94SThomas Moestl {
1063948d3d94SThomas Moestl 	int error;
1064948d3d94SThomas Moestl 	error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
1065948d3d94SThomas Moestl 	if (!error && req->newptr) {
1066ca1d2f65SEd Schouten 		mtx_lock(&msgbuf_lock);
10674784a469SIan Dowse 		msgbuf_clear(msgbufp);
1068ca1d2f65SEd Schouten 		mtx_unlock(&msgbuf_lock);
10694784a469SIan Dowse 		msgbuf_clearflag = 0;
1070948d3d94SThomas Moestl 	}
1071948d3d94SThomas Moestl 	return (error);
1072948d3d94SThomas Moestl }
1073948d3d94SThomas Moestl 
1074948d3d94SThomas Moestl SYSCTL_PROC(_kern, OID_AUTO, msgbuf_clear,
1075ca1d2f65SEd Schouten     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE | CTLFLAG_MPSAFE,
1076ca1d2f65SEd Schouten     &msgbuf_clearflag, 0, sysctl_kern_msgbuf_clear, "I",
1077ca1d2f65SEd Schouten     "Clear kernel message buffer");
1078948d3d94SThomas Moestl 
1079e796e00dSPoul-Henning Kamp #ifdef DDB
1080e796e00dSPoul-Henning Kamp 
1081e796e00dSPoul-Henning Kamp DB_SHOW_COMMAND(msgbuf, db_show_msgbuf)
1082e796e00dSPoul-Henning Kamp {
108319e9205aSJohn Baldwin 	int i, j;
1084e796e00dSPoul-Henning Kamp 
1085e796e00dSPoul-Henning Kamp 	if (!msgbufmapped) {
1086e796e00dSPoul-Henning Kamp 		db_printf("msgbuf not mapped yet\n");
1087e796e00dSPoul-Henning Kamp 		return;
1088e796e00dSPoul-Henning Kamp 	}
1089e796e00dSPoul-Henning Kamp 	db_printf("msgbufp = %p\n", msgbufp);
10904784a469SIan Dowse 	db_printf("magic = %x, size = %d, r= %u, w = %u, ptr = %p, cksum= %u\n",
10914784a469SIan Dowse 	    msgbufp->msg_magic, msgbufp->msg_size, msgbufp->msg_rseq,
10924784a469SIan Dowse 	    msgbufp->msg_wseq, msgbufp->msg_ptr, msgbufp->msg_cksum);
109319e9205aSJohn Baldwin 	for (i = 0; i < msgbufp->msg_size && !db_pager_quit; i++) {
10944784a469SIan Dowse 		j = MSGBUF_SEQ_TO_POS(msgbufp, i + msgbufp->msg_rseq);
1095e796e00dSPoul-Henning Kamp 		db_printf("%c", msgbufp->msg_ptr[j]);
1096e796e00dSPoul-Henning Kamp 	}
1097e796e00dSPoul-Henning Kamp 	db_printf("\n");
1098e796e00dSPoul-Henning Kamp }
1099e796e00dSPoul-Henning Kamp 
1100e796e00dSPoul-Henning Kamp #endif /* DDB */
110177411499SScott Long 
110277411499SScott Long void
110330a1695bSPoul-Henning Kamp hexdump(const void *ptr, int length, const char *hdr, int flags)
110477411499SScott Long {
110577411499SScott Long 	int i, j, k;
110677411499SScott Long 	int cols;
110730a1695bSPoul-Henning Kamp 	const unsigned char *cp;
110877411499SScott Long 	char delim;
110977411499SScott Long 
111077411499SScott Long 	if ((flags & HD_DELIM_MASK) != 0)
111177411499SScott Long 		delim = (flags & HD_DELIM_MASK) >> 8;
111277411499SScott Long 	else
111377411499SScott Long 		delim = ' ';
111477411499SScott Long 
111577411499SScott Long 	if ((flags & HD_COLUMN_MASK) != 0)
111677411499SScott Long 		cols = flags & HD_COLUMN_MASK;
111777411499SScott Long 	else
111877411499SScott Long 		cols = 16;
111977411499SScott Long 
112077411499SScott Long 	cp = ptr;
112177411499SScott Long 	for (i = 0; i < length; i+= cols) {
112277411499SScott Long 		if (hdr != NULL)
112377411499SScott Long 			printf("%s", hdr);
112477411499SScott Long 
112577411499SScott Long 		if ((flags & HD_OMIT_COUNT) == 0)
112677411499SScott Long 			printf("%04x  ", i);
112777411499SScott Long 
112877411499SScott Long 		if ((flags & HD_OMIT_HEX) == 0) {
112977411499SScott Long 			for (j = 0; j < cols; j++) {
113077411499SScott Long 				k = i + j;
113177411499SScott Long 				if (k < length)
113277411499SScott Long 					printf("%c%02x", delim, cp[k]);
113377411499SScott Long 				else
113477411499SScott Long 					printf("   ");
113577411499SScott Long 			}
113677411499SScott Long 		}
113777411499SScott Long 
113877411499SScott Long 		if ((flags & HD_OMIT_CHARS) == 0) {
113977411499SScott Long 			printf("  |");
114077411499SScott Long 			for (j = 0; j < cols; j++) {
114177411499SScott Long 				k = i + j;
114277411499SScott Long 				if (k >= length)
114377411499SScott Long 					printf(" ");
114477411499SScott Long 				else if (cp[k] >= ' ' && cp[k] <= '~')
114577411499SScott Long 					printf("%c", cp[k]);
114677411499SScott Long 				else
114777411499SScott Long 					printf(".");
114877411499SScott Long 			}
11496ec6fb9bSScott Long 			printf("|");
115077411499SScott Long 		}
11516ec6fb9bSScott Long 		printf("\n");
115277411499SScott Long 	}
115377411499SScott Long }
11545672fac9SKenneth D. Merry #endif /* _KERNEL */
11555672fac9SKenneth D. Merry 
11565672fac9SKenneth D. Merry void
11575672fac9SKenneth D. Merry sbuf_hexdump(struct sbuf *sb, const void *ptr, int length, const char *hdr,
11585672fac9SKenneth D. Merry 	     int flags)
11595672fac9SKenneth D. Merry {
11605672fac9SKenneth D. Merry 	int i, j, k;
11615672fac9SKenneth D. Merry 	int cols;
11625672fac9SKenneth D. Merry 	const unsigned char *cp;
11635672fac9SKenneth D. Merry 	char delim;
11645672fac9SKenneth D. Merry 
11655672fac9SKenneth D. Merry 	if ((flags & HD_DELIM_MASK) != 0)
11665672fac9SKenneth D. Merry 		delim = (flags & HD_DELIM_MASK) >> 8;
11675672fac9SKenneth D. Merry 	else
11685672fac9SKenneth D. Merry 		delim = ' ';
11695672fac9SKenneth D. Merry 
11705672fac9SKenneth D. Merry 	if ((flags & HD_COLUMN_MASK) != 0)
11715672fac9SKenneth D. Merry 		cols = flags & HD_COLUMN_MASK;
11725672fac9SKenneth D. Merry 	else
11735672fac9SKenneth D. Merry 		cols = 16;
11745672fac9SKenneth D. Merry 
11755672fac9SKenneth D. Merry 	cp = ptr;
11765672fac9SKenneth D. Merry 	for (i = 0; i < length; i+= cols) {
11775672fac9SKenneth D. Merry 		if (hdr != NULL)
11785672fac9SKenneth D. Merry 			sbuf_printf(sb, "%s", hdr);
11795672fac9SKenneth D. Merry 
11805672fac9SKenneth D. Merry 		if ((flags & HD_OMIT_COUNT) == 0)
11815672fac9SKenneth D. Merry 			sbuf_printf(sb, "%04x  ", i);
11825672fac9SKenneth D. Merry 
11835672fac9SKenneth D. Merry 		if ((flags & HD_OMIT_HEX) == 0) {
11845672fac9SKenneth D. Merry 			for (j = 0; j < cols; j++) {
11855672fac9SKenneth D. Merry 				k = i + j;
11865672fac9SKenneth D. Merry 				if (k < length)
11875672fac9SKenneth D. Merry 					sbuf_printf(sb, "%c%02x", delim, cp[k]);
11885672fac9SKenneth D. Merry 				else
11895672fac9SKenneth D. Merry 					sbuf_printf(sb, "   ");
11905672fac9SKenneth D. Merry 			}
11915672fac9SKenneth D. Merry 		}
11925672fac9SKenneth D. Merry 
11935672fac9SKenneth D. Merry 		if ((flags & HD_OMIT_CHARS) == 0) {
11945672fac9SKenneth D. Merry 			sbuf_printf(sb, "  |");
11955672fac9SKenneth D. Merry 			for (j = 0; j < cols; j++) {
11965672fac9SKenneth D. Merry 				k = i + j;
11975672fac9SKenneth D. Merry 				if (k >= length)
11985672fac9SKenneth D. Merry 					sbuf_printf(sb, " ");
11995672fac9SKenneth D. Merry 				else if (cp[k] >= ' ' && cp[k] <= '~')
12005672fac9SKenneth D. Merry 					sbuf_printf(sb, "%c", cp[k]);
12015672fac9SKenneth D. Merry 				else
12025672fac9SKenneth D. Merry 					sbuf_printf(sb, ".");
12035672fac9SKenneth D. Merry 			}
12045672fac9SKenneth D. Merry 			sbuf_printf(sb, "|");
12055672fac9SKenneth D. Merry 		}
12065672fac9SKenneth D. Merry 		sbuf_printf(sb, "\n");
12075672fac9SKenneth D. Merry 	}
12085672fac9SKenneth D. Merry }
12095672fac9SKenneth D. Merry 
1210492fe1b7SKonstantin Belousov #ifdef _KERNEL
12119837947bSKonstantin Belousov void
12129837947bSKonstantin Belousov counted_warning(unsigned *counter, const char *msg)
12139837947bSKonstantin Belousov {
12149837947bSKonstantin Belousov 	struct thread *td;
12159837947bSKonstantin Belousov 	unsigned c;
12169837947bSKonstantin Belousov 
12179837947bSKonstantin Belousov 	for (;;) {
12189837947bSKonstantin Belousov 		c = *counter;
12199837947bSKonstantin Belousov 		if (c == 0)
12209837947bSKonstantin Belousov 			break;
12219837947bSKonstantin Belousov 		if (atomic_cmpset_int(counter, c, c - 1)) {
12229837947bSKonstantin Belousov 			td = curthread;
12239837947bSKonstantin Belousov 			log(LOG_INFO, "pid %d (%s) %s%s\n",
12249837947bSKonstantin Belousov 			    td->td_proc->p_pid, td->td_name, msg,
12259837947bSKonstantin Belousov 			    c > 1 ? "" : " - not logging anymore");
12269837947bSKonstantin Belousov 			break;
12279837947bSKonstantin Belousov 		}
12289837947bSKonstantin Belousov 	}
12299837947bSKonstantin Belousov }
1230492fe1b7SKonstantin Belousov #endif
1231388f3ce6SScott Long 
1232388f3ce6SScott Long #ifdef _KERNEL
1233388f3ce6SScott Long void
1234388f3ce6SScott Long sbuf_putbuf(struct sbuf *sb)
1235388f3ce6SScott Long {
1236388f3ce6SScott Long 
1237388f3ce6SScott Long 	prf_putbuf(sbuf_data(sb), TOLOG | TOCONS, -1);
1238388f3ce6SScott Long }
1239388f3ce6SScott Long #else
1240388f3ce6SScott Long void
1241388f3ce6SScott Long sbuf_putbuf(struct sbuf *sb)
1242388f3ce6SScott Long {
1243388f3ce6SScott Long 
1244388f3ce6SScott Long 	printf("%s", sbuf_data(sb));
1245388f3ce6SScott Long }
1246388f3ce6SScott Long #endif
1247