xref: /csrg-svn/sys/kern/subr_prf.c (revision 2781)
1*2781Swnj /*	subr_prf.c	4.11	02/28/81	*/
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"
8285Sbill #include "../h/mtpr.h"
91184Sbill #include "../h/reboot.h"
102172Swnj #include "../h/vm.h"
112172Swnj #include "../h/msgbuf.h"
122360Skre #include "../h/dir.h"
132360Skre #include "../h/user.h"
142360Skre #include "../h/tty.h"
1531Sbill 
1631Sbill /*
1731Sbill  * In case console is off,
1831Sbill  * panicstr contains argument to last
1931Sbill  * call to panic.
2031Sbill  */
2131Sbill char	*panicstr;
2231Sbill 
2331Sbill /*
2431Sbill  * Scaled down version of C Library printf.
25*2781Swnj  * Used to print diagnostic information directly on console tty.
26*2781Swnj  * Since it is not interrupt driven, all system activities are
27*2781Swnj  * suspended.  Printf should not be used for chit-chat.
28*2781Swnj  *
29*2781Swnj  * One additional format: %b is supported to decode error registers.
30*2781Swnj  * Usage is:
31*2781Swnj  *	printf("reg=%b\n", regval, "<base><arg>*");
32*2781Swnj  * Where <base> is the output base expressed as a control character,
33*2781Swnj  * e.g. \10 gives octal; \20 gives hex.  Each arg is a sequence of
34*2781Swnj  * characters, the first of which gives the bit number to be inspected
35*2781Swnj  * (origin 1), and the next characters (up to a control character, i.e.
36*2781Swnj  * a character <= 32), give the name of the register.  Thus
37*2781Swnj  *	printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
38*2781Swnj  * would produce output:
39*2781Swnj  *	reg=2<BITTWO,BITONE>
4031Sbill  */
4131Sbill /*VARARGS1*/
4231Sbill printf(fmt, x1)
43*2781Swnj 	char *fmt;
44*2781Swnj 	unsigned x1;
4531Sbill {
46285Sbill 
47285Sbill 	prf(fmt, &x1, 0);
48285Sbill }
49285Sbill 
502377Swnj /*
51*2781Swnj  * Uprintf prints to the current user's terminal,
52*2781Swnj  * guarantees not to sleep (so can be called by interrupt routines)
53*2781Swnj  * and does no watermark checking - (so no verbose messages).
542377Swnj  */
552377Swnj /*VARARGS1*/
562377Swnj uprintf(fmt, x1)
57*2781Swnj 	char *fmt;
582377Swnj 	unsigned x1;
59285Sbill {
60285Sbill 
612377Swnj 	prf(fmt, &x1, 2);
62285Sbill }
63285Sbill 
642377Swnj prf(fmt, adx, touser)
65*2781Swnj 	register char *fmt;
66*2781Swnj 	register u_int *adx;
67285Sbill {
682434Swnj 	register int b, c, i;
6931Sbill 	char *s;
702678Swnj 	int any;
7131Sbill 
7231Sbill loop:
732377Swnj 	while ((c = *fmt++) != '%') {
7431Sbill 		if(c == '\0')
7531Sbill 			return;
762377Swnj 		putchar(c, touser);
7731Sbill 	}
782377Swnj again:
7931Sbill 	c = *fmt++;
80*2781Swnj 	/* THIS CODE IS VAX DEPENDENT IN HANDLING %l? AND %c */
812377Swnj 	switch (c) {
822377Swnj 
832377Swnj 	case 'l':
842377Swnj 		goto again;
852377Swnj 	case 'x': case 'X':
862377Swnj 		b = 16;
872377Swnj 		goto number;
882377Swnj 	case 'd': case 'D':
892377Swnj 	case 'u':		/* what a joke */
902377Swnj 		b = 10;
912377Swnj 		goto number;
922377Swnj 	case 'o': case 'O':
932377Swnj 		b = 8;
942377Swnj number:
952377Swnj 		printn(*adx, b, touser);
962377Swnj 		break;
972377Swnj 	case 'c':
982434Swnj 		b = *adx;
992434Swnj 		for (i = 24; i >= 0; i -= 8)
1002434Swnj 			if (c = (b >> i) & 0x7f)
1012434Swnj 				putchar(c, touser);
1022377Swnj 		break;
1032678Swnj 	case 'b':
1042678Swnj 		b = *adx++;
1052678Swnj 		s = (char *)*adx;
1062678Swnj 		printn(b, *s++, touser);
1072678Swnj 		any = 0;
1082678Swnj 		if (b) {
1092678Swnj 			putchar('<', touser);
1102678Swnj 			while (i = *s++) {
1112678Swnj 				if (b & (1 << (i-1))) {
1122678Swnj 					if (any)
1132678Swnj 						putchar(',', touser);
1142678Swnj 					any = 1;
1152678Swnj 					for (; (c = *s) > 32; s++)
1162678Swnj 						putchar(c, touser);
1172678Swnj 				} else
1182678Swnj 					for (; *s > 32; s++)
1192678Swnj 						;
1202678Swnj 			}
1212678Swnj 			putchar('>', touser);
1222678Swnj 		}
1232678Swnj 		break;
1242678Swnj 
1252377Swnj 	case 's':
12631Sbill 		s = (char *)*adx;
127285Sbill 		while (c = *s++)
1282377Swnj 			putchar(c, touser);
1292377Swnj 		break;
13031Sbill 	}
13131Sbill 	adx++;
13231Sbill 	goto loop;
13331Sbill }
13431Sbill 
135*2781Swnj /*
136*2781Swnj  * Printn prints a number n in base b.
137*2781Swnj  * We don't use recursion to avoid deep kernel stacks.
138*2781Swnj  */
1392377Swnj printn(n, b, touser)
1402377Swnj 	unsigned long n;
14131Sbill {
1422434Swnj 	char prbuf[11];
1432377Swnj 	register char *cp;
14431Sbill 
1452377Swnj 	if (b == 10 && (int)n < 0) {
1462377Swnj 		putchar('-', touser);
1472377Swnj 		n = (unsigned)(-(int)n);
14831Sbill 	}
1492434Swnj 	cp = prbuf;
1502377Swnj 	do {
1512377Swnj 		*cp++ = "0123456789abcdef"[n%b];
1522377Swnj 		n /= b;
1532377Swnj 	} while (n);
1542377Swnj 	do
1552377Swnj 		putchar(*--cp, touser);
1562434Swnj 	while (cp > prbuf);
15731Sbill }
15831Sbill 
15931Sbill /*
1601184Sbill  * Panic is called on unresolvable fatal errors.
161*2781Swnj  * It prints "panic: mesg", and then reboots.
162*2781Swnj  * If we are called twice, then we avoid trying to
163*2781Swnj  * sync the disks as this often leads to recursive panics.
16431Sbill  */
16531Sbill panic(s)
166*2781Swnj 	char *s;
16731Sbill {
168*2781Swnj 	int bootopt = panicstr ? RB_AUTOBOOT : RB_AUTOBOOT|RB_NOSYNC;
1692377Swnj 
17031Sbill 	panicstr = s;
17131Sbill 	printf("panic: %s\n", s);
1721787Sbill 	(void) spl0();
173*2781Swnj 	boot(RB_PANIC, bootopt);
17431Sbill }
17531Sbill 
17631Sbill /*
177*2781Swnj  * Prdev prints a warning message of the form "mesg on dev x/y".
178*2781Swnj  * x and y are the major and minor parts of the device argument.
179*2781Swnj  *
180*2781Swnj  * PRDEV SHOULD COMPUTE AND USE DEVICE NAMES
18131Sbill  */
18231Sbill prdev(str, dev)
1832377Swnj 	char *str;
1842377Swnj 	dev_t dev;
18531Sbill {
18631Sbill 
1872377Swnj 	printf("%s on dev %d/%d\n", str, major(dev), minor(dev));
18831Sbill }
18931Sbill 
190*2781Swnj /*
191*2781Swnj  * Hard error is the preface to plaintive error messages
192*2781Swnj  * about failing device transfers.
193*2781Swnj  */
1942678Swnj harderr(bp)
1952678Swnj 	struct buf *bp;
19631Sbill {
19731Sbill 
198*2781Swnj 	printf("hard err bn%d ", bp->b_blkno);
19931Sbill }
200*2781Swnj 
201285Sbill /*
2022377Swnj  * Print a character on console or users terminal.
203285Sbill  * If destination is console then the last MSGBUFS characters
204285Sbill  * are saved in msgbuf for inspection later.
205285Sbill  */
2061785Sbill /*ARGSUSED*/
2072377Swnj putchar(c, touser)
2082377Swnj 	register int c;
209285Sbill {
210285Sbill 
2112377Swnj 	if (touser) {
2122377Swnj 		register struct tty *tp = u.u_ttyp;
2132360Skre 
2142377Swnj 		if (tp && (tp->t_state&CARR_ON)) {
2152377Swnj 			register s = spl6();
2162377Swnj 			if (c == '\n')
2172377Swnj 				ttyoutput('\r', tp);
2182360Skre 			ttyoutput(c, tp);
2192360Skre 			ttstart(tp);
2202360Skre 			splx(s);
2212360Skre 		}
2222360Skre 		return;
2232360Skre 	}
2242386Swnj 	if (c != '\0' && c != '\r' && c != 0177 && mfpr(MAPEN)) {
2252172Swnj 		if (msgbuf.msg_magic != MSG_MAGIC) {
2262172Swnj 			msgbuf.msg_bufx = 0;
2272172Swnj 			msgbuf.msg_magic = MSG_MAGIC;
2282172Swnj 		}
2292172Swnj 		if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE)
2302172Swnj 			msgbuf.msg_bufx = 0;
2312172Swnj 		msgbuf.msg_bufc[msgbuf.msg_bufx++] = c;
232285Sbill 	}
233285Sbill 	if (c == 0)
234285Sbill 		return;
235285Sbill 	cnputc(c);
236285Sbill }
237