xref: /csrg-svn/sys/kern/subr_prf.c (revision 49062)
1*49062Sbostic /*-
2*49062Sbostic  * Copyright (c) 1986, 1988, 1991 The Regents of the University of California.
3*49062Sbostic  * All rights reserved.
423381Smckusick  *
5*49062Sbostic  * %sccs.include.redist.c%
6*49062Sbostic  *
7*49062Sbostic  *	@(#)subr_prf.c	7.22 (Berkeley) 05/04/91
823381Smckusick  */
931Sbill 
1017094Sbloom #include "param.h"
1117094Sbloom #include "systm.h"
1217094Sbloom #include "buf.h"
1317094Sbloom #include "conf.h"
1417094Sbloom #include "reboot.h"
1517094Sbloom #include "msgbuf.h"
1617094Sbloom #include "proc.h"
1717577Sbloom #include "ioctl.h"
1839560Smarc #include "vnode.h"
1939560Smarc #include "file.h"
2017094Sbloom #include "tty.h"
2144386Smarc #include "tprintf.h"
2218364Skarels #include "syslog.h"
2344386Smarc #include "malloc.h"
2431Sbill 
25*49062Sbostic /*
26*49062Sbostic  * Note that stdarg.h and the ANSI style va_start macro is used for both
27*49062Sbostic  * ANSI and traditional C compilers.
28*49062Sbostic  */
29*49062Sbostic #include <machine/stdarg.h>
30*49062Sbostic 
3135282Skarels #ifdef KADB
3237496Smckusick #include "machine/kdbparam.h"
3330625Skarels #endif
3430625Skarels 
35*49062Sbostic #define TOCONS	0x01
36*49062Sbostic #define TOTTY	0x02
37*49062Sbostic #define TOLOG	0x04
3816724Sralph 
3930549Skarels struct	tty *constty;			/* pointer to console "window" tty */
4030549Skarels 
4140808Smarc #ifdef KADB
4240808Smarc extern	cngetc();			/* standard console getc */
43*49062Sbostic int	(*v_getc)() = cngetc;		/* "" getc from virtual console */
4440808Smarc extern	cnpoll();
4540808Smarc int	(*v_poll)() = cnpoll;		/* kdb hook to enable input polling */
4640808Smarc #endif
47*49062Sbostic extern	cnputc();			/* standard console putc */
48*49062Sbostic int	(*v_putc)() = cnputc;          	/* routine to putc on virtual console */
4940808Smarc 
50*49062Sbostic static void logpri __P((int));
51*49062Sbostic static void putchar __P((int, int, struct tty *));
52*49062Sbostic static void kprintf __P((const char *, int, struct tty *, ...));
53*49062Sbostic static void kprintn __P((u_long, int));
54*49062Sbostic 
5531Sbill /*
56*49062Sbostic  * Variable panicstr contains argument to first call to panic; used
57*49062Sbostic  * as flag to indicate that the kernel has already called panic.
5831Sbill  */
59*49062Sbostic char	*panicstr;
6029946Skarels 
61*49062Sbostic /*
62*49062Sbostic  * Panic is called on unresolvable fatal errors.  It prints "panic: mesg",
63*49062Sbostic  * and then reboots.  If we are called twice, then we avoid trying to sync
64*49062Sbostic  * the disks as this often leads to recursive panics.
65*49062Sbostic  */
66*49062Sbostic void
67*49062Sbostic panic(msg)
68*49062Sbostic 	char *msg;
69*49062Sbostic {
70*49062Sbostic 	int bootopt = RB_AUTOBOOT | RB_DUMP;
71*49062Sbostic 	int s;
7248426Skarels 
73*49062Sbostic 	if (panicstr)
74*49062Sbostic 		bootopt |= RB_NOSYNC;
75*49062Sbostic 	else
76*49062Sbostic 		panicstr = msg;
77*49062Sbostic 	printf("panic: %s\n", msg);
78*49062Sbostic #ifdef KGDB
79*49062Sbostic 	kgdb_panic();
80*49062Sbostic #endif
81*49062Sbostic #ifdef KADB
82*49062Sbostic 	if (boothowto & RB_KDB) {
83*49062Sbostic 		s = splnet();		/* below kdb pri */
84*49062Sbostic 		setsoftkdb();
85*49062Sbostic 		splx(s);
86*49062Sbostic 	}
87*49062Sbostic #endif
88*49062Sbostic 	boot(bootopt);
89*49062Sbostic }
90*49062Sbostic 
91*49062Sbostic /*
92*49062Sbostic  * Warn that a system table is full.
93*49062Sbostic  */
94*49062Sbostic void
95*49062Sbostic tablefull(tab)
96*49062Sbostic 	char *tab;
9731Sbill {
98285Sbill 
99*49062Sbostic 	log(LOG_ERR, "%s: table is full\n", tab);
100285Sbill }
101285Sbill 
1022377Swnj /*
10339560Smarc  * Uprintf prints to the controlling terminal for the current process.
104*49062Sbostic  * It may block if the tty queue is overfull.  No message is printed if
105*49062Sbostic  * the queue does not clear in a reasonable time.
1062377Swnj  */
107*49062Sbostic void
108*49062Sbostic #ifdef __STDC__
109*49062Sbostic uprintf(const char *fmt, ...)
110*49062Sbostic #else
111*49062Sbostic uprintf(fmt /*, va_alist */)
1122781Swnj 	char *fmt;
113*49062Sbostic #endif
114285Sbill {
11547540Skarels 	register struct proc *p = curproc;
116*49062Sbostic 	va_list ap;
117285Sbill 
118*49062Sbostic 	va_start(ap, fmt);
11944386Smarc 	if (p->p_flag & SCTTY && p->p_session->s_ttyvp)
120*49062Sbostic 		kprintf(fmt, TOTTY, p->p_session->s_ttyp, ap);
121*49062Sbostic 	va_end(ap);
122285Sbill }
123285Sbill 
12444386Smarc tpr_t
12548426Skarels tprintf_open(p)
12648426Skarels 	register struct proc *p;
12744386Smarc {
12844386Smarc 	if (p->p_flag & SCTTY && p->p_session->s_ttyvp) {
12944386Smarc 		SESSHOLD(p->p_session);
13048426Skarels 		return ((tpr_t) p->p_session);
131*49062Sbostic 	}
132*49062Sbostic 	return ((tpr_t) NULL);
13344386Smarc }
13444386Smarc 
13548426Skarels void
13644386Smarc tprintf_close(sess)
13744386Smarc 	tpr_t sess;
13844386Smarc {
13944386Smarc 	if (sess)
14048426Skarels 		SESSRELE((struct session *) sess);
14144386Smarc }
14244386Smarc 
14318364Skarels /*
14444386Smarc  * tprintf prints on the controlling terminal associated
145*49062Sbostic  * with the given session.
14618364Skarels  */
147*49062Sbostic void
148*49062Sbostic #ifdef __STDC__
149*49062Sbostic tprintf(tpr_t tpr, const char *fmt, ...)
150*49062Sbostic #else
151*49062Sbostic tprintf(tpr, fmt /*, va_alist */)
15248426Skarels 	tpr_t tpr;
15316724Sralph 	char *fmt;
154*49062Sbostic #endif
15516724Sralph {
15648426Skarels 	register struct session *sess = (struct session *)tpr;
15748426Skarels 	struct tty *tp = NULL;
15844386Smarc 	int flags = TOLOG;
159*49062Sbostic 	va_list ap;
16016724Sralph 
16125389Skarels 	logpri(LOG_INFO);
16248426Skarels 	if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) {
16344386Smarc 		flags |= TOTTY;
16448426Skarels 		tp = sess->s_ttyp;
16548426Skarels 	}
166*49062Sbostic 	va_start(ap, fmt);
167*49062Sbostic 	kprintf(fmt, flags, tp, ap);
168*49062Sbostic 	va_end(ap);
16925389Skarels 	logwakeup();
17016724Sralph }
17116724Sralph 
172*49062Sbostic /*
173*49062Sbostic  * Ttyprintf displays a message on a tty; it should be used only by
174*49062Sbostic  * the tty driver, or anything that knows the underlying tty will not
175*49062Sbostic  * be revoke(2)'d away.  Other callers should use tprintf.
176*49062Sbostic  */
177*49062Sbostic void
178*49062Sbostic #ifdef __STDC__
179*49062Sbostic ttyprintf(struct tty *tp, const char *fmt, ...)
180*49062Sbostic #else
181*49062Sbostic ttyprintf(tp, fmt /*, va_alist */)
182*49062Sbostic 	struct tty *tp;
183*49062Sbostic 	char *fmt;
184*49062Sbostic #endif
185*49062Sbostic {
186*49062Sbostic 	va_list ap;
187*49062Sbostic 
188*49062Sbostic 	va_start(ap, fmt);
189*49062Sbostic 	kprintf(fmt, TOTTY, tp, ap);
190*49062Sbostic 	va_end(ap);
191*49062Sbostic }
192*49062Sbostic 
19348426Skarels extern	int log_open;
19444386Smarc 
19516724Sralph /*
196*49062Sbostic  * Log writes to the log buffer, and guarantees not to sleep (so can be
197*49062Sbostic  * called by interrupt routines).  If there is no process reading the
198*49062Sbostic  * log yet, it writes to the console also.
19916724Sralph  */
200*49062Sbostic void
201*49062Sbostic #ifdef __STDC__
202*49062Sbostic log(int level, const char *fmt, ...)
203*49062Sbostic #else
204*49062Sbostic log(level, fmt /*, va_alist */)
205*49062Sbostic 	int level;
20616724Sralph 	char *fmt;
207*49062Sbostic #endif
20816724Sralph {
20916724Sralph 	register s = splhigh();
210*49062Sbostic 	va_list ap;
21116724Sralph 
21225389Skarels 	logpri(level);
213*49062Sbostic 	va_start(ap, fmt);
214*49062Sbostic 	kprintf(fmt, TOLOG, NULL, ap);
21516724Sralph 	splx(s);
21618364Skarels 	if (!log_open)
217*49062Sbostic 		kprintf(fmt, TOCONS, NULL, ap);
218*49062Sbostic 	va_end(ap);
21916724Sralph 	logwakeup();
22016724Sralph }
22116724Sralph 
222*49062Sbostic static void
22325389Skarels logpri(level)
22425389Skarels 	int level;
22525389Skarels {
22625389Skarels 
227*49062Sbostic 	putchar('<', TOLOG, NULL);
228*49062Sbostic 	kprintn((u_long)level, 10, TOLOG, NULL);
229*49062Sbostic 	putchar('>', TOLOG, NULL);
23025389Skarels }
23125389Skarels 
232*49062Sbostic void
233*49062Sbostic #ifdef __STDC__
234*49062Sbostic addlog(const char *fmt, ...)
235*49062Sbostic #else
236*49062Sbostic addlog(fmt /*, va_alist */)
23733479Skarels 	char *fmt;
238*49062Sbostic #endif
23933479Skarels {
24033479Skarels 	register s = splhigh();
241*49062Sbostic 	va_list ap;
24233479Skarels 
243*49062Sbostic 	va_start(ap, fmt);
244*49062Sbostic 	kprintf(fmt, TOLOG, NULL, ap);
24533479Skarels 	splx(s);
24633479Skarels 	if (!log_open)
247*49062Sbostic 		kprintf(fmt, TOCONS, NULL, ap);
248*49062Sbostic 	va_end(ap);
24933479Skarels 	logwakeup();
25033479Skarels }
25133479Skarels 
252*49062Sbostic int	consintr = 1;			/* ok to handle console interrupts? */
25331Sbill 
254*49062Sbostic void
255*49062Sbostic #ifdef __STDC__
256*49062Sbostic printf(const char *fmt, ...)
257*49062Sbostic #else
258*49062Sbostic printf(fmt /*, va_alist */)
259*49062Sbostic 	char *fmt;
26029946Skarels #endif
261*49062Sbostic {
262*49062Sbostic 	register int savintr;
263*49062Sbostic 	va_list ap;
2642678Swnj 
265*49062Sbostic 	savintr = consintr;		/* disable interrupts */
266*49062Sbostic 	consintr = 0;
267*49062Sbostic 	va_start(ap, fmt);
268*49062Sbostic 	kprintf(fmt, TOCONS | TOLOG, NULL, ap);
269*49062Sbostic 	va_end(ap);
270*49062Sbostic 	if (!panicstr)
271*49062Sbostic 		logwakeup();
272*49062Sbostic 	consintr = savintr;		/* reenable interrupts */
27331Sbill }
27431Sbill 
2752781Swnj /*
276*49062Sbostic  * Scaled down version of printf(3).
277*49062Sbostic  *
278*49062Sbostic  * Two additional formats:
279*49062Sbostic  *
280*49062Sbostic  * The format %b is supported to decode error registers.
281*49062Sbostic  * Its usage is:
282*49062Sbostic  *
283*49062Sbostic  *	kprintf("reg=%b\n", regval, "<base><arg>*");
284*49062Sbostic  *
285*49062Sbostic  * where <base> is the output base expressed as a control character, e.g.
286*49062Sbostic  * \10 gives octal; \20 gives hex.  Each arg is a sequence of characters,
287*49062Sbostic  * the first of which gives the bit number to be inspected (origin 1), and
288*49062Sbostic  * the next characters (up to a control character, i.e. a character <= 32),
289*49062Sbostic  * give the name of the register.  Thus:
290*49062Sbostic  *
291*49062Sbostic  *	kprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
292*49062Sbostic  *
293*49062Sbostic  * would produce output:
294*49062Sbostic  *
295*49062Sbostic  *	reg=3<BITTWO,BITONE>
296*49062Sbostic  *
297*49062Sbostic  * The format %r is supposed to pass an additional format string and argument
298*49062Sbostic  * list recursively.
299*49062Sbostic  * Its usage is:
300*49062Sbostic  *
301*49062Sbostic  * fn(otherstuff, fmt [, arg1, ... ])
302*49062Sbostic  *	char *fmt;
303*49062Sbostic  *	u_int arg1, ...;
304*49062Sbostic  *
305*49062Sbostic  *	kprintf("prefix: %r, other stuff\n", fmt, ap);
3062781Swnj  */
307*49062Sbostic static void
308*49062Sbostic kprintf(fmt, flags, ttyp, ap)
309*49062Sbostic 	register char *fmt;
310*49062Sbostic 	int flags;
31144386Smarc 	struct tty *ttyp;
312*49062Sbostic 	va_list ap;
31331Sbill {
314*49062Sbostic 	register char *p;
315*49062Sbostic 	register int ch, n;
316*49062Sbostic 	unsigned long ul;
317*49062Sbostic 	int lflag, set;
31831Sbill 
319*49062Sbostic 	for (;;) {
320*49062Sbostic 		while ((ch = *fmt++) != '%') {
321*49062Sbostic 			if (ch == '\0')
322*49062Sbostic 				return;
323*49062Sbostic 			putchar(ch, flags, ttyp);
32429946Skarels 		}
325*49062Sbostic 		lflag = 0;
326*49062Sbostic reswitch:	switch (ch = *fmt++) {
327*49062Sbostic 		case 'l':
328*49062Sbostic 			lflag = 1;
329*49062Sbostic 			goto reswitch;
330*49062Sbostic 		case 'b':
331*49062Sbostic 			ul = va_arg(ap, int);
332*49062Sbostic 			p = va_arg(ap, char *);
333*49062Sbostic 			kprintn(ul, *p++);
33431Sbill 
335*49062Sbostic 			if (!ul)
336*49062Sbostic 				break;
3372377Swnj 
338*49062Sbostic 			for (set = 0; n = *p++;) {
339*49062Sbostic 				if (ul & (1 << (n - 1))) {
340*49062Sbostic 					putchar(set ? ',' : '<', flags, ttyp);
341*49062Sbostic 					for (; (n = *p) > ' '; ++p)
342*49062Sbostic 						putchar(n, flags, ttyp);
343*49062Sbostic 					set = 1;
344*49062Sbostic 				} else
345*49062Sbostic 					for (; *p > ' '; ++p);
346*49062Sbostic 			}
347*49062Sbostic 			if (set)
348*49062Sbostic 				putchar('>', flags, ttyp);
349*49062Sbostic 			break;
350*49062Sbostic 		case 'c':
351*49062Sbostic 			putchar(va_arg(ap, int), flags, ttyp);
352*49062Sbostic 			break;
353*49062Sbostic 		case 'r':
354*49062Sbostic 			p = va_arg(ap, char *);
355*49062Sbostic 			kprintf(p, flags, ttyp, va_arg(ap, va_list));
356*49062Sbostic 			break;
357*49062Sbostic 		case 's':
358*49062Sbostic 			p = va_arg(ap, char *);
359*49062Sbostic 			while (ch = *p++)
360*49062Sbostic 				putchar(ch, flags, ttyp);
361*49062Sbostic 			break;
362*49062Sbostic 		case 'D':
363*49062Sbostic 			lflag = 1;
364*49062Sbostic 			/* FALLTHROUGH */
365*49062Sbostic 		case 'd':
366*49062Sbostic 			ul = lflag ?
367*49062Sbostic 			    va_arg(ap, long) : va_arg(ap, int);
368*49062Sbostic 			if ((long)ul < 0) {
369*49062Sbostic 				putchar('-', flags, ttyp);
370*49062Sbostic 				ul = -(long)ul;
371*49062Sbostic 			}
372*49062Sbostic 			kprintn(ul, 10);
373*49062Sbostic 			break;
374*49062Sbostic 		case 'O':
375*49062Sbostic 			lflag = 1;
376*49062Sbostic 			/* FALLTHROUGH */
377*49062Sbostic 		case 'o':
378*49062Sbostic 			ul = lflag ?
379*49062Sbostic 			    va_arg(ap, u_long) : va_arg(ap, u_int);
380*49062Sbostic 			kprintn(ul, 8);
381*49062Sbostic 			break;
382*49062Sbostic 		case 'U':
383*49062Sbostic 			lflag = 1;
384*49062Sbostic 			/* FALLTHROUGH */
385*49062Sbostic 		case 'u':
386*49062Sbostic 			ul = lflag ?
387*49062Sbostic 			    va_arg(ap, u_long) : va_arg(ap, u_int);
388*49062Sbostic 			kprintn(ul, 10);
389*49062Sbostic 			break;
390*49062Sbostic 		case 'X':
391*49062Sbostic 			lflag = 1;
392*49062Sbostic 			/* FALLTHROUGH */
393*49062Sbostic 		case 'x':
394*49062Sbostic 			ul = lflag ?
395*49062Sbostic 			    va_arg(ap, u_long) : va_arg(ap, u_int);
396*49062Sbostic 			kprintn(ul, 16);
397*49062Sbostic 			break;
398*49062Sbostic 		default:
399*49062Sbostic 			putchar('%', flags, ttyp);
400*49062Sbostic 			if (lflag)
401*49062Sbostic 				putchar('l', flags, ttyp);
402*49062Sbostic 			putchar(ch, flags, ttyp);
403*49062Sbostic 		}
40430625Skarels 	}
405*49062Sbostic 	va_end(ap);
40631Sbill }
40731Sbill 
408*49062Sbostic static void
409*49062Sbostic kprintn(ul, base)
410*49062Sbostic 	u_long ul;
411*49062Sbostic 	int base;
4122941Swnj {
413*49062Sbostic 					/* hold a long in base 8 */
414*49062Sbostic 	char *p, buf[(sizeof(long) * NBBY >> 3) + 1];
4152941Swnj 
416*49062Sbostic 	p = buf;
417*49062Sbostic 	do {
418*49062Sbostic 		*p++ = "0123456789abcdef"[ul % base];
419*49062Sbostic 	} while (ul /= base);
420*49062Sbostic 	do {
421*49062Sbostic 		putchar(*--p);
422*49062Sbostic 	} while (p > buf);
4232941Swnj }
4242941Swnj 
4252941Swnj /*
426*49062Sbostic  * Print a character on console or users terminal.  If destination is
427*49062Sbostic  * the console then the last MSGBUFS characters are saved in msgbuf for
428*49062Sbostic  * inspection later.
429285Sbill  */
430*49062Sbostic static void
43144386Smarc putchar(c, flags, ttyp)
4322377Swnj 	register int c;
433*49062Sbostic 	int flags;
43444386Smarc 	struct tty *ttyp;
435285Sbill {
43633479Skarels 	extern int msgbufmapped;
437*49062Sbostic 	register struct msgbuf *mbp;
438285Sbill 
43930549Skarels 	if (panicstr)
440*49062Sbostic 		constty = NULL;
44144386Smarc 	if ((flags & TOCONS) && ttyp == NULL && constty) {
44244386Smarc 		ttyp = constty;
44330549Skarels 		flags |= TOTTY;
44430549Skarels 	}
44544386Smarc 	if ((flags & TOTTY) && ttyp && tputchar(c, ttyp) < 0 &&
44644386Smarc 	    (flags & TOCONS) && ttyp == constty)
447*49062Sbostic 		constty = NULL;
448*49062Sbostic 	if ((flags & TOLOG) &&
449*49062Sbostic 	    c != '\0' && c != '\r' && c != 0177 && msgbufmapped) {
450*49062Sbostic  		mbp = msgbufp;
45145733Smckusick 		if (mbp->msg_magic != MSG_MAGIC) {
45212494Ssam 			register int i;
45312494Ssam 
45445733Smckusick 			mbp->msg_magic = MSG_MAGIC;
45545733Smckusick 			mbp->msg_bufx = mbp->msg_bufr = 0;
456*49062Sbostic 			for (i = 0; i < MSG_BSIZE; i++)
45745733Smckusick 				mbp->msg_bufc[i] = 0;
4582172Swnj 		}
45945733Smckusick 		mbp->msg_bufc[mbp->msg_bufx++] = c;
46045733Smckusick 		if (mbp->msg_bufx < 0 || mbp->msg_bufx >= MSG_BSIZE)
46145733Smckusick 			mbp->msg_bufx = 0;
462285Sbill 	}
463*49062Sbostic 	if ((flags & TOCONS) && constty == NULL && c != '\0')
46430549Skarels 		(*v_putc)(c);
465285Sbill }
466