xref: /csrg-svn/sys/kern/subr_prf.c (revision 25389)
123381Smckusick /*
223381Smckusick  * Copyright (c) 1982 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*25389Skarels  *	@(#)subr_prf.c	6.10 (Berkeley) 11/04/85
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 "dir.h"
1817094Sbloom #include "user.h"
1917094Sbloom #include "proc.h"
2017577Sbloom #include "ioctl.h"
2117094Sbloom #include "tty.h"
2218364Skarels #include "syslog.h"
2331Sbill 
2413531Ssam #ifdef vax
2513531Ssam #include "../vax/mtpr.h"
2613531Ssam #endif
2713531Ssam 
2816724Sralph #define TOCONS	0x1
2916724Sralph #define TOTTY	0x2
3016724Sralph #define TOLOG	0x4
3116724Sralph 
3231Sbill /*
3331Sbill  * In case console is off,
3431Sbill  * panicstr contains argument to last
3531Sbill  * call to panic.
3631Sbill  */
3731Sbill char	*panicstr;
3831Sbill 
3931Sbill /*
4031Sbill  * Scaled down version of C Library printf.
412781Swnj  * Used to print diagnostic information directly on console tty.
422781Swnj  * Since it is not interrupt driven, all system activities are
432781Swnj  * suspended.  Printf should not be used for chit-chat.
442781Swnj  *
452781Swnj  * One additional format: %b is supported to decode error registers.
462781Swnj  * Usage is:
472781Swnj  *	printf("reg=%b\n", regval, "<base><arg>*");
482781Swnj  * Where <base> is the output base expressed as a control character,
492781Swnj  * e.g. \10 gives octal; \20 gives hex.  Each arg is a sequence of
502781Swnj  * characters, the first of which gives the bit number to be inspected
512781Swnj  * (origin 1), and the next characters (up to a control character, i.e.
522781Swnj  * a character <= 32), give the name of the register.  Thus
532781Swnj  *	printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
542781Swnj  * would produce output:
5517594Skarels  *	reg=3<BITTWO,BITONE>
5631Sbill  */
5731Sbill /*VARARGS1*/
5831Sbill printf(fmt, x1)
592781Swnj 	char *fmt;
602781Swnj 	unsigned x1;
6131Sbill {
62285Sbill 
6316724Sralph 	prf(fmt, &x1, TOCONS | TOLOG, (struct tty *)0);
6416724Sralph 	logwakeup();
65285Sbill }
66285Sbill 
672377Swnj /*
68*25389Skarels  * Uprintf prints to the current user's terminal.
69*25389Skarels  * It may block if the tty queue is overfull.
70*25389Skarels  * Should determine whether current terminal user is related
71*25389Skarels  * to this process.
722377Swnj  */
732377Swnj /*VARARGS1*/
742377Swnj uprintf(fmt, x1)
752781Swnj 	char *fmt;
762377Swnj 	unsigned x1;
77285Sbill {
78*25389Skarels 	register struct proc *p;
79*25389Skarels 	register struct tty *tp;
80285Sbill 
81*25389Skarels 	if ((tp = u.u_ttyp) == NULL)
82*25389Skarels 		return;
83*25389Skarels #ifdef notdef
84*25389Skarels 	if (tp->t_pgrp && (p = pfind(tp->t_pgrp)))
85*25389Skarels 		if (p->p_uid != u.u_uid)
86*25389Skarels 			return;
87*25389Skarels #endif
88*25389Skarels 	(void)ttycheckoutq(tp, 1);
89*25389Skarels 	prf(fmt, &x1, TOTTY, tp);
90285Sbill }
91285Sbill 
9218364Skarels /*
9318364Skarels  * tprintf prints on the specified terminal (console if none)
9418364Skarels  * and logs the message.  It is designed for error messages from
95*25389Skarels  * single-open devices, and may be called from interrupt level
96*25389Skarels  * (does not sleep).
9718364Skarels  */
9816724Sralph /*VARARGS2*/
99*25389Skarels tprintf(tp, fmt, x1)
100*25389Skarels 	register struct tty *tp;
10116724Sralph 	char *fmt;
10216724Sralph 	unsigned x1;
10316724Sralph {
104*25389Skarels 	int flags = TOTTY | TOLOG;
105*25389Skarels 	extern struct tty cons;
10616724Sralph 
107*25389Skarels 	logpri(LOG_INFO);
108*25389Skarels 	if (tp == (struct tty *)NULL)
109*25389Skarels 		tp = &cons;
110*25389Skarels 	if (ttycheckoutq(tp, 0) == 0)
111*25389Skarels 		flags = TOLOG;
112*25389Skarels 	prf(fmt, &x1, flags, tp);
113*25389Skarels 	logwakeup();
11416724Sralph }
11516724Sralph 
11616724Sralph /*
11716724Sralph  * Log writes to the log buffer,
11817594Skarels  * and guarantees not to sleep (so can be called by interrupt routines).
11918364Skarels  * If there is no process reading the log yet, it writes to the console also.
12016724Sralph  */
12116724Sralph /*VARARGS2*/
12216724Sralph log(level, fmt, x1)
12316724Sralph 	char *fmt;
12416724Sralph 	unsigned x1;
12516724Sralph {
12616724Sralph 	register s = splhigh();
12718364Skarels 	extern int log_open;
12816724Sralph 
129*25389Skarels 	logpri(level);
13016724Sralph 	prf(fmt, &x1, TOLOG, (struct tty *)0);
13116724Sralph 	splx(s);
13218364Skarels 	if (!log_open)
13318364Skarels 		prf(fmt, &x1, TOCONS, (struct tty *)0);
13416724Sralph 	logwakeup();
13516724Sralph }
13616724Sralph 
137*25389Skarels logpri(level)
138*25389Skarels 	int level;
139*25389Skarels {
140*25389Skarels 
141*25389Skarels 	putchar('<', TOLOG, (struct tty *)0);
142*25389Skarels 	printn(level, 10, TOLOG, (struct tty *)0);
143*25389Skarels 	putchar('>', TOLOG, (struct tty *)0);
144*25389Skarels }
145*25389Skarels 
14616724Sralph prf(fmt, adx, flags, ttyp)
1472781Swnj 	register char *fmt;
1482781Swnj 	register u_int *adx;
14916724Sralph 	struct tty *ttyp;
150285Sbill {
1512434Swnj 	register int b, c, i;
15231Sbill 	char *s;
1532678Swnj 	int any;
15431Sbill 
15531Sbill loop:
1562377Swnj 	while ((c = *fmt++) != '%') {
15716724Sralph 		if (c == '\0')
15831Sbill 			return;
15916724Sralph 		putchar(c, flags, ttyp);
16031Sbill 	}
1612377Swnj again:
16231Sbill 	c = *fmt++;
1632781Swnj 	/* THIS CODE IS VAX DEPENDENT IN HANDLING %l? AND %c */
1642377Swnj 	switch (c) {
1652377Swnj 
1662377Swnj 	case 'l':
1672377Swnj 		goto again;
1682377Swnj 	case 'x': case 'X':
1692377Swnj 		b = 16;
1702377Swnj 		goto number;
1712377Swnj 	case 'd': case 'D':
1722377Swnj 	case 'u':		/* what a joke */
1732377Swnj 		b = 10;
1742377Swnj 		goto number;
1752377Swnj 	case 'o': case 'O':
1762377Swnj 		b = 8;
1772377Swnj number:
17816724Sralph 		printn((u_long)*adx, b, flags, ttyp);
1792377Swnj 		break;
1802377Swnj 	case 'c':
1812434Swnj 		b = *adx;
1822434Swnj 		for (i = 24; i >= 0; i -= 8)
1832434Swnj 			if (c = (b >> i) & 0x7f)
18416724Sralph 				putchar(c, flags, ttyp);
1852377Swnj 		break;
1862678Swnj 	case 'b':
1872678Swnj 		b = *adx++;
1882678Swnj 		s = (char *)*adx;
18916724Sralph 		printn((u_long)b, *s++, flags, ttyp);
1902678Swnj 		any = 0;
1912678Swnj 		if (b) {
1922678Swnj 			while (i = *s++) {
1932678Swnj 				if (b & (1 << (i-1))) {
19417594Skarels 					putchar(any? ',' : '<', flags, ttyp);
1952678Swnj 					any = 1;
1962678Swnj 					for (; (c = *s) > 32; s++)
19716724Sralph 						putchar(c, flags, ttyp);
1982678Swnj 				} else
1992678Swnj 					for (; *s > 32; s++)
2002678Swnj 						;
2012678Swnj 			}
2023878Swnj 			if (any)
20316724Sralph 				putchar('>', flags, ttyp);
2042678Swnj 		}
2052678Swnj 		break;
2062678Swnj 
2072377Swnj 	case 's':
20831Sbill 		s = (char *)*adx;
209285Sbill 		while (c = *s++)
21016724Sralph 			putchar(c, flags, ttyp);
2112377Swnj 		break;
2123736Sroot 
2133736Sroot 	case '%':
21416724Sralph 		putchar('%', flags, ttyp);
2153736Sroot 		break;
21631Sbill 	}
21731Sbill 	adx++;
21831Sbill 	goto loop;
21931Sbill }
22031Sbill 
2212781Swnj /*
2222781Swnj  * Printn prints a number n in base b.
2232781Swnj  * We don't use recursion to avoid deep kernel stacks.
2242781Swnj  */
22516724Sralph printn(n, b, flags, ttyp)
2263101Swnj 	u_long n;
22716724Sralph 	struct tty *ttyp;
22831Sbill {
2292434Swnj 	char prbuf[11];
2302377Swnj 	register char *cp;
23131Sbill 
2322377Swnj 	if (b == 10 && (int)n < 0) {
23316724Sralph 		putchar('-', flags, ttyp);
2342377Swnj 		n = (unsigned)(-(int)n);
23531Sbill 	}
2362434Swnj 	cp = prbuf;
2372377Swnj 	do {
2382377Swnj 		*cp++ = "0123456789abcdef"[n%b];
2392377Swnj 		n /= b;
2402377Swnj 	} while (n);
2412377Swnj 	do
24216724Sralph 		putchar(*--cp, flags, ttyp);
2432434Swnj 	while (cp > prbuf);
24431Sbill }
24531Sbill 
24631Sbill /*
2471184Sbill  * Panic is called on unresolvable fatal errors.
2482781Swnj  * It prints "panic: mesg", and then reboots.
2492781Swnj  * If we are called twice, then we avoid trying to
2502781Swnj  * sync the disks as this often leads to recursive panics.
25131Sbill  */
25231Sbill panic(s)
2532781Swnj 	char *s;
25431Sbill {
2555416Swnj 	int bootopt = RB_AUTOBOOT;
2562377Swnj 
2575416Swnj 	if (panicstr)
2585416Swnj 		bootopt |= RB_NOSYNC;
2599758Ssam 	else {
2609758Ssam 		panicstr = s;
2618950Sroot 	}
2623285Swnj 	printf("panic: %s\n", s);
2632781Swnj 	boot(RB_PANIC, bootopt);
26431Sbill }
26531Sbill 
26631Sbill /*
2672941Swnj  * Warn that a system table is full.
2682941Swnj  */
2692941Swnj tablefull(tab)
2702941Swnj 	char *tab;
2712941Swnj {
2722941Swnj 
27324839Seric 	log(LOG_ERR, "%s: table is full\n", tab);
2742941Swnj }
2752941Swnj 
2762941Swnj /*
2772781Swnj  * Hard error is the preface to plaintive error messages
2782941Swnj  * about failing disk transfers.
2792781Swnj  */
2802941Swnj harderr(bp, cp)
2812678Swnj 	struct buf *bp;
2822941Swnj 	char *cp;
28331Sbill {
28431Sbill 
2852941Swnj 	printf("%s%d%c: hard error sn%d ", cp,
28624759Skarels 	    minor(bp->b_dev) >> 3, 'a'+(minor(bp->b_dev)&07), bp->b_blkno);
28731Sbill }
2882781Swnj 
289285Sbill /*
2902377Swnj  * Print a character on console or users terminal.
291285Sbill  * If destination is console then the last MSGBUFS characters
292285Sbill  * are saved in msgbuf for inspection later.
293285Sbill  */
2941785Sbill /*ARGSUSED*/
29517594Skarels putchar(c, flags, tp)
2962377Swnj 	register int c;
29717594Skarels 	struct tty *tp;
298285Sbill {
299285Sbill 
30016724Sralph 	if (flags & TOTTY) {
301*25389Skarels 		register s = spltty();
302*25389Skarels 
303*25389Skarels 		if (tp && (tp->t_state & (TS_CARR_ON | TS_ISOPEN)) ==
304*25389Skarels 		    (TS_CARR_ON | TS_ISOPEN)) {
3052377Swnj 			if (c == '\n')
3064970Swnj 				(void) ttyoutput('\r', tp);
3074970Swnj 			(void) ttyoutput(c, tp);
3082360Skre 			ttstart(tp);
3092360Skre 		}
310*25389Skarels 		splx(s);
3112360Skre 	}
31216724Sralph 	if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177
3138966Sroot #ifdef vax
3148950Sroot 	    && mfpr(MAPEN)
3158950Sroot #endif
3168950Sroot 	    ) {
3172172Swnj 		if (msgbuf.msg_magic != MSG_MAGIC) {
31812494Ssam 			register int i;
31912494Ssam 
3202172Swnj 			msgbuf.msg_magic = MSG_MAGIC;
32116724Sralph 			msgbuf.msg_bufx = msgbuf.msg_bufr = 0;
32212494Ssam 			for (i=0; i < MSG_BSIZE; i++)
32312494Ssam 				msgbuf.msg_bufc[i] = 0;
3242172Swnj 		}
3252172Swnj 		if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE)
3262172Swnj 			msgbuf.msg_bufx = 0;
3272172Swnj 		msgbuf.msg_bufc[msgbuf.msg_bufx++] = c;
328285Sbill 	}
32916724Sralph 	if ((flags & TOCONS) && c != '\0')
33016724Sralph 		cnputc(c);
331285Sbill }
332