xref: /csrg-svn/sys/kern/subr_prf.c (revision 26427)
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*26427Sbloom  *	@(#)subr_prf.c	6.13 (Berkeley) 02/26/86
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 /*
6825389Skarels  * Uprintf prints to the current user's terminal.
6925389Skarels  * It may block if the tty queue is overfull.
7025389Skarels  * Should determine whether current terminal user is related
7125389Skarels  * to this process.
722377Swnj  */
732377Swnj /*VARARGS1*/
742377Swnj uprintf(fmt, x1)
752781Swnj 	char *fmt;
762377Swnj 	unsigned x1;
77285Sbill {
7826250Skarels #ifdef notdef
7925389Skarels 	register struct proc *p;
8026250Skarels #endif
8125389Skarels 	register struct tty *tp;
82285Sbill 
8325389Skarels 	if ((tp = u.u_ttyp) == NULL)
8425389Skarels 		return;
8525389Skarels #ifdef notdef
8625389Skarels 	if (tp->t_pgrp && (p = pfind(tp->t_pgrp)))
8726250Skarels 		if (p->p_uid != u.u_uid)	/* doesn't account for setuid */
8825389Skarels 			return;
8925389Skarels #endif
9025389Skarels 	(void)ttycheckoutq(tp, 1);
9125389Skarels 	prf(fmt, &x1, TOTTY, tp);
92285Sbill }
93285Sbill 
9418364Skarels /*
9518364Skarels  * tprintf prints on the specified terminal (console if none)
9618364Skarels  * and logs the message.  It is designed for error messages from
9725389Skarels  * single-open devices, and may be called from interrupt level
9825389Skarels  * (does not sleep).
9918364Skarels  */
10016724Sralph /*VARARGS2*/
10125389Skarels tprintf(tp, fmt, x1)
10225389Skarels 	register struct tty *tp;
10316724Sralph 	char *fmt;
10416724Sralph 	unsigned x1;
10516724Sralph {
10625389Skarels 	int flags = TOTTY | TOLOG;
10725389Skarels 	extern struct tty cons;
10816724Sralph 
10925389Skarels 	logpri(LOG_INFO);
11025389Skarels 	if (tp == (struct tty *)NULL)
11125389Skarels 		tp = &cons;
11225389Skarels 	if (ttycheckoutq(tp, 0) == 0)
11325389Skarels 		flags = TOLOG;
11425389Skarels 	prf(fmt, &x1, flags, tp);
11525389Skarels 	logwakeup();
11616724Sralph }
11716724Sralph 
11816724Sralph /*
11916724Sralph  * Log writes to the log buffer,
12017594Skarels  * and guarantees not to sleep (so can be called by interrupt routines).
12118364Skarels  * If there is no process reading the log yet, it writes to the console also.
12216724Sralph  */
12316724Sralph /*VARARGS2*/
12416724Sralph log(level, fmt, x1)
12516724Sralph 	char *fmt;
12616724Sralph 	unsigned x1;
12716724Sralph {
12816724Sralph 	register s = splhigh();
12918364Skarels 	extern int log_open;
13016724Sralph 
13125389Skarels 	logpri(level);
13216724Sralph 	prf(fmt, &x1, TOLOG, (struct tty *)0);
13316724Sralph 	splx(s);
13418364Skarels 	if (!log_open)
13518364Skarels 		prf(fmt, &x1, TOCONS, (struct tty *)0);
13616724Sralph 	logwakeup();
13716724Sralph }
13816724Sralph 
13925389Skarels logpri(level)
14025389Skarels 	int level;
14125389Skarels {
14225389Skarels 
14325389Skarels 	putchar('<', TOLOG, (struct tty *)0);
14426356Skarels 	printn((u_long)level, 10, TOLOG, (struct tty *)0);
14525389Skarels 	putchar('>', TOLOG, (struct tty *)0);
14625389Skarels }
14725389Skarels 
14816724Sralph prf(fmt, adx, flags, ttyp)
1492781Swnj 	register char *fmt;
1502781Swnj 	register u_int *adx;
15116724Sralph 	struct tty *ttyp;
152285Sbill {
1532434Swnj 	register int b, c, i;
15431Sbill 	char *s;
1552678Swnj 	int any;
15631Sbill 
15731Sbill loop:
1582377Swnj 	while ((c = *fmt++) != '%') {
15916724Sralph 		if (c == '\0')
16031Sbill 			return;
16116724Sralph 		putchar(c, flags, ttyp);
16231Sbill 	}
1632377Swnj again:
16431Sbill 	c = *fmt++;
1652781Swnj 	/* THIS CODE IS VAX DEPENDENT IN HANDLING %l? AND %c */
1662377Swnj 	switch (c) {
1672377Swnj 
1682377Swnj 	case 'l':
1692377Swnj 		goto again;
1702377Swnj 	case 'x': case 'X':
1712377Swnj 		b = 16;
1722377Swnj 		goto number;
1732377Swnj 	case 'd': case 'D':
1742377Swnj 	case 'u':		/* what a joke */
1752377Swnj 		b = 10;
1762377Swnj 		goto number;
1772377Swnj 	case 'o': case 'O':
1782377Swnj 		b = 8;
1792377Swnj number:
18016724Sralph 		printn((u_long)*adx, b, flags, ttyp);
1812377Swnj 		break;
1822377Swnj 	case 'c':
1832434Swnj 		b = *adx;
1842434Swnj 		for (i = 24; i >= 0; i -= 8)
1852434Swnj 			if (c = (b >> i) & 0x7f)
18616724Sralph 				putchar(c, flags, ttyp);
1872377Swnj 		break;
1882678Swnj 	case 'b':
1892678Swnj 		b = *adx++;
1902678Swnj 		s = (char *)*adx;
19116724Sralph 		printn((u_long)b, *s++, flags, ttyp);
1922678Swnj 		any = 0;
1932678Swnj 		if (b) {
1942678Swnj 			while (i = *s++) {
1952678Swnj 				if (b & (1 << (i-1))) {
19617594Skarels 					putchar(any? ',' : '<', flags, ttyp);
1972678Swnj 					any = 1;
1982678Swnj 					for (; (c = *s) > 32; s++)
19916724Sralph 						putchar(c, flags, ttyp);
2002678Swnj 				} else
2012678Swnj 					for (; *s > 32; s++)
2022678Swnj 						;
2032678Swnj 			}
2043878Swnj 			if (any)
20516724Sralph 				putchar('>', flags, ttyp);
2062678Swnj 		}
2072678Swnj 		break;
2082678Swnj 
2092377Swnj 	case 's':
21031Sbill 		s = (char *)*adx;
211285Sbill 		while (c = *s++)
21216724Sralph 			putchar(c, flags, ttyp);
2132377Swnj 		break;
2143736Sroot 
2153736Sroot 	case '%':
21616724Sralph 		putchar('%', flags, ttyp);
2173736Sroot 		break;
21831Sbill 	}
21931Sbill 	adx++;
22031Sbill 	goto loop;
22131Sbill }
22231Sbill 
2232781Swnj /*
2242781Swnj  * Printn prints a number n in base b.
2252781Swnj  * We don't use recursion to avoid deep kernel stacks.
2262781Swnj  */
22716724Sralph printn(n, b, flags, ttyp)
2283101Swnj 	u_long n;
22916724Sralph 	struct tty *ttyp;
23031Sbill {
2312434Swnj 	char prbuf[11];
2322377Swnj 	register char *cp;
23331Sbill 
2342377Swnj 	if (b == 10 && (int)n < 0) {
23516724Sralph 		putchar('-', flags, ttyp);
2362377Swnj 		n = (unsigned)(-(int)n);
23731Sbill 	}
2382434Swnj 	cp = prbuf;
2392377Swnj 	do {
2402377Swnj 		*cp++ = "0123456789abcdef"[n%b];
2412377Swnj 		n /= b;
2422377Swnj 	} while (n);
2432377Swnj 	do
24416724Sralph 		putchar(*--cp, flags, ttyp);
2452434Swnj 	while (cp > prbuf);
24631Sbill }
24731Sbill 
24831Sbill /*
2491184Sbill  * Panic is called on unresolvable fatal errors.
2502781Swnj  * It prints "panic: mesg", and then reboots.
2512781Swnj  * If we are called twice, then we avoid trying to
2522781Swnj  * sync the disks as this often leads to recursive panics.
25331Sbill  */
25431Sbill panic(s)
2552781Swnj 	char *s;
25631Sbill {
2575416Swnj 	int bootopt = RB_AUTOBOOT;
2582377Swnj 
2595416Swnj 	if (panicstr)
2605416Swnj 		bootopt |= RB_NOSYNC;
2619758Ssam 	else {
2629758Ssam 		panicstr = s;
2638950Sroot 	}
2643285Swnj 	printf("panic: %s\n", s);
2652781Swnj 	boot(RB_PANIC, bootopt);
26631Sbill }
26731Sbill 
26831Sbill /*
2692941Swnj  * Warn that a system table is full.
2702941Swnj  */
2712941Swnj tablefull(tab)
2722941Swnj 	char *tab;
2732941Swnj {
2742941Swnj 
27524839Seric 	log(LOG_ERR, "%s: table is full\n", tab);
2762941Swnj }
2772941Swnj 
2782941Swnj /*
2792781Swnj  * Hard error is the preface to plaintive error messages
2802941Swnj  * about failing disk transfers.
2812781Swnj  */
2822941Swnj harderr(bp, cp)
2832678Swnj 	struct buf *bp;
2842941Swnj 	char *cp;
28531Sbill {
28631Sbill 
2872941Swnj 	printf("%s%d%c: hard error sn%d ", cp,
28824759Skarels 	    minor(bp->b_dev) >> 3, 'a'+(minor(bp->b_dev)&07), bp->b_blkno);
28931Sbill }
2902781Swnj 
291285Sbill /*
2922377Swnj  * Print a character on console or users terminal.
293285Sbill  * If destination is console then the last MSGBUFS characters
294285Sbill  * are saved in msgbuf for inspection later.
295285Sbill  */
2961785Sbill /*ARGSUSED*/
29717594Skarels putchar(c, flags, tp)
2982377Swnj 	register int c;
29917594Skarels 	struct tty *tp;
300285Sbill {
301285Sbill 
30216724Sralph 	if (flags & TOTTY) {
30325389Skarels 		register s = spltty();
30425389Skarels 
30525389Skarels 		if (tp && (tp->t_state & (TS_CARR_ON | TS_ISOPEN)) ==
30625389Skarels 		    (TS_CARR_ON | TS_ISOPEN)) {
3072377Swnj 			if (c == '\n')
3084970Swnj 				(void) ttyoutput('\r', tp);
3094970Swnj 			(void) ttyoutput(c, tp);
3102360Skre 			ttstart(tp);
3112360Skre 		}
31225389Skarels 		splx(s);
3132360Skre 	}
31416724Sralph 	if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177
3158966Sroot #ifdef vax
3168950Sroot 	    && mfpr(MAPEN)
3178950Sroot #endif
3188950Sroot 	    ) {
3192172Swnj 		if (msgbuf.msg_magic != MSG_MAGIC) {
32012494Ssam 			register int i;
32112494Ssam 
3222172Swnj 			msgbuf.msg_magic = MSG_MAGIC;
32316724Sralph 			msgbuf.msg_bufx = msgbuf.msg_bufr = 0;
32412494Ssam 			for (i=0; i < MSG_BSIZE; i++)
32512494Ssam 				msgbuf.msg_bufc[i] = 0;
3262172Swnj 		}
327*26427Sbloom 		msgbuf.msg_bufc[msgbuf.msg_bufx++] = c;
3282172Swnj 		if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE)
3292172Swnj 			msgbuf.msg_bufx = 0;
330285Sbill 	}
33116724Sralph 	if ((flags & TOCONS) && c != '\0')
33216724Sralph 		cnputc(c);
333285Sbill }
334