hexdump.c revision 69214
138032Speter/*-
264562Sgshapiro * Copyright (c) 1986, 1988, 1991, 1993
338032Speter *	The Regents of the University of California.  All rights reserved.
490792Sgshapiro * (c) UNIX System Laboratories, Inc.
590792Sgshapiro * All or some portions of this file are derived from material licensed
690792Sgshapiro * to the University of California by American Telephone and Telegraph
790792Sgshapiro * Co. or Unix System Laboratories, Inc. and are reproduced herein with
838032Speter * the permission of UNIX System Laboratories, Inc.
990792Sgshapiro *
1090792Sgshapiro * Redistribution and use in source and binary forms, with or without
1190792Sgshapiro * modification, are permitted provided that the following conditions
1290792Sgshapiro * are met:
1338032Speter * 1. Redistributions of source code must retain the above copyright
1490792Sgshapiro *    notice, this list of conditions and the following disclaimer.
1538032Speter * 2. Redistributions in binary form must reproduce the above copyright
1690792Sgshapiro *    notice, this list of conditions and the following disclaimer in the
1790792Sgshapiro *    documentation and/or other materials provided with the distribution.
1890792Sgshapiro * 3. All advertising materials mentioning features or use of this software
1990792Sgshapiro *    must display the following acknowledgement:
2090792Sgshapiro *	This product includes software developed by the University of
2190792Sgshapiro *	California, Berkeley and its contributors.
2290792Sgshapiro * 4. Neither the name of the University nor the names of its contributors
2390792Sgshapiro *    may be used to endorse or promote products derived from this software
2490792Sgshapiro *    without specific prior written permission.
2590792Sgshapiro *
2690792Sgshapiro * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2790792Sgshapiro * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2890792Sgshapiro * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2990792Sgshapiro * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3090792Sgshapiro * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31132943Sgshapiro * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3290792Sgshapiro * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3390792Sgshapiro * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3490792Sgshapiro * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3590792Sgshapiro * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3690792Sgshapiro * SUCH DAMAGE.
3790792Sgshapiro *
3890792Sgshapiro *	@(#)subr_prf.c	8.3 (Berkeley) 1/21/94
3990792Sgshapiro * $FreeBSD: head/sys/kern/subr_prf.c 69214 2000-11-26 20:35:21Z phk $
4090792Sgshapiro */
4190792Sgshapiro
4290792Sgshapiro#include <sys/param.h>
4390792Sgshapiro#include <sys/systm.h>
4490792Sgshapiro#include <sys/kernel.h>
4590792Sgshapiro#include <sys/msgbuf.h>
4690792Sgshapiro#include <sys/malloc.h>
4790792Sgshapiro#include <sys/proc.h>
4890792Sgshapiro#include <sys/tty.h>
4938032Speter#include <sys/syslog.h>
5090792Sgshapiro#include <sys/cons.h>
5138032Speter
5238032Speter/*
5338032Speter * Note that stdarg.h and the ANSI style va_start macro is used for both
5438032Speter * ANSI and traditional C compilers.
5538032Speter */
5638032Speter#include <machine/stdarg.h>
5738032Speter
5838032Speter#define TOCONS	0x01
5938032Speter#define TOTTY	0x02
6038032Speter#define TOLOG	0x04
6164562Sgshapiro
6264562Sgshapiro/* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */
6364562Sgshapiro#define MAXNBUF	(sizeof(quad_t) * NBBY + 1)
6464562Sgshapiro
6564562Sgshapirostruct putchar_arg {
6638032Speter	int	flags;
6738032Speter	struct	tty *tty;
6838032Speter};
6938032Speter
7038032Speterstruct snprintf_arg {
7138032Speter	char	*str;
7238032Speter	size_t	remain;
7338032Speter};
7438032Speter
7538032Speterstruct	tty *constty;			/* pointer to console "window" tty */
7638032Speter
7738032Speterstatic void (*v_putc)(int) = cnputc;	/* routine to putc on virtual console */
7838032Speterstatic void  logpri __P((int level));
7938032Speterstatic void  msglogchar(int c, void *dummyarg);
80261194Sgshapirostatic void  putchar __P((int ch, void *arg));
8164562Sgshapirostatic char *ksprintn __P((char *nbuf, u_long num, int base, int *len));
8238032Speterstatic char *ksprintqn __P((char *nbuf, u_quad_t num, int base, int *len));
8338032Speterstatic void  snprintf_func __P((int ch, void *arg));
8438032Speter
8538032Speterstatic int consintr = 1;		/* Ok to handle console interrupts? */
8638032Speterstatic int msgbufmapped;		/* Set when safe to use msgbuf */
8738032Speter
8838032Speter/*
8938032Speter * Warn that a system table is full.
9038032Speter */
9138032Spetervoid
9238032Spetertablefull(tab)
9338032Speter	const char *tab;
9438032Speter{
9538032Speter
9638032Speter	log(LOG_ERR, "%s: table is full\n", tab);
9738032Speter}
9838032Speter
9938032Speter/*
10038032Speter * Uprintf prints to the controlling terminal for the current process.
10138032Speter * It may block if the tty queue is overfull.  No message is printed if
10238032Speter * the queue does not clear in a reasonable time.
10338032Speter */
10464562Sgshapiroint
10538032Speteruprintf(const char *fmt, ...)
10638032Speter{
10738032Speter	struct proc *p = curproc;
10838032Speter	va_list ap;
10938032Speter	struct putchar_arg pca;
11064562Sgshapiro	int retval = 0;
11138032Speter
11238032Speter	if (p && p != idleproc && p->p_flag & P_CONTROLT &&
11338032Speter	    p->p_session->s_ttyvp) {
11464562Sgshapiro		va_start(ap, fmt);
11538032Speter		pca.tty = p->p_session->s_ttyp;
11638032Speter		pca.flags = TOTTY;
11738032Speter		retval = kvprintf(fmt, putchar, &pca, 10, ap);
11838032Speter		va_end(ap);
11938032Speter	}
12038032Speter	return retval;
12138032Speter}
12264562Sgshapiro
12338032Speter/*
12438032Speter * tprintf prints on the controlling terminal associated
12564562Sgshapiro * with the given session, possibly to the log as well.
12638032Speter */
12738032Spetervoid
12838032Spetertprintf(struct proc *p, int pri, const char *fmt, ...)
12964562Sgshapiro{
13064562Sgshapiro	struct tty *tp = NULL;
13138032Speter	int flags = 0, shld = 0;
13290792Sgshapiro	va_list ap;
13390792Sgshapiro	struct putchar_arg pca;
134132943Sgshapiro	int retval;
135132943Sgshapiro
13638032Speter	if (pri != -1) {
13738032Speter		logpri(pri);
13838032Speter		flags |= TOLOG;
13938032Speter	}
14038032Speter	if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
14138032Speter		SESSHOLD(p->p_session);
14238032Speter		shld++;
14390792Sgshapiro		if (ttycheckoutq(p->p_session->s_ttyp, 0)) {
14464562Sgshapiro			flags |= TOTTY;
14564562Sgshapiro			tp = p->p_session->s_ttyp;
14638032Speter		}
14764562Sgshapiro	}
14864562Sgshapiro	pca.tty = tp;
14964562Sgshapiro	pca.flags = flags;
15064562Sgshapiro	va_start(ap, fmt);
15138032Speter	retval = kvprintf(fmt, putchar, &pca, 10, ap);
15290792Sgshapiro	va_end(ap);
15390792Sgshapiro	if (shld)
15490792Sgshapiro		SESSRELE(p->p_session);
15590792Sgshapiro	logwakeup();
15690792Sgshapiro}
15790792Sgshapiro
15890792Sgshapiro/*
15964562Sgshapiro * Ttyprintf displays a message on a tty; it should be used only by
16090792Sgshapiro * the tty driver, or anything that knows the underlying tty will not
161285229Sgshapiro * be revoke(2)'d away.  Other callers should use tprintf.
162285229Sgshapiro */
163285229Sgshapiroint
164285229Sgshapirottyprintf(struct tty *tp, const char *fmt, ...)
165285229Sgshapiro{
166285229Sgshapiro	va_list ap;
167285229Sgshapiro	struct putchar_arg pca;
168285229Sgshapiro	int retval;
169285229Sgshapiro
170285229Sgshapiro	va_start(ap, fmt);
171285229Sgshapiro	pca.tty = tp;
172285229Sgshapiro	pca.flags = TOTTY;
173285229Sgshapiro	retval = kvprintf(fmt, putchar, &pca, 10, ap);
174285229Sgshapiro	va_end(ap);
175285229Sgshapiro	return retval;
176285229Sgshapiro}
177285229Sgshapiro
178285229Sgshapiroextern	int log_open;
179285229Sgshapiro
180285229Sgshapiro/*
18138032Speter * Log writes to the log buffer, and guarantees not to sleep (so can be
18238032Speter * called by interrupt routines).  If there is no process reading the
18338032Speter * log yet, it writes to the console also.
18438032Speter */
18538032Spetervoid
18638032Speterlog(int level, const char *fmt, ...)
18738032Speter{
18838032Speter	int s;
18938032Speter	va_list ap;
19038032Speter	int retval;
19138032Speter
19238032Speter	s = splhigh();
19338032Speter	if (level != -1)
19438032Speter		logpri(level);
19538032Speter	va_start(ap, fmt);
19638032Speter
19738032Speter	retval = kvprintf(fmt, msglogchar, NULL, 10, ap);
19838032Speter	va_end(ap);
19938032Speter
20038032Speter	splx(s);
20138032Speter	if (!log_open) {
20238032Speter		struct putchar_arg pca;
20364562Sgshapiro		va_start(ap, fmt);
20438032Speter		pca.tty = NULL;
20564562Sgshapiro		pca.flags = TOCONS;
20638032Speter		retval += kvprintf(fmt, putchar, &pca, 10, ap);
20738032Speter		va_end(ap);
20838032Speter	}
20938032Speter	logwakeup();
21038032Speter}
21138032Speter
21238032Speterstatic void
213110560Sgshapirologpri(level)
214110560Sgshapiro	int level;
215110560Sgshapiro{
216110560Sgshapiro	char nbuf[MAXNBUF];
217110560Sgshapiro	char *p;
218110560Sgshapiro
21990792Sgshapiro	msglogchar('<', NULL);
220110560Sgshapiro	for (p = ksprintn(nbuf, (u_long)level, 10, NULL); *p;)
22190792Sgshapiro		msglogchar(*p--, NULL);
22290792Sgshapiro	msglogchar('>', NULL);
22390792Sgshapiro}
22490792Sgshapiro
22590792Sgshapiroint
22690792Sgshapiroprintf(const char *fmt, ...)
22790792Sgshapiro{
22890792Sgshapiro	va_list ap;
22990792Sgshapiro	int savintr;
23090792Sgshapiro	struct putchar_arg pca;
23190792Sgshapiro	int retval;
23290792Sgshapiro
23390792Sgshapiro	savintr = consintr;		/* disable interrupts */
23438032Speter	consintr = 0;
23538032Speter	va_start(ap, fmt);
23638032Speter	pca.tty = NULL;
23738032Speter	pca.flags = TOCONS | TOLOG;
23838032Speter	retval = kvprintf(fmt, putchar, &pca, 10, ap);
23938032Speter	va_end(ap);
24064562Sgshapiro	if (!panicstr)
24164562Sgshapiro		logwakeup();
24264562Sgshapiro	consintr = savintr;		/* reenable interrupts */
24364562Sgshapiro	return retval;
24464562Sgshapiro}
24538032Speter
24664562Sgshapiroint
24764562Sgshapirovprintf(const char *fmt, va_list ap)
24864562Sgshapiro{
24964562Sgshapiro	int savintr;
25064562Sgshapiro	struct putchar_arg pca;
25164562Sgshapiro	int retval;
25264562Sgshapiro
25364562Sgshapiro	savintr = consintr;		/* disable interrupts */
25464562Sgshapiro	consintr = 0;
25564562Sgshapiro	pca.tty = NULL;
25664562Sgshapiro	pca.flags = TOCONS | TOLOG;
25764562Sgshapiro	retval = kvprintf(fmt, putchar, &pca, 10, ap);
25864562Sgshapiro	if (!panicstr)
25964562Sgshapiro		logwakeup();
26064562Sgshapiro	consintr = savintr;		/* reenable interrupts */
26164562Sgshapiro	return retval;
26264562Sgshapiro}
26364562Sgshapiro
26464562Sgshapiro/*
26564562Sgshapiro * Print a character on console or users terminal.  If destination is
26664562Sgshapiro * the console then the last bunch of characters are saved in msgbuf for
26764562Sgshapiro * inspection later.
26864562Sgshapiro */
26964562Sgshapirostatic void
27064562Sgshapiroputchar(int c, void *arg)
27164562Sgshapiro{
27264562Sgshapiro	struct putchar_arg *ap = (struct putchar_arg*) arg;
27364562Sgshapiro	int flags = ap->flags;
27464562Sgshapiro	struct tty *tp = ap->tty;
27564562Sgshapiro	if (panicstr)
27664562Sgshapiro		constty = NULL;
27764562Sgshapiro	if ((flags & TOCONS) && tp == NULL && constty) {
27864562Sgshapiro		tp = constty;
27964562Sgshapiro		flags |= TOTTY;
28064562Sgshapiro	}
28164562Sgshapiro	if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 &&
28264562Sgshapiro	    (flags & TOCONS) && tp == constty)
28364562Sgshapiro		constty = NULL;
28464562Sgshapiro	if ((flags & TOLOG))
28564562Sgshapiro		msglogchar(c, NULL);
28664562Sgshapiro	if ((flags & TOCONS) && constty == NULL && c != '\0')
28764562Sgshapiro		(*v_putc)(c);
28864562Sgshapiro}
28964562Sgshapiro
29064562Sgshapiro/*
29164562Sgshapiro * Scaled down version of sprintf(3).
29264562Sgshapiro */
29364562Sgshapiroint
29464562Sgshapirosprintf(char *buf, const char *cfmt, ...)
29564562Sgshapiro{
29680785Sgshapiro	int retval;
29780785Sgshapiro	va_list ap;
29880785Sgshapiro
29980785Sgshapiro	va_start(ap, cfmt);
30080785Sgshapiro	retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
30138032Speter	buf[retval] = '\0';
30238032Speter	va_end(ap);
30338032Speter	return retval;
30438032Speter}
30538032Speter
30638032Speter/*
30738032Speter * Scaled down version of vsprintf(3).
30838032Speter */
30938032Speterint
31038032Spetervsprintf(char *buf, const char *cfmt, va_list ap)
31138032Speter{
31238032Speter	int retval;
31338032Speter
31438032Speter	retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
31538032Speter	buf[retval] = '\0';
31638032Speter	return retval;
31738032Speter}
31838032Speter
31938032Speter/*
32038032Speter * Scaled down version of snprintf(3).
32164562Sgshapiro */
32238032Speterint
32338032Spetersnprintf(char *str, size_t size, const char *format, ...)
32438032Speter{
32538032Speter	int retval;
32638032Speter	va_list ap;
32738032Speter
32864562Sgshapiro	va_start(ap, format);
32938032Speter	retval = vsnprintf(str, size, format, ap);
33038032Speter	va_end(ap);
33138032Speter	return(retval);
33264562Sgshapiro}
33364562Sgshapiro
33473188Sgshapiro/*
33564562Sgshapiro * Scaled down version of vsnprintf(3).
33673188Sgshapiro */
33764562Sgshapiroint
33873188Sgshapirovsnprintf(char *str, size_t size, const char *format, va_list ap)
33973188Sgshapiro{
34090792Sgshapiro	struct snprintf_arg info;
34190792Sgshapiro	int retval;
34290792Sgshapiro
34390792Sgshapiro	info.str = str;
34464562Sgshapiro	info.remain = size;
34538032Speter	retval = kvprintf(format, snprintf_func, &info, 10, ap);
34638032Speter	if (info.remain >= 1)
34764562Sgshapiro		*info.str++ = '\0';
34864562Sgshapiro	return retval;
34938032Speter}
35038032Speter
35138032Speterstatic void
35238032Spetersnprintf_func(int ch, void *arg)
35364562Sgshapiro{
35464562Sgshapiro	struct snprintf_arg *const info = arg;
35564562Sgshapiro
35638032Speter	if (info->remain >= 2) {
35738032Speter		*info->str++ = ch;
35838032Speter		info->remain--;
35938032Speter	}
36064562Sgshapiro}
36164562Sgshapiro
36264562Sgshapiro/*
36364562Sgshapiro * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
36464562Sgshapiro * order; return an optional length and a pointer to the last character
36538032Speter * written in the buffer (i.e., the first character of the string).
36638032Speter * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
36738032Speter */
36838032Speterstatic char *
36938032Speterksprintn(nbuf, ul, base, lenp)
37038032Speter	char *nbuf;
37138032Speter	u_long ul;
37290792Sgshapiro	int base, *lenp;
37338032Speter{
37438032Speter	char *p;
37564562Sgshapiro
37638032Speter	p = nbuf;
37790792Sgshapiro	*p = '\0';
37890792Sgshapiro	do {
37990792Sgshapiro		*++p = hex2ascii(ul % base);
38090792Sgshapiro	} while (ul /= base);
381102528Sgshapiro	if (lenp)
38238032Speter		*lenp = p - nbuf;
38390792Sgshapiro	return (p);
38438032Speter}
38564562Sgshapiro/* ksprintn, but for a quad_t. */
38664562Sgshapirostatic char *
38764562Sgshapiroksprintqn(nbuf, uq, base, lenp)
38864562Sgshapiro	char *nbuf;
38964562Sgshapiro	u_quad_t uq;
39064562Sgshapiro	int base, *lenp;
39164562Sgshapiro{
39238032Speter	char *p;
39364562Sgshapiro
39438032Speter	p = nbuf;
39564562Sgshapiro	*p = '\0';
39664562Sgshapiro	do {
39764562Sgshapiro		*++p = hex2ascii(uq % base);
39894334Sgshapiro	} while (uq /= base);
39994334Sgshapiro	if (lenp)
40094334Sgshapiro		*lenp = p - nbuf;
40166494Sgshapiro	return (p);
40238032Speter}
40338032Speter
40466494Sgshapiro/*
40566494Sgshapiro * Scaled down version of printf(3).
40666494Sgshapiro *
40766494Sgshapiro * Two additional formats:
40890792Sgshapiro *
40990792Sgshapiro * The format %b is supported to decode error registers.
41090792Sgshapiro * Its usage is:
41190792Sgshapiro *
41290792Sgshapiro *	printf("reg=%b\n", regval, "<base><arg>*");
41364562Sgshapiro *
41464562Sgshapiro * where <base> is the output base expressed as a control character, e.g.
41564562Sgshapiro * \10 gives octal; \20 gives hex.  Each arg is a sequence of characters,
41638032Speter * the first of which gives the bit number to be inspected (origin 1), and
41738032Speter * the next characters (up to a control character, i.e. a character <= 32),
41838032Speter * give the name of the register.  Thus:
41938032Speter *
420285229Sgshapiro *	kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
421285229Sgshapiro *
422285229Sgshapiro * would produce output:
423285229Sgshapiro *
424168515Sgshapiro *	reg=3<BITTWO,BITONE>
425168515Sgshapiro *
426168515Sgshapiro * XXX:  %D  -- Hexdump, takes pointer and separator string:
42738032Speter *		("%6D", ptr, ":")   -> XX:XX:XX:XX:XX:XX
42838032Speter *		("%*D", len, ptr, " " -> XX XX XX XX ...
42938032Speter */
43038032Speterint
43138032Speterkvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap)
43238032Speter{
43338032Speter#define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; }
43438032Speter	char nbuf[MAXNBUF];
43538032Speter	char *p, *q, *d;
43638032Speter	u_char *up;
43738032Speter	int ch, n;
43838032Speter	u_long ul;
43990792Sgshapiro	u_quad_t uq;
44038032Speter	int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
44138032Speter	int dwidth;
44238032Speter	char padc;
44338032Speter	int retval = 0;
44438032Speter
44538032Speter	ul = 0;
44638032Speter	uq = 0;
44764562Sgshapiro	if (!func)
44838032Speter		d = (char *) arg;
44938032Speter	else
45090792Sgshapiro		d = NULL;
45138032Speter
45243730Speter	if (fmt == NULL)
45343730Speter		fmt = "(fmt null)\n";
45438032Speter
45564562Sgshapiro	if (radix < 2 || radix > 36)
45643730Speter		radix = 10;
45738032Speter
45838032Speter	for (;;) {
45938032Speter		padc = ' ';
46043730Speter		width = 0;
46138032Speter		while ((ch = (u_char)*fmt++) != '%') {
46238032Speter			if (ch == '\0')
46338032Speter				return retval;
46490792Sgshapiro			PCHAR(ch);
46538032Speter		}
46638032Speter		qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
46738032Speter		sign = 0; dot = 0; dwidth = 0;
46838032Speterreswitch:	switch (ch = (u_char)*fmt++) {
46990792Sgshapiro		case '.':
47038032Speter			dot = 1;
47138032Speter			goto reswitch;
47264562Sgshapiro		case '#':
47364562Sgshapiro			sharpflag = 1;
47438032Speter			goto reswitch;
47590792Sgshapiro		case '+':
47664562Sgshapiro			sign = 1;
47738032Speter			goto reswitch;
47838032Speter		case '-':
47938032Speter			ladjust = 1;
48038032Speter			goto reswitch;
48138032Speter		case '%':
48238032Speter			PCHAR(ch);
48338032Speter			break;
48438032Speter		case '*':
48538032Speter			if (!dot) {
48690792Sgshapiro				width = va_arg(ap, int);
48764562Sgshapiro				if (width < 0) {
48864562Sgshapiro					ladjust = !ladjust;
48938032Speter					width = -width;
49038032Speter				}
49198121Sgshapiro			} else {
49298121Sgshapiro				dwidth = va_arg(ap, int);
49398121Sgshapiro			}
49498121Sgshapiro			goto reswitch;
49598121Sgshapiro		case '0':
49698121Sgshapiro			if (!dot) {
49798121Sgshapiro				padc = '0';
49898121Sgshapiro				goto reswitch;
49998121Sgshapiro			}
50098121Sgshapiro		case '1': case '2': case '3': case '4':
50198121Sgshapiro		case '5': case '6': case '7': case '8': case '9':
50298121Sgshapiro				for (n = 0;; ++fmt) {
50398121Sgshapiro					n = n * 10 + ch - '0';
504110560Sgshapiro					ch = *fmt;
505110560Sgshapiro					if (ch < '0' || ch > '9')
506110560Sgshapiro						break;
507110560Sgshapiro				}
50838032Speter			if (dot)
50943730Speter				dwidth = n;
51043730Speter			else
51164562Sgshapiro				width = n;
51264562Sgshapiro			goto reswitch;
51364562Sgshapiro		case 'b':
51464562Sgshapiro			ul = va_arg(ap, int);
51564562Sgshapiro			p = va_arg(ap, char *);
51664562Sgshapiro			for (q = ksprintn(nbuf, ul, *p++, NULL); *q;)
51764562Sgshapiro				PCHAR(*q--);
51890792Sgshapiro
51990792Sgshapiro			if (!ul)
52038032Speter				break;
52164562Sgshapiro
522157001Sgshapiro			for (tmp = 0; *p;) {
523157001Sgshapiro				n = *p++;
524157001Sgshapiro				if (ul & (1 << (n - 1))) {
525157001Sgshapiro					PCHAR(tmp ? ',' : '<');
526157001Sgshapiro					for (; (n = *p) > ' '; ++p)
527157001Sgshapiro						PCHAR(n);
52838032Speter					tmp = 1;
52964562Sgshapiro				} else
53038032Speter					for (; *p > ' '; ++p)
53190792Sgshapiro						continue;
53290792Sgshapiro			}
53390792Sgshapiro			if (tmp)
53464562Sgshapiro				PCHAR('>');
53564562Sgshapiro			break;
53664562Sgshapiro		case 'c':
53764562Sgshapiro			PCHAR(va_arg(ap, int));
53864562Sgshapiro			break;
53938032Speter		case 'D':
54038032Speter			up = va_arg(ap, u_char *);
54138032Speter			p = va_arg(ap, char *);
54238032Speter			if (!width)
54338032Speter				width = 16;
54464562Sgshapiro			while(width--) {
54538032Speter				PCHAR(hex2ascii(*up >> 4));
54638032Speter				PCHAR(hex2ascii(*up & 0x0f));
54738032Speter				up++;
54838032Speter				if (width)
54938032Speter					for (q=p;*q;q++)
55038032Speter						PCHAR(*q);
55138032Speter			}
55238032Speter			break;
55338032Speter		case 'd':
55438032Speter			if (qflag)
55538032Speter				uq = va_arg(ap, quad_t);
55638032Speter			else if (lflag)
55738032Speter				ul = va_arg(ap, long);
55871345Sgshapiro			else
55982017Sgshapiro				ul = va_arg(ap, int);
56071345Sgshapiro			sign = 1;
56171345Sgshapiro			base = 10;
56290792Sgshapiro			goto number;
56371345Sgshapiro		case 'l':
56471345Sgshapiro			if (lflag) {
56571345Sgshapiro				lflag = 0;
56671345Sgshapiro				qflag = 1;
56771345Sgshapiro			} else
56838032Speter				lflag = 1;
56964562Sgshapiro			goto reswitch;
57064562Sgshapiro		case 'o':
57164562Sgshapiro			if (qflag)
57238032Speter				uq = va_arg(ap, u_quad_t);
57338032Speter			else if (lflag)
57438032Speter				ul = va_arg(ap, u_long);
57538032Speter			else
57638032Speter				ul = va_arg(ap, u_int);
57738032Speter			base = 8;
57838032Speter			goto nosign;
57938032Speter		case 'p':
58038032Speter			ul = (uintptr_t)va_arg(ap, void *);
58138032Speter			base = 16;
58238032Speter			sharpflag = (width == 0);
58338032Speter			goto nosign;
58438032Speter		case 'q':
58538032Speter			qflag = 1;
58638032Speter			goto reswitch;
58738032Speter		case 'n':
58838032Speter		case 'r':
58938032Speter			if (qflag)
59038032Speter				uq = va_arg(ap, u_quad_t);
59138032Speter			else if (lflag)
59290792Sgshapiro				ul = va_arg(ap, u_long);
59338032Speter			else
59438032Speter				ul = sign ?
59538032Speter				    (u_long)va_arg(ap, int) : va_arg(ap, u_int);
59638032Speter			base = radix;
59738032Speter			goto number;
59838032Speter		case 's':
59990792Sgshapiro			p = va_arg(ap, char *);
60038032Speter			if (p == NULL)
60138032Speter				p = "(null)";
60238032Speter			if (!dot)
60338032Speter				n = strlen (p);
60438032Speter			else
60538032Speter				for (n = 0; n < dwidth && p[n]; n++)
60638032Speter					continue;
60738032Speter
60838032Speter			width -= n;
60938032Speter
61064562Sgshapiro			if (!ladjust && width > 0)
61138032Speter				while (width--)
61238032Speter					PCHAR(padc);
61338032Speter			while (n--)
61438032Speter				PCHAR(*p++);
61564562Sgshapiro			if (ladjust && width > 0)
61664562Sgshapiro				while (width--)
61764562Sgshapiro					PCHAR(padc);
61838032Speter			break;
61966494Sgshapiro		case 'u':
62038032Speter			if (qflag)
62138032Speter				uq = va_arg(ap, u_quad_t);
62238032Speter			else if (lflag)
62338032Speter				ul = va_arg(ap, u_long);
62490792Sgshapiro			else
62590792Sgshapiro				ul = va_arg(ap, u_int);
62690792Sgshapiro			base = 10;
62738032Speter			goto nosign;
62864562Sgshapiro		case 'x':
62964562Sgshapiro		case 'X':
63064562Sgshapiro			if (qflag)
63138032Speter				uq = va_arg(ap, u_quad_t);
63238032Speter			else if (lflag)
63338032Speter				ul = va_arg(ap, u_long);
63438032Speter			else
63538032Speter				ul = va_arg(ap, u_int);
63638032Speter			base = 16;
63738032Speter			goto nosign;
63838032Speter		case 'z':
63938032Speter			if (qflag)
64038032Speter				uq = va_arg(ap, u_quad_t);
64138032Speter			else if (lflag)
64238032Speter				ul = va_arg(ap, u_long);
64338032Speter			else
64471345Sgshapiro				ul = sign ?
64538032Speter				    (u_long)va_arg(ap, int) : va_arg(ap, u_int);
64638032Speter			base = 16;
64738032Speter			goto number;
64838032Speternosign:			sign = 0;
64938032Speternumber:
65038032Speter			if (qflag) {
65138032Speter				if (sign && (quad_t)uq < 0) {
65238032Speter					neg = 1;
65338032Speter					uq = -(quad_t)uq;
65438032Speter				}
65538032Speter				p = ksprintqn(nbuf, uq, base, &tmp);
65638032Speter			} else {
65738032Speter				if (sign && (long)ul < 0) {
65838032Speter					neg = 1;
65938032Speter					ul = -(long)ul;
66038032Speter				}
66138032Speter				p = ksprintn(nbuf, ul, base, &tmp);
662111823Sgshapiro			}
663111823Sgshapiro			if (sharpflag && (qflag ? uq != 0 : ul != 0)) {
66443730Speter				if (base == 8)
66538032Speter					tmp++;
66638032Speter				else if (base == 16)
66790792Sgshapiro					tmp += 2;
66890792Sgshapiro			}
66990792Sgshapiro			if (neg)
67038032Speter				tmp++;
67138032Speter
67238032Speter			if (!ladjust && width && (width -= tmp) > 0)
67338032Speter				while (width--)
67438032Speter					PCHAR(padc);
67538032Speter			if (neg)
67638032Speter				PCHAR('-');
67738032Speter			if (sharpflag && (qflag ? uq != 0 : ul != 0)) {
67838032Speter				if (base == 8) {
67938032Speter					PCHAR('0');
68038032Speter				} else if (base == 16) {
68138032Speter					PCHAR('0');
68238032Speter					PCHAR('x');
68390792Sgshapiro				}
68490792Sgshapiro			}
68590792Sgshapiro
68690792Sgshapiro			while (*p)
68790792Sgshapiro				PCHAR(*p--);
68890792Sgshapiro
68938032Speter			if (ladjust && width && (width -= tmp) > 0)
69098121Sgshapiro				while (width--)
69198121Sgshapiro					PCHAR(padc);
69298121Sgshapiro
69398121Sgshapiro			break;
69498121Sgshapiro		default:
69598121Sgshapiro			PCHAR('%');
69698121Sgshapiro			if (lflag)
69798121Sgshapiro				PCHAR('l');
69864562Sgshapiro			PCHAR(ch);
69964562Sgshapiro			break;
70038032Speter		}
70138032Speter	}
70238032Speter#undef PCHAR
70343730Speter}
70443730Speter
70543730Speter/*
70643730Speter * Put character in log buffer.
70738032Speter */
70838032Speterstatic void
70938032Spetermsglogchar(int c, void *dummyarg)
71038032Speter{
71138032Speter	struct msgbuf *mbp;
71238032Speter
71338032Speter	if (c != '\0' && c != '\r' && c != 0177 && msgbufmapped) {
71438032Speter		mbp = msgbufp;
71538032Speter		mbp->msg_ptr[mbp->msg_bufx++] = c;
71643730Speter		if (mbp->msg_bufx >= mbp->msg_size)
71738032Speter			mbp->msg_bufx = 0;
71864562Sgshapiro		/* If the buffer is full, keep the most recent data. */
71990792Sgshapiro		if (mbp->msg_bufr == mbp->msg_bufx) {
72064562Sgshapiro			if (++mbp->msg_bufr >= mbp->msg_size)
72138032Speter				mbp->msg_bufr = 0;
72243730Speter		}
72338032Speter	}
72438032Speter}
72564562Sgshapiro
72638032Speterstatic void
72738032Spetermsgbufcopy(struct msgbuf *oldp)
72838032Speter{
72938032Speter	int pos;
73038032Speter
73164562Sgshapiro	pos = oldp->msg_bufr;
73264562Sgshapiro	while (pos != oldp->msg_bufx) {
73338032Speter		msglogchar(oldp->msg_ptr[pos], NULL);
73490792Sgshapiro		if (++pos >= oldp->msg_size)
73590792Sgshapiro			pos = 0;
73690792Sgshapiro	}
73790792Sgshapiro}
73890792Sgshapiro
73938032Spetervoid
74038032Spetermsgbufinit(void *ptr, size_t size)
74164562Sgshapiro{
74264562Sgshapiro	char *cp;
74364562Sgshapiro	static struct msgbuf *oldp = NULL;
74464562Sgshapiro
74564562Sgshapiro	cp = (char *)ptr;
74664562Sgshapiro	msgbufp = (struct msgbuf *) (cp + size - sizeof(*msgbufp));
74764562Sgshapiro	if (msgbufp->msg_magic != MSG_MAGIC || msgbufp->msg_ptr != cp) {
74838032Speter		bzero(cp, size);
74964562Sgshapiro		msgbufp->msg_magic = MSG_MAGIC;
75064562Sgshapiro		msgbufp->msg_size = (char *)msgbufp - cp;
75164562Sgshapiro		msgbufp->msg_ptr = cp;
75264562Sgshapiro	}
75364562Sgshapiro	if (msgbufmapped && oldp != msgbufp)
75438032Speter		msgbufcopy(oldp);
75538032Speter	msgbufmapped = 1;
75664562Sgshapiro	oldp = msgbufp;
75738032Speter}
75838032Speter
75938032Speter#include "opt_ddb.h"
76064562Sgshapiro#ifdef DDB
76164562Sgshapiro#include <ddb/ddb.h>
76264562Sgshapiro
76364562SgshapiroDB_SHOW_COMMAND(msgbuf, db_show_msgbuf)
76464562Sgshapiro{
76564562Sgshapiro	int i, j;
76690792Sgshapiro
76764562Sgshapiro	if (!msgbufmapped) {
76864562Sgshapiro		db_printf("msgbuf not mapped yet\n");
76938032Speter		return;
770285229Sgshapiro	}
771285229Sgshapiro	db_printf("msgbufp = %p\n", msgbufp);
772285229Sgshapiro	db_printf("magic = %x, size = %d, r= %d, w = %d, ptr = %p\n",
773285229Sgshapiro	    msgbufp->msg_magic, msgbufp->msg_size, msgbufp->msg_bufr,
774285229Sgshapiro	    msgbufp->msg_bufx, msgbufp->msg_ptr);
775285229Sgshapiro	for (i = 0; i < msgbufp->msg_size; i++) {
776285229Sgshapiro		j = (i + msgbufp->msg_bufr) % msgbufp->msg_size;
777285229Sgshapiro		db_printf("%c", msgbufp->msg_ptr[j]);
778285229Sgshapiro	}
779285229Sgshapiro	db_printf("\n");
78064562Sgshapiro}
78171345Sgshapiro
78271345Sgshapiro#endif /* DDB */
78371345Sgshapiro