xref: /csrg-svn/sys/kern/subr_prf.c (revision 39560)
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*39560Smarc  *	@(#)subr_prf.c	7.15 (Berkeley) 11/20/89
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"
20*39560Smarc #include "vnode.h"
21*39560Smarc #include "file.h"
2217094Sbloom #include "tty.h"
2318364Skarels #include "syslog.h"
2431Sbill 
2537496Smckusick #include "machine/mtpr.h"
2635282Skarels #ifdef KADB
2737496Smckusick #include "machine/kdbparam.h"
2830625Skarels #endif
2930625Skarels 
3016724Sralph #define TOCONS	0x1
3116724Sralph #define TOTTY	0x2
3216724Sralph #define TOLOG	0x4
3316724Sralph 
3431Sbill /*
3531Sbill  * In case console is off,
3631Sbill  * panicstr contains argument to last
3731Sbill  * call to panic.
3831Sbill  */
3931Sbill char	*panicstr;
4031Sbill 
4130549Skarels extern	cnputc();			/* standard console putc */
4230549Skarels extern	struct tty cons;		/* standard console tty */
4330549Skarels struct	tty *constty;			/* pointer to console "window" tty */
4430549Skarels int	(*v_putc)() = cnputc;		/* routine to putc on virtual console */
4530549Skarels 
4631Sbill /*
4731Sbill  * Scaled down version of C Library printf.
482781Swnj  * Used to print diagnostic information directly on console tty.
492781Swnj  * Since it is not interrupt driven, all system activities are
502781Swnj  * suspended.  Printf should not be used for chit-chat.
512781Swnj  *
522781Swnj  * One additional format: %b is supported to decode error registers.
532781Swnj  * Usage is:
542781Swnj  *	printf("reg=%b\n", regval, "<base><arg>*");
552781Swnj  * Where <base> is the output base expressed as a control character,
562781Swnj  * e.g. \10 gives octal; \20 gives hex.  Each arg is a sequence of
572781Swnj  * characters, the first of which gives the bit number to be inspected
582781Swnj  * (origin 1), and the next characters (up to a control character, i.e.
592781Swnj  * a character <= 32), give the name of the register.  Thus
602781Swnj  *	printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
612781Swnj  * would produce output:
6217594Skarels  *	reg=3<BITTWO,BITONE>
6334478Skarels  *
6434478Skarels  * Another additional format: %r is used to pass an additional format string
6534478Skarels  * and argument list recursively.  Usage is typically:
6634478Skarels  *
6734478Skarels  * fn(otherstuff, fmt [, arg1, ... ] )
6834478Skarels  *	char *fmt;
6934478Skarels  *	u_int arg1, ...;
7034478Skarels  *
7134478Skarels  *	printf("prefix: %r, other stuff\n", fmt, &arg1);
7231Sbill  */
7329946Skarels #if defined(tahoe)
7429946Skarels int	consintr;
7529946Skarels #endif
7629946Skarels 
7731Sbill /*VARARGS1*/
7831Sbill printf(fmt, x1)
792781Swnj 	char *fmt;
802781Swnj 	unsigned x1;
8131Sbill {
8229946Skarels #if defined(tahoe)
8329946Skarels 	register int savintr;
84285Sbill 
8529946Skarels 	savintr = consintr, consintr = 0;	/* disable interrupts */
8629946Skarels #endif
87*39560Smarc 	prf(fmt, &x1, TOCONS | TOLOG, (caddr_t)0);
8816724Sralph 	logwakeup();
8929946Skarels #if defined(tahoe)
9029946Skarels 	consintr = savintr;			/* reenable interrupts */
9129946Skarels #endif
92285Sbill }
93285Sbill 
942377Swnj /*
95*39560Smarc  * Uprintf prints to the controlling terminal for the current process.
9625389Skarels  * It may block if the tty queue is overfull.
9730695Skarels  * No message is printed if the queue does not clear
9830695Skarels  * in a reasonable time.
992377Swnj  */
1002377Swnj /*VARARGS1*/
1012377Swnj uprintf(fmt, x1)
1022781Swnj 	char *fmt;
1032377Swnj 	unsigned x1;
104285Sbill {
105*39560Smarc 	register struct tty *tp = u.u_procp->p_session->s_ttyp;
106285Sbill 
107*39560Smarc 	if (tp != NULL && tp->t_session == u.u_procp->p_session)
10830695Skarels 		prf(fmt, &x1, TOTTY, tp);
109285Sbill }
110285Sbill 
11118364Skarels /*
11218364Skarels  * tprintf prints on the specified terminal (console if none)
11318364Skarels  * and logs the message.  It is designed for error messages from
11425389Skarels  * single-open devices, and may be called from interrupt level
11525389Skarels  * (does not sleep).
11618364Skarels  */
11716724Sralph /*VARARGS2*/
118*39560Smarc tprintf(vp, fmt, x1)
119*39560Smarc 	register caddr_t vp;
12016724Sralph 	char *fmt;
12116724Sralph 	unsigned x1;
12216724Sralph {
12325389Skarels 	int flags = TOTTY | TOLOG;
12416724Sralph 
125*39560Smarc #ifdef notyet
12625389Skarels 	logpri(LOG_INFO);
127*39560Smarc 
128*39560Smarc 	if (vp == NULL ||
129*39560Smarc 	    VOP_IOCTL(vp, TIOCCHECKOUTQ, &val, FWRITE, NOCRED) != 0 ||
130*39560Smarc 	    val == 0)
13125389Skarels 		flags = TOLOG;
132*39560Smarc 	prf(fmt, &x1, flags, vp);
13325389Skarels 	logwakeup();
134*39560Smarc #else
135*39560Smarc 	printf("tprintf called\n");
136*39560Smarc #endif
13716724Sralph }
13816724Sralph 
13916724Sralph /*
14016724Sralph  * Log writes to the log buffer,
14117594Skarels  * and guarantees not to sleep (so can be called by interrupt routines).
14218364Skarels  * If there is no process reading the log yet, it writes to the console also.
14316724Sralph  */
14416724Sralph /*VARARGS2*/
14516724Sralph log(level, fmt, x1)
14616724Sralph 	char *fmt;
14716724Sralph 	unsigned x1;
14816724Sralph {
14916724Sralph 	register s = splhigh();
15018364Skarels 	extern int log_open;
15116724Sralph 
15225389Skarels 	logpri(level);
153*39560Smarc 	prf(fmt, &x1, TOLOG, (caddr_t)0);
15416724Sralph 	splx(s);
15518364Skarels 	if (!log_open)
156*39560Smarc 		prf(fmt, &x1, TOCONS, (caddr_t)0);
15716724Sralph 	logwakeup();
15816724Sralph }
15916724Sralph 
16025389Skarels logpri(level)
16125389Skarels 	int level;
16225389Skarels {
16325389Skarels 
16425389Skarels 	putchar('<', TOLOG, (struct tty *)0);
16526356Skarels 	printn((u_long)level, 10, TOLOG, (struct tty *)0);
16625389Skarels 	putchar('>', TOLOG, (struct tty *)0);
16725389Skarels }
16825389Skarels 
16933479Skarels /*VARARGS1*/
17033479Skarels addlog(fmt, x1)
17133479Skarels 	char *fmt;
17233479Skarels 	unsigned x1;
17333479Skarels {
17433479Skarels 	register s = splhigh();
17533479Skarels 
176*39560Smarc 	prf(fmt, &x1, TOLOG, (caddr_t)0);
17733479Skarels 	splx(s);
17833479Skarels 	if (!log_open)
179*39560Smarc 		prf(fmt, &x1, TOCONS, (caddr_t)0);
18033479Skarels 	logwakeup();
18133479Skarels }
18233479Skarels 
183*39560Smarc prf(fmt, adx, flags, where)
1842781Swnj 	register char *fmt;
1852781Swnj 	register u_int *adx;
186*39560Smarc 	caddr_t where;
187285Sbill {
1882434Swnj 	register int b, c, i;
18931Sbill 	char *s;
1902678Swnj 	int any;
19131Sbill 
19231Sbill loop:
1932377Swnj 	while ((c = *fmt++) != '%') {
19416724Sralph 		if (c == '\0')
19531Sbill 			return;
196*39560Smarc 		putchar(c, flags, where);
19731Sbill 	}
1982377Swnj again:
19931Sbill 	c = *fmt++;
20029946Skarels 	/* THIS CODE IS MACHINE DEPENDENT IN HANDLING %l? AND %c */
2012377Swnj 	switch (c) {
2022377Swnj 
2032377Swnj 	case 'l':
2042377Swnj 		goto again;
2052377Swnj 	case 'x': case 'X':
2062377Swnj 		b = 16;
2072377Swnj 		goto number;
2082377Swnj 	case 'd': case 'D':
20929946Skarels 		b = -10;
21029946Skarels 		goto number;
21129946Skarels 	case 'u':
2122377Swnj 		b = 10;
2132377Swnj 		goto number;
2142377Swnj 	case 'o': case 'O':
2152377Swnj 		b = 8;
2162377Swnj number:
217*39560Smarc 		printn((u_long)*adx, b, flags, where);
2182377Swnj 		break;
2192377Swnj 	case 'c':
2202434Swnj 		b = *adx;
22133479Skarels #if BYTE_ORDER == LITTLE_ENDIAN
2222434Swnj 		for (i = 24; i >= 0; i -= 8)
2232434Swnj 			if (c = (b >> i) & 0x7f)
224*39560Smarc 				putchar(c, flags, where);
22529946Skarels #endif
22633479Skarels #if BYTE_ORDER == BIG_ENDIAN
22729946Skarels 		if (c = (b & 0x7f))
228*39560Smarc 			putchar(c, flags, where);
22929946Skarels #endif
2302377Swnj 		break;
2312678Swnj 	case 'b':
2322678Swnj 		b = *adx++;
2332678Swnj 		s = (char *)*adx;
234*39560Smarc 		printn((u_long)b, *s++, flags, where);
2352678Swnj 		any = 0;
2362678Swnj 		if (b) {
2372678Swnj 			while (i = *s++) {
2382678Swnj 				if (b & (1 << (i-1))) {
239*39560Smarc 					putchar(any ? ',' : '<', flags, where);
2402678Swnj 					any = 1;
2412678Swnj 					for (; (c = *s) > 32; s++)
242*39560Smarc 						putchar(c, flags, where);
2432678Swnj 				} else
2442678Swnj 					for (; *s > 32; s++)
2452678Swnj 						;
2462678Swnj 			}
2473878Swnj 			if (any)
248*39560Smarc 				putchar('>', flags, where);
2492678Swnj 		}
2502678Swnj 		break;
2512678Swnj 
2522377Swnj 	case 's':
25331Sbill 		s = (char *)*adx;
254285Sbill 		while (c = *s++)
255*39560Smarc 			putchar(c, flags, where);
2562377Swnj 		break;
2573736Sroot 
25833479Skarels 	case 'r':
25933479Skarels 		s = (char *)*adx++;
260*39560Smarc 		prf(s, (u_int *)*adx, flags, where);
26133479Skarels 		break;
26233479Skarels 
2633736Sroot 	case '%':
264*39560Smarc 		putchar('%', flags, where);
2653736Sroot 		break;
26631Sbill 	}
26731Sbill 	adx++;
26831Sbill 	goto loop;
26931Sbill }
27031Sbill 
2712781Swnj /*
2722781Swnj  * Printn prints a number n in base b.
2732781Swnj  * We don't use recursion to avoid deep kernel stacks.
2742781Swnj  */
275*39560Smarc printn(n, b, flags, where)
2763101Swnj 	u_long n;
277*39560Smarc 	caddr_t where;
27831Sbill {
2792434Swnj 	char prbuf[11];
2802377Swnj 	register char *cp;
28131Sbill 
28229946Skarels 	if (b == -10) {
28329946Skarels 		if ((int)n < 0) {
284*39560Smarc 			putchar('-', flags, where);
28529946Skarels 			n = (unsigned)(-(int)n);
28629946Skarels 		}
28729946Skarels 		b = -b;
28831Sbill 	}
2892434Swnj 	cp = prbuf;
2902377Swnj 	do {
2912377Swnj 		*cp++ = "0123456789abcdef"[n%b];
2922377Swnj 		n /= b;
2932377Swnj 	} while (n);
2942377Swnj 	do
295*39560Smarc 		putchar(*--cp, flags, where);
2962434Swnj 	while (cp > prbuf);
29731Sbill }
29831Sbill 
29931Sbill /*
3001184Sbill  * Panic is called on unresolvable fatal errors.
3012781Swnj  * It prints "panic: mesg", and then reboots.
3022781Swnj  * If we are called twice, then we avoid trying to
3032781Swnj  * sync the disks as this often leads to recursive panics.
30431Sbill  */
30531Sbill panic(s)
3062781Swnj 	char *s;
30731Sbill {
30830566Skarels 	int bootopt = RB_AUTOBOOT | RB_DUMP;
3092377Swnj 
3105416Swnj 	if (panicstr)
3115416Swnj 		bootopt |= RB_NOSYNC;
3129758Ssam 	else {
3139758Ssam 		panicstr = s;
3148950Sroot 	}
3153285Swnj 	printf("panic: %s\n", s);
31635282Skarels #ifdef KADB
31730625Skarels 	if (boothowto & RB_KDB) {
31834420Skarels 		int x = splnet();	/* below kdb pri */
31930625Skarels 
32030625Skarels 		setsoftkdb();
32134420Skarels 		splx(x);
32230625Skarels 	}
32330625Skarels #endif
32430566Skarels 	boot(bootopt);
32531Sbill }
32631Sbill 
32731Sbill /*
3282941Swnj  * Warn that a system table is full.
3292941Swnj  */
3302941Swnj tablefull(tab)
3312941Swnj 	char *tab;
3322941Swnj {
3332941Swnj 
33424839Seric 	log(LOG_ERR, "%s: table is full\n", tab);
3352941Swnj }
3362941Swnj 
3372941Swnj /*
3382377Swnj  * Print a character on console or users terminal.
339285Sbill  * If destination is console then the last MSGBUFS characters
340285Sbill  * are saved in msgbuf for inspection later.
341285Sbill  */
3421785Sbill /*ARGSUSED*/
343*39560Smarc putchar(c, flags, where)
3442377Swnj 	register int c;
345*39560Smarc 	caddr_t where;
346285Sbill {
34733479Skarels 	extern int msgbufmapped;
348285Sbill 
34930549Skarels 	if (panicstr)
35030549Skarels 		constty = 0;
351*39560Smarc 	if ((flags & TOCONS) && where == 0 && constty) {
352*39560Smarc 		where = (caddr_t)constty;
35330549Skarels 		flags |= TOTTY;
35430549Skarels 	}
355*39560Smarc 	if ((flags & TOTTY) && where && tputchar(c, (struct tty *)where) < 0 &&
356*39560Smarc 	    (flags & TOCONS) && (struct tty *)where == constty)
357*39560Smarc 		constty = 0;
35833479Skarels 	if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177 &&
35933479Skarels 	    msgbufmapped) {
3602172Swnj 		if (msgbuf.msg_magic != MSG_MAGIC) {
36112494Ssam 			register int i;
36212494Ssam 
3632172Swnj 			msgbuf.msg_magic = MSG_MAGIC;
36416724Sralph 			msgbuf.msg_bufx = msgbuf.msg_bufr = 0;
36512494Ssam 			for (i=0; i < MSG_BSIZE; i++)
36612494Ssam 				msgbuf.msg_bufc[i] = 0;
3672172Swnj 		}
36826427Sbloom 		msgbuf.msg_bufc[msgbuf.msg_bufx++] = c;
3692172Swnj 		if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE)
3702172Swnj 			msgbuf.msg_bufx = 0;
371285Sbill 	}
37230549Skarels 	if ((flags & TOCONS) && constty == 0 && c != '\0')
37330549Skarels 		(*v_putc)(c);
374285Sbill }
375