xref: /csrg-svn/sys/kern/subr_prf.c (revision 29946)
123381Smckusick /*
229101Smckusick  * Copyright (c) 1982, 1986 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*29946Skarels  *	@(#)subr_prf.c	7.3 (Berkeley) 11/03/86
723381Smckusick  */
8*29946Skarels #include "../machine/mtpr.h"
931Sbill 
1017094Sbloom #include "param.h"
1117094Sbloom #include "systm.h"
1217094Sbloom #include "seg.h"
1317094Sbloom #include "buf.h"
1417094Sbloom #include "conf.h"
1517094Sbloom #include "reboot.h"
1617094Sbloom #include "vm.h"
1717094Sbloom #include "msgbuf.h"
1817094Sbloom #include "dir.h"
1917094Sbloom #include "user.h"
2017094Sbloom #include "proc.h"
2117577Sbloom #include "ioctl.h"
2217094Sbloom #include "tty.h"
2318364Skarels #include "syslog.h"
2431Sbill 
2516724Sralph #define TOCONS	0x1
2616724Sralph #define TOTTY	0x2
2716724Sralph #define TOLOG	0x4
2816724Sralph 
2931Sbill /*
3031Sbill  * In case console is off,
3131Sbill  * panicstr contains argument to last
3231Sbill  * call to panic.
3331Sbill  */
3431Sbill char	*panicstr;
3531Sbill 
3631Sbill /*
3731Sbill  * Scaled down version of C Library printf.
382781Swnj  * Used to print diagnostic information directly on console tty.
392781Swnj  * Since it is not interrupt driven, all system activities are
402781Swnj  * suspended.  Printf should not be used for chit-chat.
412781Swnj  *
422781Swnj  * One additional format: %b is supported to decode error registers.
432781Swnj  * Usage is:
442781Swnj  *	printf("reg=%b\n", regval, "<base><arg>*");
452781Swnj  * Where <base> is the output base expressed as a control character,
462781Swnj  * e.g. \10 gives octal; \20 gives hex.  Each arg is a sequence of
472781Swnj  * characters, the first of which gives the bit number to be inspected
482781Swnj  * (origin 1), and the next characters (up to a control character, i.e.
492781Swnj  * a character <= 32), give the name of the register.  Thus
502781Swnj  *	printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
512781Swnj  * would produce output:
5217594Skarels  *	reg=3<BITTWO,BITONE>
5331Sbill  */
54*29946Skarels #if defined(tahoe)
55*29946Skarels int	consintr;
56*29946Skarels #endif
57*29946Skarels 
5831Sbill /*VARARGS1*/
5931Sbill printf(fmt, x1)
602781Swnj 	char *fmt;
612781Swnj 	unsigned x1;
6231Sbill {
63*29946Skarels #if defined(tahoe)
64*29946Skarels 	register int savintr;
65285Sbill 
66*29946Skarels 	savintr = consintr, consintr = 0;	/* disable interrupts */
67*29946Skarels #endif
6816724Sralph 	prf(fmt, &x1, TOCONS | TOLOG, (struct tty *)0);
6916724Sralph 	logwakeup();
70*29946Skarels #if defined(tahoe)
71*29946Skarels 	consintr = savintr;			/* reenable interrupts */
72*29946Skarels #endif
73285Sbill }
74285Sbill 
752377Swnj /*
7625389Skarels  * Uprintf prints to the current user's terminal.
7725389Skarels  * It may block if the tty queue is overfull.
7825389Skarels  * Should determine whether current terminal user is related
7925389Skarels  * to this process.
802377Swnj  */
812377Swnj /*VARARGS1*/
822377Swnj uprintf(fmt, x1)
832781Swnj 	char *fmt;
842377Swnj 	unsigned x1;
85285Sbill {
8626250Skarels #ifdef notdef
8725389Skarels 	register struct proc *p;
8826250Skarels #endif
8925389Skarels 	register struct tty *tp;
90285Sbill 
9125389Skarels 	if ((tp = u.u_ttyp) == NULL)
9225389Skarels 		return;
9325389Skarels #ifdef notdef
9425389Skarels 	if (tp->t_pgrp && (p = pfind(tp->t_pgrp)))
9526250Skarels 		if (p->p_uid != u.u_uid)	/* doesn't account for setuid */
9625389Skarels 			return;
9725389Skarels #endif
9825389Skarels 	(void)ttycheckoutq(tp, 1);
9925389Skarels 	prf(fmt, &x1, TOTTY, tp);
100285Sbill }
101285Sbill 
10218364Skarels /*
10318364Skarels  * tprintf prints on the specified terminal (console if none)
10418364Skarels  * and logs the message.  It is designed for error messages from
10525389Skarels  * single-open devices, and may be called from interrupt level
10625389Skarels  * (does not sleep).
10718364Skarels  */
10816724Sralph /*VARARGS2*/
10925389Skarels tprintf(tp, fmt, x1)
11025389Skarels 	register struct tty *tp;
11116724Sralph 	char *fmt;
11216724Sralph 	unsigned x1;
11316724Sralph {
11425389Skarels 	int flags = TOTTY | TOLOG;
115*29946Skarels 	extern struct tty cons;
11616724Sralph 
11725389Skarels 	logpri(LOG_INFO);
118*29946Skarels 	if (tp == (struct tty *)NULL)
119*29946Skarels 		tp = &cons;
12025389Skarels 	if (ttycheckoutq(tp, 0) == 0)
12125389Skarels 		flags = TOLOG;
12225389Skarels 	prf(fmt, &x1, flags, tp);
12325389Skarels 	logwakeup();
12416724Sralph }
12516724Sralph 
12616724Sralph /*
12716724Sralph  * Log writes to the log buffer,
12817594Skarels  * and guarantees not to sleep (so can be called by interrupt routines).
12918364Skarels  * If there is no process reading the log yet, it writes to the console also.
13016724Sralph  */
13116724Sralph /*VARARGS2*/
13216724Sralph log(level, fmt, x1)
13316724Sralph 	char *fmt;
13416724Sralph 	unsigned x1;
13516724Sralph {
13616724Sralph 	register s = splhigh();
13718364Skarels 	extern int log_open;
13816724Sralph 
13925389Skarels 	logpri(level);
14016724Sralph 	prf(fmt, &x1, TOLOG, (struct tty *)0);
14116724Sralph 	splx(s);
14218364Skarels 	if (!log_open)
14318364Skarels 		prf(fmt, &x1, TOCONS, (struct tty *)0);
14416724Sralph 	logwakeup();
14516724Sralph }
14616724Sralph 
14725389Skarels logpri(level)
14825389Skarels 	int level;
14925389Skarels {
15025389Skarels 
15125389Skarels 	putchar('<', TOLOG, (struct tty *)0);
15226356Skarels 	printn((u_long)level, 10, TOLOG, (struct tty *)0);
15325389Skarels 	putchar('>', TOLOG, (struct tty *)0);
15425389Skarels }
15525389Skarels 
15616724Sralph prf(fmt, adx, flags, ttyp)
1572781Swnj 	register char *fmt;
1582781Swnj 	register u_int *adx;
15916724Sralph 	struct tty *ttyp;
160285Sbill {
1612434Swnj 	register int b, c, i;
16231Sbill 	char *s;
1632678Swnj 	int any;
16431Sbill 
16531Sbill loop:
1662377Swnj 	while ((c = *fmt++) != '%') {
16716724Sralph 		if (c == '\0')
16831Sbill 			return;
16916724Sralph 		putchar(c, flags, ttyp);
17031Sbill 	}
1712377Swnj again:
17231Sbill 	c = *fmt++;
173*29946Skarels 	/* THIS CODE IS MACHINE DEPENDENT IN HANDLING %l? AND %c */
1742377Swnj 	switch (c) {
1752377Swnj 
1762377Swnj 	case 'l':
1772377Swnj 		goto again;
1782377Swnj 	case 'x': case 'X':
1792377Swnj 		b = 16;
1802377Swnj 		goto number;
1812377Swnj 	case 'd': case 'D':
182*29946Skarels 		b = -10;
183*29946Skarels 		goto number;
184*29946Skarels 	case 'u':
1852377Swnj 		b = 10;
1862377Swnj 		goto number;
1872377Swnj 	case 'o': case 'O':
1882377Swnj 		b = 8;
1892377Swnj number:
19016724Sralph 		printn((u_long)*adx, b, flags, ttyp);
1912377Swnj 		break;
1922377Swnj 	case 'c':
1932434Swnj 		b = *adx;
194*29946Skarels #if ENDIAN == LITTLE
1952434Swnj 		for (i = 24; i >= 0; i -= 8)
1962434Swnj 			if (c = (b >> i) & 0x7f)
19716724Sralph 				putchar(c, flags, ttyp);
198*29946Skarels #endif
199*29946Skarels #if ENDIAN == BIG
200*29946Skarels 		if (c = (b & 0x7f))
201*29946Skarels 			putchar(c, flags, ttyp);
202*29946Skarels #endif
2032377Swnj 		break;
2042678Swnj 	case 'b':
2052678Swnj 		b = *adx++;
2062678Swnj 		s = (char *)*adx;
20716724Sralph 		printn((u_long)b, *s++, flags, ttyp);
2082678Swnj 		any = 0;
2092678Swnj 		if (b) {
2102678Swnj 			while (i = *s++) {
2112678Swnj 				if (b & (1 << (i-1))) {
212*29946Skarels 					putchar(any ? ',' : '<', flags, ttyp);
2132678Swnj 					any = 1;
2142678Swnj 					for (; (c = *s) > 32; s++)
21516724Sralph 						putchar(c, flags, ttyp);
2162678Swnj 				} else
2172678Swnj 					for (; *s > 32; s++)
2182678Swnj 						;
2192678Swnj 			}
2203878Swnj 			if (any)
22116724Sralph 				putchar('>', flags, ttyp);
2222678Swnj 		}
2232678Swnj 		break;
2242678Swnj 
2252377Swnj 	case 's':
22631Sbill 		s = (char *)*adx;
227285Sbill 		while (c = *s++)
22816724Sralph 			putchar(c, flags, ttyp);
2292377Swnj 		break;
2303736Sroot 
2313736Sroot 	case '%':
23216724Sralph 		putchar('%', flags, ttyp);
2333736Sroot 		break;
23431Sbill 	}
23531Sbill 	adx++;
23631Sbill 	goto loop;
23731Sbill }
23831Sbill 
2392781Swnj /*
2402781Swnj  * Printn prints a number n in base b.
2412781Swnj  * We don't use recursion to avoid deep kernel stacks.
2422781Swnj  */
24316724Sralph printn(n, b, flags, ttyp)
2443101Swnj 	u_long n;
24516724Sralph 	struct tty *ttyp;
24631Sbill {
2472434Swnj 	char prbuf[11];
2482377Swnj 	register char *cp;
24931Sbill 
250*29946Skarels 	if (b == -10) {
251*29946Skarels 		if ((int)n < 0) {
252*29946Skarels 			putchar('-', flags, ttyp);
253*29946Skarels 			n = (unsigned)(-(int)n);
254*29946Skarels 		}
255*29946Skarels 		b = -b;
25631Sbill 	}
2572434Swnj 	cp = prbuf;
2582377Swnj 	do {
2592377Swnj 		*cp++ = "0123456789abcdef"[n%b];
2602377Swnj 		n /= b;
2612377Swnj 	} while (n);
2622377Swnj 	do
26316724Sralph 		putchar(*--cp, flags, ttyp);
2642434Swnj 	while (cp > prbuf);
26531Sbill }
26631Sbill 
26731Sbill /*
2681184Sbill  * Panic is called on unresolvable fatal errors.
2692781Swnj  * It prints "panic: mesg", and then reboots.
2702781Swnj  * If we are called twice, then we avoid trying to
2712781Swnj  * sync the disks as this often leads to recursive panics.
27231Sbill  */
27331Sbill panic(s)
2742781Swnj 	char *s;
27531Sbill {
2765416Swnj 	int bootopt = RB_AUTOBOOT;
2772377Swnj 
2785416Swnj 	if (panicstr)
2795416Swnj 		bootopt |= RB_NOSYNC;
2809758Ssam 	else {
2819758Ssam 		panicstr = s;
2828950Sroot 	}
2833285Swnj 	printf("panic: %s\n", s);
2842781Swnj 	boot(RB_PANIC, bootopt);
28531Sbill }
28631Sbill 
28731Sbill /*
2882941Swnj  * Warn that a system table is full.
2892941Swnj  */
2902941Swnj tablefull(tab)
2912941Swnj 	char *tab;
2922941Swnj {
2932941Swnj 
29424839Seric 	log(LOG_ERR, "%s: table is full\n", tab);
2952941Swnj }
2962941Swnj 
2972941Swnj /*
2982781Swnj  * Hard error is the preface to plaintive error messages
2992941Swnj  * about failing disk transfers.
3002781Swnj  */
3012941Swnj harderr(bp, cp)
3022678Swnj 	struct buf *bp;
3032941Swnj 	char *cp;
30431Sbill {
30531Sbill 
3062941Swnj 	printf("%s%d%c: hard error sn%d ", cp,
30724759Skarels 	    minor(bp->b_dev) >> 3, 'a'+(minor(bp->b_dev)&07), bp->b_blkno);
30831Sbill }
3092781Swnj 
310285Sbill /*
3112377Swnj  * Print a character on console or users terminal.
312285Sbill  * If destination is console then the last MSGBUFS characters
313285Sbill  * are saved in msgbuf for inspection later.
314285Sbill  */
3151785Sbill /*ARGSUSED*/
31617594Skarels putchar(c, flags, tp)
3172377Swnj 	register int c;
31817594Skarels 	struct tty *tp;
319285Sbill {
320285Sbill 
32116724Sralph 	if (flags & TOTTY) {
32225389Skarels 		register s = spltty();
32325389Skarels 
32425389Skarels 		if (tp && (tp->t_state & (TS_CARR_ON | TS_ISOPEN)) ==
32525389Skarels 		    (TS_CARR_ON | TS_ISOPEN)) {
3262377Swnj 			if (c == '\n')
3274970Swnj 				(void) ttyoutput('\r', tp);
3284970Swnj 			(void) ttyoutput(c, tp);
3292360Skre 			ttstart(tp);
330*29946Skarels 		}
33125389Skarels 		splx(s);
3322360Skre 	}
333*29946Skarels 	/*
334*29946Skarels 	 * Can send to log only after memory management enabled:
335*29946Skarels 	 * this has happened by the time maxmem is set.
336*29946Skarels 	 */
337*29946Skarels 	if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177 && maxmem) {
3382172Swnj 		if (msgbuf.msg_magic != MSG_MAGIC) {
33912494Ssam 			register int i;
34012494Ssam 
3412172Swnj 			msgbuf.msg_magic = MSG_MAGIC;
34216724Sralph 			msgbuf.msg_bufx = msgbuf.msg_bufr = 0;
34312494Ssam 			for (i=0; i < MSG_BSIZE; i++)
34412494Ssam 				msgbuf.msg_bufc[i] = 0;
3452172Swnj 		}
34626427Sbloom 		msgbuf.msg_bufc[msgbuf.msg_bufx++] = c;
3472172Swnj 		if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE)
3482172Swnj 			msgbuf.msg_bufx = 0;
349285Sbill 	}
35016724Sralph 	if ((flags & TOCONS) && c != '\0')
351*29946Skarels 		cnputc(c);
352285Sbill }
353