11541Srgrimes/*-
21541Srgrimes * Copyright (c) 1986, 1988, 1991, 1993
31541Srgrimes *	The Regents of the University of California.  All rights reserved.
41541Srgrimes * (c) UNIX System Laboratories, Inc.
51541Srgrimes * All or some portions of this file are derived from material licensed
61541Srgrimes * to the University of California by American Telephone and Telegraph
71541Srgrimes * Co. or Unix System Laboratories, Inc. and are reproduced herein with
81541Srgrimes * the permission of UNIX System Laboratories, Inc.
91541Srgrimes *
101541Srgrimes * Redistribution and use in source and binary forms, with or without
111541Srgrimes * modification, are permitted provided that the following conditions
121541Srgrimes * are met:
131541Srgrimes * 1. Redistributions of source code must retain the above copyright
141541Srgrimes *    notice, this list of conditions and the following disclaimer.
151541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
161541Srgrimes *    notice, this list of conditions and the following disclaimer in the
171541Srgrimes *    documentation and/or other materials provided with the distribution.
181541Srgrimes * 4. Neither the name of the University nor the names of its contributors
191541Srgrimes *    may be used to endorse or promote products derived from this software
201541Srgrimes *    without specific prior written permission.
211541Srgrimes *
221541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
231541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
241541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
251541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
261541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
271541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
281541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
291541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
301541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
311541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
321541Srgrimes * SUCH DAMAGE.
331541Srgrimes *
341541Srgrimes *	@(#)subr_prf.c	8.3 (Berkeley) 1/21/94
351541Srgrimes */
361541Srgrimes
37116182Sobrien#include <sys/cdefs.h>
38116182Sobrien__FBSDID("$FreeBSD: stable/10/sys/kern/subr_prf.c 321108 2017-07-18 06:45:41Z ngie $");
39116182Sobrien
40284435Sken#ifdef _KERNEL
41108678Sphk#include "opt_ddb.h"
42164760Sjb#include "opt_printf.h"
43284435Sken#endif  /* _KERNEL */
44108678Sphk
451541Srgrimes#include <sys/param.h>
46284435Sken#ifdef _KERNEL
471541Srgrimes#include <sys/systm.h>
4891140Stanimura#include <sys/lock.h>
49131931Smarcel#include <sys/kdb.h>
5091140Stanimura#include <sys/mutex.h>
5191140Stanimura#include <sys/sx.h>
5236441Sphk#include <sys/kernel.h>
531541Srgrimes#include <sys/msgbuf.h>
5430354Sphk#include <sys/malloc.h>
55164033Srwatson#include <sys/priv.h>
561541Srgrimes#include <sys/proc.h>
57106855Smux#include <sys/stddef.h>
5890490Sphk#include <sys/sysctl.h>
591541Srgrimes#include <sys/tty.h>
601541Srgrimes#include <sys/syslog.h>
6149558Sphk#include <sys/cons.h>
6270239Sphk#include <sys/uio.h>
63284435Sken#endif
64156518Sjkim#include <sys/ctype.h>
65284435Sken#include <sys/sbuf.h>
661541Srgrimes
67108678Sphk#ifdef DDB
68108678Sphk#include <ddb/ddb.h>
69108678Sphk#endif
70108678Sphk
711541Srgrimes/*
721541Srgrimes * Note that stdarg.h and the ANSI style va_start macro is used for both
731541Srgrimes * ANSI and traditional C compilers.
741541Srgrimes */
75321108Sngie#ifdef _KERNEL
761541Srgrimes#include <machine/stdarg.h>
77321108Sngie#else
78321108Sngie#include <stdarg.h>
79321108Sngie#endif
801541Srgrimes
81321108Sngie/*
82321108Sngie * This is needed for sbuf_putbuf() when compiled into userland.  Due to the
83321108Sngie * shared nature of this file, it's the only place to put it.
84321108Sngie */
85321108Sngie#ifndef _KERNEL
86321108Sngie#include <stdio.h>
87321108Sngie#endif
88321108Sngie
89284435Sken#ifdef _KERNEL
90284435Sken
911541Srgrimes#define TOCONS	0x01
921541Srgrimes#define TOTTY	0x02
931541Srgrimes#define TOLOG	0x04
941541Srgrimes
9548728Speter/* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */
9697749Sdes#define MAXNBUF	(sizeof(intmax_t) * NBBY + 1)
9747773Sarchie
9841479Sarchiestruct putchar_arg {
9947822Sarchie	int	flags;
10070239Sphk	int	pri;
10147822Sarchie	struct	tty *tty;
102163858Sjb	char	*p_bufr;
103163858Sjb	size_t	n_bufr;
104163858Sjb	char	*p_next;
105163858Sjb	size_t	remain;
10641479Sarchie};
10741479Sarchie
10841479Sarchiestruct snprintf_arg {
10947822Sarchie	char	*str;
11047822Sarchie	size_t	remain;
11141479Sarchie};
11241479Sarchie
11370239Sphkextern	int log_open;
11470239Sphk
11570239Sphkstatic void  msglogchar(int c, int pri);
116222537Skenstatic void  msglogstr(char *str, int pri, int filter_cr);
11792723Salfredstatic void  putchar(int ch, void *arg);
118156518Sjkimstatic char *ksprintn(char *nbuf, uintmax_t num, int base, int *len, int upper);
11992723Salfredstatic void  snprintf_func(int ch, void *arg);
1201541Srgrimes
12136441Sphkstatic int msgbufmapped;		/* Set when safe to use msgbuf */
12270239Sphkint msgbuftrigger;
1231541Srgrimes
12495713Sdwmalonestatic int      log_console_output = 1;
125101693SdwmaloneTUNABLE_INT("kern.log_console_output", &log_console_output);
12695713SdwmaloneSYSCTL_INT(_kern, OID_AUTO, log_console_output, CTLFLAG_RW,
127130700Sgreen    &log_console_output, 0, "Duplicate console output to the syslog.");
12895713Sdwmalone
129222537Sken/*
130222537Sken * See the comment in log_console() below for more explanation of this.
131222537Sken */
132222537Skenstatic int log_console_add_linefeed = 0;
133222537SkenTUNABLE_INT("kern.log_console_add_linefeed", &log_console_add_linefeed);
134222537SkenSYSCTL_INT(_kern, OID_AUTO, log_console_add_linefeed, CTLFLAG_RW,
135222537Sken    &log_console_add_linefeed, 0, "log_console() adds extra newlines.");
136222537Sken
137130700Sgreenstatic int	always_console_output = 0;
138130700SgreenTUNABLE_INT("kern.always_console_output", &always_console_output);
139130700SgreenSYSCTL_INT(_kern, OID_AUTO, always_console_output, CTLFLAG_RW,
140130700Sgreen    &always_console_output, 0, "Always output to console despite TIOCCONS.");
141130700Sgreen
1421541Srgrimes/*
1431541Srgrimes * Warn that a system table is full.
1441541Srgrimes */
1451541Srgrimesvoid
14670239Sphktablefull(const char *tab)
1471541Srgrimes{
1481541Srgrimes
1491541Srgrimes	log(LOG_ERR, "%s: table is full\n", tab);
1501541Srgrimes}
1511541Srgrimes
1521541Srgrimes/*
1531541Srgrimes * Uprintf prints to the controlling terminal for the current process.
1541541Srgrimes */
15549047Sdfrint
1561541Srgrimesuprintf(const char *fmt, ...)
1571541Srgrimes{
1581541Srgrimes	va_list ap;
15913446Sphk	struct putchar_arg pca;
160189102Sed	struct proc *p;
161189102Sed	struct thread *td;
16291140Stanimura	int retval;
1631541Srgrimes
164189102Sed	td = curthread;
165189102Sed	if (TD_IS_IDLETHREAD(td))
16691140Stanimura		return (0);
16791140Stanimura
168181905Sed	sx_slock(&proctree_lock);
169189102Sed	p = td->td_proc;
17091140Stanimura	PROC_LOCK(p);
17191140Stanimura	if ((p->p_flag & P_CONTROLT) == 0) {
17291140Stanimura		PROC_UNLOCK(p);
173255509Skib		sx_sunlock(&proctree_lock);
174255509Skib		return (0);
1751541Srgrimes	}
17691140Stanimura	SESS_LOCK(p->p_session);
17791140Stanimura	pca.tty = p->p_session->s_ttyp;
17891140Stanimura	SESS_UNLOCK(p->p_session);
17991140Stanimura	PROC_UNLOCK(p);
180150560Srwatson	if (pca.tty == NULL) {
181255509Skib		sx_sunlock(&proctree_lock);
182255509Skib		return (0);
183150560Srwatson	}
18491140Stanimura	pca.flags = TOTTY;
185222804Sken	pca.p_bufr = NULL;
18691140Stanimura	va_start(ap, fmt);
187181905Sed	tty_lock(pca.tty);
188255509Skib	sx_sunlock(&proctree_lock);
18991140Stanimura	retval = kvprintf(fmt, putchar, &pca, 10, ap);
190181905Sed	tty_unlock(pca.tty);
19191140Stanimura	va_end(ap);
19290490Sphk	return (retval);
1931541Srgrimes}
1941541Srgrimes
1951541Srgrimes/*
196255351Snp * tprintf and vtprintf print on the controlling terminal associated with the
197255351Snp * given session, possibly to the log as well.
1981541Srgrimes */
19969214Sphkvoid
20069214Sphktprintf(struct proc *p, int pri, const char *fmt, ...)
2011541Srgrimes{
202255351Snp	va_list ap;
203255351Snp
204255351Snp	va_start(ap, fmt);
205255351Snp	vtprintf(p, pri, fmt, ap);
206255351Snp	va_end(ap);
207255351Snp}
208255351Snp
209255351Snpvoid
210255351Snpvtprintf(struct proc *p, int pri, const char *fmt, va_list ap)
211255351Snp{
2121541Srgrimes	struct tty *tp = NULL;
213113634Sjhb	int flags = 0;
21413446Sphk	struct putchar_arg pca;
215113634Sjhb	struct session *sess = NULL;
2161541Srgrimes
217181905Sed	sx_slock(&proctree_lock);
21870239Sphk	if (pri != -1)
21969214Sphk		flags |= TOLOG;
22091140Stanimura	if (p != NULL) {
22191140Stanimura		PROC_LOCK(p);
22291140Stanimura		if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
223113634Sjhb			sess = p->p_session;
224181905Sed			sess_hold(sess);
22591140Stanimura			PROC_UNLOCK(p);
226113634Sjhb			tp = sess->s_ttyp;
227181905Sed			if (tp != NULL && tty_checkoutq(tp))
22891140Stanimura				flags |= TOTTY;
22991140Stanimura			else
23091140Stanimura				tp = NULL;
23191140Stanimura		} else
23291140Stanimura			PROC_UNLOCK(p);
23369214Sphk	}
23470239Sphk	pca.pri = pri;
23513446Sphk	pca.tty = tp;
23613446Sphk	pca.flags = flags;
237222804Sken	pca.p_bufr = NULL;
238181905Sed	if (pca.tty != NULL)
239181905Sed		tty_lock(pca.tty);
240255509Skib	sx_sunlock(&proctree_lock);
241115538Sphk	kvprintf(fmt, putchar, &pca, 10, ap);
242181905Sed	if (pca.tty != NULL)
243181905Sed		tty_unlock(pca.tty);
244143740Sphk	if (sess != NULL)
245181905Sed		sess_release(sess);
24670239Sphk	msgbuftrigger = 1;
2471541Srgrimes}
2481541Srgrimes
2491541Srgrimes/*
2501541Srgrimes * Ttyprintf displays a message on a tty; it should be used only by
2511541Srgrimes * the tty driver, or anything that knows the underlying tty will not
2521541Srgrimes * be revoke(2)'d away.  Other callers should use tprintf.
2531541Srgrimes */
25449047Sdfrint
2551541Srgrimesttyprintf(struct tty *tp, const char *fmt, ...)
2561541Srgrimes{
2571541Srgrimes	va_list ap;
25813446Sphk	struct putchar_arg pca;
25949047Sdfr	int retval;
26049047Sdfr
2611541Srgrimes	va_start(ap, fmt);
26213446Sphk	pca.tty = tp;
26313446Sphk	pca.flags = TOTTY;
264222804Sken	pca.p_bufr = NULL;
26549047Sdfr	retval = kvprintf(fmt, putchar, &pca, 10, ap);
2661541Srgrimes	va_end(ap);
26790490Sphk	return (retval);
2681541Srgrimes}
2691541Srgrimes
270263941Sbdrewerystatic int
271263941Sbdrewery_vprintf(int level, int flags, const char *fmt, va_list ap)
2721541Srgrimes{
27370239Sphk	struct putchar_arg pca;
274263941Sbdrewery	int retval;
275222537Sken#ifdef PRINTF_BUFR_SIZE
276222537Sken	char bufr[PRINTF_BUFR_SIZE];
277222537Sken#endif
2781541Srgrimes
27970239Sphk	pca.tty = NULL;
28070239Sphk	pca.pri = level;
281263941Sbdrewery	pca.flags = flags;
282222537Sken#ifdef PRINTF_BUFR_SIZE
283222537Sken	pca.p_bufr = bufr;
284222537Sken	pca.p_next = pca.p_bufr;
285222537Sken	pca.n_bufr = sizeof(bufr);
286222537Sken	pca.remain = sizeof(bufr);
287222537Sken	*pca.p_next = '\0';
288222537Sken#else
289263941Sbdrewery	/* Don't buffer console output. */
290163858Sjb	pca.p_bufr = NULL;
291222537Sken#endif
29270239Sphk
293263941Sbdrewery	retval = kvprintf(fmt, putchar, &pca, 10, ap);
29413446Sphk
295222537Sken#ifdef PRINTF_BUFR_SIZE
296222537Sken	/* Write any buffered console/log output: */
297222537Sken	if (*pca.p_bufr != '\0') {
298222537Sken		if (pca.flags & TOLOG)
299222537Sken			msglogstr(pca.p_bufr, level, /*filter_cr*/1);
300222537Sken
301222537Sken		if (pca.flags & TOCONS)
302222537Sken			cnputs(pca.p_bufr);
303222537Sken	}
304222537Sken#endif
305263941Sbdrewery
306263941Sbdrewery	return (retval);
307263941Sbdrewery}
308263941Sbdrewery
309263941Sbdrewery/*
310263941Sbdrewery * Log writes to the log buffer, and guarantees not to sleep (so can be
311263941Sbdrewery * called by interrupt routines).  If there is no process reading the
312263941Sbdrewery * log yet, it writes to the console also.
313263941Sbdrewery */
314263941Sbdreweryvoid
315263941Sbdrewerylog(int level, const char *fmt, ...)
316263941Sbdrewery{
317263941Sbdrewery	va_list ap;
318263941Sbdrewery
319263941Sbdrewery	va_start(ap, fmt);
320288497Svangyzen	(void)_vprintf(level, log_open ? TOLOG : TOCONS | TOLOG, fmt, ap);
321263941Sbdrewery	va_end(ap);
322263941Sbdrewery
32370240Sphk	msgbuftrigger = 1;
3241541Srgrimes}
3251541Srgrimes
32670239Sphk#define CONSCHUNK 128
32770239Sphk
32870239Sphkvoid
32970239Sphklog_console(struct uio *uio)
3301541Srgrimes{
331222537Sken	int c, error, nl;
33270239Sphk	char *consbuffer;
33370239Sphk	int pri;
3341541Srgrimes
33595713Sdwmalone	if (!log_console_output)
33695713Sdwmalone		return;
33795713Sdwmalone
33870239Sphk	pri = LOG_INFO | LOG_CONSOLE;
339131897Sphk	uio = cloneuio(uio);
340131897Sphk	consbuffer = malloc(CONSCHUNK, M_TEMP, M_WAITOK);
34170239Sphk
342186383Sed	nl = 0;
34370239Sphk	while (uio->uio_resid > 0) {
344222537Sken		c = imin(uio->uio_resid, CONSCHUNK - 1);
34570239Sphk		error = uiomove(consbuffer, c, uio);
34670239Sphk		if (error != 0)
347104114Sphk			break;
348222537Sken		/* Make sure we're NUL-terminated */
349222537Sken		consbuffer[c] = '\0';
350222537Sken		if (consbuffer[c - 1] == '\n')
351222537Sken			nl = 1;
352222537Sken		else
353222537Sken			nl = 0;
354222537Sken		msglogstr(consbuffer, pri, /*filter_cr*/ 1);
35570239Sphk	}
356222537Sken	/*
357222537Sken	 * The previous behavior in log_console() is preserved when
358222537Sken	 * log_console_add_linefeed is non-zero.  For that behavior, if an
359222537Sken	 * individual console write came in that was not terminated with a
360222537Sken	 * line feed, it would add a line feed.
361222537Sken	 *
362222537Sken	 * This results in different data in the message buffer than
363222537Sken	 * appears on the system console (which doesn't add extra line feed
364222537Sken	 * characters).
365222537Sken	 *
366222537Sken	 * A number of programs and rc scripts write a line feed, or a period
367222537Sken	 * and a line feed when they have completed their operation.  On
368222537Sken	 * the console, this looks seamless, but when displayed with
369222537Sken	 * 'dmesg -a', you wind up with output that looks like this:
370222537Sken	 *
371222537Sken	 * Updating motd:
372222537Sken	 * .
373222537Sken	 *
374222537Sken	 * On the console, it looks like this:
375222537Sken	 * Updating motd:.
376222537Sken	 *
377222537Sken	 * We could add logic to detect that situation, or just not insert
378222537Sken	 * the extra newlines.  Set the kern.log_console_add_linefeed
379222537Sken	 * sysctl/tunable variable to get the old behavior.
380222537Sken	 */
381222537Sken	if (!nl && log_console_add_linefeed) {
382222537Sken		consbuffer[0] = '\n';
383222537Sken		consbuffer[1] = '\0';
384222537Sken		msglogstr(consbuffer, pri, /*filter_cr*/ 1);
385222537Sken	}
38670240Sphk	msgbuftrigger = 1;
387131897Sphk	free(uio, M_IOV);
388131897Sphk	free(consbuffer, M_TEMP);
3891541Srgrimes}
3901541Srgrimes
39115680Sgpalmerint
3921541Srgrimesprintf(const char *fmt, ...)
3931541Srgrimes{
3941541Srgrimes	va_list ap;
39513694Sgibbs	int retval;
3961541Srgrimes
3971541Srgrimes	va_start(ap, fmt);
398189104Sed	retval = vprintf(fmt, ap);
3991541Srgrimes	va_end(ap);
400163858Sjb
40190490Sphk	return (retval);
4021541Srgrimes}
4031541Srgrimes
40449047Sdfrint
40513446Sphkvprintf(const char *fmt, va_list ap)
40613446Sphk{
40749047Sdfr	int retval;
40813446Sphk
409263941Sbdrewery	retval = _vprintf(-1, TOCONS | TOLOG, fmt, ap);
410163858Sjb
41113446Sphk	if (!panicstr)
41270240Sphk		msgbuftrigger = 1;
413163858Sjb
41490490Sphk	return (retval);
41513446Sphk}
41613446Sphk
417163858Sjbstatic void
418321108Sngieprf_putbuf(char *bufr, int flags, int pri)
419321108Sngie{
420321108Sngie
421321108Sngie	if (flags & TOLOG)
422321108Sngie		msglogstr(bufr, pri, /*filter_cr*/1);
423321108Sngie
424321108Sngie	if (flags & TOCONS) {
425321108Sngie		if ((panicstr == NULL) && (constty != NULL))
426321108Sngie			msgbuf_addstr(&consmsgbuf, -1,
427321108Sngie			    bufr, /*filter_cr*/ 0);
428321108Sngie
429321108Sngie		if ((constty == NULL) ||(always_console_output))
430321108Sngie			cnputs(bufr);
431321108Sngie	}
432321108Sngie}
433321108Sngie
434321108Sngiestatic void
435222537Skenputbuf(int c, struct putchar_arg *ap)
436163858Sjb{
437163858Sjb	/* Check if no console output buffer was provided. */
438222537Sken	if (ap->p_bufr == NULL) {
439163858Sjb		/* Output direct to the console. */
440222537Sken		if (ap->flags & TOCONS)
441222537Sken			cnputc(c);
442222537Sken
443222537Sken		if (ap->flags & TOLOG)
444222537Sken			msglogchar(c, ap->pri);
445222537Sken	} else {
446163858Sjb		/* Buffer the character: */
447163858Sjb		*ap->p_next++ = c;
448163858Sjb		ap->remain--;
449163858Sjb
450163858Sjb		/* Always leave the buffer zero terminated. */
451163858Sjb		*ap->p_next = '\0';
452163858Sjb
453163858Sjb		/* Check if the buffer needs to be flushed. */
454222537Sken		if (ap->remain == 2 || c == '\n') {
455321108Sngie			prf_putbuf(ap->p_bufr, ap->flags, ap->pri);
456222537Sken
457163858Sjb			ap->p_next = ap->p_bufr;
458163858Sjb			ap->remain = ap->n_bufr;
459163858Sjb			*ap->p_next = '\0';
460163858Sjb		}
461222537Sken
462222537Sken		/*
463222537Sken		 * Since we fill the buffer up one character at a time,
464222537Sken		 * this should not happen.  We should always catch it when
465222537Sken		 * ap->remain == 2 (if not sooner due to a newline), flush
466222537Sken		 * the buffer and move on.  One way this could happen is
467222537Sken		 * if someone sets PRINTF_BUFR_SIZE to 1 or something
468222537Sken		 * similarly silly.
469222537Sken		 */
470222537Sken		KASSERT(ap->remain > 2, ("Bad buffer logic, remain = %zd",
471222537Sken		    ap->remain));
472163858Sjb	}
473163858Sjb}
474163858Sjb
4751541Srgrimes/*
47613446Sphk * Print a character on console or users terminal.  If destination is
47736441Sphk * the console then the last bunch of characters are saved in msgbuf for
47813446Sphk * inspection later.
47913446Sphk */
48013446Sphkstatic void
48113446Sphkputchar(int c, void *arg)
48213446Sphk{
48313446Sphk	struct putchar_arg *ap = (struct putchar_arg*) arg;
48413446Sphk	struct tty *tp = ap->tty;
485163858Sjb	int flags = ap->flags;
486116663Siedowse
487116664Siedowse	/* Don't use the tty code after a panic or while in ddb. */
488163858Sjb	if (kdb_active) {
489116663Siedowse		if (c != '\0')
490116663Siedowse			cnputc(c);
491226435Smarcel		return;
492226435Smarcel	}
493222537Sken
494226435Smarcel	if ((flags & TOTTY) && tp != NULL && panicstr == NULL)
495226435Smarcel		tty_putchar(tp, c);
496226435Smarcel
497226435Smarcel	if ((flags & (TOCONS | TOLOG)) && c != '\0')
498226435Smarcel		putbuf(c, ap);
49913446Sphk}
50013446Sphk
50113446Sphk/*
50213446Sphk * Scaled down version of sprintf(3).
50313446Sphk */
50413446Sphkint
50513446Sphksprintf(char *buf, const char *cfmt, ...)
50613446Sphk{
50713446Sphk	int retval;
50813446Sphk	va_list ap;
50913446Sphk
51013446Sphk	va_start(ap, cfmt);
51113446Sphk	retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
51213494Sphk	buf[retval] = '\0';
51313446Sphk	va_end(ap);
51490490Sphk	return (retval);
51513446Sphk}
51613446Sphk
51713446Sphk/*
51838874Sache * Scaled down version of vsprintf(3).
51938874Sache */
52038874Sacheint
52138874Sachevsprintf(char *buf, const char *cfmt, va_list ap)
52238874Sache{
52338874Sache	int retval;
52438874Sache
52538874Sache	retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
52638874Sache	buf[retval] = '\0';
52790490Sphk	return (retval);
52838874Sache}
52938874Sache
53038874Sache/*
53141479Sarchie * Scaled down version of snprintf(3).
53241479Sarchie */
53341479Sarchieint
53441479Sarchiesnprintf(char *str, size_t size, const char *format, ...)
53541479Sarchie{
53641479Sarchie	int retval;
53741479Sarchie	va_list ap;
53841479Sarchie
53941479Sarchie	va_start(ap, format);
54041479Sarchie	retval = vsnprintf(str, size, format, ap);
54141479Sarchie	va_end(ap);
54241479Sarchie	return(retval);
54341479Sarchie}
54441479Sarchie
54541479Sarchie/*
54641479Sarchie * Scaled down version of vsnprintf(3).
54741479Sarchie */
54841479Sarchieint
54941479Sarchievsnprintf(char *str, size_t size, const char *format, va_list ap)
55041479Sarchie{
55141479Sarchie	struct snprintf_arg info;
55241479Sarchie	int retval;
55341479Sarchie
55441479Sarchie	info.str = str;
55541479Sarchie	info.remain = size;
55641479Sarchie	retval = kvprintf(format, snprintf_func, &info, 10, ap);
55741479Sarchie	if (info.remain >= 1)
55841479Sarchie		*info.str++ = '\0';
55990490Sphk	return (retval);
56041479Sarchie}
56141479Sarchie
562110316Sphk/*
563110316Sphk * Kernel version which takes radix argument vsnprintf(3).
564110316Sphk */
565110316Sphkint
566110316Sphkvsnrprintf(char *str, size_t size, int radix, const char *format, va_list ap)
567110316Sphk{
568110316Sphk	struct snprintf_arg info;
569110316Sphk	int retval;
570110316Sphk
571110316Sphk	info.str = str;
572110316Sphk	info.remain = size;
573110316Sphk	retval = kvprintf(format, snprintf_func, &info, radix, ap);
574110316Sphk	if (info.remain >= 1)
575110316Sphk		*info.str++ = '\0';
576110316Sphk	return (retval);
577110316Sphk}
578110316Sphk
57941479Sarchiestatic void
58041479Sarchiesnprintf_func(int ch, void *arg)
58141479Sarchie{
58241479Sarchie	struct snprintf_arg *const info = arg;
58341479Sarchie
58441479Sarchie	if (info->remain >= 2) {
58541479Sarchie		*info->str++ = ch;
58641479Sarchie		info->remain--;
58741479Sarchie	}
58841479Sarchie}
58941479Sarchie
59041479Sarchie/*
59148728Speter * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
59247822Sarchie * order; return an optional length and a pointer to the last character
59347822Sarchie * written in the buffer (i.e., the first character of the string).
59447822Sarchie * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
59513446Sphk */
59613446Sphkstatic char *
597156518Sjkimksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
59847822Sarchie{
599156518Sjkim	char *p, c;
60013446Sphk
60147822Sarchie	p = nbuf;
60247773Sarchie	*p = '\0';
60313446Sphk	do {
604156518Sjkim		c = hex2ascii(num % base);
605156518Sjkim		*++p = upper ? toupper(c) : c;
60697749Sdes	} while (num /= base);
60713446Sphk	if (lenp)
60847822Sarchie		*lenp = p - nbuf;
60913446Sphk	return (p);
61013446Sphk}
61113446Sphk
61213446Sphk/*
6131541Srgrimes * Scaled down version of printf(3).
6141541Srgrimes *
6151541Srgrimes * Two additional formats:
6161541Srgrimes *
6171541Srgrimes * The format %b is supported to decode error registers.
6181541Srgrimes * Its usage is:
6191541Srgrimes *
6201541Srgrimes *	printf("reg=%b\n", regval, "<base><arg>*");
6211541Srgrimes *
6221541Srgrimes * where <base> is the output base expressed as a control character, e.g.
6231541Srgrimes * \10 gives octal; \20 gives hex.  Each arg is a sequence of characters,
6241541Srgrimes * the first of which gives the bit number to be inspected (origin 1), and
6251541Srgrimes * the next characters (up to a control character, i.e. a character <= 32),
6261541Srgrimes * give the name of the register.  Thus:
6271541Srgrimes *
62815700Sgpalmer *	kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
6291541Srgrimes *
6301541Srgrimes * would produce output:
6311541Srgrimes *
6321541Srgrimes *	reg=3<BITTWO,BITONE>
6331541Srgrimes *
63413618Sphk * XXX:  %D  -- Hexdump, takes pointer and separator string:
63513618Sphk *		("%6D", ptr, ":")   -> XX:XX:XX:XX:XX:XX
63613618Sphk *		("%*D", len, ptr, " " -> XX XX XX XX ...
6371541Srgrimes */
63813446Sphkint
63913446Sphkkvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap)
6401541Srgrimes{
64113446Sphk#define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; }
64247773Sarchie	char nbuf[MAXNBUF];
64397749Sdes	char *d;
64497749Sdes	const char *p, *percent, *q;
64513618Sphk	u_char *up;
64613446Sphk	int ch, n;
64797749Sdes	uintmax_t num;
64848714Speter	int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
649125985Snjl	int cflag, hflag, jflag, tflag, zflag;
650156518Sjkim	int dwidth, upper;
6511541Srgrimes	char padc;
652149756Sphk	int stop = 0, retval = 0;
6531541Srgrimes
65497749Sdes	num = 0;
65513494Sphk	if (!func)
65613446Sphk		d = (char *) arg;
65713446Sphk	else
65813494Sphk		d = NULL;
65913446Sphk
6605261Sdg	if (fmt == NULL)
6615288Sbde		fmt = "(fmt null)\n";
66213563Sphk
66313618Sphk	if (radix < 2 || radix > 36)
66413563Sphk		radix = 10;
66513563Sphk
6661541Srgrimes	for (;;) {
6671541Srgrimes		padc = ' ';
6681541Srgrimes		width = 0;
669149756Sphk		while ((ch = (u_char)*fmt++) != '%' || stop) {
67097750Sdes			if (ch == '\0')
67190490Sphk				return (retval);
67213446Sphk			PCHAR(ch);
6731541Srgrimes		}
67497749Sdes		percent = fmt - 1;
67548714Speter		qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
676156518Sjkim		sign = 0; dot = 0; dwidth = 0; upper = 0;
677125985Snjl		cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
67817974Sbdereswitch:	switch (ch = (u_char)*fmt++) {
67913466Sphk		case '.':
68013466Sphk			dot = 1;
68113466Sphk			goto reswitch;
68213446Sphk		case '#':
68313446Sphk			sharpflag = 1;
68413446Sphk			goto reswitch;
68513446Sphk		case '+':
68613446Sphk			sign = 1;
68713446Sphk			goto reswitch;
68813446Sphk		case '-':
68913446Sphk			ladjust = 1;
69013446Sphk			goto reswitch;
69113446Sphk		case '%':
69213446Sphk			PCHAR(ch);
69313446Sphk			break;
69413446Sphk		case '*':
69513501Sphk			if (!dot) {
69613501Sphk				width = va_arg(ap, int);
69713501Sphk				if (width < 0) {
69813501Sphk					ladjust = !ladjust;
69913501Sphk					width = -width;
70013501Sphk				}
70113501Sphk			} else {
70213501Sphk				dwidth = va_arg(ap, int);
70313446Sphk			}
70413446Sphk			goto reswitch;
7051541Srgrimes		case '0':
70613480Sphk			if (!dot) {
70713480Sphk				padc = '0';
70813480Sphk				goto reswitch;
70913480Sphk			}
7101541Srgrimes		case '1': case '2': case '3': case '4':
7111541Srgrimes		case '5': case '6': case '7': case '8': case '9':
71213480Sphk				for (n = 0;; ++fmt) {
71313480Sphk					n = n * 10 + ch - '0';
71413480Sphk					ch = *fmt;
71513480Sphk					if (ch < '0' || ch > '9')
71613480Sphk						break;
71713480Sphk				}
71813480Sphk			if (dot)
71913480Sphk				dwidth = n;
72013480Sphk			else
72113480Sphk				width = n;
7221541Srgrimes			goto reswitch;
7231541Srgrimes		case 'b':
724108890Sjhb			num = (u_int)va_arg(ap, int);
7251541Srgrimes			p = va_arg(ap, char *);
726156518Sjkim			for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;)
72713446Sphk				PCHAR(*q--);
7281541Srgrimes
72997749Sdes			if (num == 0)
7301541Srgrimes				break;
7311541Srgrimes
7323308Sphk			for (tmp = 0; *p;) {
7333308Sphk				n = *p++;
73497749Sdes				if (num & (1 << (n - 1))) {
73513446Sphk					PCHAR(tmp ? ',' : '<');
7361541Srgrimes					for (; (n = *p) > ' '; ++p)
73713446Sphk						PCHAR(n);
7381541Srgrimes					tmp = 1;
7391541Srgrimes				} else
7401541Srgrimes					for (; *p > ' '; ++p)
7411541Srgrimes						continue;
7421541Srgrimes			}
7431541Srgrimes			if (tmp)
74413446Sphk				PCHAR('>');
7451541Srgrimes			break;
7461541Srgrimes		case 'c':
74713446Sphk			PCHAR(va_arg(ap, int));
7481541Srgrimes			break;
74913618Sphk		case 'D':
75013618Sphk			up = va_arg(ap, u_char *);
75113618Sphk			p = va_arg(ap, char *);
75213618Sphk			if (!width)
75313618Sphk				width = 16;
75413618Sphk			while(width--) {
75513618Sphk				PCHAR(hex2ascii(*up >> 4));
75613618Sphk				PCHAR(hex2ascii(*up & 0x0f));
75713618Sphk				up++;
75813618Sphk				if (width)
75913618Sphk					for (q=p;*q;q++)
76013618Sphk						PCHAR(*q);
76113618Sphk			}
76213618Sphk			break;
7631541Srgrimes		case 'd':
76499459Simp		case 'i':
76597749Sdes			base = 10;
76613446Sphk			sign = 1;
76797749Sdes			goto handle_sign;
768125985Snjl		case 'h':
769125985Snjl			if (hflag) {
770125985Snjl				hflag = 0;
771125985Snjl				cflag = 1;
772125985Snjl			} else
773125985Snjl				hflag = 1;
774125985Snjl			goto reswitch;
77597749Sdes		case 'j':
77697749Sdes			jflag = 1;
77797749Sdes			goto reswitch;
77813446Sphk		case 'l':
77949502Sgreen			if (lflag) {
78049502Sgreen				lflag = 0;
78149502Sgreen				qflag = 1;
78249502Sgreen			} else
78349502Sgreen				lflag = 1;
78413446Sphk			goto reswitch;
78597749Sdes		case 'n':
78697749Sdes			if (jflag)
78797749Sdes				*(va_arg(ap, intmax_t *)) = retval;
78897749Sdes			else if (qflag)
78997749Sdes				*(va_arg(ap, quad_t *)) = retval;
79048714Speter			else if (lflag)
79197749Sdes				*(va_arg(ap, long *)) = retval;
792105954Smux			else if (zflag)
793105954Smux				*(va_arg(ap, size_t *)) = retval;
794125985Snjl			else if (hflag)
795125985Snjl				*(va_arg(ap, short *)) = retval;
796125985Snjl			else if (cflag)
797125985Snjl				*(va_arg(ap, char *)) = retval;
79848714Speter			else
79997749Sdes				*(va_arg(ap, int *)) = retval;
80097749Sdes			break;
80197749Sdes		case 'o':
8021541Srgrimes			base = 8;
80397749Sdes			goto handle_nosign;
8049224Sbde		case 'p':
8059224Sbde			base = 16;
80638224Sbde			sharpflag = (width == 0);
80797749Sdes			sign = 0;
80897749Sdes			num = (uintptr_t)va_arg(ap, void *);
80997749Sdes			goto number;
81048714Speter		case 'q':
81148714Speter			qflag = 1;
81248714Speter			goto reswitch;
81337505Sbde		case 'r':
81437505Sbde			base = radix;
81597749Sdes			if (sign)
81697749Sdes				goto handle_sign;
81797749Sdes			goto handle_nosign;
81813446Sphk		case 's':
81913446Sphk			p = va_arg(ap, char *);
82013446Sphk			if (p == NULL)
82113446Sphk				p = "(null)";
82213466Sphk			if (!dot)
82313466Sphk				n = strlen (p);
82413466Sphk			else
82513480Sphk				for (n = 0; n < dwidth && p[n]; n++)
82613466Sphk					continue;
82713480Sphk
82813466Sphk			width -= n;
82913480Sphk
83013446Sphk			if (!ladjust && width > 0)
83113446Sphk				while (width--)
83213446Sphk					PCHAR(padc);
83313466Sphk			while (n--)
83413446Sphk				PCHAR(*p++);
83513446Sphk			if (ladjust && width > 0)
83613446Sphk				while (width--)
83713446Sphk					PCHAR(padc);
83813446Sphk			break;
839106855Smux		case 't':
840106855Smux			tflag = 1;
841106855Smux			goto reswitch;
8421541Srgrimes		case 'u':
8431541Srgrimes			base = 10;
84497749Sdes			goto handle_nosign;
845156518Sjkim		case 'X':
846156518Sjkim			upper = 1;
8471541Srgrimes		case 'x':
8481541Srgrimes			base = 16;
84997749Sdes			goto handle_nosign;
850105954Smux		case 'y':
85197749Sdes			base = 16;
852104924Sjhb			sign = 1;
853104924Sjhb			goto handle_sign;
854105954Smux		case 'z':
855105954Smux			zflag = 1;
856105954Smux			goto reswitch;
85797749Sdeshandle_nosign:
85897749Sdes			sign = 0;
85997749Sdes			if (jflag)
86097749Sdes				num = va_arg(ap, uintmax_t);
86197749Sdes			else if (qflag)
86297749Sdes				num = va_arg(ap, u_quad_t);
863106855Smux			else if (tflag)
864106855Smux				num = va_arg(ap, ptrdiff_t);
86548714Speter			else if (lflag)
86697749Sdes				num = va_arg(ap, u_long);
867105954Smux			else if (zflag)
868105954Smux				num = va_arg(ap, size_t);
869125985Snjl			else if (hflag)
870125985Snjl				num = (u_short)va_arg(ap, int);
871125985Snjl			else if (cflag)
872125985Snjl				num = (u_char)va_arg(ap, int);
87348714Speter			else
87497749Sdes				num = va_arg(ap, u_int);
87537505Sbde			goto number;
87697749Sdeshandle_sign:
87797749Sdes			if (jflag)
87897749Sdes				num = va_arg(ap, intmax_t);
87997749Sdes			else if (qflag)
88097749Sdes				num = va_arg(ap, quad_t);
881106855Smux			else if (tflag)
882106855Smux				num = va_arg(ap, ptrdiff_t);
88397749Sdes			else if (lflag)
88497749Sdes				num = va_arg(ap, long);
885105954Smux			else if (zflag)
886185036Sdelphij				num = va_arg(ap, ssize_t);
887125985Snjl			else if (hflag)
888125985Snjl				num = (short)va_arg(ap, int);
889125985Snjl			else if (cflag)
890125985Snjl				num = (char)va_arg(ap, int);
89197749Sdes			else
89297749Sdes				num = va_arg(ap, int);
89397749Sdesnumber:
89497749Sdes			if (sign && (intmax_t)num < 0) {
89597749Sdes				neg = 1;
89697749Sdes				num = -(intmax_t)num;
89713446Sphk			}
898209836Sjkim			p = ksprintn(nbuf, num, base, &n, upper);
899209836Sjkim			tmp = 0;
90097749Sdes			if (sharpflag && num != 0) {
90113446Sphk				if (base == 8)
90213446Sphk					tmp++;
90313446Sphk				else if (base == 16)
90413446Sphk					tmp += 2;
90513446Sphk			}
90613446Sphk			if (neg)
90713446Sphk				tmp++;
90813446Sphk
909209836Sjkim			if (!ladjust && padc == '0')
910209836Sjkim				dwidth = width - tmp;
911209949Sjkim			width -= tmp + imax(dwidth, n);
912209836Sjkim			dwidth -= n;
913209836Sjkim			if (!ladjust)
914209836Sjkim				while (width-- > 0)
915209836Sjkim					PCHAR(' ');
91613446Sphk			if (neg)
91713446Sphk				PCHAR('-');
91897749Sdes			if (sharpflag && num != 0) {
91913446Sphk				if (base == 8) {
92013446Sphk					PCHAR('0');
92113446Sphk				} else if (base == 16) {
92213446Sphk					PCHAR('0');
92313446Sphk					PCHAR('x');
92413446Sphk				}
92513446Sphk			}
926209836Sjkim			while (dwidth-- > 0)
927209836Sjkim				PCHAR('0');
92813446Sphk
9293308Sphk			while (*p)
93013446Sphk				PCHAR(*p--);
93113446Sphk
932209836Sjkim			if (ladjust)
933209836Sjkim				while (width-- > 0)
934209836Sjkim					PCHAR(' ');
93513446Sphk
9361541Srgrimes			break;
9371541Srgrimes		default:
93897749Sdes			while (percent < fmt)
93997749Sdes				PCHAR(*percent++);
940149756Sphk			/*
941266026Sbdrewery			 * Since we ignore a formatting argument it is no
942149756Sphk			 * longer safe to obey the remaining formatting
943149756Sphk			 * arguments as the arguments will no longer match
944149756Sphk			 * the format specs.
945149756Sphk			 */
946149756Sphk			stop = 1;
94713446Sphk			break;
9481541Srgrimes		}
9491541Srgrimes	}
95013446Sphk#undef PCHAR
9511541Srgrimes}
9521541Srgrimes
9531541Srgrimes/*
95470239Sphk * Put character in log buffer with a particular priority.
9551541Srgrimes */
9561541Srgrimesstatic void
95770239Sphkmsglogchar(int c, int pri)
9581541Srgrimes{
95970239Sphk	static int lastpri = -1;
96070239Sphk	static int dangling;
96170239Sphk	char nbuf[MAXNBUF];
96270239Sphk	char *p;
9631541Srgrimes
96470239Sphk	if (!msgbufmapped)
96570239Sphk		return;
96670239Sphk	if (c == '\0' || c == '\r')
96770239Sphk		return;
96870239Sphk	if (pri != -1 && pri != lastpri) {
96970239Sphk		if (dangling) {
970116660Siedowse			msgbuf_addchar(msgbufp, '\n');
97170239Sphk			dangling = 0;
9726561Sbde		}
973116660Siedowse		msgbuf_addchar(msgbufp, '<');
974156518Sjkim		for (p = ksprintn(nbuf, (uintmax_t)pri, 10, NULL, 0); *p;)
975116660Siedowse			msgbuf_addchar(msgbufp, *p--);
976116660Siedowse		msgbuf_addchar(msgbufp, '>');
97770239Sphk		lastpri = pri;
9781541Srgrimes	}
979116660Siedowse	msgbuf_addchar(msgbufp, c);
98070239Sphk	if (c == '\n') {
98170239Sphk		dangling = 0;
98270239Sphk		lastpri = -1;
98370239Sphk	} else {
98470239Sphk		dangling = 1;
98570239Sphk	}
9861541Srgrimes}
98736441Sphk
988222537Skenstatic void
989222537Skenmsglogstr(char *str, int pri, int filter_cr)
990222537Sken{
991222537Sken	if (!msgbufmapped)
992222537Sken		return;
993222537Sken
994222537Sken	msgbuf_addstr(msgbufp, pri, str, filter_cr);
995222537Sken}
996222537Sken
99736441Sphkvoid
998106917Stmmmsgbufinit(void *ptr, int size)
99936441Sphk{
100036441Sphk	char *cp;
100147678Sjlemon	static struct msgbuf *oldp = NULL;
100236441Sphk
100386238Siedowse	size -= sizeof(*msgbufp);
100436441Sphk	cp = (char *)ptr;
1005116660Siedowse	msgbufp = (struct msgbuf *)(cp + size);
1006116660Siedowse	msgbuf_reinit(msgbufp, cp, size);
100747678Sjlemon	if (msgbufmapped && oldp != msgbufp)
1008116660Siedowse		msgbuf_copy(oldp, msgbufp);
100936441Sphk	msgbufmapped = 1;
101047678Sjlemon	oldp = msgbufp;
101136441Sphk}
101236441Sphk
101387150Srwatsonstatic int unprivileged_read_msgbuf = 1;
101489414SarrSYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_read_msgbuf,
101587150Srwatson    CTLFLAG_RW, &unprivileged_read_msgbuf, 0,
101687150Srwatson    "Unprivileged processes may read the kernel message buffer");
101787150Srwatson
101879153Stmm/* Sysctls for accessing/clearing the msgbuf */
101979153Stmmstatic int
102079153Stmmsysctl_kern_msgbuf(SYSCTL_HANDLER_ARGS)
102179153Stmm{
1022116660Siedowse	char buf[128];
1023116660Siedowse	u_int seq;
1024116660Siedowse	int error, len;
102579153Stmm
102687150Srwatson	if (!unprivileged_read_msgbuf) {
1027164033Srwatson		error = priv_check(req->td, PRIV_MSGBUF);
102887150Srwatson		if (error)
102987150Srwatson			return (error);
103087150Srwatson	}
103187150Srwatson
1032116660Siedowse	/* Read the whole buffer, one chunk at a time. */
1033198860Sed	mtx_lock(&msgbuf_lock);
1034116660Siedowse	msgbuf_peekbytes(msgbufp, NULL, 0, &seq);
1035198860Sed	for (;;) {
1036198860Sed		len = msgbuf_peekbytes(msgbufp, buf, sizeof(buf), &seq);
1037198860Sed		mtx_unlock(&msgbuf_lock);
1038198860Sed		if (len == 0)
1039198860Sed			return (0);
1040198860Sed
1041116660Siedowse		error = sysctl_handle_opaque(oidp, buf, len, req);
1042116660Siedowse		if (error)
1043116660Siedowse			return (error);
1044198860Sed
1045198860Sed		mtx_lock(&msgbuf_lock);
104679153Stmm	}
104779153Stmm}
104879153Stmm
1049198860SedSYSCTL_PROC(_kern, OID_AUTO, msgbuf,
1050198860Sed    CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
1051188057Simp    NULL, 0, sysctl_kern_msgbuf, "A", "Contents of kernel message buffer");
105279153Stmm
1053116660Siedowsestatic int msgbuf_clearflag;
105479153Stmm
105579153Stmmstatic int
105679153Stmmsysctl_kern_msgbuf_clear(SYSCTL_HANDLER_ARGS)
105779153Stmm{
105879153Stmm	int error;
105979153Stmm	error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
106079153Stmm	if (!error && req->newptr) {
1061198860Sed		mtx_lock(&msgbuf_lock);
1062116660Siedowse		msgbuf_clear(msgbufp);
1063198860Sed		mtx_unlock(&msgbuf_lock);
1064116660Siedowse		msgbuf_clearflag = 0;
106579153Stmm	}
106679153Stmm	return (error);
106779153Stmm}
106879153Stmm
106979153StmmSYSCTL_PROC(_kern, OID_AUTO, msgbuf_clear,
1070198860Sed    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE | CTLFLAG_MPSAFE,
1071198860Sed    &msgbuf_clearflag, 0, sysctl_kern_msgbuf_clear, "I",
1072198860Sed    "Clear kernel message buffer");
107379153Stmm
107436441Sphk#ifdef DDB
107536441Sphk
107636441SphkDB_SHOW_COMMAND(msgbuf, db_show_msgbuf)
107736441Sphk{
1078160312Sjhb	int i, j;
107936441Sphk
108036441Sphk	if (!msgbufmapped) {
108136441Sphk		db_printf("msgbuf not mapped yet\n");
108236441Sphk		return;
108336441Sphk	}
108436441Sphk	db_printf("msgbufp = %p\n", msgbufp);
1085116660Siedowse	db_printf("magic = %x, size = %d, r= %u, w = %u, ptr = %p, cksum= %u\n",
1086116660Siedowse	    msgbufp->msg_magic, msgbufp->msg_size, msgbufp->msg_rseq,
1087116660Siedowse	    msgbufp->msg_wseq, msgbufp->msg_ptr, msgbufp->msg_cksum);
1088160312Sjhb	for (i = 0; i < msgbufp->msg_size && !db_pager_quit; i++) {
1089116660Siedowse		j = MSGBUF_SEQ_TO_POS(msgbufp, i + msgbufp->msg_rseq);
109036441Sphk		db_printf("%c", msgbufp->msg_ptr[j]);
109136441Sphk	}
109236441Sphk	db_printf("\n");
109336441Sphk}
109436441Sphk
109536441Sphk#endif /* DDB */
1096123215Sscottl
1097123215Sscottlvoid
1098144706Sphkhexdump(const void *ptr, int length, const char *hdr, int flags)
1099123215Sscottl{
1100123215Sscottl	int i, j, k;
1101123215Sscottl	int cols;
1102144706Sphk	const unsigned char *cp;
1103123215Sscottl	char delim;
1104123215Sscottl
1105123215Sscottl	if ((flags & HD_DELIM_MASK) != 0)
1106123215Sscottl		delim = (flags & HD_DELIM_MASK) >> 8;
1107123215Sscottl	else
1108123215Sscottl		delim = ' ';
1109123215Sscottl
1110123215Sscottl	if ((flags & HD_COLUMN_MASK) != 0)
1111123215Sscottl		cols = flags & HD_COLUMN_MASK;
1112123215Sscottl	else
1113123215Sscottl		cols = 16;
1114123215Sscottl
1115123215Sscottl	cp = ptr;
1116123215Sscottl	for (i = 0; i < length; i+= cols) {
1117123215Sscottl		if (hdr != NULL)
1118123215Sscottl			printf("%s", hdr);
1119123215Sscottl
1120123215Sscottl		if ((flags & HD_OMIT_COUNT) == 0)
1121123215Sscottl			printf("%04x  ", i);
1122123215Sscottl
1123123215Sscottl		if ((flags & HD_OMIT_HEX) == 0) {
1124123215Sscottl			for (j = 0; j < cols; j++) {
1125123215Sscottl				k = i + j;
1126123215Sscottl				if (k < length)
1127123215Sscottl					printf("%c%02x", delim, cp[k]);
1128123215Sscottl				else
1129123215Sscottl					printf("   ");
1130123215Sscottl			}
1131123215Sscottl		}
1132123215Sscottl
1133123215Sscottl		if ((flags & HD_OMIT_CHARS) == 0) {
1134123215Sscottl			printf("  |");
1135123215Sscottl			for (j = 0; j < cols; j++) {
1136123215Sscottl				k = i + j;
1137123215Sscottl				if (k >= length)
1138123215Sscottl					printf(" ");
1139123215Sscottl				else if (cp[k] >= ' ' && cp[k] <= '~')
1140123215Sscottl					printf("%c", cp[k]);
1141123215Sscottl				else
1142123215Sscottl					printf(".");
1143123215Sscottl			}
1144156001Sscottl			printf("|");
1145123215Sscottl		}
1146156001Sscottl		printf("\n");
1147123215Sscottl	}
1148123215Sscottl}
1149284435Sken#endif /* _KERNEL */
1150284435Sken
1151284435Skenvoid
1152284435Skensbuf_hexdump(struct sbuf *sb, const void *ptr, int length, const char *hdr,
1153284435Sken	     int flags)
1154284435Sken{
1155284435Sken	int i, j, k;
1156284435Sken	int cols;
1157284435Sken	const unsigned char *cp;
1158284435Sken	char delim;
1159284435Sken
1160284435Sken	if ((flags & HD_DELIM_MASK) != 0)
1161284435Sken		delim = (flags & HD_DELIM_MASK) >> 8;
1162284435Sken	else
1163284435Sken		delim = ' ';
1164284435Sken
1165284435Sken	if ((flags & HD_COLUMN_MASK) != 0)
1166284435Sken		cols = flags & HD_COLUMN_MASK;
1167284435Sken	else
1168284435Sken		cols = 16;
1169284435Sken
1170284435Sken	cp = ptr;
1171284435Sken	for (i = 0; i < length; i+= cols) {
1172284435Sken		if (hdr != NULL)
1173284435Sken			sbuf_printf(sb, "%s", hdr);
1174284435Sken
1175284435Sken		if ((flags & HD_OMIT_COUNT) == 0)
1176284435Sken			sbuf_printf(sb, "%04x  ", i);
1177284435Sken
1178284435Sken		if ((flags & HD_OMIT_HEX) == 0) {
1179284435Sken			for (j = 0; j < cols; j++) {
1180284435Sken				k = i + j;
1181284435Sken				if (k < length)
1182284435Sken					sbuf_printf(sb, "%c%02x", delim, cp[k]);
1183284435Sken				else
1184284435Sken					sbuf_printf(sb, "   ");
1185284435Sken			}
1186284435Sken		}
1187284435Sken
1188284435Sken		if ((flags & HD_OMIT_CHARS) == 0) {
1189284435Sken			sbuf_printf(sb, "  |");
1190284435Sken			for (j = 0; j < cols; j++) {
1191284435Sken				k = i + j;
1192284435Sken				if (k >= length)
1193284435Sken					sbuf_printf(sb, " ");
1194284435Sken				else if (cp[k] >= ' ' && cp[k] <= '~')
1195284435Sken					sbuf_printf(sb, "%c", cp[k]);
1196284435Sken				else
1197284435Sken					sbuf_printf(sb, ".");
1198284435Sken			}
1199284435Sken			sbuf_printf(sb, "|");
1200284435Sken		}
1201284435Sken		sbuf_printf(sb, "\n");
1202284435Sken	}
1203284435Sken}
1204284435Sken
1205303433Skib#ifdef _KERNEL
1206303433Skibvoid
1207303433Skibcounted_warning(unsigned *counter, const char *msg)
1208303433Skib{
1209303433Skib	struct thread *td;
1210303433Skib	unsigned c;
1211303433Skib
1212303433Skib	for (;;) {
1213303433Skib		c = *counter;
1214303433Skib		if (c == 0)
1215303433Skib			break;
1216303433Skib		if (atomic_cmpset_int(counter, c, c - 1)) {
1217303433Skib			td = curthread;
1218303433Skib			log(LOG_INFO, "pid %d (%s) %s%s\n",
1219303433Skib			    td->td_proc->p_pid, td->td_name, msg,
1220303433Skib			    c > 1 ? "" : " - not logging anymore");
1221303433Skib			break;
1222303433Skib		}
1223303433Skib	}
1224303433Skib}
1225303433Skib#endif
1226321108Sngie
1227321108Sngie#ifdef _KERNEL
1228321108Sngievoid
1229321108Sngiesbuf_putbuf(struct sbuf *sb)
1230321108Sngie{
1231321108Sngie
1232321108Sngie	prf_putbuf(sbuf_data(sb), TOLOG | TOCONS, -1);
1233321108Sngie}
1234321108Sngie#else
1235321108Sngievoid
1236321108Sngiesbuf_putbuf(struct sbuf *sb)
1237321108Sngie{
1238321108Sngie
1239321108Sngie	printf("%s", sbuf_data(sb));
1240321108Sngie}
1241321108Sngie#endif
1242