xref: /csrg-svn/sys/kern/subr_prf.c (revision 48426)
123381Smckusick /*
2*48426Skarels  * Copyright (c) 1982, 1986, 1988, 1991 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*48426Skarels  *	@(#)subr_prf.c	7.21 (Berkeley) 04/20/91
723381Smckusick  */
831Sbill 
917094Sbloom #include "param.h"
1017094Sbloom #include "systm.h"
1117094Sbloom #include "buf.h"
1217094Sbloom #include "conf.h"
1317094Sbloom #include "reboot.h"
1417094Sbloom #include "msgbuf.h"
1517094Sbloom #include "proc.h"
1617577Sbloom #include "ioctl.h"
1739560Smarc #include "vnode.h"
1839560Smarc #include "file.h"
1917094Sbloom #include "tty.h"
2044386Smarc #include "tprintf.h"
2118364Skarels #include "syslog.h"
2244386Smarc #include "malloc.h"
2331Sbill 
2435282Skarels #ifdef KADB
2537496Smckusick #include "machine/kdbparam.h"
2630625Skarels #endif
2730625Skarels 
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 
3930549Skarels extern	cnputc();			/* standard console putc */
4040808Smarc int	(*v_putc)() = cnputc;		/* routine to putc on virtual console */
4130549Skarels extern	struct tty cons;		/* standard console tty */
4230549Skarels struct	tty *constty;			/* pointer to console "window" tty */
4330549Skarels 
4440808Smarc #ifdef KADB
4540808Smarc extern	cngetc();			/* standard console getc */
4640808Smarc extern	cnpoll();
4740808Smarc int	(*v_getc)() = cngetc;		/* "" getc from virtual console */
4840808Smarc int	(*v_poll)() = cnpoll;		/* kdb hook to enable input polling */
4940808Smarc #endif
5040808Smarc 
5131Sbill /*
5231Sbill  * Scaled down version of C Library printf.
532781Swnj  * Used to print diagnostic information directly on console tty.
542781Swnj  * Since it is not interrupt driven, all system activities are
552781Swnj  * suspended.  Printf should not be used for chit-chat.
562781Swnj  *
572781Swnj  * One additional format: %b is supported to decode error registers.
582781Swnj  * Usage is:
592781Swnj  *	printf("reg=%b\n", regval, "<base><arg>*");
602781Swnj  * Where <base> is the output base expressed as a control character,
612781Swnj  * e.g. \10 gives octal; \20 gives hex.  Each arg is a sequence of
622781Swnj  * characters, the first of which gives the bit number to be inspected
632781Swnj  * (origin 1), and the next characters (up to a control character, i.e.
642781Swnj  * a character <= 32), give the name of the register.  Thus
652781Swnj  *	printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
662781Swnj  * would produce output:
6717594Skarels  *	reg=3<BITTWO,BITONE>
6834478Skarels  *
6934478Skarels  * Another additional format: %r is used to pass an additional format string
7034478Skarels  * and argument list recursively.  Usage is typically:
7134478Skarels  *
7234478Skarels  * fn(otherstuff, fmt [, arg1, ... ] )
7334478Skarels  *	char *fmt;
7434478Skarels  *	u_int arg1, ...;
7534478Skarels  *
7634478Skarels  *	printf("prefix: %r, other stuff\n", fmt, &arg1);
7731Sbill  */
7829946Skarels 
79*48426Skarels int	consintr = 1;			/* ok to handle console interrupts? */
80*48426Skarels 
8131Sbill /*VARARGS1*/
8247540Skarels printf(fmt, args)
832781Swnj 	char *fmt;
8447540Skarels 	unsigned args;
8531Sbill {
8629946Skarels 	register int savintr;
87285Sbill 
8829946Skarels 	savintr = consintr, consintr = 0;	/* disable interrupts */
8947540Skarels 	prf(fmt, &args, TOCONS | TOLOG, (struct tty *)NULL);
9041972Smckusick 	if (!panicstr)
9141972Smckusick 		logwakeup();
9229946Skarels 	consintr = savintr;			/* reenable interrupts */
93285Sbill }
94285Sbill 
952377Swnj /*
9639560Smarc  * Uprintf prints to the controlling terminal for the current process.
9725389Skarels  * It may block if the tty queue is overfull.
9830695Skarels  * No message is printed if the queue does not clear
9930695Skarels  * in a reasonable time.
1002377Swnj  */
1012377Swnj /*VARARGS1*/
10247540Skarels uprintf(fmt, args)
1032781Swnj 	char *fmt;
10447540Skarels 	unsigned args;
105285Sbill {
10647540Skarels 	register struct proc *p = curproc;
107285Sbill 
10844386Smarc 	if (p->p_flag & SCTTY && p->p_session->s_ttyvp)
10947540Skarels 		prf(fmt, &args, TOTTY, p->p_session->s_ttyp);
110285Sbill }
111285Sbill 
11244386Smarc tpr_t
113*48426Skarels tprintf_open(p)
114*48426Skarels 	register struct proc *p;
11544386Smarc {
11644386Smarc 
11744386Smarc 	if (p->p_flag & SCTTY && p->p_session->s_ttyvp) {
11844386Smarc 		SESSHOLD(p->p_session);
119*48426Skarels 		return ((tpr_t) p->p_session);
12044386Smarc 	} else
121*48426Skarels 		return ((tpr_t) NULL);
12244386Smarc }
12344386Smarc 
124*48426Skarels void
12544386Smarc tprintf_close(sess)
12644386Smarc 	tpr_t sess;
12744386Smarc {
12844386Smarc 	if (sess)
129*48426Skarels 		SESSRELE((struct session *) sess);
13044386Smarc }
13144386Smarc 
13218364Skarels /*
13344386Smarc  * tprintf prints on the controlling terminal associated
13444386Smarc  * with the given session.
13518364Skarels  */
13616724Sralph /*VARARGS2*/
137*48426Skarels tprintf(tpr, fmt, args)
138*48426Skarels 	tpr_t tpr;
13916724Sralph 	char *fmt;
14047540Skarels 	unsigned args;
14116724Sralph {
142*48426Skarels 	register struct session *sess = (struct session *)tpr;
143*48426Skarels 	struct tty *tp = NULL;
14444386Smarc 	int flags = TOLOG;
14516724Sralph 
14625389Skarels 	logpri(LOG_INFO);
14739560Smarc 
148*48426Skarels 	if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) {
14944386Smarc 		flags |= TOTTY;
150*48426Skarels 		tp = sess->s_ttyp;
151*48426Skarels 	}
152*48426Skarels 	prf(fmt, &args, flags, tp);
15325389Skarels 	logwakeup();
15416724Sralph }
15516724Sralph 
156*48426Skarels extern	int log_open;
15744386Smarc 
15816724Sralph /*
15916724Sralph  * Log writes to the log buffer,
16017594Skarels  * and guarantees not to sleep (so can be called by interrupt routines).
16118364Skarels  * If there is no process reading the log yet, it writes to the console also.
16216724Sralph  */
16316724Sralph /*VARARGS2*/
16447540Skarels log(level, fmt, args)
16516724Sralph 	char *fmt;
16647540Skarels 	unsigned args;
16716724Sralph {
16816724Sralph 	register s = splhigh();
16916724Sralph 
17025389Skarels 	logpri(level);
17147540Skarels 	prf(fmt, &args, TOLOG, (struct tty *)NULL);
17216724Sralph 	splx(s);
17318364Skarels 	if (!log_open)
17447540Skarels 		prf(fmt, &args, TOCONS, (struct tty *)NULL);
17516724Sralph 	logwakeup();
17616724Sralph }
17716724Sralph 
17825389Skarels logpri(level)
17925389Skarels 	int level;
18025389Skarels {
18125389Skarels 
18244386Smarc 	putchar('<', TOLOG, (struct tty *)NULL);
18344386Smarc 	printn((u_long)level, 10, TOLOG, (struct tty *)NULL);
18444386Smarc 	putchar('>', TOLOG, (struct tty *)NULL);
18525389Skarels }
18625389Skarels 
18733479Skarels /*VARARGS1*/
18847540Skarels addlog(fmt, args)
18933479Skarels 	char *fmt;
19047540Skarels 	unsigned args;
19133479Skarels {
19233479Skarels 	register s = splhigh();
19333479Skarels 
19447540Skarels 	prf(fmt, &args, TOLOG, (struct tty *)NULL);
19533479Skarels 	splx(s);
19633479Skarels 	if (!log_open)
19747540Skarels 		prf(fmt, &args, TOCONS, (struct tty *)NULL);
19833479Skarels 	logwakeup();
19933479Skarels }
20033479Skarels 
20147540Skarels prf(fmt, argp, flags, ttyp)
2022781Swnj 	register char *fmt;
20347540Skarels 	register u_int *argp;
20444386Smarc 	struct tty *ttyp;
205285Sbill {
2062434Swnj 	register int b, c, i;
20731Sbill 	char *s;
2082678Swnj 	int any;
20931Sbill 
21031Sbill loop:
2112377Swnj 	while ((c = *fmt++) != '%') {
21216724Sralph 		if (c == '\0')
21331Sbill 			return;
21444386Smarc 		putchar(c, flags, ttyp);
21531Sbill 	}
2162377Swnj again:
21731Sbill 	c = *fmt++;
21829946Skarels 	/* THIS CODE IS MACHINE DEPENDENT IN HANDLING %l? AND %c */
2192377Swnj 	switch (c) {
2202377Swnj 
2212377Swnj 	case 'l':
2222377Swnj 		goto again;
2232377Swnj 	case 'x': case 'X':
2242377Swnj 		b = 16;
2252377Swnj 		goto number;
2262377Swnj 	case 'd': case 'D':
22729946Skarels 		b = -10;
22829946Skarels 		goto number;
22929946Skarels 	case 'u':
2302377Swnj 		b = 10;
2312377Swnj 		goto number;
2322377Swnj 	case 'o': case 'O':
2332377Swnj 		b = 8;
2342377Swnj number:
23547540Skarels 		printn((u_long)*argp, b, flags, ttyp);
2362377Swnj 		break;
2372377Swnj 	case 'c':
23847540Skarels 		b = *argp;
23933479Skarels #if BYTE_ORDER == LITTLE_ENDIAN
2402434Swnj 		for (i = 24; i >= 0; i -= 8)
2412434Swnj 			if (c = (b >> i) & 0x7f)
24244386Smarc 				putchar(c, flags, ttyp);
24329946Skarels #endif
24433479Skarels #if BYTE_ORDER == BIG_ENDIAN
24529946Skarels 		if (c = (b & 0x7f))
24644386Smarc 			putchar(c, flags, ttyp);
24729946Skarels #endif
2482377Swnj 		break;
2492678Swnj 	case 'b':
25047540Skarels 		b = *argp++;
25147540Skarels 		s = (char *)*argp;
25244386Smarc 		printn((u_long)b, *s++, flags, ttyp);
2532678Swnj 		any = 0;
2542678Swnj 		if (b) {
2552678Swnj 			while (i = *s++) {
2562678Swnj 				if (b & (1 << (i-1))) {
25744386Smarc 					putchar(any ? ',' : '<', flags, ttyp);
2582678Swnj 					any = 1;
2592678Swnj 					for (; (c = *s) > 32; s++)
26044386Smarc 						putchar(c, flags, ttyp);
2612678Swnj 				} else
2622678Swnj 					for (; *s > 32; s++)
2632678Swnj 						;
2642678Swnj 			}
2653878Swnj 			if (any)
26644386Smarc 				putchar('>', flags, ttyp);
2672678Swnj 		}
2682678Swnj 		break;
2692678Swnj 
2702377Swnj 	case 's':
27147540Skarels 		s = (char *)*argp;
272285Sbill 		while (c = *s++)
27344386Smarc 			putchar(c, flags, ttyp);
2742377Swnj 		break;
2753736Sroot 
27633479Skarels 	case 'r':
27747540Skarels 		s = (char *)*argp++;
27847540Skarels 		prf(s, (u_int *)*argp, flags, ttyp);
27933479Skarels 		break;
28033479Skarels 
2813736Sroot 	case '%':
28244386Smarc 		putchar('%', flags, ttyp);
2833736Sroot 		break;
28431Sbill 	}
28547540Skarels 	argp++;
28631Sbill 	goto loop;
28731Sbill }
28831Sbill 
2892781Swnj /*
2902781Swnj  * Printn prints a number n in base b.
29147540Skarels  * We avoid recursion to avoid deep kernel stacks.
2922781Swnj  */
29344386Smarc printn(n, b, flags, ttyp)
2943101Swnj 	u_long n;
29544386Smarc 	struct tty *ttyp;
29631Sbill {
2972434Swnj 	char prbuf[11];
2982377Swnj 	register char *cp;
29931Sbill 
30029946Skarels 	if (b == -10) {
30129946Skarels 		if ((int)n < 0) {
30244386Smarc 			putchar('-', flags, ttyp);
30329946Skarels 			n = (unsigned)(-(int)n);
30429946Skarels 		}
30529946Skarels 		b = -b;
30631Sbill 	}
3072434Swnj 	cp = prbuf;
3082377Swnj 	do {
3092377Swnj 		*cp++ = "0123456789abcdef"[n%b];
3102377Swnj 		n /= b;
3112377Swnj 	} while (n);
3122377Swnj 	do
31344386Smarc 		putchar(*--cp, flags, ttyp);
3142434Swnj 	while (cp > prbuf);
31531Sbill }
31631Sbill 
31731Sbill /*
3181184Sbill  * Panic is called on unresolvable fatal errors.
3192781Swnj  * It prints "panic: mesg", and then reboots.
3202781Swnj  * If we are called twice, then we avoid trying to
3212781Swnj  * sync the disks as this often leads to recursive panics.
32231Sbill  */
32331Sbill panic(s)
3242781Swnj 	char *s;
32531Sbill {
32630566Skarels 	int bootopt = RB_AUTOBOOT | RB_DUMP;
3272377Swnj 
3285416Swnj 	if (panicstr)
3295416Swnj 		bootopt |= RB_NOSYNC;
33047540Skarels 	else
3319758Ssam 		panicstr = s;
3323285Swnj 	printf("panic: %s\n", s);
33347540Skarels #ifdef KGDB
33447540Skarels 	kgdb_panic();
33547540Skarels #endif
33635282Skarels #ifdef KADB
33730625Skarels 	if (boothowto & RB_KDB) {
33834420Skarels 		int x = splnet();	/* below kdb pri */
33930625Skarels 
34030625Skarels 		setsoftkdb();
34134420Skarels 		splx(x);
34230625Skarels 	}
34330625Skarels #endif
34430566Skarels 	boot(bootopt);
34531Sbill }
34631Sbill 
34731Sbill /*
3482941Swnj  * Warn that a system table is full.
3492941Swnj  */
3502941Swnj tablefull(tab)
3512941Swnj 	char *tab;
3522941Swnj {
3532941Swnj 
35424839Seric 	log(LOG_ERR, "%s: table is full\n", tab);
3552941Swnj }
3562941Swnj 
3572941Swnj /*
3582377Swnj  * Print a character on console or users terminal.
359285Sbill  * If destination is console then the last MSGBUFS characters
360285Sbill  * are saved in msgbuf for inspection later.
361285Sbill  */
3621785Sbill /*ARGSUSED*/
36344386Smarc putchar(c, flags, ttyp)
3642377Swnj 	register int c;
36544386Smarc 	struct tty *ttyp;
366285Sbill {
36745733Smckusick 	register struct msgbuf *mbp = msgbufp;
36833479Skarels 	extern int msgbufmapped;
369285Sbill 
37030549Skarels 	if (panicstr)
37130549Skarels 		constty = 0;
37244386Smarc 	if ((flags & TOCONS) && ttyp == NULL && constty) {
37344386Smarc 		ttyp = constty;
37430549Skarels 		flags |= TOTTY;
37530549Skarels 	}
37644386Smarc 	if ((flags & TOTTY) && ttyp && tputchar(c, ttyp) < 0 &&
37744386Smarc 	    (flags & TOCONS) && ttyp == constty)
37839560Smarc 		constty = 0;
37933479Skarels 	if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177 &&
38033479Skarels 	    msgbufmapped) {
38145733Smckusick 		if (mbp->msg_magic != MSG_MAGIC) {
38212494Ssam 			register int i;
38312494Ssam 
38445733Smckusick 			mbp->msg_magic = MSG_MAGIC;
38545733Smckusick 			mbp->msg_bufx = mbp->msg_bufr = 0;
38612494Ssam 			for (i=0; i < MSG_BSIZE; i++)
38745733Smckusick 				mbp->msg_bufc[i] = 0;
3882172Swnj 		}
38945733Smckusick 		mbp->msg_bufc[mbp->msg_bufx++] = c;
39045733Smckusick 		if (mbp->msg_bufx < 0 || mbp->msg_bufx >= MSG_BSIZE)
39145733Smckusick 			mbp->msg_bufx = 0;
392285Sbill 	}
39330549Skarels 	if ((flags & TOCONS) && constty == 0 && c != '\0')
39430549Skarels 		(*v_putc)(c);
395285Sbill }
396