Home | History | Annotate | Line # | Download | only in kern
subr_prf.c revision 1.40
      1  1.40   thorpej /*	$NetBSD: subr_prf.c,v 1.40 1997/04/17 00:06:28 thorpej Exp $	*/
      2  1.15       cgd 
      3  1.12       cgd /*-
      4  1.12       cgd  * Copyright (c) 1986, 1988, 1991, 1993
      5  1.12       cgd  *	The Regents of the University of California.  All rights reserved.
      6  1.12       cgd  * (c) UNIX System Laboratories, Inc.
      7  1.12       cgd  * All or some portions of this file are derived from material licensed
      8  1.12       cgd  * to the University of California by American Telephone and Telegraph
      9  1.12       cgd  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
     10  1.12       cgd  * the permission of UNIX System Laboratories, Inc.
     11  1.12       cgd  *
     12  1.12       cgd  * Redistribution and use in source and binary forms, with or without
     13  1.12       cgd  * modification, are permitted provided that the following conditions
     14  1.12       cgd  * are met:
     15  1.12       cgd  * 1. Redistributions of source code must retain the above copyright
     16  1.12       cgd  *    notice, this list of conditions and the following disclaimer.
     17  1.12       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     18  1.12       cgd  *    notice, this list of conditions and the following disclaimer in the
     19  1.12       cgd  *    documentation and/or other materials provided with the distribution.
     20  1.12       cgd  * 3. All advertising materials mentioning features or use of this software
     21  1.12       cgd  *    must display the following acknowledgement:
     22  1.12       cgd  *	This product includes software developed by the University of
     23  1.12       cgd  *	California, Berkeley and its contributors.
     24  1.12       cgd  * 4. Neither the name of the University nor the names of its contributors
     25  1.12       cgd  *    may be used to endorse or promote products derived from this software
     26  1.12       cgd  *    without specific prior written permission.
     27  1.12       cgd  *
     28  1.12       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     29  1.12       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     30  1.12       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     31  1.12       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     32  1.12       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     33  1.12       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     34  1.12       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     35  1.12       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     36  1.12       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     37  1.12       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     38  1.12       cgd  * SUCH DAMAGE.
     39  1.12       cgd  *
     40  1.15       cgd  *	@(#)subr_prf.c	8.3 (Berkeley) 1/21/94
     41  1.12       cgd  */
     42  1.12       cgd 
     43  1.12       cgd #include <sys/param.h>
     44  1.12       cgd #include <sys/systm.h>
     45  1.12       cgd #include <sys/buf.h>
     46  1.12       cgd #include <sys/conf.h>
     47  1.12       cgd #include <sys/reboot.h>
     48  1.12       cgd #include <sys/msgbuf.h>
     49  1.12       cgd #include <sys/proc.h>
     50  1.12       cgd #include <sys/ioctl.h>
     51  1.12       cgd #include <sys/vnode.h>
     52  1.12       cgd #include <sys/file.h>
     53  1.12       cgd #include <sys/tty.h>
     54  1.12       cgd #include <sys/tprintf.h>
     55  1.12       cgd #include <sys/syslog.h>
     56  1.12       cgd #include <sys/malloc.h>
     57  1.12       cgd 
     58  1.20  christos #include <dev/cons.h>
     59  1.20  christos 
     60  1.12       cgd /*
     61  1.12       cgd  * Note that stdarg.h and the ANSI style va_start macro is used for both
     62  1.12       cgd  * ANSI and traditional C compilers.
     63  1.35       gwr  * XXX: This requires that stdarg.h defines: va_alist, va_dcl
     64  1.12       cgd  */
     65  1.12       cgd #include <machine/stdarg.h>
     66  1.12       cgd 
     67  1.32        ws #include "ipkdb.h"
     68  1.28        ws 
     69  1.12       cgd #ifdef KADB
     70  1.12       cgd #include <machine/kdbparam.h>
     71  1.22  christos #endif
     72  1.22  christos #ifdef KGDB
     73  1.22  christos #include <machine/cpu.h>
     74  1.12       cgd #endif
     75  1.20  christos 
     76  1.12       cgd #define TOCONS	0x01
     77  1.12       cgd #define TOTTY	0x02
     78  1.12       cgd #define TOLOG	0x04
     79  1.12       cgd 
     80  1.37   thorpej /*
     81  1.37   thorpej  * This is the size of the buffer that should be passed to ksnprintn().
     82  1.37   thorpej  * It's the length of a long in base 8, plus NULL.
     83  1.37   thorpej  */
     84  1.37   thorpej #define KSNPRINTN_BUFSIZE	(sizeof(long) * NBBY / 3 + 2)
     85  1.37   thorpej 
     86  1.12       cgd struct	tty *constty;			/* pointer to console "window" tty */
     87  1.12       cgd 
     88  1.20  christos void	(*v_putc) __P((int)) = cnputc;	/* routine to putc on virtual console */
     89  1.12       cgd 
     90  1.20  christos static void putchar __P((int, int, struct tty *));
     91  1.37   thorpej static char *ksnprintn __P((u_long, int, int *, char *, size_t));
     92  1.30  christos void kprintf __P((const char *, int, struct tty *, va_list));
     93  1.12       cgd 
     94  1.14       cgd int consintr = 1;			/* Ok to handle console interrupts? */
     95  1.12       cgd 
     96  1.12       cgd /*
     97  1.14       cgd  * Variable panicstr contains argument to first call to panic; used as flag
     98  1.14       cgd  * to indicate that the kernel has already called panic.
     99  1.12       cgd  */
    100  1.14       cgd const char *panicstr;
    101  1.12       cgd 
    102  1.12       cgd /*
    103  1.12       cgd  * Panic is called on unresolvable fatal errors.  It prints "panic: mesg",
    104  1.12       cgd  * and then reboots.  If we are called twice, then we avoid trying to sync
    105  1.12       cgd  * the disks as this often leads to recursive panics.
    106  1.12       cgd  */
    107  1.14       cgd void
    108  1.12       cgd #ifdef __STDC__
    109  1.12       cgd panic(const char *fmt, ...)
    110  1.12       cgd #else
    111  1.14       cgd panic(fmt, va_alist)
    112  1.12       cgd 	char *fmt;
    113  1.20  christos 	va_dcl
    114  1.12       cgd #endif
    115  1.12       cgd {
    116  1.14       cgd 	int bootopt;
    117  1.12       cgd 	va_list ap;
    118  1.12       cgd 
    119  1.14       cgd 	bootopt = RB_AUTOBOOT | RB_DUMP;
    120  1.12       cgd 	if (panicstr)
    121  1.12       cgd 		bootopt |= RB_NOSYNC;
    122  1.12       cgd 	else
    123  1.12       cgd 		panicstr = fmt;
    124  1.12       cgd 
    125  1.12       cgd 	va_start(ap, fmt);
    126  1.40   thorpej #ifdef __powerpc__				/* XXX */
    127  1.40   thorpej 	printf("panic: ");			/* XXX */
    128  1.40   thorpej 	vprintf(fmt, ap);			/* XXX */
    129  1.40   thorpej 	printf("\n");				/* XXX */
    130  1.40   thorpej #else						/* XXX */
    131  1.40   thorpej 	printf("panic: %:\n", fmt, ap);		/* XXX */
    132  1.40   thorpej #endif						/* XXX */
    133  1.12       cgd 	va_end(ap);
    134  1.12       cgd 
    135  1.32        ws #if NIPKDB > 0
    136  1.32        ws 	ipkdb_panic();
    137  1.28        ws #endif
    138  1.12       cgd #ifdef KGDB
    139  1.12       cgd 	kgdb_panic();
    140  1.12       cgd #endif
    141  1.12       cgd #ifdef KADB
    142  1.14       cgd 	if (boothowto & RB_KDB)
    143  1.14       cgd 		kdbpanic();
    144  1.12       cgd #endif
    145  1.12       cgd #ifdef DDB
    146  1.38   thorpej 	if (db_onpanic)
    147  1.38   thorpej 		Debugger();
    148  1.12       cgd #endif
    149  1.39       gwr 	cpu_reboot(bootopt, NULL);
    150  1.12       cgd }
    151  1.12       cgd 
    152  1.12       cgd /*
    153  1.12       cgd  * Warn that a system table is full.
    154  1.12       cgd  */
    155  1.12       cgd void
    156  1.12       cgd tablefull(tab)
    157  1.12       cgd 	const char *tab;
    158  1.12       cgd {
    159  1.12       cgd 
    160  1.12       cgd 	log(LOG_ERR, "%s: table is full\n", tab);
    161  1.12       cgd }
    162  1.12       cgd 
    163  1.12       cgd /*
    164  1.12       cgd  * Uprintf prints to the controlling terminal for the current process.
    165  1.12       cgd  * It may block if the tty queue is overfull.  No message is printed if
    166  1.12       cgd  * the queue does not clear in a reasonable time.
    167  1.12       cgd  */
    168  1.12       cgd void
    169  1.12       cgd #ifdef __STDC__
    170  1.12       cgd uprintf(const char *fmt, ...)
    171  1.12       cgd #else
    172  1.14       cgd uprintf(fmt, va_alist)
    173  1.12       cgd 	char *fmt;
    174  1.20  christos 	va_dcl
    175  1.12       cgd #endif
    176  1.12       cgd {
    177  1.12       cgd 	register struct proc *p = curproc;
    178  1.12       cgd 	va_list ap;
    179  1.12       cgd 
    180  1.12       cgd 	if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
    181  1.12       cgd 		va_start(ap, fmt);
    182  1.30  christos 		kprintf(fmt, TOTTY, p->p_session->s_ttyp, ap);
    183  1.12       cgd 		va_end(ap);
    184  1.12       cgd 	}
    185  1.12       cgd }
    186  1.12       cgd 
    187  1.12       cgd tpr_t
    188  1.12       cgd tprintf_open(p)
    189  1.12       cgd 	register struct proc *p;
    190  1.12       cgd {
    191  1.12       cgd 
    192  1.12       cgd 	if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
    193  1.12       cgd 		SESSHOLD(p->p_session);
    194  1.12       cgd 		return ((tpr_t) p->p_session);
    195  1.12       cgd 	}
    196  1.12       cgd 	return ((tpr_t) NULL);
    197  1.12       cgd }
    198  1.12       cgd 
    199  1.12       cgd void
    200  1.12       cgd tprintf_close(sess)
    201  1.12       cgd 	tpr_t sess;
    202  1.12       cgd {
    203  1.12       cgd 
    204  1.12       cgd 	if (sess)
    205  1.12       cgd 		SESSRELE((struct session *) sess);
    206  1.12       cgd }
    207  1.12       cgd 
    208  1.12       cgd /*
    209  1.12       cgd  * tprintf prints on the controlling terminal associated
    210  1.12       cgd  * with the given session.
    211  1.12       cgd  */
    212  1.12       cgd void
    213  1.12       cgd #ifdef __STDC__
    214  1.12       cgd tprintf(tpr_t tpr, const char *fmt, ...)
    215  1.12       cgd #else
    216  1.14       cgd tprintf(tpr, fmt, va_alist)
    217  1.12       cgd 	tpr_t tpr;
    218  1.12       cgd 	char *fmt;
    219  1.20  christos 	va_dcl
    220  1.12       cgd #endif
    221  1.12       cgd {
    222  1.12       cgd 	register struct session *sess = (struct session *)tpr;
    223  1.12       cgd 	struct tty *tp = NULL;
    224  1.12       cgd 	int flags = TOLOG;
    225  1.12       cgd 	va_list ap;
    226  1.12       cgd 
    227  1.12       cgd 	logpri(LOG_INFO);
    228  1.12       cgd 	if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) {
    229  1.12       cgd 		flags |= TOTTY;
    230  1.12       cgd 		tp = sess->s_ttyp;
    231  1.12       cgd 	}
    232  1.12       cgd 	va_start(ap, fmt);
    233  1.30  christos 	kprintf(fmt, flags, tp, ap);
    234  1.12       cgd 	va_end(ap);
    235  1.12       cgd 	logwakeup();
    236  1.12       cgd }
    237  1.12       cgd 
    238  1.12       cgd /*
    239  1.12       cgd  * Ttyprintf displays a message on a tty; it should be used only by
    240  1.12       cgd  * the tty driver, or anything that knows the underlying tty will not
    241  1.12       cgd  * be revoke(2)'d away.  Other callers should use tprintf.
    242  1.12       cgd  */
    243  1.12       cgd void
    244  1.12       cgd #ifdef __STDC__
    245  1.12       cgd ttyprintf(struct tty *tp, const char *fmt, ...)
    246  1.12       cgd #else
    247  1.14       cgd ttyprintf(tp, fmt, va_alist)
    248  1.12       cgd 	struct tty *tp;
    249  1.12       cgd 	char *fmt;
    250  1.20  christos 	va_dcl
    251  1.12       cgd #endif
    252  1.12       cgd {
    253  1.12       cgd 	va_list ap;
    254  1.12       cgd 
    255  1.12       cgd 	va_start(ap, fmt);
    256  1.30  christos 	kprintf(fmt, TOTTY, tp, ap);
    257  1.12       cgd 	va_end(ap);
    258  1.12       cgd }
    259  1.12       cgd 
    260  1.12       cgd extern	int log_open;
    261  1.12       cgd 
    262  1.12       cgd /*
    263  1.12       cgd  * Log writes to the log buffer, and guarantees not to sleep (so can be
    264  1.12       cgd  * called by interrupt routines).  If there is no process reading the
    265  1.12       cgd  * log yet, it writes to the console also.
    266  1.12       cgd  */
    267  1.12       cgd void
    268  1.12       cgd #ifdef __STDC__
    269  1.12       cgd log(int level, const char *fmt, ...)
    270  1.12       cgd #else
    271  1.14       cgd log(level, fmt, va_alist)
    272  1.12       cgd 	int level;
    273  1.12       cgd 	char *fmt;
    274  1.20  christos 	va_dcl
    275  1.12       cgd #endif
    276  1.12       cgd {
    277  1.12       cgd 	register int s;
    278  1.12       cgd 	va_list ap;
    279  1.12       cgd 
    280  1.12       cgd 	s = splhigh();
    281  1.12       cgd 	logpri(level);
    282  1.12       cgd 	va_start(ap, fmt);
    283  1.30  christos 	kprintf(fmt, TOLOG, NULL, ap);
    284  1.12       cgd 	splx(s);
    285  1.12       cgd 	va_end(ap);
    286  1.12       cgd 	if (!log_open) {
    287  1.12       cgd 		va_start(ap, fmt);
    288  1.30  christos 		kprintf(fmt, TOCONS, NULL, ap);
    289  1.12       cgd 		va_end(ap);
    290  1.12       cgd 	}
    291  1.12       cgd 	logwakeup();
    292  1.12       cgd }
    293  1.12       cgd 
    294  1.13   mycroft void
    295  1.12       cgd logpri(level)
    296  1.12       cgd 	int level;
    297  1.12       cgd {
    298  1.12       cgd 	register int ch;
    299  1.12       cgd 	register char *p;
    300  1.37   thorpej 	char snbuf[KSNPRINTN_BUFSIZE];
    301  1.12       cgd 
    302  1.12       cgd 	putchar('<', TOLOG, NULL);
    303  1.37   thorpej 	for (p = ksnprintn((u_long)level, 10, NULL, snbuf, sizeof(snbuf));
    304  1.37   thorpej 	    (ch = *p--) != 0;)
    305  1.12       cgd 		putchar(ch, TOLOG, NULL);
    306  1.12       cgd 	putchar('>', TOLOG, NULL);
    307  1.12       cgd }
    308  1.12       cgd 
    309  1.12       cgd void
    310  1.12       cgd #ifdef __STDC__
    311  1.12       cgd addlog(const char *fmt, ...)
    312  1.12       cgd #else
    313  1.14       cgd addlog(fmt, va_alist)
    314  1.12       cgd 	char *fmt;
    315  1.20  christos 	va_dcl
    316  1.12       cgd #endif
    317  1.12       cgd {
    318  1.12       cgd 	register int s;
    319  1.12       cgd 	va_list ap;
    320  1.12       cgd 
    321  1.12       cgd 	s = splhigh();
    322  1.12       cgd 	va_start(ap, fmt);
    323  1.30  christos 	kprintf(fmt, TOLOG, NULL, ap);
    324  1.12       cgd 	splx(s);
    325  1.12       cgd 	va_end(ap);
    326  1.12       cgd 	if (!log_open) {
    327  1.12       cgd 		va_start(ap, fmt);
    328  1.30  christos 		kprintf(fmt, TOCONS, NULL, ap);
    329  1.12       cgd 		va_end(ap);
    330  1.12       cgd 	}
    331  1.12       cgd 	logwakeup();
    332  1.12       cgd }
    333  1.12       cgd 
    334  1.12       cgd void
    335  1.12       cgd #ifdef __STDC__
    336  1.30  christos printf(const char *fmt, ...)
    337  1.12       cgd #else
    338  1.30  christos printf(fmt, va_alist)
    339  1.12       cgd 	char *fmt;
    340  1.20  christos 	va_dcl
    341  1.12       cgd #endif
    342  1.12       cgd {
    343  1.12       cgd 	va_list ap;
    344  1.12       cgd 	register int savintr;
    345  1.12       cgd 
    346  1.12       cgd 	savintr = consintr;		/* disable interrupts */
    347  1.12       cgd 	consintr = 0;
    348  1.12       cgd 	va_start(ap, fmt);
    349  1.30  christos 	kprintf(fmt, TOCONS | TOLOG, NULL, ap);
    350  1.12       cgd 	va_end(ap);
    351  1.12       cgd 	if (!panicstr)
    352  1.12       cgd 		logwakeup();
    353  1.12       cgd 	consintr = savintr;		/* reenable interrupts */
    354  1.12       cgd }
    355  1.12       cgd 
    356  1.40   thorpej #ifdef __powerpc__			/* XXX XXX XXX */
    357  1.40   thorpej void
    358  1.40   thorpej vprintf(fmt, ap)
    359  1.40   thorpej 	const char *fmt;
    360  1.40   thorpej 	va_list ap;
    361  1.40   thorpej {
    362  1.40   thorpej 	register int savintr;
    363  1.40   thorpej 
    364  1.40   thorpej 	savintr = consintr;		/* disable interrupts */
    365  1.40   thorpej 	consintr = 0;
    366  1.40   thorpej 	kprintf(fmt, TOCONS | TOLOG, NULL, ap);
    367  1.40   thorpej 	if (!panicstr)
    368  1.40   thorpej 		logwakeup();
    369  1.40   thorpej 	consintr = savintr;		/* reenable interrupts */
    370  1.40   thorpej }
    371  1.40   thorpej #endif /* __powerpc__ */		/* XXX XXX XXX */
    372  1.40   thorpej 
    373  1.12       cgd /*
    374  1.12       cgd  * Scaled down version of printf(3).
    375  1.12       cgd  *
    376  1.12       cgd  * Two additional formats:
    377  1.12       cgd  *
    378  1.12       cgd  * The format %b is supported to decode error registers.
    379  1.12       cgd  * Its usage is:
    380  1.12       cgd  *
    381  1.30  christos  *	printf("reg=%b\n", regval, "<base><arg>*");
    382  1.12       cgd  *
    383  1.12       cgd  * where <base> is the output base expressed as a control character, e.g.
    384  1.12       cgd  * \10 gives octal; \20 gives hex.  Each arg is a sequence of characters,
    385  1.12       cgd  * the first of which gives the bit number to be inspected (origin 1), and
    386  1.12       cgd  * the next characters (up to a control character, i.e. a character <= 32),
    387  1.12       cgd  * give the name of the register.  Thus:
    388  1.12       cgd  *
    389  1.30  christos  *	kprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
    390  1.12       cgd  *
    391  1.12       cgd  * would produce output:
    392  1.12       cgd  *
    393  1.12       cgd  *	reg=3<BITTWO,BITONE>
    394  1.12       cgd  *
    395  1.24  christos  * The format %: passes an additional format string and argument list
    396  1.14       cgd  * recursively.  Its usage is:
    397  1.12       cgd  *
    398  1.14       cgd  * fn(char *fmt, ...)
    399  1.12       cgd  * {
    400  1.12       cgd  *	va_list ap;
    401  1.12       cgd  *	va_start(ap, fmt);
    402  1.30  christos  *	printf("prefix: %: suffix\n", fmt, ap);
    403  1.12       cgd  *	va_end(ap);
    404  1.14       cgd  * }
    405  1.12       cgd  *
    406  1.12       cgd  * Space or zero padding and a field width are supported for the numeric
    407  1.12       cgd  * formats only.
    408  1.12       cgd  */
    409  1.12       cgd void
    410  1.30  christos kprintf(fmt, flags, tp, ap)
    411  1.12       cgd 	register const char *fmt;
    412  1.12       cgd 	int flags;
    413  1.12       cgd 	struct tty *tp;
    414  1.12       cgd 	va_list ap;
    415  1.12       cgd {
    416  1.14       cgd 	register char *p, *q;
    417  1.12       cgd 	register int ch, n;
    418  1.12       cgd 	u_long ul;
    419  1.12       cgd 	int base, lflag, tmp, width;
    420  1.37   thorpej 	char padc, snbuf[KSNPRINTN_BUFSIZE];
    421  1.12       cgd 
    422  1.12       cgd 	for (;;) {
    423  1.12       cgd 		padc = ' ';
    424  1.12       cgd 		width = 0;
    425  1.33       cgd 		while ((ch = *(const u_char *)fmt++) != '%') {
    426  1.12       cgd 			if (ch == '\0')
    427  1.12       cgd 				return;
    428  1.12       cgd 			putchar(ch, flags, tp);
    429  1.12       cgd 		}
    430  1.12       cgd 		lflag = 0;
    431  1.33       cgd reswitch:	switch (ch = *(const u_char *)fmt++) {
    432  1.12       cgd 		case '0':
    433  1.27  christos 		case '.':
    434  1.12       cgd 			padc = '0';
    435  1.12       cgd 			goto reswitch;
    436  1.12       cgd 		case '1': case '2': case '3': case '4':
    437  1.12       cgd 		case '5': case '6': case '7': case '8': case '9':
    438  1.12       cgd 			for (width = 0;; ++fmt) {
    439  1.12       cgd 				width = width * 10 + ch - '0';
    440  1.12       cgd 				ch = *fmt;
    441  1.12       cgd 				if (ch < '0' || ch > '9')
    442  1.12       cgd 					break;
    443  1.12       cgd 			}
    444  1.12       cgd 			goto reswitch;
    445  1.12       cgd 		case 'l':
    446  1.12       cgd 			lflag = 1;
    447  1.12       cgd 			goto reswitch;
    448  1.12       cgd 		case 'b':
    449  1.12       cgd 			ul = va_arg(ap, int);
    450  1.12       cgd 			p = va_arg(ap, char *);
    451  1.37   thorpej 			for (q = ksnprintn(ul, *p++, NULL, snbuf,
    452  1.37   thorpej 			    sizeof(snbuf)); (ch = *q--) != 0;)
    453  1.12       cgd 				putchar(ch, flags, tp);
    454  1.12       cgd 
    455  1.12       cgd 			if (!ul)
    456  1.12       cgd 				break;
    457  1.12       cgd 
    458  1.20  christos 			for (tmp = 0; (n = *p++) != 0;) {
    459  1.12       cgd 				if (ul & (1 << (n - 1))) {
    460  1.12       cgd 					putchar(tmp ? ',' : '<', flags, tp);
    461  1.12       cgd 					for (; (n = *p) > ' '; ++p)
    462  1.12       cgd 						putchar(n, flags, tp);
    463  1.12       cgd 					tmp = 1;
    464  1.12       cgd 				} else
    465  1.14       cgd 					for (; *p > ' '; ++p)
    466  1.14       cgd 						continue;
    467  1.12       cgd 			}
    468  1.12       cgd 			if (tmp)
    469  1.12       cgd 				putchar('>', flags, tp);
    470  1.12       cgd 			break;
    471  1.12       cgd 		case 'c':
    472  1.12       cgd 			putchar(va_arg(ap, int), flags, tp);
    473  1.12       cgd 			break;
    474  1.40   thorpej #ifndef __powerpc__			/* XXX XXX XXX */
    475  1.24  christos 		case ':':
    476  1.12       cgd 			p = va_arg(ap, char *);
    477  1.30  christos 			kprintf(p, flags, tp, va_arg(ap, va_list));
    478  1.12       cgd 			break;
    479  1.40   thorpej #endif /* __powerpc__ */		/* XXX XXX XXX */
    480  1.12       cgd 		case 's':
    481  1.16   mycroft 			if ((p = va_arg(ap, char *)) == NULL)
    482  1.16   mycroft 				p = "(null)";
    483  1.20  christos 			while ((ch = *p++) != 0)
    484  1.12       cgd 				putchar(ch, flags, tp);
    485  1.12       cgd 			break;
    486  1.12       cgd 		case 'd':
    487  1.12       cgd 			ul = lflag ? va_arg(ap, long) : va_arg(ap, int);
    488  1.12       cgd 			if ((long)ul < 0) {
    489  1.12       cgd 				putchar('-', flags, tp);
    490  1.12       cgd 				ul = -(long)ul;
    491  1.12       cgd 			}
    492  1.12       cgd 			base = 10;
    493  1.12       cgd 			goto number;
    494  1.12       cgd 		case 'o':
    495  1.12       cgd 			ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
    496  1.12       cgd 			base = 8;
    497  1.12       cgd 			goto number;
    498  1.12       cgd 		case 'u':
    499  1.12       cgd 			ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
    500  1.12       cgd 			base = 10;
    501  1.12       cgd 			goto number;
    502  1.17   mycroft 		case 'p':
    503  1.17   mycroft 			putchar('0', flags, tp);
    504  1.17   mycroft 			putchar('x', flags, tp);
    505  1.18   mycroft 			ul = (u_long)va_arg(ap, void *);
    506  1.18   mycroft 			base = 16;
    507  1.18   mycroft 			goto number;
    508  1.12       cgd 		case 'x':
    509  1.12       cgd 			ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
    510  1.12       cgd 			base = 16;
    511  1.37   thorpej number:			p = ksnprintn(ul, base, &tmp, snbuf, sizeof(snbuf));
    512  1.12       cgd 			if (width && (width -= tmp) > 0)
    513  1.12       cgd 				while (width--)
    514  1.12       cgd 					putchar(padc, flags, tp);
    515  1.20  christos 			while ((ch = *p--) != 0)
    516  1.12       cgd 				putchar(ch, flags, tp);
    517  1.12       cgd 			break;
    518  1.12       cgd 		default:
    519  1.12       cgd 			putchar('%', flags, tp);
    520  1.12       cgd 			if (lflag)
    521  1.12       cgd 				putchar('l', flags, tp);
    522  1.12       cgd 			/* FALLTHROUGH */
    523  1.12       cgd 		case '%':
    524  1.12       cgd 			putchar(ch, flags, tp);
    525  1.12       cgd 		}
    526  1.12       cgd 	}
    527  1.12       cgd }
    528  1.12       cgd 
    529  1.12       cgd /*
    530  1.12       cgd  * Print a character on console or users terminal.  If destination is
    531  1.12       cgd  * the console then the last MSGBUFS characters are saved in msgbuf for
    532  1.12       cgd  * inspection later.
    533  1.12       cgd  */
    534  1.12       cgd static void
    535  1.12       cgd putchar(c, flags, tp)
    536  1.12       cgd 	register int c;
    537  1.12       cgd 	int flags;
    538  1.12       cgd 	struct tty *tp;
    539  1.12       cgd {
    540  1.14       cgd 	extern int msgbufmapped;
    541  1.12       cgd 	register struct msgbuf *mbp;
    542  1.12       cgd 
    543  1.12       cgd 	if (panicstr)
    544  1.12       cgd 		constty = NULL;
    545  1.12       cgd 	if ((flags & TOCONS) && tp == NULL && constty) {
    546  1.12       cgd 		tp = constty;
    547  1.12       cgd 		flags |= TOTTY;
    548  1.12       cgd 	}
    549  1.12       cgd 	if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 &&
    550  1.12       cgd 	    (flags & TOCONS) && tp == constty)
    551  1.12       cgd 		constty = NULL;
    552  1.12       cgd 	if ((flags & TOLOG) &&
    553  1.12       cgd 	    c != '\0' && c != '\r' && c != 0177 && msgbufmapped) {
    554  1.12       cgd 		mbp = msgbufp;
    555  1.12       cgd 		if (mbp->msg_magic != MSG_MAGIC) {
    556  1.12       cgd 			bzero((caddr_t)mbp, sizeof(*mbp));
    557  1.12       cgd 			mbp->msg_magic = MSG_MAGIC;
    558  1.12       cgd 		}
    559  1.12       cgd 		mbp->msg_bufc[mbp->msg_bufx++] = c;
    560  1.12       cgd 		if (mbp->msg_bufx < 0 || mbp->msg_bufx >= MSG_BSIZE)
    561  1.12       cgd 			mbp->msg_bufx = 0;
    562  1.12       cgd 	}
    563  1.12       cgd 	if ((flags & TOCONS) && constty == NULL && c != '\0')
    564  1.12       cgd 		(*v_putc)(c);
    565  1.12       cgd }
    566  1.12       cgd 
    567  1.12       cgd /*
    568  1.12       cgd  * Scaled down version of sprintf(3).
    569  1.12       cgd  */
    570  1.20  christos int
    571  1.12       cgd #ifdef __STDC__
    572  1.30  christos sprintf(char *buf, const char *cfmt, ...)
    573  1.12       cgd #else
    574  1.30  christos sprintf(buf, cfmt, va_alist)
    575  1.34       gwr 	char *buf;
    576  1.36       gwr 	const char *cfmt;
    577  1.20  christos 	va_dcl
    578  1.12       cgd #endif
    579  1.12       cgd {
    580  1.36       gwr 	register const char *fmt = cfmt;
    581  1.12       cgd 	register char *p, *bp;
    582  1.12       cgd 	register int ch, base;
    583  1.12       cgd 	u_long ul;
    584  1.19       cgd 	int lflag, tmp, width;
    585  1.12       cgd 	va_list ap;
    586  1.37   thorpej 	char padc, snbuf[KSNPRINTN_BUFSIZE];
    587  1.12       cgd 
    588  1.12       cgd 	va_start(ap, cfmt);
    589  1.12       cgd 	for (bp = buf; ; ) {
    590  1.19       cgd 		padc = ' ';
    591  1.19       cgd 		width = 0;
    592  1.33       cgd 		while ((ch = *(const u_char *)fmt++) != '%')
    593  1.12       cgd 			if ((*bp++ = ch) == '\0')
    594  1.12       cgd 				return ((bp - buf) - 1);
    595  1.12       cgd 
    596  1.12       cgd 		lflag = 0;
    597  1.33       cgd reswitch:	switch (ch = *(const u_char *)fmt++) {
    598  1.19       cgd 		case '0':
    599  1.19       cgd 			padc = '0';
    600  1.19       cgd 			goto reswitch;
    601  1.19       cgd 		case '1': case '2': case '3': case '4':
    602  1.19       cgd 		case '5': case '6': case '7': case '8': case '9':
    603  1.19       cgd 			for (width = 0;; ++fmt) {
    604  1.19       cgd 				width = width * 10 + ch - '0';
    605  1.19       cgd 				ch = *fmt;
    606  1.19       cgd 				if (ch < '0' || ch > '9')
    607  1.19       cgd 					break;
    608  1.19       cgd 			}
    609  1.19       cgd 			goto reswitch;
    610  1.12       cgd 		case 'l':
    611  1.12       cgd 			lflag = 1;
    612  1.12       cgd 			goto reswitch;
    613  1.19       cgd 		/* case 'b': ... break; XXX */
    614  1.12       cgd 		case 'c':
    615  1.12       cgd 			*bp++ = va_arg(ap, int);
    616  1.12       cgd 			break;
    617  1.19       cgd 		/* case 'r': ... break; XXX */
    618  1.12       cgd 		case 's':
    619  1.12       cgd 			p = va_arg(ap, char *);
    620  1.20  christos 			while ((*bp++ = *p++) != 0)
    621  1.14       cgd 				continue;
    622  1.12       cgd 			--bp;
    623  1.12       cgd 			break;
    624  1.12       cgd 		case 'd':
    625  1.12       cgd 			ul = lflag ? va_arg(ap, long) : va_arg(ap, int);
    626  1.12       cgd 			if ((long)ul < 0) {
    627  1.12       cgd 				*bp++ = '-';
    628  1.12       cgd 				ul = -(long)ul;
    629  1.12       cgd 			}
    630  1.12       cgd 			base = 10;
    631  1.12       cgd 			goto number;
    632  1.12       cgd 			break;
    633  1.12       cgd 		case 'o':
    634  1.12       cgd 			ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
    635  1.12       cgd 			base = 8;
    636  1.12       cgd 			goto number;
    637  1.12       cgd 			break;
    638  1.12       cgd 		case 'u':
    639  1.12       cgd 			ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
    640  1.12       cgd 			base = 10;
    641  1.12       cgd 			goto number;
    642  1.12       cgd 			break;
    643  1.19       cgd 		case 'p':
    644  1.19       cgd 			*bp++ = '0';
    645  1.19       cgd 			*bp++ = 'x';
    646  1.19       cgd 			ul = (u_long)va_arg(ap, void *);
    647  1.19       cgd 			base = 16;
    648  1.19       cgd 			goto number;
    649  1.12       cgd 		case 'x':
    650  1.12       cgd 			ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
    651  1.12       cgd 			base = 16;
    652  1.37   thorpej number:			p = ksnprintn(ul, base, &tmp, snbuf, sizeof(snbuf));
    653  1.19       cgd 			if (width && (width -= tmp) > 0)
    654  1.19       cgd 				while (width--)
    655  1.19       cgd 					*bp++ = padc;
    656  1.20  christos 			while ((ch = *p--) != 0)
    657  1.12       cgd 				*bp++ = ch;
    658  1.12       cgd 			break;
    659  1.12       cgd 		default:
    660  1.12       cgd 			*bp++ = '%';
    661  1.12       cgd 			if (lflag)
    662  1.12       cgd 				*bp++ = 'l';
    663  1.12       cgd 			/* FALLTHROUGH */
    664  1.12       cgd 		case '%':
    665  1.12       cgd 			*bp++ = ch;
    666  1.12       cgd 		}
    667  1.12       cgd 	}
    668  1.12       cgd 	va_end(ap);
    669  1.12       cgd }
    670  1.12       cgd 
    671  1.12       cgd /*
    672  1.12       cgd  * Put a number (base <= 16) in a buffer in reverse order; return an
    673  1.12       cgd  * optional length and a pointer to the NULL terminated (preceded?)
    674  1.12       cgd  * buffer.
    675  1.12       cgd  */
    676  1.12       cgd static char *
    677  1.37   thorpej ksnprintn(ul, base, lenp, buf, buflen)
    678  1.12       cgd 	register u_long ul;
    679  1.12       cgd 	register int base, *lenp;
    680  1.37   thorpej 	char *buf;
    681  1.37   thorpej 	size_t buflen;
    682  1.37   thorpej {
    683  1.12       cgd 	register char *p;
    684  1.12       cgd 
    685  1.12       cgd 	p = buf;
    686  1.37   thorpej 	*p = '\0';			/* ensure NULL `termination' */
    687  1.37   thorpej 
    688  1.37   thorpej 	/*
    689  1.37   thorpej 	 * Don't even bother of the buffer's not big enough.  No
    690  1.37   thorpej 	 * value at all is better than a wrong value, and we
    691  1.37   thorpej 	 * have a lot of control over the buffer that's passed
    692  1.37   thorpej 	 * to this function, since it's not exported.
    693  1.37   thorpej 	 */
    694  1.37   thorpej 	if (buflen < KSNPRINTN_BUFSIZE)
    695  1.37   thorpej 		return (p);
    696  1.37   thorpej 
    697  1.12       cgd 	do {
    698  1.12       cgd 		*++p = "0123456789abcdef"[ul % base];
    699  1.12       cgd 	} while (ul /= base);
    700  1.12       cgd 	if (lenp)
    701  1.12       cgd 		*lenp = p - buf;
    702  1.12       cgd 	return (p);
    703  1.37   thorpej }
    704  1.37   thorpej 
    705  1.37   thorpej /*
    706  1.37   thorpej  * Print a bitmask into the provided buffer, and return a pointer
    707  1.37   thorpej  * to that buffer.
    708  1.37   thorpej  */
    709  1.37   thorpej char *
    710  1.37   thorpej bitmask_snprintf(ul, p, buf, buflen)
    711  1.37   thorpej 	u_long ul;
    712  1.37   thorpej 	const char *p;
    713  1.37   thorpej 	char *buf;
    714  1.37   thorpej 	size_t buflen;
    715  1.37   thorpej {
    716  1.37   thorpej 	char *bp, *q;
    717  1.37   thorpej 	size_t left;
    718  1.37   thorpej 	register int n;
    719  1.37   thorpej 	int ch, tmp;
    720  1.37   thorpej 	char snbuf[KSNPRINTN_BUFSIZE];
    721  1.37   thorpej 
    722  1.37   thorpej 	bp = buf;
    723  1.37   thorpej 	bzero(buf, buflen);
    724  1.37   thorpej 
    725  1.37   thorpej 	/*
    726  1.37   thorpej 	 * Always leave room for the trailing NULL.
    727  1.37   thorpej 	 */
    728  1.37   thorpej 	left = buflen - 1;
    729  1.37   thorpej 
    730  1.37   thorpej 	/*
    731  1.37   thorpej 	 * Print the value into the buffer.  Abort if there's not
    732  1.37   thorpej 	 * enough room.
    733  1.37   thorpej 	 */
    734  1.37   thorpej 	if (buflen < KSNPRINTN_BUFSIZE)
    735  1.37   thorpej 		return (buf);
    736  1.37   thorpej 
    737  1.37   thorpej 	for (q = ksnprintn(ul, *p++, NULL, snbuf, sizeof(snbuf));
    738  1.37   thorpej 	    (ch = *q--) != 0;) {
    739  1.37   thorpej 		*bp++ = ch;
    740  1.37   thorpej 		left--;
    741  1.37   thorpej 	}
    742  1.37   thorpej 
    743  1.37   thorpej 	/*
    744  1.37   thorpej 	 * If the value we printed was 0, or if we don't have room for
    745  1.37   thorpej 	 * "<x>", we're done.
    746  1.37   thorpej 	 */
    747  1.37   thorpej 	if (ul == 0 || left < 3)
    748  1.37   thorpej 		return (buf);
    749  1.37   thorpej 
    750  1.37   thorpej #define PUTBYTE(b, c, l)	\
    751  1.37   thorpej 	*(b)++ = (c);		\
    752  1.37   thorpej 	if (--(l) == 0)		\
    753  1.37   thorpej 		goto out;
    754  1.37   thorpej 
    755  1.37   thorpej 	for (tmp = 0; (n = *p++) != 0;) {
    756  1.37   thorpej 		if (ul & (1 << (n - 1))) {
    757  1.37   thorpej 			PUTBYTE(bp, tmp ? ',' : '<', left);
    758  1.37   thorpej 				for (; (n = *p) > ' '; ++p) {
    759  1.37   thorpej 					PUTBYTE(bp, n, left);
    760  1.37   thorpej 				}
    761  1.37   thorpej 				tmp = 1;
    762  1.37   thorpej 		} else
    763  1.37   thorpej 			for (; *p > ' '; ++p)
    764  1.37   thorpej 				continue;
    765  1.37   thorpej 	}
    766  1.37   thorpej 	if (tmp)
    767  1.37   thorpej 		*bp = '>';
    768  1.37   thorpej 
    769  1.37   thorpej #undef PUTBYTE
    770  1.37   thorpej 
    771  1.37   thorpej  out:
    772  1.37   thorpej 	return (buf);
    773  1.12       cgd }
    774