xref: /csrg-svn/sys/kern/subr_prf.c (revision 37496)
123381Smckusick /*
234420Skarels  * Copyright (c) 1982, 1986, 1988 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*37496Smckusick  *	@(#)subr_prf.c	7.13 (Berkeley) 04/25/89
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 
24*37496Smckusick #include "machine/mtpr.h"
2535282Skarels #ifdef KADB
26*37496Smckusick #include "machine/kdbparam.h"
2730625Skarels #endif
2830625Skarels 
2916724Sralph #define TOCONS	0x1
3016724Sralph #define TOTTY	0x2
3116724Sralph #define TOLOG	0x4
3216724Sralph 
3331Sbill /*
3431Sbill  * In case console is off,
3531Sbill  * panicstr contains argument to last
3631Sbill  * call to panic.
3731Sbill  */
3831Sbill char	*panicstr;
3931Sbill 
4030549Skarels extern	cnputc();			/* standard console putc */
4130549Skarels extern	struct tty cons;		/* standard console tty */
4230549Skarels struct	tty *constty;			/* pointer to console "window" tty */
4330549Skarels int	(*v_putc)() = cnputc;		/* routine to putc on virtual console */
4430549Skarels 
4531Sbill /*
4631Sbill  * Scaled down version of C Library printf.
472781Swnj  * Used to print diagnostic information directly on console tty.
482781Swnj  * Since it is not interrupt driven, all system activities are
492781Swnj  * suspended.  Printf should not be used for chit-chat.
502781Swnj  *
512781Swnj  * One additional format: %b is supported to decode error registers.
522781Swnj  * Usage is:
532781Swnj  *	printf("reg=%b\n", regval, "<base><arg>*");
542781Swnj  * Where <base> is the output base expressed as a control character,
552781Swnj  * e.g. \10 gives octal; \20 gives hex.  Each arg is a sequence of
562781Swnj  * characters, the first of which gives the bit number to be inspected
572781Swnj  * (origin 1), and the next characters (up to a control character, i.e.
582781Swnj  * a character <= 32), give the name of the register.  Thus
592781Swnj  *	printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
602781Swnj  * would produce output:
6117594Skarels  *	reg=3<BITTWO,BITONE>
6234478Skarels  *
6334478Skarels  * Another additional format: %r is used to pass an additional format string
6434478Skarels  * and argument list recursively.  Usage is typically:
6534478Skarels  *
6634478Skarels  * fn(otherstuff, fmt [, arg1, ... ] )
6734478Skarels  *	char *fmt;
6834478Skarels  *	u_int arg1, ...;
6934478Skarels  *
7034478Skarels  *	printf("prefix: %r, other stuff\n", fmt, &arg1);
7131Sbill  */
7229946Skarels #if defined(tahoe)
7329946Skarels int	consintr;
7429946Skarels #endif
7529946Skarels 
7631Sbill /*VARARGS1*/
7731Sbill printf(fmt, x1)
782781Swnj 	char *fmt;
792781Swnj 	unsigned x1;
8031Sbill {
8129946Skarels #if defined(tahoe)
8229946Skarels 	register int savintr;
83285Sbill 
8429946Skarels 	savintr = consintr, consintr = 0;	/* disable interrupts */
8529946Skarels #endif
8616724Sralph 	prf(fmt, &x1, TOCONS | TOLOG, (struct tty *)0);
8716724Sralph 	logwakeup();
8829946Skarels #if defined(tahoe)
8929946Skarels 	consintr = savintr;			/* reenable interrupts */
9029946Skarels #endif
91285Sbill }
92285Sbill 
932377Swnj /*
9425389Skarels  * Uprintf prints to the current user's terminal.
9525389Skarels  * It may block if the tty queue is overfull.
9630695Skarels  * No message is printed if the queue does not clear
9730695Skarels  * in a reasonable time.
9825389Skarels  * Should determine whether current terminal user is related
9925389Skarels  * to this process.
1002377Swnj  */
1012377Swnj /*VARARGS1*/
1022377Swnj uprintf(fmt, x1)
1032781Swnj 	char *fmt;
1042377Swnj 	unsigned x1;
105285Sbill {
10626250Skarels #ifdef notdef
10725389Skarels 	register struct proc *p;
10826250Skarels #endif
10925389Skarels 	register struct tty *tp;
110285Sbill 
11125389Skarels 	if ((tp = u.u_ttyp) == NULL)
11225389Skarels 		return;
11325389Skarels #ifdef notdef
11425389Skarels 	if (tp->t_pgrp && (p = pfind(tp->t_pgrp)))
11526250Skarels 		if (p->p_uid != u.u_uid)	/* doesn't account for setuid */
11625389Skarels 			return;
11725389Skarels #endif
11830695Skarels 	if (ttycheckoutq(tp, 1))
11930695Skarels 		prf(fmt, &x1, TOTTY, tp);
120285Sbill }
121285Sbill 
12218364Skarels /*
12318364Skarels  * tprintf prints on the specified terminal (console if none)
12418364Skarels  * and logs the message.  It is designed for error messages from
12525389Skarels  * single-open devices, and may be called from interrupt level
12625389Skarels  * (does not sleep).
12718364Skarels  */
12816724Sralph /*VARARGS2*/
12925389Skarels tprintf(tp, fmt, x1)
13025389Skarels 	register struct tty *tp;
13116724Sralph 	char *fmt;
13216724Sralph 	unsigned x1;
13316724Sralph {
13425389Skarels 	int flags = TOTTY | TOLOG;
13516724Sralph 
13625389Skarels 	logpri(LOG_INFO);
13729946Skarels 	if (tp == (struct tty *)NULL)
13829946Skarels 		tp = &cons;
13925389Skarels 	if (ttycheckoutq(tp, 0) == 0)
14025389Skarels 		flags = TOLOG;
14125389Skarels 	prf(fmt, &x1, flags, tp);
14225389Skarels 	logwakeup();
14316724Sralph }
14416724Sralph 
14516724Sralph /*
14616724Sralph  * Log writes to the log buffer,
14717594Skarels  * and guarantees not to sleep (so can be called by interrupt routines).
14818364Skarels  * If there is no process reading the log yet, it writes to the console also.
14916724Sralph  */
15016724Sralph /*VARARGS2*/
15116724Sralph log(level, fmt, x1)
15216724Sralph 	char *fmt;
15316724Sralph 	unsigned x1;
15416724Sralph {
15516724Sralph 	register s = splhigh();
15618364Skarels 	extern int log_open;
15716724Sralph 
15825389Skarels 	logpri(level);
15916724Sralph 	prf(fmt, &x1, TOLOG, (struct tty *)0);
16016724Sralph 	splx(s);
16118364Skarels 	if (!log_open)
16218364Skarels 		prf(fmt, &x1, TOCONS, (struct tty *)0);
16316724Sralph 	logwakeup();
16416724Sralph }
16516724Sralph 
16625389Skarels logpri(level)
16725389Skarels 	int level;
16825389Skarels {
16925389Skarels 
17025389Skarels 	putchar('<', TOLOG, (struct tty *)0);
17126356Skarels 	printn((u_long)level, 10, TOLOG, (struct tty *)0);
17225389Skarels 	putchar('>', TOLOG, (struct tty *)0);
17325389Skarels }
17425389Skarels 
17533479Skarels /*VARARGS1*/
17633479Skarels addlog(fmt, x1)
17733479Skarels 	char *fmt;
17833479Skarels 	unsigned x1;
17933479Skarels {
18033479Skarels 	register s = splhigh();
18133479Skarels 
18233479Skarels 	prf(fmt, &x1, TOLOG, (struct tty *)0);
18333479Skarels 	splx(s);
18433479Skarels 	if (!log_open)
18533479Skarels 		prf(fmt, &x1, TOCONS, (struct tty *)0);
18633479Skarels 	logwakeup();
18733479Skarels }
18833479Skarels 
18916724Sralph prf(fmt, adx, flags, ttyp)
1902781Swnj 	register char *fmt;
1912781Swnj 	register u_int *adx;
19216724Sralph 	struct tty *ttyp;
193285Sbill {
1942434Swnj 	register int b, c, i;
19531Sbill 	char *s;
1962678Swnj 	int any;
19731Sbill 
19831Sbill loop:
1992377Swnj 	while ((c = *fmt++) != '%') {
20016724Sralph 		if (c == '\0')
20131Sbill 			return;
20216724Sralph 		putchar(c, flags, ttyp);
20331Sbill 	}
2042377Swnj again:
20531Sbill 	c = *fmt++;
20629946Skarels 	/* THIS CODE IS MACHINE DEPENDENT IN HANDLING %l? AND %c */
2072377Swnj 	switch (c) {
2082377Swnj 
2092377Swnj 	case 'l':
2102377Swnj 		goto again;
2112377Swnj 	case 'x': case 'X':
2122377Swnj 		b = 16;
2132377Swnj 		goto number;
2142377Swnj 	case 'd': case 'D':
21529946Skarels 		b = -10;
21629946Skarels 		goto number;
21729946Skarels 	case 'u':
2182377Swnj 		b = 10;
2192377Swnj 		goto number;
2202377Swnj 	case 'o': case 'O':
2212377Swnj 		b = 8;
2222377Swnj number:
22316724Sralph 		printn((u_long)*adx, b, flags, ttyp);
2242377Swnj 		break;
2252377Swnj 	case 'c':
2262434Swnj 		b = *adx;
22733479Skarels #if BYTE_ORDER == LITTLE_ENDIAN
2282434Swnj 		for (i = 24; i >= 0; i -= 8)
2292434Swnj 			if (c = (b >> i) & 0x7f)
23016724Sralph 				putchar(c, flags, ttyp);
23129946Skarels #endif
23233479Skarels #if BYTE_ORDER == BIG_ENDIAN
23329946Skarels 		if (c = (b & 0x7f))
23429946Skarels 			putchar(c, flags, ttyp);
23529946Skarels #endif
2362377Swnj 		break;
2372678Swnj 	case 'b':
2382678Swnj 		b = *adx++;
2392678Swnj 		s = (char *)*adx;
24016724Sralph 		printn((u_long)b, *s++, flags, ttyp);
2412678Swnj 		any = 0;
2422678Swnj 		if (b) {
2432678Swnj 			while (i = *s++) {
2442678Swnj 				if (b & (1 << (i-1))) {
24529946Skarels 					putchar(any ? ',' : '<', flags, ttyp);
2462678Swnj 					any = 1;
2472678Swnj 					for (; (c = *s) > 32; s++)
24816724Sralph 						putchar(c, flags, ttyp);
2492678Swnj 				} else
2502678Swnj 					for (; *s > 32; s++)
2512678Swnj 						;
2522678Swnj 			}
2533878Swnj 			if (any)
25416724Sralph 				putchar('>', flags, ttyp);
2552678Swnj 		}
2562678Swnj 		break;
2572678Swnj 
2582377Swnj 	case 's':
25931Sbill 		s = (char *)*adx;
260285Sbill 		while (c = *s++)
26116724Sralph 			putchar(c, flags, ttyp);
2622377Swnj 		break;
2633736Sroot 
26433479Skarels 	case 'r':
26533479Skarels 		s = (char *)*adx++;
26634478Skarels 		prf(s, (u_int *)*adx, flags, ttyp);
26733479Skarels 		break;
26833479Skarels 
2693736Sroot 	case '%':
27016724Sralph 		putchar('%', flags, ttyp);
2713736Sroot 		break;
27231Sbill 	}
27331Sbill 	adx++;
27431Sbill 	goto loop;
27531Sbill }
27631Sbill 
2772781Swnj /*
2782781Swnj  * Printn prints a number n in base b.
2792781Swnj  * We don't use recursion to avoid deep kernel stacks.
2802781Swnj  */
28116724Sralph printn(n, b, flags, ttyp)
2823101Swnj 	u_long n;
28316724Sralph 	struct tty *ttyp;
28431Sbill {
2852434Swnj 	char prbuf[11];
2862377Swnj 	register char *cp;
28731Sbill 
28829946Skarels 	if (b == -10) {
28929946Skarels 		if ((int)n < 0) {
29029946Skarels 			putchar('-', flags, ttyp);
29129946Skarels 			n = (unsigned)(-(int)n);
29229946Skarels 		}
29329946Skarels 		b = -b;
29431Sbill 	}
2952434Swnj 	cp = prbuf;
2962377Swnj 	do {
2972377Swnj 		*cp++ = "0123456789abcdef"[n%b];
2982377Swnj 		n /= b;
2992377Swnj 	} while (n);
3002377Swnj 	do
30116724Sralph 		putchar(*--cp, flags, ttyp);
3022434Swnj 	while (cp > prbuf);
30331Sbill }
30431Sbill 
30531Sbill /*
3061184Sbill  * Panic is called on unresolvable fatal errors.
3072781Swnj  * It prints "panic: mesg", and then reboots.
3082781Swnj  * If we are called twice, then we avoid trying to
3092781Swnj  * sync the disks as this often leads to recursive panics.
31031Sbill  */
31131Sbill panic(s)
3122781Swnj 	char *s;
31331Sbill {
31430566Skarels 	int bootopt = RB_AUTOBOOT | RB_DUMP;
3152377Swnj 
3165416Swnj 	if (panicstr)
3175416Swnj 		bootopt |= RB_NOSYNC;
3189758Ssam 	else {
3199758Ssam 		panicstr = s;
3208950Sroot 	}
3213285Swnj 	printf("panic: %s\n", s);
32235282Skarels #ifdef KADB
32330625Skarels 	if (boothowto & RB_KDB) {
32434420Skarels 		int x = splnet();	/* below kdb pri */
32530625Skarels 
32630625Skarels 		setsoftkdb();
32734420Skarels 		splx(x);
32830625Skarels 	}
32930625Skarels #endif
33030566Skarels 	boot(bootopt);
33131Sbill }
33231Sbill 
33331Sbill /*
3342941Swnj  * Warn that a system table is full.
3352941Swnj  */
3362941Swnj tablefull(tab)
3372941Swnj 	char *tab;
3382941Swnj {
3392941Swnj 
34024839Seric 	log(LOG_ERR, "%s: table is full\n", tab);
3412941Swnj }
3422941Swnj 
3432941Swnj /*
3442377Swnj  * Print a character on console or users terminal.
345285Sbill  * If destination is console then the last MSGBUFS characters
346285Sbill  * are saved in msgbuf for inspection later.
347285Sbill  */
3481785Sbill /*ARGSUSED*/
34917594Skarels putchar(c, flags, tp)
3502377Swnj 	register int c;
35117594Skarels 	struct tty *tp;
352285Sbill {
35333479Skarels 	extern int msgbufmapped;
354285Sbill 
35530549Skarels 	if (panicstr)
35630549Skarels 		constty = 0;
35730549Skarels 	if ((flags & TOCONS) && tp == 0 && constty) {
35830549Skarels 		tp = constty;
35930549Skarels 		flags |= TOTTY;
36030549Skarels 	}
36116724Sralph 	if (flags & TOTTY) {
36225389Skarels 		register s = spltty();
36325389Skarels 
36425389Skarels 		if (tp && (tp->t_state & (TS_CARR_ON | TS_ISOPEN)) ==
36525389Skarels 		    (TS_CARR_ON | TS_ISOPEN)) {
3662377Swnj 			if (c == '\n')
3674970Swnj 				(void) ttyoutput('\r', tp);
3684970Swnj 			(void) ttyoutput(c, tp);
3692360Skre 			ttstart(tp);
37030549Skarels 		} else if ((flags & TOCONS) && tp == constty)
37130549Skarels 			constty = 0;
37225389Skarels 		splx(s);
3732360Skre 	}
37433479Skarels 	if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177 &&
37533479Skarels 	    msgbufmapped) {
3762172Swnj 		if (msgbuf.msg_magic != MSG_MAGIC) {
37712494Ssam 			register int i;
37812494Ssam 
3792172Swnj 			msgbuf.msg_magic = MSG_MAGIC;
38016724Sralph 			msgbuf.msg_bufx = msgbuf.msg_bufr = 0;
38112494Ssam 			for (i=0; i < MSG_BSIZE; i++)
38212494Ssam 				msgbuf.msg_bufc[i] = 0;
3832172Swnj 		}
38426427Sbloom 		msgbuf.msg_bufc[msgbuf.msg_bufx++] = c;
3852172Swnj 		if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE)
3862172Swnj 			msgbuf.msg_bufx = 0;
387285Sbill 	}
38830549Skarels 	if ((flags & TOCONS) && constty == 0 && c != '\0')
38930549Skarels 		(*v_putc)(c);
390285Sbill }
391