xref: /csrg-svn/sys/kern/subr_prf.c (revision 18364)
1*18364Skarels /*	subr_prf.c	6.6	85/03/18	*/
231Sbill 
317094Sbloom #include "param.h"
417094Sbloom #include "systm.h"
517094Sbloom #include "seg.h"
617094Sbloom #include "buf.h"
717094Sbloom #include "conf.h"
817094Sbloom #include "reboot.h"
917094Sbloom #include "vm.h"
1017094Sbloom #include "msgbuf.h"
1117094Sbloom #include "dir.h"
1217094Sbloom #include "user.h"
1317094Sbloom #include "proc.h"
1417577Sbloom #include "ioctl.h"
1517094Sbloom #include "tty.h"
16*18364Skarels #include "syslog.h"
1731Sbill 
1813531Ssam #ifdef vax
1913531Ssam #include "../vax/mtpr.h"
2013531Ssam #endif
2113531Ssam 
2216724Sralph #define TOCONS	0x1
2316724Sralph #define TOTTY	0x2
2416724Sralph #define TOLOG	0x4
2516724Sralph 
2631Sbill /*
2731Sbill  * In case console is off,
2831Sbill  * panicstr contains argument to last
2931Sbill  * call to panic.
3031Sbill  */
3131Sbill char	*panicstr;
3231Sbill 
3331Sbill /*
3431Sbill  * Scaled down version of C Library printf.
352781Swnj  * Used to print diagnostic information directly on console tty.
362781Swnj  * Since it is not interrupt driven, all system activities are
372781Swnj  * suspended.  Printf should not be used for chit-chat.
382781Swnj  *
392781Swnj  * One additional format: %b is supported to decode error registers.
402781Swnj  * Usage is:
412781Swnj  *	printf("reg=%b\n", regval, "<base><arg>*");
422781Swnj  * Where <base> is the output base expressed as a control character,
432781Swnj  * e.g. \10 gives octal; \20 gives hex.  Each arg is a sequence of
442781Swnj  * characters, the first of which gives the bit number to be inspected
452781Swnj  * (origin 1), and the next characters (up to a control character, i.e.
462781Swnj  * a character <= 32), give the name of the register.  Thus
472781Swnj  *	printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
482781Swnj  * would produce output:
4917594Skarels  *	reg=3<BITTWO,BITONE>
5031Sbill  */
5131Sbill /*VARARGS1*/
5231Sbill printf(fmt, x1)
532781Swnj 	char *fmt;
542781Swnj 	unsigned x1;
5531Sbill {
56285Sbill 
5716724Sralph 	prf(fmt, &x1, TOCONS | TOLOG, (struct tty *)0);
5816724Sralph 	logwakeup();
59285Sbill }
60285Sbill 
612377Swnj /*
6217594Skarels  * Uprintf prints to the current user's terminal
632781Swnj  * and does no watermark checking - (so no verbose messages).
642377Swnj  */
652377Swnj /*VARARGS1*/
662377Swnj uprintf(fmt, x1)
672781Swnj 	char *fmt;
682377Swnj 	unsigned x1;
69285Sbill {
70285Sbill 
7116724Sralph 	prf(fmt, &x1, TOTTY, u.u_ttyp);
72285Sbill }
73285Sbill 
74*18364Skarels /*
75*18364Skarels  * tprintf prints on the specified terminal (console if none)
76*18364Skarels  * and logs the message.  It is designed for error messages from
77*18364Skarels  * single-open devices, and may be called from interrupt level.
78*18364Skarels  */
7916724Sralph /*VARARGS2*/
8016724Sralph tprintf(ttyp, fmt, x1)
8116724Sralph 	struct tty *ttyp;
8216724Sralph 	char *fmt;
8316724Sralph 	unsigned x1;
8416724Sralph {
8516724Sralph 
86*18364Skarels 	prf(fmt, &x1, TOTTY | TOLOG, ttyp);
8716724Sralph }
8816724Sralph 
8916724Sralph /*
9016724Sralph  * Log writes to the log buffer,
9117594Skarels  * and guarantees not to sleep (so can be called by interrupt routines).
92*18364Skarels  * If there is no process reading the log yet, it writes to the console also.
9316724Sralph  */
9416724Sralph /*VARARGS2*/
9516724Sralph log(level, fmt, x1)
9616724Sralph 	char *fmt;
9716724Sralph 	unsigned x1;
9816724Sralph {
9916724Sralph 	register s = splhigh();
100*18364Skarels 	extern int log_open;
10116724Sralph 
10216724Sralph 	putchar('<', TOLOG, (struct tty *)0);
10316724Sralph 	printn(level, 10, TOLOG, (struct tty *)0);
10416724Sralph 	putchar('>', TOLOG, (struct tty *)0);
10516724Sralph 	prf(fmt, &x1, TOLOG, (struct tty *)0);
10616724Sralph 	splx(s);
107*18364Skarels 	if (!log_open)
108*18364Skarels 		prf(fmt, &x1, TOCONS, (struct tty *)0);
10916724Sralph 	logwakeup();
11016724Sralph }
11116724Sralph 
11216724Sralph prf(fmt, adx, flags, ttyp)
1132781Swnj 	register char *fmt;
1142781Swnj 	register u_int *adx;
11516724Sralph 	struct tty *ttyp;
116285Sbill {
1172434Swnj 	register int b, c, i;
11831Sbill 	char *s;
1192678Swnj 	int any;
12031Sbill 
12131Sbill loop:
1222377Swnj 	while ((c = *fmt++) != '%') {
12316724Sralph 		if (c == '\0')
12431Sbill 			return;
12516724Sralph 		putchar(c, flags, ttyp);
12631Sbill 	}
1272377Swnj again:
12831Sbill 	c = *fmt++;
1292781Swnj 	/* THIS CODE IS VAX DEPENDENT IN HANDLING %l? AND %c */
1302377Swnj 	switch (c) {
1312377Swnj 
1322377Swnj 	case 'l':
1332377Swnj 		goto again;
1342377Swnj 	case 'x': case 'X':
1352377Swnj 		b = 16;
1362377Swnj 		goto number;
1372377Swnj 	case 'd': case 'D':
1382377Swnj 	case 'u':		/* what a joke */
1392377Swnj 		b = 10;
1402377Swnj 		goto number;
1412377Swnj 	case 'o': case 'O':
1422377Swnj 		b = 8;
1432377Swnj number:
14416724Sralph 		printn((u_long)*adx, b, flags, ttyp);
1452377Swnj 		break;
1462377Swnj 	case 'c':
1472434Swnj 		b = *adx;
1482434Swnj 		for (i = 24; i >= 0; i -= 8)
1492434Swnj 			if (c = (b >> i) & 0x7f)
15016724Sralph 				putchar(c, flags, ttyp);
1512377Swnj 		break;
1522678Swnj 	case 'b':
1532678Swnj 		b = *adx++;
1542678Swnj 		s = (char *)*adx;
15516724Sralph 		printn((u_long)b, *s++, flags, ttyp);
1562678Swnj 		any = 0;
1572678Swnj 		if (b) {
1582678Swnj 			while (i = *s++) {
1592678Swnj 				if (b & (1 << (i-1))) {
16017594Skarels 					putchar(any? ',' : '<', flags, ttyp);
1612678Swnj 					any = 1;
1622678Swnj 					for (; (c = *s) > 32; s++)
16316724Sralph 						putchar(c, flags, ttyp);
1642678Swnj 				} else
1652678Swnj 					for (; *s > 32; s++)
1662678Swnj 						;
1672678Swnj 			}
1683878Swnj 			if (any)
16916724Sralph 				putchar('>', flags, ttyp);
1702678Swnj 		}
1712678Swnj 		break;
1722678Swnj 
1732377Swnj 	case 's':
17431Sbill 		s = (char *)*adx;
175285Sbill 		while (c = *s++)
17616724Sralph 			putchar(c, flags, ttyp);
1772377Swnj 		break;
1783736Sroot 
1793736Sroot 	case '%':
18016724Sralph 		putchar('%', flags, ttyp);
1813736Sroot 		break;
18231Sbill 	}
18331Sbill 	adx++;
18431Sbill 	goto loop;
18531Sbill }
18631Sbill 
1872781Swnj /*
1882781Swnj  * Printn prints a number n in base b.
1892781Swnj  * We don't use recursion to avoid deep kernel stacks.
1902781Swnj  */
19116724Sralph printn(n, b, flags, ttyp)
1923101Swnj 	u_long n;
19316724Sralph 	struct tty *ttyp;
19431Sbill {
1952434Swnj 	char prbuf[11];
1962377Swnj 	register char *cp;
19731Sbill 
1982377Swnj 	if (b == 10 && (int)n < 0) {
19916724Sralph 		putchar('-', flags, ttyp);
2002377Swnj 		n = (unsigned)(-(int)n);
20131Sbill 	}
2022434Swnj 	cp = prbuf;
2032377Swnj 	do {
2042377Swnj 		*cp++ = "0123456789abcdef"[n%b];
2052377Swnj 		n /= b;
2062377Swnj 	} while (n);
2072377Swnj 	do
20816724Sralph 		putchar(*--cp, flags, ttyp);
2092434Swnj 	while (cp > prbuf);
21031Sbill }
21131Sbill 
21231Sbill /*
2131184Sbill  * Panic is called on unresolvable fatal errors.
2142781Swnj  * It prints "panic: mesg", and then reboots.
2152781Swnj  * If we are called twice, then we avoid trying to
2162781Swnj  * sync the disks as this often leads to recursive panics.
21731Sbill  */
21831Sbill panic(s)
2192781Swnj 	char *s;
22031Sbill {
2215416Swnj 	int bootopt = RB_AUTOBOOT;
2222377Swnj 
2235416Swnj 	if (panicstr)
2245416Swnj 		bootopt |= RB_NOSYNC;
2259758Ssam 	else {
2269758Ssam 		panicstr = s;
2278950Sroot 	}
2283285Swnj 	printf("panic: %s\n", s);
2292781Swnj 	boot(RB_PANIC, bootopt);
23031Sbill }
23131Sbill 
23231Sbill /*
2332941Swnj  * Warn that a system table is full.
2342941Swnj  */
2352941Swnj tablefull(tab)
2362941Swnj 	char *tab;
2372941Swnj {
2382941Swnj 
239*18364Skarels 	log(KERN_FAIL, "%s: table is full\n", tab);
2402941Swnj }
2412941Swnj 
2422941Swnj /*
2432781Swnj  * Hard error is the preface to plaintive error messages
2442941Swnj  * about failing disk transfers.
2452781Swnj  */
2462941Swnj harderr(bp, cp)
2472678Swnj 	struct buf *bp;
2482941Swnj 	char *cp;
24931Sbill {
25031Sbill 
2512941Swnj 	printf("%s%d%c: hard error sn%d ", cp,
2522941Swnj 	    dkunit(bp), 'a'+(minor(bp->b_dev)&07), bp->b_blkno);
25331Sbill }
2542781Swnj 
255285Sbill /*
2562377Swnj  * Print a character on console or users terminal.
257285Sbill  * If destination is console then the last MSGBUFS characters
258285Sbill  * are saved in msgbuf for inspection later.
259285Sbill  */
2601785Sbill /*ARGSUSED*/
26117594Skarels putchar(c, flags, tp)
2622377Swnj 	register int c;
26317594Skarels 	struct tty *tp;
264285Sbill {
26517594Skarels 	extern struct tty cons;
266285Sbill 
26716724Sralph 	if (flags & TOTTY) {
26817594Skarels 		if (tp == (struct tty *)NULL && (flags & TOCONS) == 0)
26917594Skarels 			tp = &cons;
27016724Sralph 		if (tp && (tp->t_state & TS_CARR_ON)) {
2712377Swnj 			register s = spl6();
2722377Swnj 			if (c == '\n')
2734970Swnj 				(void) ttyoutput('\r', tp);
2744970Swnj 			(void) ttyoutput(c, tp);
2752360Skre 			ttstart(tp);
2762360Skre 			splx(s);
2772360Skre 		}
2782360Skre 	}
27916724Sralph 	if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177
2808966Sroot #ifdef vax
2818950Sroot 	    && mfpr(MAPEN)
2828950Sroot #endif
2838950Sroot 	    ) {
2842172Swnj 		if (msgbuf.msg_magic != MSG_MAGIC) {
28512494Ssam 			register int i;
28612494Ssam 
2872172Swnj 			msgbuf.msg_magic = MSG_MAGIC;
28816724Sralph 			msgbuf.msg_bufx = msgbuf.msg_bufr = 0;
28912494Ssam 			for (i=0; i < MSG_BSIZE; i++)
29012494Ssam 				msgbuf.msg_bufc[i] = 0;
2912172Swnj 		}
2922172Swnj 		if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE)
2932172Swnj 			msgbuf.msg_bufx = 0;
2942172Swnj 		msgbuf.msg_bufc[msgbuf.msg_bufx++] = c;
295285Sbill 	}
29616724Sralph 	if ((flags & TOCONS) && c != '\0')
29716724Sralph 		cnputc(c);
298285Sbill }
299