xref: /csrg-svn/sys/kern/subr_prf.c (revision 17594)
1 /*	subr_prf.c	6.5	84/12/27	*/
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=3<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  * and does no watermark checking - (so no verbose messages).
63  */
64 /*VARARGS1*/
65 uprintf(fmt, x1)
66 	char *fmt;
67 	unsigned x1;
68 {
69 
70 	prf(fmt, &x1, TOTTY, u.u_ttyp);
71 }
72 
73 /*VARARGS2*/
74 tprintf(ttyp, fmt, x1)
75 	struct tty *ttyp;
76 	char *fmt;
77 	unsigned x1;
78 {
79 
80 	prf(fmt, &x1, TOTTY, ttyp);
81 }
82 
83 /*
84  * Log writes to the log buffer,
85  * and guarantees not to sleep (so can be called by interrupt routines).
86  */
87 /*VARARGS2*/
88 log(level, fmt, x1)
89 	char *fmt;
90 	unsigned x1;
91 {
92 	register s = splhigh();
93 
94 	putchar('<', TOLOG, (struct tty *)0);
95 	printn(level, 10, TOLOG, (struct tty *)0);
96 	putchar('>', TOLOG, (struct tty *)0);
97 	prf(fmt, &x1, TOLOG, (struct tty *)0);
98 	splx(s);
99 	logwakeup();
100 }
101 
102 prf(fmt, adx, flags, ttyp)
103 	register char *fmt;
104 	register u_int *adx;
105 	struct tty *ttyp;
106 {
107 	register int b, c, i;
108 	char *s;
109 	int any;
110 
111 loop:
112 	while ((c = *fmt++) != '%') {
113 		if (c == '\0')
114 			return;
115 		putchar(c, flags, ttyp);
116 	}
117 again:
118 	c = *fmt++;
119 	/* THIS CODE IS VAX DEPENDENT IN HANDLING %l? AND %c */
120 	switch (c) {
121 
122 	case 'l':
123 		goto again;
124 	case 'x': case 'X':
125 		b = 16;
126 		goto number;
127 	case 'd': case 'D':
128 	case 'u':		/* what a joke */
129 		b = 10;
130 		goto number;
131 	case 'o': case 'O':
132 		b = 8;
133 number:
134 		printn((u_long)*adx, b, flags, ttyp);
135 		break;
136 	case 'c':
137 		b = *adx;
138 		for (i = 24; i >= 0; i -= 8)
139 			if (c = (b >> i) & 0x7f)
140 				putchar(c, flags, ttyp);
141 		break;
142 	case 'b':
143 		b = *adx++;
144 		s = (char *)*adx;
145 		printn((u_long)b, *s++, flags, ttyp);
146 		any = 0;
147 		if (b) {
148 			while (i = *s++) {
149 				if (b & (1 << (i-1))) {
150 					putchar(any? ',' : '<', flags, ttyp);
151 					any = 1;
152 					for (; (c = *s) > 32; s++)
153 						putchar(c, flags, ttyp);
154 				} else
155 					for (; *s > 32; s++)
156 						;
157 			}
158 			if (any)
159 				putchar('>', flags, ttyp);
160 		}
161 		break;
162 
163 	case 's':
164 		s = (char *)*adx;
165 		while (c = *s++)
166 			putchar(c, flags, ttyp);
167 		break;
168 
169 	case '%':
170 		putchar('%', flags, ttyp);
171 		break;
172 	}
173 	adx++;
174 	goto loop;
175 }
176 
177 /*
178  * Printn prints a number n in base b.
179  * We don't use recursion to avoid deep kernel stacks.
180  */
181 printn(n, b, flags, ttyp)
182 	u_long n;
183 	struct tty *ttyp;
184 {
185 	char prbuf[11];
186 	register char *cp;
187 
188 	if (b == 10 && (int)n < 0) {
189 		putchar('-', flags, ttyp);
190 		n = (unsigned)(-(int)n);
191 	}
192 	cp = prbuf;
193 	do {
194 		*cp++ = "0123456789abcdef"[n%b];
195 		n /= b;
196 	} while (n);
197 	do
198 		putchar(*--cp, flags, ttyp);
199 	while (cp > prbuf);
200 }
201 
202 /*
203  * Panic is called on unresolvable fatal errors.
204  * It prints "panic: mesg", and then reboots.
205  * If we are called twice, then we avoid trying to
206  * sync the disks as this often leads to recursive panics.
207  */
208 panic(s)
209 	char *s;
210 {
211 	int bootopt = RB_AUTOBOOT;
212 
213 	if (panicstr)
214 		bootopt |= RB_NOSYNC;
215 	else {
216 		panicstr = s;
217 	}
218 	printf("panic: %s\n", s);
219 	boot(RB_PANIC, bootopt);
220 }
221 
222 /*
223  * Warn that a system table is full.
224  */
225 tablefull(tab)
226 	char *tab;
227 {
228 
229 	printf("%s: table is full\n", tab);
230 }
231 
232 /*
233  * Hard error is the preface to plaintive error messages
234  * about failing disk transfers.
235  */
236 harderr(bp, cp)
237 	struct buf *bp;
238 	char *cp;
239 {
240 
241 	printf("%s%d%c: hard error sn%d ", cp,
242 	    dkunit(bp), 'a'+(minor(bp->b_dev)&07), bp->b_blkno);
243 }
244 
245 /*
246  * Print a character on console or users terminal.
247  * If destination is console then the last MSGBUFS characters
248  * are saved in msgbuf for inspection later.
249  */
250 /*ARGSUSED*/
251 putchar(c, flags, tp)
252 	register int c;
253 	struct tty *tp;
254 {
255 	extern struct tty cons;
256 
257 	if (flags & TOTTY) {
258 		if (tp == (struct tty *)NULL && (flags & TOCONS) == 0)
259 			tp = &cons;
260 		if (tp && (tp->t_state & TS_CARR_ON)) {
261 			register s = spl6();
262 			if (c == '\n')
263 				(void) ttyoutput('\r', tp);
264 			(void) ttyoutput(c, tp);
265 			ttstart(tp);
266 			splx(s);
267 		}
268 	}
269 	if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177
270 #ifdef vax
271 	    && mfpr(MAPEN)
272 #endif
273 	    ) {
274 		if (msgbuf.msg_magic != MSG_MAGIC) {
275 			register int i;
276 
277 			msgbuf.msg_magic = MSG_MAGIC;
278 			msgbuf.msg_bufx = msgbuf.msg_bufr = 0;
279 			for (i=0; i < MSG_BSIZE; i++)
280 				msgbuf.msg_bufc[i] = 0;
281 		}
282 		if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE)
283 			msgbuf.msg_bufx = 0;
284 		msgbuf.msg_bufc[msgbuf.msg_bufx++] = c;
285 	}
286 	if ((flags & TOCONS) && c != '\0')
287 		cnputc(c);
288 }
289