xref: /csrg-svn/sys/kern/subr_prf.c (revision 44386)
123381Smckusick /*
234420Skarels  * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
323381Smckusick  * All rights reserved.  The Berkeley software License Agreement
423381Smckusick  * specifies the terms and conditions for redistribution.
523381Smckusick  *
6*44386Smarc  *	@(#)subr_prf.c	7.18 (Berkeley) 06/28/90
723381Smckusick  */
831Sbill 
917094Sbloom #include "param.h"
1017094Sbloom #include "systm.h"
1117094Sbloom #include "seg.h"
1217094Sbloom #include "buf.h"
1317094Sbloom #include "conf.h"
1417094Sbloom #include "reboot.h"
1517094Sbloom #include "vm.h"
1617094Sbloom #include "msgbuf.h"
1717094Sbloom #include "user.h"
1817094Sbloom #include "proc.h"
1917577Sbloom #include "ioctl.h"
2039560Smarc #include "vnode.h"
2139560Smarc #include "file.h"
2217094Sbloom #include "tty.h"
23*44386Smarc #include "tprintf.h"
2418364Skarels #include "syslog.h"
25*44386Smarc #include "malloc.h"
2631Sbill 
2737496Smckusick #include "machine/mtpr.h"
2835282Skarels #ifdef KADB
2937496Smckusick #include "machine/kdbparam.h"
3030625Skarels #endif
3130625Skarels 
3216724Sralph #define TOCONS	0x1
3316724Sralph #define TOTTY	0x2
3416724Sralph #define TOLOG	0x4
3516724Sralph 
3631Sbill /*
3731Sbill  * In case console is off,
3831Sbill  * panicstr contains argument to last
3931Sbill  * call to panic.
4031Sbill  */
4131Sbill char	*panicstr;
4231Sbill 
4330549Skarels extern	cnputc();			/* standard console putc */
4440808Smarc int	(*v_putc)() = cnputc;		/* routine to putc on virtual console */
4530549Skarels extern	struct tty cons;		/* standard console tty */
4630549Skarels struct	tty *constty;			/* pointer to console "window" tty */
4730549Skarels 
4840808Smarc #ifdef KADB
4940808Smarc extern	cngetc();			/* standard console getc */
5040808Smarc extern	cnpoll();
5140808Smarc int	(*v_getc)() = cngetc;		/* "" getc from virtual console */
5240808Smarc int	(*v_poll)() = cnpoll;		/* kdb hook to enable input polling */
5340808Smarc #endif
5440808Smarc 
5531Sbill /*
5631Sbill  * Scaled down version of C Library printf.
572781Swnj  * Used to print diagnostic information directly on console tty.
582781Swnj  * Since it is not interrupt driven, all system activities are
592781Swnj  * suspended.  Printf should not be used for chit-chat.
602781Swnj  *
612781Swnj  * One additional format: %b is supported to decode error registers.
622781Swnj  * Usage is:
632781Swnj  *	printf("reg=%b\n", regval, "<base><arg>*");
642781Swnj  * Where <base> is the output base expressed as a control character,
652781Swnj  * e.g. \10 gives octal; \20 gives hex.  Each arg is a sequence of
662781Swnj  * characters, the first of which gives the bit number to be inspected
672781Swnj  * (origin 1), and the next characters (up to a control character, i.e.
682781Swnj  * a character <= 32), give the name of the register.  Thus
692781Swnj  *	printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
702781Swnj  * would produce output:
7117594Skarels  *	reg=3<BITTWO,BITONE>
7234478Skarels  *
7334478Skarels  * Another additional format: %r is used to pass an additional format string
7434478Skarels  * and argument list recursively.  Usage is typically:
7534478Skarels  *
7634478Skarels  * fn(otherstuff, fmt [, arg1, ... ] )
7734478Skarels  *	char *fmt;
7834478Skarels  *	u_int arg1, ...;
7934478Skarels  *
8034478Skarels  *	printf("prefix: %r, other stuff\n", fmt, &arg1);
8131Sbill  */
8229946Skarels #if defined(tahoe)
8329946Skarels int	consintr;
8429946Skarels #endif
8529946Skarels 
8631Sbill /*VARARGS1*/
8731Sbill printf(fmt, x1)
882781Swnj 	char *fmt;
892781Swnj 	unsigned x1;
9031Sbill {
9129946Skarels #if defined(tahoe)
9229946Skarels 	register int savintr;
93285Sbill 
9429946Skarels 	savintr = consintr, consintr = 0;	/* disable interrupts */
9529946Skarels #endif
96*44386Smarc 	prf(fmt, &x1, TOCONS | TOLOG, (struct tty *)NULL);
9741972Smckusick 	if (!panicstr)
9841972Smckusick 		logwakeup();
9929946Skarels #if defined(tahoe)
10029946Skarels 	consintr = savintr;			/* reenable interrupts */
10129946Skarels #endif
102285Sbill }
103285Sbill 
1042377Swnj /*
10539560Smarc  * Uprintf prints to the controlling terminal for the current process.
10625389Skarels  * It may block if the tty queue is overfull.
10730695Skarels  * No message is printed if the queue does not clear
10830695Skarels  * in a reasonable time.
1092377Swnj  */
1102377Swnj /*VARARGS1*/
1112377Swnj uprintf(fmt, x1)
1122781Swnj 	char *fmt;
1132377Swnj 	unsigned x1;
114285Sbill {
115*44386Smarc 	register struct proc *p = u.u_procp;
116285Sbill 
117*44386Smarc 	if (p->p_flag & SCTTY && p->p_session->s_ttyvp)
118*44386Smarc 		prf(fmt, &x1, TOTTY, p->p_session->s_ttyp);
119285Sbill }
120285Sbill 
121*44386Smarc tpr_t
122*44386Smarc tprintf_open()
123*44386Smarc {
124*44386Smarc 	register struct proc *p = u.u_procp;
125*44386Smarc 
126*44386Smarc 	if (p->p_flag & SCTTY && p->p_session->s_ttyvp) {
127*44386Smarc 		SESSHOLD(p->p_session);
128*44386Smarc 		return ((tpr_t)p->p_session);
129*44386Smarc 	} else
130*44386Smarc 		return ((tpr_t)NULL);
131*44386Smarc }
132*44386Smarc 
133*44386Smarc tprintf_close(sess)
134*44386Smarc 	tpr_t sess;
135*44386Smarc {
136*44386Smarc 	if (sess)
137*44386Smarc 		SESSRELE(sess);
138*44386Smarc }
139*44386Smarc 
14018364Skarels /*
141*44386Smarc  * tprintf prints on the controlling terminal associated
142*44386Smarc  * with the given session.
14318364Skarels  */
14416724Sralph /*VARARGS2*/
145*44386Smarc tprintf(sess, fmt, x1)
146*44386Smarc 	register tpr_t sess;
14716724Sralph 	char *fmt;
14816724Sralph 	unsigned x1;
14916724Sralph {
150*44386Smarc 	int flags = TOLOG;
15116724Sralph 
15225389Skarels 	logpri(LOG_INFO);
15339560Smarc 
154*44386Smarc 	if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0))
155*44386Smarc 		flags |= TOTTY;
156*44386Smarc 	prf(fmt, &x1, flags, sess->s_ttyp);
15725389Skarels 	logwakeup();
15816724Sralph }
15916724Sralph 
160*44386Smarc 
16116724Sralph /*
16216724Sralph  * Log writes to the log buffer,
16317594Skarels  * and guarantees not to sleep (so can be called by interrupt routines).
16418364Skarels  * If there is no process reading the log yet, it writes to the console also.
16516724Sralph  */
16616724Sralph /*VARARGS2*/
16716724Sralph log(level, fmt, x1)
16816724Sralph 	char *fmt;
16916724Sralph 	unsigned x1;
17016724Sralph {
17116724Sralph 	register s = splhigh();
17218364Skarels 	extern int log_open;
17316724Sralph 
17425389Skarels 	logpri(level);
175*44386Smarc 	prf(fmt, &x1, TOLOG, (struct tty *)NULL);
17616724Sralph 	splx(s);
17718364Skarels 	if (!log_open)
178*44386Smarc 		prf(fmt, &x1, TOCONS, (struct tty *)NULL);
17916724Sralph 	logwakeup();
18016724Sralph }
18116724Sralph 
18225389Skarels logpri(level)
18325389Skarels 	int level;
18425389Skarels {
18525389Skarels 
186*44386Smarc 	putchar('<', TOLOG, (struct tty *)NULL);
187*44386Smarc 	printn((u_long)level, 10, TOLOG, (struct tty *)NULL);
188*44386Smarc 	putchar('>', TOLOG, (struct tty *)NULL);
18925389Skarels }
19025389Skarels 
19133479Skarels /*VARARGS1*/
19233479Skarels addlog(fmt, x1)
19333479Skarels 	char *fmt;
19433479Skarels 	unsigned x1;
19533479Skarels {
19633479Skarels 	register s = splhigh();
19733479Skarels 
198*44386Smarc 	prf(fmt, &x1, TOLOG, (struct tty *)NULL);
19933479Skarels 	splx(s);
20033479Skarels 	if (!log_open)
201*44386Smarc 		prf(fmt, &x1, TOCONS, (struct tty *)NULL);
20233479Skarels 	logwakeup();
20333479Skarels }
20433479Skarels 
205*44386Smarc prf(fmt, adx, flags, ttyp)
2062781Swnj 	register char *fmt;
2072781Swnj 	register u_int *adx;
208*44386Smarc 	struct tty *ttyp;
209285Sbill {
2102434Swnj 	register int b, c, i;
21131Sbill 	char *s;
2122678Swnj 	int any;
21331Sbill 
21431Sbill loop:
2152377Swnj 	while ((c = *fmt++) != '%') {
21616724Sralph 		if (c == '\0')
21731Sbill 			return;
218*44386Smarc 		putchar(c, flags, ttyp);
21931Sbill 	}
2202377Swnj again:
22131Sbill 	c = *fmt++;
22229946Skarels 	/* THIS CODE IS MACHINE DEPENDENT IN HANDLING %l? AND %c */
2232377Swnj 	switch (c) {
2242377Swnj 
2252377Swnj 	case 'l':
2262377Swnj 		goto again;
2272377Swnj 	case 'x': case 'X':
2282377Swnj 		b = 16;
2292377Swnj 		goto number;
2302377Swnj 	case 'd': case 'D':
23129946Skarels 		b = -10;
23229946Skarels 		goto number;
23329946Skarels 	case 'u':
2342377Swnj 		b = 10;
2352377Swnj 		goto number;
2362377Swnj 	case 'o': case 'O':
2372377Swnj 		b = 8;
2382377Swnj number:
239*44386Smarc 		printn((u_long)*adx, b, flags, ttyp);
2402377Swnj 		break;
2412377Swnj 	case 'c':
2422434Swnj 		b = *adx;
24333479Skarels #if BYTE_ORDER == LITTLE_ENDIAN
2442434Swnj 		for (i = 24; i >= 0; i -= 8)
2452434Swnj 			if (c = (b >> i) & 0x7f)
246*44386Smarc 				putchar(c, flags, ttyp);
24729946Skarels #endif
24833479Skarels #if BYTE_ORDER == BIG_ENDIAN
24929946Skarels 		if (c = (b & 0x7f))
250*44386Smarc 			putchar(c, flags, ttyp);
25129946Skarels #endif
2522377Swnj 		break;
2532678Swnj 	case 'b':
2542678Swnj 		b = *adx++;
2552678Swnj 		s = (char *)*adx;
256*44386Smarc 		printn((u_long)b, *s++, flags, ttyp);
2572678Swnj 		any = 0;
2582678Swnj 		if (b) {
2592678Swnj 			while (i = *s++) {
2602678Swnj 				if (b & (1 << (i-1))) {
261*44386Smarc 					putchar(any ? ',' : '<', flags, ttyp);
2622678Swnj 					any = 1;
2632678Swnj 					for (; (c = *s) > 32; s++)
264*44386Smarc 						putchar(c, flags, ttyp);
2652678Swnj 				} else
2662678Swnj 					for (; *s > 32; s++)
2672678Swnj 						;
2682678Swnj 			}
2693878Swnj 			if (any)
270*44386Smarc 				putchar('>', flags, ttyp);
2712678Swnj 		}
2722678Swnj 		break;
2732678Swnj 
2742377Swnj 	case 's':
27531Sbill 		s = (char *)*adx;
276285Sbill 		while (c = *s++)
277*44386Smarc 			putchar(c, flags, ttyp);
2782377Swnj 		break;
2793736Sroot 
28033479Skarels 	case 'r':
28133479Skarels 		s = (char *)*adx++;
282*44386Smarc 		prf(s, (u_int *)*adx, flags, ttyp);
28333479Skarels 		break;
28433479Skarels 
2853736Sroot 	case '%':
286*44386Smarc 		putchar('%', flags, ttyp);
2873736Sroot 		break;
28831Sbill 	}
28931Sbill 	adx++;
29031Sbill 	goto loop;
29131Sbill }
29231Sbill 
2932781Swnj /*
2942781Swnj  * Printn prints a number n in base b.
2952781Swnj  * We don't use recursion to avoid deep kernel stacks.
2962781Swnj  */
297*44386Smarc printn(n, b, flags, ttyp)
2983101Swnj 	u_long n;
299*44386Smarc 	struct tty *ttyp;
30031Sbill {
3012434Swnj 	char prbuf[11];
3022377Swnj 	register char *cp;
30331Sbill 
30429946Skarels 	if (b == -10) {
30529946Skarels 		if ((int)n < 0) {
306*44386Smarc 			putchar('-', flags, ttyp);
30729946Skarels 			n = (unsigned)(-(int)n);
30829946Skarels 		}
30929946Skarels 		b = -b;
31031Sbill 	}
3112434Swnj 	cp = prbuf;
3122377Swnj 	do {
3132377Swnj 		*cp++ = "0123456789abcdef"[n%b];
3142377Swnj 		n /= b;
3152377Swnj 	} while (n);
3162377Swnj 	do
317*44386Smarc 		putchar(*--cp, flags, ttyp);
3182434Swnj 	while (cp > prbuf);
31931Sbill }
32031Sbill 
32131Sbill /*
3221184Sbill  * Panic is called on unresolvable fatal errors.
3232781Swnj  * It prints "panic: mesg", and then reboots.
3242781Swnj  * If we are called twice, then we avoid trying to
3252781Swnj  * sync the disks as this often leads to recursive panics.
32631Sbill  */
32731Sbill panic(s)
3282781Swnj 	char *s;
32931Sbill {
33030566Skarels 	int bootopt = RB_AUTOBOOT | RB_DUMP;
3312377Swnj 
3325416Swnj 	if (panicstr)
3335416Swnj 		bootopt |= RB_NOSYNC;
3349758Ssam 	else {
3359758Ssam 		panicstr = s;
3368950Sroot 	}
3373285Swnj 	printf("panic: %s\n", s);
33835282Skarels #ifdef KADB
33930625Skarels 	if (boothowto & RB_KDB) {
34034420Skarels 		int x = splnet();	/* below kdb pri */
34130625Skarels 
34230625Skarels 		setsoftkdb();
34334420Skarels 		splx(x);
34430625Skarels 	}
34530625Skarels #endif
34630566Skarels 	boot(bootopt);
34731Sbill }
34831Sbill 
34931Sbill /*
3502941Swnj  * Warn that a system table is full.
3512941Swnj  */
3522941Swnj tablefull(tab)
3532941Swnj 	char *tab;
3542941Swnj {
3552941Swnj 
35624839Seric 	log(LOG_ERR, "%s: table is full\n", tab);
3572941Swnj }
3582941Swnj 
3592941Swnj /*
3602377Swnj  * Print a character on console or users terminal.
361285Sbill  * If destination is console then the last MSGBUFS characters
362285Sbill  * are saved in msgbuf for inspection later.
363285Sbill  */
3641785Sbill /*ARGSUSED*/
365*44386Smarc putchar(c, flags, ttyp)
3662377Swnj 	register int c;
367*44386Smarc 	struct tty *ttyp;
368285Sbill {
36933479Skarels 	extern int msgbufmapped;
370285Sbill 
37130549Skarels 	if (panicstr)
37230549Skarels 		constty = 0;
373*44386Smarc 	if ((flags & TOCONS) && ttyp == NULL && constty) {
374*44386Smarc 		ttyp = constty;
37530549Skarels 		flags |= TOTTY;
37630549Skarels 	}
377*44386Smarc 	if ((flags & TOTTY) && ttyp && tputchar(c, ttyp) < 0 &&
378*44386Smarc 	    (flags & TOCONS) && ttyp == constty)
37939560Smarc 		constty = 0;
38033479Skarels 	if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177 &&
38133479Skarels 	    msgbufmapped) {
3822172Swnj 		if (msgbuf.msg_magic != MSG_MAGIC) {
38312494Ssam 			register int i;
38412494Ssam 
3852172Swnj 			msgbuf.msg_magic = MSG_MAGIC;
38616724Sralph 			msgbuf.msg_bufx = msgbuf.msg_bufr = 0;
38712494Ssam 			for (i=0; i < MSG_BSIZE; i++)
38812494Ssam 				msgbuf.msg_bufc[i] = 0;
3892172Swnj 		}
39026427Sbloom 		msgbuf.msg_bufc[msgbuf.msg_bufx++] = c;
3912172Swnj 		if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE)
3922172Swnj 			msgbuf.msg_bufx = 0;
393285Sbill 	}
39430549Skarels 	if ((flags & TOCONS) && constty == 0 && c != '\0')
39530549Skarels 		(*v_putc)(c);
396285Sbill }
397