xref: /csrg-svn/sys/kern/subr_prf.c (revision 17577)
1 /*	subr_prf.c	6.4	84/12/21	*/
2 
3 #include "param.h"
4 #include "systm.h"
5 #include "seg.h"
6 #include "buf.h"
7 #include "conf.h"
8 #include "reboot.h"
9 #include "vm.h"
10 #include "msgbuf.h"
11 #include "dir.h"
12 #include "user.h"
13 #include "proc.h"
14 #include "ioctl.h"
15 #include "tty.h"
16 
17 #ifdef vax
18 #include "../vax/mtpr.h"
19 #endif
20 
21 #define TOCONS	0x1
22 #define TOTTY	0x2
23 #define TOLOG	0x4
24 
25 /*
26  * In case console is off,
27  * panicstr contains argument to last
28  * call to panic.
29  */
30 char	*panicstr;
31 
32 /*
33  * Scaled down version of C Library printf.
34  * Used to print diagnostic information directly on console tty.
35  * Since it is not interrupt driven, all system activities are
36  * suspended.  Printf should not be used for chit-chat.
37  *
38  * One additional format: %b is supported to decode error registers.
39  * Usage is:
40  *	printf("reg=%b\n", regval, "<base><arg>*");
41  * Where <base> is the output base expressed as a control character,
42  * e.g. \10 gives octal; \20 gives hex.  Each arg is a sequence of
43  * characters, the first of which gives the bit number to be inspected
44  * (origin 1), and the next characters (up to a control character, i.e.
45  * a character <= 32), give the name of the register.  Thus
46  *	printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
47  * would produce output:
48  *	reg=2<BITTWO,BITONE>
49  */
50 /*VARARGS1*/
51 printf(fmt, x1)
52 	char *fmt;
53 	unsigned x1;
54 {
55 
56 	prf(fmt, &x1, TOCONS | TOLOG, (struct tty *)0);
57 	logwakeup();
58 }
59 
60 /*
61  * Uprintf prints to the current user's terminal,
62  * guarantees not to sleep (so can be called by interrupt routines)
63  * and does no watermark checking - (so no verbose messages).
64  */
65 /*VARARGS1*/
66 uprintf(fmt, x1)
67 	char *fmt;
68 	unsigned x1;
69 {
70 
71 	prf(fmt, &x1, TOTTY, u.u_ttyp);
72 }
73 
74 /*VARARGS2*/
75 tprintf(ttyp, fmt, x1)
76 	struct tty *ttyp;
77 	char *fmt;
78 	unsigned x1;
79 {
80 
81 	prf(fmt, &x1, TOTTY, ttyp);
82 }
83 
84 /*
85  * Log writes to the log buffer,
86  * guarantees not to sleep (so can be called by interrupt routines)
87  * and does no watermark checking - (so no verbose messages).
88  */
89 /*VARARGS2*/
90 log(level, fmt, x1)
91 	char *fmt;
92 	unsigned x1;
93 {
94 	register s = splhigh();
95 
96 	putchar('<', TOLOG, (struct tty *)0);
97 	printn(level, 10, TOLOG, (struct tty *)0);
98 	putchar('>', TOLOG, (struct tty *)0);
99 	prf(fmt, &x1, TOLOG, (struct tty *)0);
100 	splx(s);
101 	logwakeup();
102 }
103 
104 prf(fmt, adx, flags, ttyp)
105 	register char *fmt;
106 	register u_int *adx;
107 	struct tty *ttyp;
108 {
109 	register int b, c, i;
110 	char *s;
111 	int any;
112 
113 loop:
114 	while ((c = *fmt++) != '%') {
115 		if (c == '\0')
116 			return;
117 		putchar(c, flags, ttyp);
118 	}
119 again:
120 	c = *fmt++;
121 	/* THIS CODE IS VAX DEPENDENT IN HANDLING %l? AND %c */
122 	switch (c) {
123 
124 	case 'l':
125 		goto again;
126 	case 'x': case 'X':
127 		b = 16;
128 		goto number;
129 	case 'd': case 'D':
130 	case 'u':		/* what a joke */
131 		b = 10;
132 		goto number;
133 	case 'o': case 'O':
134 		b = 8;
135 number:
136 		printn((u_long)*adx, b, flags, ttyp);
137 		break;
138 	case 'c':
139 		b = *adx;
140 		for (i = 24; i >= 0; i -= 8)
141 			if (c = (b >> i) & 0x7f)
142 				putchar(c, flags, ttyp);
143 		break;
144 	case 'b':
145 		b = *adx++;
146 		s = (char *)*adx;
147 		printn((u_long)b, *s++, flags, ttyp);
148 		any = 0;
149 		if (b) {
150 			putchar('<', flags, ttyp);
151 			while (i = *s++) {
152 				if (b & (1 << (i-1))) {
153 					if (any)
154 						putchar(',', flags, ttyp);
155 					any = 1;
156 					for (; (c = *s) > 32; s++)
157 						putchar(c, flags, ttyp);
158 				} else
159 					for (; *s > 32; s++)
160 						;
161 			}
162 			if (any)
163 				putchar('>', flags, ttyp);
164 		}
165 		break;
166 
167 	case 's':
168 		s = (char *)*adx;
169 		while (c = *s++)
170 			putchar(c, flags, ttyp);
171 		break;
172 
173 	case '%':
174 		putchar('%', flags, ttyp);
175 		break;
176 	}
177 	adx++;
178 	goto loop;
179 }
180 
181 /*
182  * Printn prints a number n in base b.
183  * We don't use recursion to avoid deep kernel stacks.
184  */
185 printn(n, b, flags, ttyp)
186 	u_long n;
187 	struct tty *ttyp;
188 {
189 	char prbuf[11];
190 	register char *cp;
191 
192 	if (b == 10 && (int)n < 0) {
193 		putchar('-', flags, ttyp);
194 		n = (unsigned)(-(int)n);
195 	}
196 	cp = prbuf;
197 	do {
198 		*cp++ = "0123456789abcdef"[n%b];
199 		n /= b;
200 	} while (n);
201 	do
202 		putchar(*--cp, flags, ttyp);
203 	while (cp > prbuf);
204 }
205 
206 /*
207  * Panic is called on unresolvable fatal errors.
208  * It prints "panic: mesg", and then reboots.
209  * If we are called twice, then we avoid trying to
210  * sync the disks as this often leads to recursive panics.
211  */
212 panic(s)
213 	char *s;
214 {
215 	int bootopt = RB_AUTOBOOT;
216 
217 	if (panicstr)
218 		bootopt |= RB_NOSYNC;
219 	else {
220 		panicstr = s;
221 	}
222 	printf("panic: %s\n", s);
223 	boot(RB_PANIC, bootopt);
224 }
225 
226 /*
227  * Warn that a system table is full.
228  */
229 tablefull(tab)
230 	char *tab;
231 {
232 
233 	printf("%s: table is full\n", tab);
234 }
235 
236 /*
237  * Hard error is the preface to plaintive error messages
238  * about failing disk transfers.
239  */
240 harderr(bp, cp)
241 	struct buf *bp;
242 	char *cp;
243 {
244 
245 	printf("%s%d%c: hard error sn%d ", cp,
246 	    dkunit(bp), 'a'+(minor(bp->b_dev)&07), bp->b_blkno);
247 }
248 
249 /*
250  * Print a character on console or users terminal.
251  * If destination is console then the last MSGBUFS characters
252  * are saved in msgbuf for inspection later.
253  */
254 /*ARGSUSED*/
255 putchar(c, flags, ttyp)
256 	register int c;
257 	struct tty *ttyp;
258 {
259 
260 	if (flags & TOTTY) {
261 		register struct tty *tp = ttyp;
262 
263 		if (tp && (tp->t_state & TS_CARR_ON)) {
264 			register s = spl6();
265 			if (c == '\n')
266 				(void) ttyoutput('\r', tp);
267 			(void) ttyoutput(c, tp);
268 			ttstart(tp);
269 			splx(s);
270 		}
271 	}
272 	if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177
273 #ifdef vax
274 	    && mfpr(MAPEN)
275 #endif
276 	    ) {
277 		if (msgbuf.msg_magic != MSG_MAGIC) {
278 			register int i;
279 
280 			msgbuf.msg_magic = MSG_MAGIC;
281 			msgbuf.msg_bufx = msgbuf.msg_bufr = 0;
282 			for (i=0; i < MSG_BSIZE; i++)
283 				msgbuf.msg_bufc[i] = 0;
284 		}
285 		if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE)
286 			msgbuf.msg_bufx = 0;
287 		msgbuf.msg_bufc[msgbuf.msg_bufx++] = c;
288 	}
289 	if ((flags & TOCONS) && c != '\0')
290 		cnputc(c);
291 }
292