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