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