xref: /csrg-svn/sys/kern/subr_prf.c (revision 13531)
1*13531Ssam /*	subr_prf.c	4.28	83/07/01	*/
231Sbill 
331Sbill #include "../h/param.h"
431Sbill #include "../h/systm.h"
531Sbill #include "../h/seg.h"
631Sbill #include "../h/buf.h"
731Sbill #include "../h/conf.h"
81184Sbill #include "../h/reboot.h"
92172Swnj #include "../h/vm.h"
102172Swnj #include "../h/msgbuf.h"
112360Skre #include "../h/dir.h"
122360Skre #include "../h/user.h"
139758Ssam #include "../h/proc.h"
142360Skre #include "../h/tty.h"
1531Sbill 
16*13531Ssam #ifdef vax
17*13531Ssam #include "../vax/mtpr.h"
18*13531Ssam #endif
19*13531Ssam 
2031Sbill /*
2131Sbill  * In case console is off,
2231Sbill  * panicstr contains argument to last
2331Sbill  * call to panic.
2431Sbill  */
2531Sbill char	*panicstr;
2631Sbill 
2731Sbill /*
2831Sbill  * Scaled down version of C Library printf.
292781Swnj  * Used to print diagnostic information directly on console tty.
302781Swnj  * Since it is not interrupt driven, all system activities are
312781Swnj  * suspended.  Printf should not be used for chit-chat.
322781Swnj  *
332781Swnj  * One additional format: %b is supported to decode error registers.
342781Swnj  * Usage is:
352781Swnj  *	printf("reg=%b\n", regval, "<base><arg>*");
362781Swnj  * Where <base> is the output base expressed as a control character,
372781Swnj  * e.g. \10 gives octal; \20 gives hex.  Each arg is a sequence of
382781Swnj  * characters, the first of which gives the bit number to be inspected
392781Swnj  * (origin 1), and the next characters (up to a control character, i.e.
402781Swnj  * a character <= 32), give the name of the register.  Thus
412781Swnj  *	printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
422781Swnj  * would produce output:
432781Swnj  *	reg=2<BITTWO,BITONE>
4431Sbill  */
4531Sbill /*VARARGS1*/
4631Sbill printf(fmt, x1)
472781Swnj 	char *fmt;
482781Swnj 	unsigned x1;
4931Sbill {
50285Sbill 
51285Sbill 	prf(fmt, &x1, 0);
52285Sbill }
53285Sbill 
542377Swnj /*
552781Swnj  * Uprintf prints to the current user's terminal,
562781Swnj  * guarantees not to sleep (so can be called by interrupt routines)
572781Swnj  * and does no watermark checking - (so no verbose messages).
582377Swnj  */
592377Swnj /*VARARGS1*/
602377Swnj uprintf(fmt, x1)
612781Swnj 	char *fmt;
622377Swnj 	unsigned x1;
63285Sbill {
64285Sbill 
652377Swnj 	prf(fmt, &x1, 2);
66285Sbill }
67285Sbill 
682377Swnj prf(fmt, adx, touser)
692781Swnj 	register char *fmt;
702781Swnj 	register u_int *adx;
71285Sbill {
722434Swnj 	register int b, c, i;
7331Sbill 	char *s;
742678Swnj 	int any;
7531Sbill 
7631Sbill loop:
772377Swnj 	while ((c = *fmt++) != '%') {
7831Sbill 		if(c == '\0')
7931Sbill 			return;
802377Swnj 		putchar(c, touser);
8131Sbill 	}
822377Swnj again:
8331Sbill 	c = *fmt++;
842781Swnj 	/* THIS CODE IS VAX DEPENDENT IN HANDLING %l? AND %c */
852377Swnj 	switch (c) {
862377Swnj 
872377Swnj 	case 'l':
882377Swnj 		goto again;
892377Swnj 	case 'x': case 'X':
902377Swnj 		b = 16;
912377Swnj 		goto number;
922377Swnj 	case 'd': case 'D':
932377Swnj 	case 'u':		/* what a joke */
942377Swnj 		b = 10;
952377Swnj 		goto number;
962377Swnj 	case 'o': case 'O':
972377Swnj 		b = 8;
982377Swnj number:
993101Swnj 		printn((u_long)*adx, b, touser);
1002377Swnj 		break;
1012377Swnj 	case 'c':
1022434Swnj 		b = *adx;
1032434Swnj 		for (i = 24; i >= 0; i -= 8)
1042434Swnj 			if (c = (b >> i) & 0x7f)
1052434Swnj 				putchar(c, touser);
1062377Swnj 		break;
1072678Swnj 	case 'b':
1082678Swnj 		b = *adx++;
1092678Swnj 		s = (char *)*adx;
1103101Swnj 		printn((u_long)b, *s++, touser);
1112678Swnj 		any = 0;
1122678Swnj 		if (b) {
1132678Swnj 			putchar('<', touser);
1142678Swnj 			while (i = *s++) {
1152678Swnj 				if (b & (1 << (i-1))) {
1162678Swnj 					if (any)
1172678Swnj 						putchar(',', touser);
1182678Swnj 					any = 1;
1192678Swnj 					for (; (c = *s) > 32; s++)
1202678Swnj 						putchar(c, touser);
1212678Swnj 				} else
1222678Swnj 					for (; *s > 32; s++)
1232678Swnj 						;
1242678Swnj 			}
1253878Swnj 			if (any)
1263878Swnj 				putchar('>', touser);
1272678Swnj 		}
1282678Swnj 		break;
1292678Swnj 
1302377Swnj 	case 's':
13131Sbill 		s = (char *)*adx;
132285Sbill 		while (c = *s++)
1332377Swnj 			putchar(c, touser);
1342377Swnj 		break;
1353736Sroot 
1363736Sroot 	case '%':
1373736Sroot 		putchar('%', touser);
1383736Sroot 		break;
13931Sbill 	}
14031Sbill 	adx++;
14131Sbill 	goto loop;
14231Sbill }
14331Sbill 
1442781Swnj /*
1452781Swnj  * Printn prints a number n in base b.
1462781Swnj  * We don't use recursion to avoid deep kernel stacks.
1472781Swnj  */
1482377Swnj printn(n, b, touser)
1493101Swnj 	u_long n;
15031Sbill {
1512434Swnj 	char prbuf[11];
1522377Swnj 	register char *cp;
15331Sbill 
1542377Swnj 	if (b == 10 && (int)n < 0) {
1552377Swnj 		putchar('-', touser);
1562377Swnj 		n = (unsigned)(-(int)n);
15731Sbill 	}
1582434Swnj 	cp = prbuf;
1592377Swnj 	do {
1602377Swnj 		*cp++ = "0123456789abcdef"[n%b];
1612377Swnj 		n /= b;
1622377Swnj 	} while (n);
1632377Swnj 	do
1642377Swnj 		putchar(*--cp, touser);
1652434Swnj 	while (cp > prbuf);
16631Sbill }
16731Sbill 
16831Sbill /*
1691184Sbill  * Panic is called on unresolvable fatal errors.
1702781Swnj  * It prints "panic: mesg", and then reboots.
1712781Swnj  * If we are called twice, then we avoid trying to
1722781Swnj  * sync the disks as this often leads to recursive panics.
17331Sbill  */
17431Sbill panic(s)
1752781Swnj 	char *s;
17631Sbill {
1775416Swnj 	int bootopt = RB_AUTOBOOT;
1782377Swnj 
1795416Swnj 	if (panicstr)
1805416Swnj 		bootopt |= RB_NOSYNC;
1819758Ssam 	else {
1829758Ssam 		panicstr = s;
1838950Sroot 	}
1843285Swnj 	printf("panic: %s\n", s);
1852781Swnj 	boot(RB_PANIC, bootopt);
18631Sbill }
18731Sbill 
18831Sbill /*
1892941Swnj  * Warn that a system table is full.
1902941Swnj  */
1912941Swnj tablefull(tab)
1922941Swnj 	char *tab;
1932941Swnj {
1942941Swnj 
1952941Swnj 	printf("%s: table is full\n", tab);
1962941Swnj }
1972941Swnj 
1982941Swnj /*
1992781Swnj  * Hard error is the preface to plaintive error messages
2002941Swnj  * about failing disk transfers.
2012781Swnj  */
2022941Swnj harderr(bp, cp)
2032678Swnj 	struct buf *bp;
2042941Swnj 	char *cp;
20531Sbill {
20631Sbill 
2072941Swnj 	printf("%s%d%c: hard error sn%d ", cp,
2082941Swnj 	    dkunit(bp), 'a'+(minor(bp->b_dev)&07), bp->b_blkno);
20931Sbill }
2102781Swnj 
211285Sbill /*
2122377Swnj  * Print a character on console or users terminal.
213285Sbill  * If destination is console then the last MSGBUFS characters
214285Sbill  * are saved in msgbuf for inspection later.
215285Sbill  */
2161785Sbill /*ARGSUSED*/
2172377Swnj putchar(c, touser)
2182377Swnj 	register int c;
219285Sbill {
220285Sbill 
2212377Swnj 	if (touser) {
2222377Swnj 		register struct tty *tp = u.u_ttyp;
2232360Skre 
2245404Swnj 		if (tp && (tp->t_state&TS_CARR_ON)) {
2252377Swnj 			register s = spl6();
2262377Swnj 			if (c == '\n')
2274970Swnj 				(void) ttyoutput('\r', tp);
2284970Swnj 			(void) ttyoutput(c, tp);
2292360Skre 			ttstart(tp);
2302360Skre 			splx(s);
2312360Skre 		}
2322360Skre 		return;
2332360Skre 	}
2348950Sroot 	if (c != '\0' && c != '\r' && c != 0177
2358966Sroot #ifdef vax
2368950Sroot 	    && mfpr(MAPEN)
2378950Sroot #endif
2388950Sroot 	    ) {
2392172Swnj 		if (msgbuf.msg_magic != MSG_MAGIC) {
24012494Ssam 			register int i;
24112494Ssam 
2422172Swnj 			msgbuf.msg_bufx = 0;
2432172Swnj 			msgbuf.msg_magic = MSG_MAGIC;
24412494Ssam 			for (i=0; i < MSG_BSIZE; i++)
24512494Ssam 				msgbuf.msg_bufc[i] = 0;
2462172Swnj 		}
2472172Swnj 		if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE)
2482172Swnj 			msgbuf.msg_bufx = 0;
2492172Swnj 		msgbuf.msg_bufc[msgbuf.msg_bufx++] = c;
250285Sbill 	}
251285Sbill 	if (c == 0)
252285Sbill 		return;
253285Sbill 	cnputc(c);
254285Sbill }
255