Home | History | Annotate | Line # | Download | only in kern
subr_prf.c revision 1.43.4.1
      1  1.43.4.1   thorpej /*	$NetBSD: subr_prf.c,v 1.43.4.1 1997/09/22 06:33:49 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.42   thorpej #include <sys/kgdb.h>
     74      1.22  christos #include <machine/cpu.h>
     75      1.12       cgd #endif
     76      1.20  christos 
     77      1.12       cgd #define TOCONS	0x01
     78      1.12       cgd #define TOTTY	0x02
     79      1.12       cgd #define TOLOG	0x04
     80      1.12       cgd 
     81      1.37   thorpej /*
     82      1.37   thorpej  * This is the size of the buffer that should be passed to ksnprintn().
     83      1.37   thorpej  * It's the length of a long in base 8, plus NULL.
     84      1.37   thorpej  */
     85      1.41  drochner #define KSNPRINTN_BUFSIZE	(sizeof(quad_t) * NBBY / 3 + 2)
     86      1.37   thorpej 
     87      1.12       cgd struct	tty *constty;			/* pointer to console "window" tty */
     88      1.12       cgd 
     89      1.20  christos void	(*v_putc) __P((int)) = cnputc;	/* routine to putc on virtual console */
     90      1.12       cgd 
     91      1.20  christos static void putchar __P((int, int, struct tty *));
     92      1.41  drochner static char *ksnprintn __P((u_quad_t, int, int *, char *, size_t));
     93      1.30  christos void kprintf __P((const char *, int, struct tty *, va_list));
     94      1.12       cgd 
     95      1.14       cgd int consintr = 1;			/* Ok to handle console interrupts? */
     96      1.12       cgd 
     97      1.12       cgd /*
     98      1.14       cgd  * Variable panicstr contains argument to first call to panic; used as flag
     99      1.14       cgd  * to indicate that the kernel has already called panic.
    100      1.12       cgd  */
    101      1.14       cgd const char *panicstr;
    102      1.12       cgd 
    103      1.12       cgd /*
    104      1.12       cgd  * Panic is called on unresolvable fatal errors.  It prints "panic: mesg",
    105      1.12       cgd  * and then reboots.  If we are called twice, then we avoid trying to sync
    106      1.12       cgd  * the disks as this often leads to recursive panics.
    107      1.12       cgd  */
    108      1.14       cgd void
    109      1.12       cgd #ifdef __STDC__
    110      1.12       cgd panic(const char *fmt, ...)
    111      1.12       cgd #else
    112      1.14       cgd panic(fmt, va_alist)
    113      1.12       cgd 	char *fmt;
    114      1.20  christos 	va_dcl
    115      1.12       cgd #endif
    116      1.12       cgd {
    117      1.14       cgd 	int bootopt;
    118      1.12       cgd 	va_list ap;
    119      1.12       cgd 
    120      1.14       cgd 	bootopt = RB_AUTOBOOT | RB_DUMP;
    121      1.12       cgd 	if (panicstr)
    122      1.12       cgd 		bootopt |= RB_NOSYNC;
    123      1.12       cgd 	else
    124      1.12       cgd 		panicstr = fmt;
    125      1.12       cgd 
    126      1.12       cgd 	va_start(ap, fmt);
    127      1.40   thorpej #ifdef __powerpc__				/* XXX */
    128      1.40   thorpej 	printf("panic: ");			/* XXX */
    129      1.40   thorpej 	vprintf(fmt, ap);			/* XXX */
    130      1.40   thorpej 	printf("\n");				/* XXX */
    131      1.40   thorpej #else						/* XXX */
    132      1.40   thorpej 	printf("panic: %:\n", fmt, ap);		/* XXX */
    133      1.40   thorpej #endif						/* XXX */
    134      1.12       cgd 	va_end(ap);
    135      1.12       cgd 
    136      1.32        ws #if NIPKDB > 0
    137      1.32        ws 	ipkdb_panic();
    138      1.28        ws #endif
    139      1.12       cgd #ifdef KGDB
    140      1.12       cgd 	kgdb_panic();
    141      1.12       cgd #endif
    142      1.12       cgd #ifdef KADB
    143      1.14       cgd 	if (boothowto & RB_KDB)
    144      1.14       cgd 		kdbpanic();
    145      1.12       cgd #endif
    146      1.12       cgd #ifdef DDB
    147      1.38   thorpej 	if (db_onpanic)
    148      1.38   thorpej 		Debugger();
    149      1.12       cgd #endif
    150      1.39       gwr 	cpu_reboot(bootopt, NULL);
    151      1.12       cgd }
    152      1.12       cgd 
    153      1.12       cgd /*
    154      1.12       cgd  * Warn that a system table is full.
    155      1.12       cgd  */
    156      1.12       cgd void
    157      1.12       cgd tablefull(tab)
    158      1.12       cgd 	const char *tab;
    159      1.12       cgd {
    160      1.12       cgd 
    161      1.12       cgd 	log(LOG_ERR, "%s: table is full\n", tab);
    162      1.12       cgd }
    163      1.12       cgd 
    164      1.12       cgd /*
    165      1.12       cgd  * Uprintf prints to the controlling terminal for the current process.
    166      1.12       cgd  * It may block if the tty queue is overfull.  No message is printed if
    167      1.12       cgd  * the queue does not clear in a reasonable time.
    168      1.12       cgd  */
    169      1.12       cgd void
    170      1.12       cgd #ifdef __STDC__
    171      1.12       cgd uprintf(const char *fmt, ...)
    172      1.12       cgd #else
    173      1.14       cgd uprintf(fmt, va_alist)
    174      1.12       cgd 	char *fmt;
    175      1.20  christos 	va_dcl
    176      1.12       cgd #endif
    177      1.12       cgd {
    178      1.12       cgd 	register struct proc *p = curproc;
    179      1.12       cgd 	va_list ap;
    180      1.12       cgd 
    181      1.12       cgd 	if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
    182      1.12       cgd 		va_start(ap, fmt);
    183      1.30  christos 		kprintf(fmt, TOTTY, p->p_session->s_ttyp, ap);
    184      1.12       cgd 		va_end(ap);
    185      1.12       cgd 	}
    186      1.12       cgd }
    187      1.12       cgd 
    188      1.12       cgd tpr_t
    189      1.12       cgd tprintf_open(p)
    190      1.12       cgd 	register struct proc *p;
    191      1.12       cgd {
    192      1.12       cgd 
    193      1.12       cgd 	if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
    194      1.12       cgd 		SESSHOLD(p->p_session);
    195      1.12       cgd 		return ((tpr_t) p->p_session);
    196      1.12       cgd 	}
    197      1.12       cgd 	return ((tpr_t) NULL);
    198      1.12       cgd }
    199      1.12       cgd 
    200      1.12       cgd void
    201      1.12       cgd tprintf_close(sess)
    202      1.12       cgd 	tpr_t sess;
    203      1.12       cgd {
    204      1.12       cgd 
    205      1.12       cgd 	if (sess)
    206      1.12       cgd 		SESSRELE((struct session *) sess);
    207      1.12       cgd }
    208      1.12       cgd 
    209      1.12       cgd /*
    210      1.12       cgd  * tprintf prints on the controlling terminal associated
    211      1.12       cgd  * with the given session.
    212      1.12       cgd  */
    213      1.12       cgd void
    214      1.12       cgd #ifdef __STDC__
    215      1.12       cgd tprintf(tpr_t tpr, const char *fmt, ...)
    216      1.12       cgd #else
    217      1.14       cgd tprintf(tpr, fmt, va_alist)
    218      1.12       cgd 	tpr_t tpr;
    219      1.12       cgd 	char *fmt;
    220      1.20  christos 	va_dcl
    221      1.12       cgd #endif
    222      1.12       cgd {
    223      1.12       cgd 	register struct session *sess = (struct session *)tpr;
    224      1.12       cgd 	struct tty *tp = NULL;
    225      1.12       cgd 	int flags = TOLOG;
    226      1.12       cgd 	va_list ap;
    227      1.12       cgd 
    228      1.12       cgd 	logpri(LOG_INFO);
    229      1.12       cgd 	if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) {
    230      1.12       cgd 		flags |= TOTTY;
    231      1.12       cgd 		tp = sess->s_ttyp;
    232      1.12       cgd 	}
    233      1.12       cgd 	va_start(ap, fmt);
    234      1.30  christos 	kprintf(fmt, flags, tp, ap);
    235      1.12       cgd 	va_end(ap);
    236      1.12       cgd 	logwakeup();
    237      1.12       cgd }
    238      1.12       cgd 
    239      1.12       cgd /*
    240      1.12       cgd  * Ttyprintf displays a message on a tty; it should be used only by
    241      1.12       cgd  * the tty driver, or anything that knows the underlying tty will not
    242      1.12       cgd  * be revoke(2)'d away.  Other callers should use tprintf.
    243      1.12       cgd  */
    244      1.12       cgd void
    245      1.12       cgd #ifdef __STDC__
    246      1.12       cgd ttyprintf(struct tty *tp, const char *fmt, ...)
    247      1.12       cgd #else
    248      1.14       cgd ttyprintf(tp, fmt, va_alist)
    249      1.12       cgd 	struct tty *tp;
    250      1.12       cgd 	char *fmt;
    251      1.20  christos 	va_dcl
    252      1.12       cgd #endif
    253      1.12       cgd {
    254      1.12       cgd 	va_list ap;
    255      1.12       cgd 
    256      1.12       cgd 	va_start(ap, fmt);
    257      1.30  christos 	kprintf(fmt, TOTTY, tp, ap);
    258      1.12       cgd 	va_end(ap);
    259      1.12       cgd }
    260      1.12       cgd 
    261      1.12       cgd extern	int log_open;
    262      1.12       cgd 
    263      1.12       cgd /*
    264      1.12       cgd  * Log writes to the log buffer, and guarantees not to sleep (so can be
    265      1.12       cgd  * called by interrupt routines).  If there is no process reading the
    266      1.12       cgd  * log yet, it writes to the console also.
    267      1.12       cgd  */
    268      1.12       cgd void
    269      1.12       cgd #ifdef __STDC__
    270      1.12       cgd log(int level, const char *fmt, ...)
    271      1.12       cgd #else
    272      1.14       cgd log(level, fmt, va_alist)
    273      1.12       cgd 	int level;
    274      1.12       cgd 	char *fmt;
    275      1.20  christos 	va_dcl
    276      1.12       cgd #endif
    277      1.12       cgd {
    278      1.12       cgd 	register int s;
    279      1.12       cgd 	va_list ap;
    280      1.12       cgd 
    281      1.12       cgd 	s = splhigh();
    282      1.12       cgd 	logpri(level);
    283      1.12       cgd 	va_start(ap, fmt);
    284      1.30  christos 	kprintf(fmt, TOLOG, NULL, ap);
    285      1.12       cgd 	splx(s);
    286      1.12       cgd 	va_end(ap);
    287      1.12       cgd 	if (!log_open) {
    288      1.12       cgd 		va_start(ap, fmt);
    289      1.30  christos 		kprintf(fmt, TOCONS, NULL, ap);
    290      1.12       cgd 		va_end(ap);
    291      1.12       cgd 	}
    292      1.12       cgd 	logwakeup();
    293      1.12       cgd }
    294      1.12       cgd 
    295      1.13   mycroft void
    296      1.12       cgd logpri(level)
    297      1.12       cgd 	int level;
    298      1.12       cgd {
    299      1.12       cgd 	register int ch;
    300      1.12       cgd 	register char *p;
    301      1.37   thorpej 	char snbuf[KSNPRINTN_BUFSIZE];
    302      1.12       cgd 
    303      1.12       cgd 	putchar('<', TOLOG, NULL);
    304      1.37   thorpej 	for (p = ksnprintn((u_long)level, 10, NULL, snbuf, sizeof(snbuf));
    305      1.37   thorpej 	    (ch = *p--) != 0;)
    306      1.12       cgd 		putchar(ch, TOLOG, NULL);
    307      1.12       cgd 	putchar('>', TOLOG, NULL);
    308      1.12       cgd }
    309      1.12       cgd 
    310      1.12       cgd void
    311      1.12       cgd #ifdef __STDC__
    312      1.12       cgd addlog(const char *fmt, ...)
    313      1.12       cgd #else
    314      1.14       cgd addlog(fmt, va_alist)
    315      1.12       cgd 	char *fmt;
    316      1.20  christos 	va_dcl
    317      1.12       cgd #endif
    318      1.12       cgd {
    319      1.12       cgd 	register int s;
    320      1.12       cgd 	va_list ap;
    321      1.12       cgd 
    322      1.12       cgd 	s = splhigh();
    323      1.12       cgd 	va_start(ap, fmt);
    324      1.30  christos 	kprintf(fmt, TOLOG, NULL, ap);
    325      1.12       cgd 	splx(s);
    326      1.12       cgd 	va_end(ap);
    327      1.12       cgd 	if (!log_open) {
    328      1.12       cgd 		va_start(ap, fmt);
    329      1.30  christos 		kprintf(fmt, TOCONS, NULL, ap);
    330      1.12       cgd 		va_end(ap);
    331      1.12       cgd 	}
    332      1.12       cgd 	logwakeup();
    333      1.12       cgd }
    334      1.12       cgd 
    335      1.12       cgd void
    336      1.12       cgd #ifdef __STDC__
    337      1.30  christos printf(const char *fmt, ...)
    338      1.12       cgd #else
    339      1.30  christos printf(fmt, va_alist)
    340      1.12       cgd 	char *fmt;
    341      1.20  christos 	va_dcl
    342      1.12       cgd #endif
    343      1.12       cgd {
    344      1.12       cgd 	va_list ap;
    345      1.12       cgd 	register int savintr;
    346      1.12       cgd 
    347      1.12       cgd 	savintr = consintr;		/* disable interrupts */
    348      1.12       cgd 	consintr = 0;
    349      1.12       cgd 	va_start(ap, fmt);
    350      1.30  christos 	kprintf(fmt, TOCONS | TOLOG, NULL, ap);
    351      1.12       cgd 	va_end(ap);
    352      1.12       cgd 	if (!panicstr)
    353      1.12       cgd 		logwakeup();
    354      1.12       cgd 	consintr = savintr;		/* reenable interrupts */
    355      1.12       cgd }
    356      1.12       cgd 
    357      1.40   thorpej #ifdef __powerpc__			/* XXX XXX XXX */
    358      1.40   thorpej void
    359      1.40   thorpej vprintf(fmt, ap)
    360      1.40   thorpej 	const char *fmt;
    361      1.40   thorpej 	va_list ap;
    362      1.40   thorpej {
    363      1.40   thorpej 	register int savintr;
    364      1.40   thorpej 
    365      1.40   thorpej 	savintr = consintr;		/* disable interrupts */
    366      1.40   thorpej 	consintr = 0;
    367      1.40   thorpej 	kprintf(fmt, TOCONS | TOLOG, NULL, ap);
    368      1.40   thorpej 	if (!panicstr)
    369      1.40   thorpej 		logwakeup();
    370      1.40   thorpej 	consintr = savintr;		/* reenable interrupts */
    371      1.40   thorpej }
    372      1.40   thorpej #endif /* __powerpc__ */		/* XXX XXX XXX */
    373      1.40   thorpej 
    374      1.12       cgd /*
    375      1.12       cgd  * Scaled down version of printf(3).
    376      1.12       cgd  *
    377      1.12       cgd  * Two additional formats:
    378      1.12       cgd  *
    379      1.12       cgd  * The format %b is supported to decode error registers.
    380      1.12       cgd  * Its usage is:
    381      1.12       cgd  *
    382      1.30  christos  *	printf("reg=%b\n", regval, "<base><arg>*");
    383      1.12       cgd  *
    384      1.12       cgd  * where <base> is the output base expressed as a control character, e.g.
    385      1.12       cgd  * \10 gives octal; \20 gives hex.  Each arg is a sequence of characters,
    386      1.12       cgd  * the first of which gives the bit number to be inspected (origin 1), and
    387      1.12       cgd  * the next characters (up to a control character, i.e. a character <= 32),
    388      1.12       cgd  * give the name of the register.  Thus:
    389      1.12       cgd  *
    390      1.30  christos  *	kprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
    391      1.12       cgd  *
    392      1.12       cgd  * would produce output:
    393      1.12       cgd  *
    394      1.12       cgd  *	reg=3<BITTWO,BITONE>
    395      1.12       cgd  *
    396      1.24  christos  * The format %: passes an additional format string and argument list
    397      1.14       cgd  * recursively.  Its usage is:
    398      1.12       cgd  *
    399      1.14       cgd  * fn(char *fmt, ...)
    400      1.12       cgd  * {
    401      1.12       cgd  *	va_list ap;
    402      1.12       cgd  *	va_start(ap, fmt);
    403      1.30  christos  *	printf("prefix: %: suffix\n", fmt, ap);
    404      1.12       cgd  *	va_end(ap);
    405      1.14       cgd  * }
    406      1.12       cgd  *
    407      1.12       cgd  * Space or zero padding and a field width are supported for the numeric
    408      1.12       cgd  * formats only.
    409      1.12       cgd  */
    410      1.41  drochner #define	LONGINT		0x010		/* long integer */
    411      1.41  drochner #define	QUADINT		0x020		/* quad integer */
    412      1.41  drochner #define	SARG() \
    413      1.41  drochner 	(flags&QUADINT ? va_arg(ap, quad_t) : \
    414      1.41  drochner 	    flags&LONGINT ? va_arg(ap, long) : \
    415      1.41  drochner 	    (long)va_arg(ap, int))
    416      1.41  drochner #define	UARG() \
    417      1.41  drochner 	(flags&QUADINT ? va_arg(ap, u_quad_t) : \
    418      1.41  drochner 	    flags&LONGINT ? va_arg(ap, u_long) : \
    419      1.41  drochner 	    (u_long)va_arg(ap, u_int))
    420      1.12       cgd void
    421      1.41  drochner kprintf(fmt, oflags, tp, ap)
    422      1.12       cgd 	register const char *fmt;
    423      1.41  drochner 	int oflags;
    424      1.12       cgd 	struct tty *tp;
    425      1.12       cgd 	va_list ap;
    426      1.12       cgd {
    427      1.14       cgd 	register char *p, *q;
    428      1.12       cgd 	register int ch, n;
    429      1.41  drochner 	u_quad_t ul;
    430      1.41  drochner 	int base, flags, tmp, width;
    431      1.37   thorpej 	char padc, snbuf[KSNPRINTN_BUFSIZE];
    432      1.12       cgd 
    433      1.12       cgd 	for (;;) {
    434      1.12       cgd 		padc = ' ';
    435      1.12       cgd 		width = 0;
    436      1.33       cgd 		while ((ch = *(const u_char *)fmt++) != '%') {
    437      1.12       cgd 			if (ch == '\0')
    438      1.12       cgd 				return;
    439      1.41  drochner 			putchar(ch, oflags, tp);
    440      1.12       cgd 		}
    441      1.41  drochner 		flags = 0;
    442      1.33       cgd reswitch:	switch (ch = *(const u_char *)fmt++) {
    443      1.43   thorpej 		case '\0':
    444      1.43   thorpej 			/* XXX Print the last format character? */
    445      1.43   thorpej 			return;
    446      1.12       cgd 		case '0':
    447      1.27  christos 		case '.':
    448      1.12       cgd 			padc = '0';
    449      1.12       cgd 			goto reswitch;
    450      1.12       cgd 		case '1': case '2': case '3': case '4':
    451      1.12       cgd 		case '5': case '6': case '7': case '8': case '9':
    452      1.12       cgd 			for (width = 0;; ++fmt) {
    453      1.12       cgd 				width = width * 10 + ch - '0';
    454      1.12       cgd 				ch = *fmt;
    455      1.12       cgd 				if (ch < '0' || ch > '9')
    456      1.12       cgd 					break;
    457      1.12       cgd 			}
    458      1.12       cgd 			goto reswitch;
    459      1.12       cgd 		case 'l':
    460      1.41  drochner 			flags |= LONGINT;
    461      1.41  drochner 			goto reswitch;
    462      1.41  drochner 		case 'q':
    463      1.41  drochner 			flags |= QUADINT;
    464      1.12       cgd 			goto reswitch;
    465      1.12       cgd 		case 'b':
    466      1.12       cgd 			ul = va_arg(ap, int);
    467      1.12       cgd 			p = va_arg(ap, char *);
    468      1.37   thorpej 			for (q = ksnprintn(ul, *p++, NULL, snbuf,
    469      1.37   thorpej 			    sizeof(snbuf)); (ch = *q--) != 0;)
    470      1.41  drochner 				putchar(ch, oflags, tp);
    471      1.12       cgd 
    472      1.12       cgd 			if (!ul)
    473      1.12       cgd 				break;
    474      1.12       cgd 
    475      1.20  christos 			for (tmp = 0; (n = *p++) != 0;) {
    476      1.12       cgd 				if (ul & (1 << (n - 1))) {
    477      1.41  drochner 					putchar(tmp ? ',' : '<', oflags, tp);
    478      1.12       cgd 					for (; (n = *p) > ' '; ++p)
    479      1.41  drochner 						putchar(n, oflags, tp);
    480      1.12       cgd 					tmp = 1;
    481      1.12       cgd 				} else
    482      1.14       cgd 					for (; *p > ' '; ++p)
    483      1.14       cgd 						continue;
    484      1.12       cgd 			}
    485      1.12       cgd 			if (tmp)
    486      1.41  drochner 				putchar('>', oflags, tp);
    487      1.12       cgd 			break;
    488      1.12       cgd 		case 'c':
    489      1.41  drochner 			putchar(va_arg(ap, int), oflags, tp);
    490      1.12       cgd 			break;
    491      1.40   thorpej #ifndef __powerpc__			/* XXX XXX XXX */
    492      1.24  christos 		case ':':
    493      1.12       cgd 			p = va_arg(ap, char *);
    494      1.41  drochner 			kprintf(p, oflags, tp, va_arg(ap, va_list));
    495      1.12       cgd 			break;
    496      1.40   thorpej #endif /* __powerpc__ */		/* XXX XXX XXX */
    497      1.12       cgd 		case 's':
    498      1.16   mycroft 			if ((p = va_arg(ap, char *)) == NULL)
    499      1.16   mycroft 				p = "(null)";
    500      1.20  christos 			while ((ch = *p++) != 0)
    501      1.41  drochner 				putchar(ch, oflags, tp);
    502      1.12       cgd 			break;
    503      1.12       cgd 		case 'd':
    504      1.41  drochner 		        ul = SARG();
    505      1.41  drochner 			if ((quad_t)ul < 0) {
    506      1.41  drochner 				putchar('-', oflags, tp);
    507      1.41  drochner 				ul = -ul;
    508      1.12       cgd 			}
    509      1.12       cgd 			base = 10;
    510      1.12       cgd 			goto number;
    511      1.12       cgd 		case 'o':
    512      1.41  drochner 			ul = UARG();
    513      1.12       cgd 			base = 8;
    514      1.12       cgd 			goto number;
    515      1.12       cgd 		case 'u':
    516      1.41  drochner 			ul = UARG();
    517      1.12       cgd 			base = 10;
    518      1.12       cgd 			goto number;
    519      1.17   mycroft 		case 'p':
    520      1.41  drochner 			putchar('0', oflags, tp);
    521      1.41  drochner 			putchar('x', oflags, tp);
    522      1.18   mycroft 			ul = (u_long)va_arg(ap, void *);
    523      1.18   mycroft 			base = 16;
    524      1.18   mycroft 			goto number;
    525      1.12       cgd 		case 'x':
    526      1.41  drochner 			ul = UARG();
    527      1.12       cgd 			base = 16;
    528      1.37   thorpej number:			p = ksnprintn(ul, base, &tmp, snbuf, sizeof(snbuf));
    529      1.12       cgd 			if (width && (width -= tmp) > 0)
    530      1.12       cgd 				while (width--)
    531      1.41  drochner 					putchar(padc, oflags, tp);
    532      1.20  christos 			while ((ch = *p--) != 0)
    533      1.41  drochner 				putchar(ch, oflags, tp);
    534      1.12       cgd 			break;
    535      1.12       cgd 		default:
    536      1.41  drochner 			putchar('%', oflags, tp);
    537      1.41  drochner 		        /* flags??? */
    538      1.12       cgd 			/* FALLTHROUGH */
    539      1.12       cgd 		case '%':
    540      1.41  drochner 			putchar(ch, oflags, tp);
    541      1.12       cgd 		}
    542      1.12       cgd 	}
    543      1.12       cgd }
    544      1.12       cgd 
    545      1.12       cgd /*
    546      1.12       cgd  * Print a character on console or users terminal.  If destination is
    547      1.12       cgd  * the console then the last MSGBUFS characters are saved in msgbuf for
    548      1.12       cgd  * inspection later.
    549      1.12       cgd  */
    550      1.12       cgd static void
    551      1.12       cgd putchar(c, flags, tp)
    552      1.12       cgd 	register int c;
    553      1.12       cgd 	int flags;
    554      1.12       cgd 	struct tty *tp;
    555      1.12       cgd {
    556  1.43.4.1   thorpej 	register struct kern_msgbuf *mbp;
    557      1.12       cgd 
    558      1.12       cgd 	if (panicstr)
    559      1.12       cgd 		constty = NULL;
    560      1.12       cgd 	if ((flags & TOCONS) && tp == NULL && constty) {
    561      1.12       cgd 		tp = constty;
    562      1.12       cgd 		flags |= TOTTY;
    563      1.12       cgd 	}
    564      1.12       cgd 	if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 &&
    565      1.12       cgd 	    (flags & TOCONS) && tp == constty)
    566      1.12       cgd 		constty = NULL;
    567      1.12       cgd 	if ((flags & TOLOG) &&
    568  1.43.4.1   thorpej 	    c != '\0' && c != '\r' && c != 0177 && msgbufenabled) {
    569      1.12       cgd 		mbp = msgbufp;
    570      1.12       cgd 		if (mbp->msg_magic != MSG_MAGIC) {
    571  1.43.4.1   thorpej 			/*
    572  1.43.4.1   thorpej 			 * Arguably should panic or somehow notify the
    573  1.43.4.1   thorpej 			 * user...  but how?  Panic may be too drastic,
    574  1.43.4.1   thorpej 			 * and would obliterate the message being kicked
    575  1.43.4.1   thorpej 			 * out (maybe a panic itself), and printf
    576  1.43.4.1   thorpej 			 * would invoke us recursively.  Silently punt
    577  1.43.4.1   thorpej 			 * for now.  If syslog is running, it should
    578  1.43.4.1   thorpej 			 * notice.
    579  1.43.4.1   thorpej 			 */
    580  1.43.4.1   thorpej 			msgbufenabled = 0;
    581  1.43.4.1   thorpej 		} else {
    582  1.43.4.1   thorpej 			mbp->msg_bufc[mbp->msg_bufx++] = c;
    583  1.43.4.1   thorpej 			if (mbp->msg_bufx < 0 || mbp->msg_bufx >= mbp->msg_bufs)
    584  1.43.4.1   thorpej 				mbp->msg_bufx = 0;
    585      1.12       cgd 		}
    586      1.12       cgd 	}
    587      1.12       cgd 	if ((flags & TOCONS) && constty == NULL && c != '\0')
    588      1.12       cgd 		(*v_putc)(c);
    589      1.12       cgd }
    590      1.12       cgd 
    591      1.12       cgd /*
    592      1.12       cgd  * Scaled down version of sprintf(3).
    593      1.12       cgd  */
    594      1.20  christos int
    595      1.12       cgd #ifdef __STDC__
    596      1.30  christos sprintf(char *buf, const char *cfmt, ...)
    597      1.12       cgd #else
    598      1.30  christos sprintf(buf, cfmt, va_alist)
    599      1.34       gwr 	char *buf;
    600      1.36       gwr 	const char *cfmt;
    601      1.20  christos 	va_dcl
    602      1.12       cgd #endif
    603      1.12       cgd {
    604      1.36       gwr 	register const char *fmt = cfmt;
    605      1.12       cgd 	register char *p, *bp;
    606      1.12       cgd 	register int ch, base;
    607      1.41  drochner 	u_quad_t ul;
    608      1.41  drochner 	int flags, tmp, width;
    609      1.12       cgd 	va_list ap;
    610      1.37   thorpej 	char padc, snbuf[KSNPRINTN_BUFSIZE];
    611      1.12       cgd 
    612      1.12       cgd 	va_start(ap, cfmt);
    613      1.12       cgd 	for (bp = buf; ; ) {
    614      1.19       cgd 		padc = ' ';
    615      1.19       cgd 		width = 0;
    616      1.33       cgd 		while ((ch = *(const u_char *)fmt++) != '%')
    617      1.12       cgd 			if ((*bp++ = ch) == '\0')
    618      1.12       cgd 				return ((bp - buf) - 1);
    619      1.12       cgd 
    620      1.41  drochner 		flags = 0;
    621      1.33       cgd reswitch:	switch (ch = *(const u_char *)fmt++) {
    622      1.43   thorpej 		case '\0':
    623      1.43   thorpej 			/* XXX Store the last format character? */
    624      1.43   thorpej 			*bp++ = '\0';
    625      1.43   thorpej 			return ((bp - buf) - 1);
    626      1.19       cgd 		case '0':
    627      1.19       cgd 			padc = '0';
    628      1.19       cgd 			goto reswitch;
    629      1.19       cgd 		case '1': case '2': case '3': case '4':
    630      1.19       cgd 		case '5': case '6': case '7': case '8': case '9':
    631      1.19       cgd 			for (width = 0;; ++fmt) {
    632      1.19       cgd 				width = width * 10 + ch - '0';
    633      1.19       cgd 				ch = *fmt;
    634      1.19       cgd 				if (ch < '0' || ch > '9')
    635      1.19       cgd 					break;
    636      1.19       cgd 			}
    637      1.19       cgd 			goto reswitch;
    638      1.12       cgd 		case 'l':
    639      1.41  drochner 			flags |= LONGINT;
    640      1.41  drochner 			goto reswitch;
    641      1.41  drochner 		case 'q':
    642      1.41  drochner 			flags |= QUADINT;
    643      1.12       cgd 			goto reswitch;
    644      1.19       cgd 		/* case 'b': ... break; XXX */
    645      1.12       cgd 		case 'c':
    646      1.12       cgd 			*bp++ = va_arg(ap, int);
    647      1.12       cgd 			break;
    648      1.19       cgd 		/* case 'r': ... break; XXX */
    649      1.12       cgd 		case 's':
    650      1.12       cgd 			p = va_arg(ap, char *);
    651      1.20  christos 			while ((*bp++ = *p++) != 0)
    652      1.14       cgd 				continue;
    653      1.12       cgd 			--bp;
    654      1.12       cgd 			break;
    655      1.12       cgd 		case 'd':
    656      1.41  drochner 		        ul = SARG();
    657      1.41  drochner 			if ((quad_t)ul < 0) {
    658      1.12       cgd 				*bp++ = '-';
    659      1.41  drochner 				ul = -ul;
    660      1.12       cgd 			}
    661      1.12       cgd 			base = 10;
    662      1.12       cgd 			goto number;
    663      1.12       cgd 		case 'o':
    664      1.41  drochner 			ul = UARG();
    665      1.12       cgd 			base = 8;
    666      1.12       cgd 			goto number;
    667      1.12       cgd 		case 'u':
    668      1.41  drochner 			ul = UARG();
    669      1.12       cgd 			base = 10;
    670      1.12       cgd 			goto number;
    671      1.19       cgd 		case 'p':
    672      1.19       cgd 			*bp++ = '0';
    673      1.19       cgd 			*bp++ = 'x';
    674      1.19       cgd 			ul = (u_long)va_arg(ap, void *);
    675      1.19       cgd 			base = 16;
    676      1.19       cgd 			goto number;
    677      1.12       cgd 		case 'x':
    678      1.41  drochner 			ul = UARG();
    679      1.12       cgd 			base = 16;
    680      1.37   thorpej number:			p = ksnprintn(ul, base, &tmp, snbuf, sizeof(snbuf));
    681      1.19       cgd 			if (width && (width -= tmp) > 0)
    682      1.19       cgd 				while (width--)
    683      1.19       cgd 					*bp++ = padc;
    684      1.20  christos 			while ((ch = *p--) != 0)
    685      1.12       cgd 				*bp++ = ch;
    686      1.12       cgd 			break;
    687      1.12       cgd 		default:
    688      1.12       cgd 			*bp++ = '%';
    689      1.41  drochner 		        /* flags??? */
    690      1.12       cgd 			/* FALLTHROUGH */
    691      1.12       cgd 		case '%':
    692      1.12       cgd 			*bp++ = ch;
    693      1.12       cgd 		}
    694      1.12       cgd 	}
    695      1.12       cgd 	va_end(ap);
    696      1.12       cgd }
    697      1.12       cgd 
    698      1.12       cgd /*
    699      1.12       cgd  * Put a number (base <= 16) in a buffer in reverse order; return an
    700      1.12       cgd  * optional length and a pointer to the NULL terminated (preceded?)
    701      1.12       cgd  * buffer.
    702      1.12       cgd  */
    703      1.12       cgd static char *
    704      1.37   thorpej ksnprintn(ul, base, lenp, buf, buflen)
    705      1.41  drochner 	register u_quad_t ul;
    706      1.12       cgd 	register int base, *lenp;
    707      1.37   thorpej 	char *buf;
    708      1.37   thorpej 	size_t buflen;
    709      1.37   thorpej {
    710      1.12       cgd 	register char *p;
    711      1.12       cgd 
    712      1.12       cgd 	p = buf;
    713      1.37   thorpej 	*p = '\0';			/* ensure NULL `termination' */
    714      1.37   thorpej 
    715      1.37   thorpej 	/*
    716      1.37   thorpej 	 * Don't even bother of the buffer's not big enough.  No
    717      1.37   thorpej 	 * value at all is better than a wrong value, and we
    718      1.37   thorpej 	 * have a lot of control over the buffer that's passed
    719      1.37   thorpej 	 * to this function, since it's not exported.
    720      1.37   thorpej 	 */
    721      1.37   thorpej 	if (buflen < KSNPRINTN_BUFSIZE)
    722      1.37   thorpej 		return (p);
    723      1.37   thorpej 
    724      1.12       cgd 	do {
    725      1.12       cgd 		*++p = "0123456789abcdef"[ul % base];
    726      1.12       cgd 	} while (ul /= base);
    727      1.12       cgd 	if (lenp)
    728      1.12       cgd 		*lenp = p - buf;
    729      1.12       cgd 	return (p);
    730      1.37   thorpej }
    731      1.37   thorpej 
    732      1.37   thorpej /*
    733      1.37   thorpej  * Print a bitmask into the provided buffer, and return a pointer
    734      1.37   thorpej  * to that buffer.
    735      1.37   thorpej  */
    736      1.37   thorpej char *
    737      1.37   thorpej bitmask_snprintf(ul, p, buf, buflen)
    738      1.37   thorpej 	u_long ul;
    739      1.37   thorpej 	const char *p;
    740      1.37   thorpej 	char *buf;
    741      1.37   thorpej 	size_t buflen;
    742      1.37   thorpej {
    743      1.37   thorpej 	char *bp, *q;
    744      1.37   thorpej 	size_t left;
    745      1.37   thorpej 	register int n;
    746      1.37   thorpej 	int ch, tmp;
    747      1.37   thorpej 	char snbuf[KSNPRINTN_BUFSIZE];
    748      1.37   thorpej 
    749      1.37   thorpej 	bp = buf;
    750      1.37   thorpej 	bzero(buf, buflen);
    751      1.37   thorpej 
    752      1.37   thorpej 	/*
    753      1.37   thorpej 	 * Always leave room for the trailing NULL.
    754      1.37   thorpej 	 */
    755      1.37   thorpej 	left = buflen - 1;
    756      1.37   thorpej 
    757      1.37   thorpej 	/*
    758      1.37   thorpej 	 * Print the value into the buffer.  Abort if there's not
    759      1.37   thorpej 	 * enough room.
    760      1.37   thorpej 	 */
    761      1.37   thorpej 	if (buflen < KSNPRINTN_BUFSIZE)
    762      1.37   thorpej 		return (buf);
    763      1.37   thorpej 
    764      1.37   thorpej 	for (q = ksnprintn(ul, *p++, NULL, snbuf, sizeof(snbuf));
    765      1.37   thorpej 	    (ch = *q--) != 0;) {
    766      1.37   thorpej 		*bp++ = ch;
    767      1.37   thorpej 		left--;
    768      1.37   thorpej 	}
    769      1.37   thorpej 
    770      1.37   thorpej 	/*
    771      1.37   thorpej 	 * If the value we printed was 0, or if we don't have room for
    772      1.37   thorpej 	 * "<x>", we're done.
    773      1.37   thorpej 	 */
    774      1.37   thorpej 	if (ul == 0 || left < 3)
    775      1.37   thorpej 		return (buf);
    776      1.37   thorpej 
    777      1.37   thorpej #define PUTBYTE(b, c, l)	\
    778      1.37   thorpej 	*(b)++ = (c);		\
    779      1.37   thorpej 	if (--(l) == 0)		\
    780      1.37   thorpej 		goto out;
    781      1.37   thorpej 
    782      1.37   thorpej 	for (tmp = 0; (n = *p++) != 0;) {
    783      1.37   thorpej 		if (ul & (1 << (n - 1))) {
    784      1.37   thorpej 			PUTBYTE(bp, tmp ? ',' : '<', left);
    785      1.37   thorpej 				for (; (n = *p) > ' '; ++p) {
    786      1.37   thorpej 					PUTBYTE(bp, n, left);
    787      1.37   thorpej 				}
    788      1.37   thorpej 				tmp = 1;
    789      1.37   thorpej 		} else
    790      1.37   thorpej 			for (; *p > ' '; ++p)
    791      1.37   thorpej 				continue;
    792      1.37   thorpej 	}
    793      1.37   thorpej 	if (tmp)
    794      1.37   thorpej 		*bp = '>';
    795      1.37   thorpej 
    796      1.37   thorpej #undef PUTBYTE
    797      1.37   thorpej 
    798      1.37   thorpej  out:
    799      1.37   thorpej 	return (buf);
    800      1.12       cgd }
    801