Commit | Line | Data |
---|---|---|
da7c5cc6 | 1 | /* |
0880b18e | 2 | * Copyright (c) 1982, 1986 Regents of the University of California. |
da7c5cc6 KM |
3 | * All rights reserved. The Berkeley software License Agreement |
4 | * specifies the terms and conditions for redistribution. | |
5 | * | |
0880b18e | 6 | * @(#)subr_prf.c 7.1 (Berkeley) %G% |
da7c5cc6 | 7 | */ |
8cbb423c | 8 | |
94368568 JB |
9 | #include "param.h" |
10 | #include "systm.h" | |
11 | #include "seg.h" | |
12 | #include "buf.h" | |
13 | #include "conf.h" | |
14 | #include "reboot.h" | |
15 | #include "vm.h" | |
16 | #include "msgbuf.h" | |
17 | #include "dir.h" | |
18 | #include "user.h" | |
19 | #include "proc.h" | |
3358b36b | 20 | #include "ioctl.h" |
94368568 | 21 | #include "tty.h" |
bd10af3f | 22 | #include "syslog.h" |
96d38f03 | 23 | |
e3d5bfde SL |
24 | #ifdef vax |
25 | #include "../vax/mtpr.h" | |
26 | #endif | |
27 | ||
34ef3482 RC |
28 | #define TOCONS 0x1 |
29 | #define TOTTY 0x2 | |
30 | #define TOLOG 0x4 | |
31 | ||
8cbb423c BJ |
32 | /* |
33 | * In case console is off, | |
34 | * panicstr contains argument to last | |
35 | * call to panic. | |
36 | */ | |
8cbb423c BJ |
37 | char *panicstr; |
38 | ||
39 | /* | |
40 | * Scaled down version of C Library printf. | |
b725a0ca BJ |
41 | * Used to print diagnostic information directly on console tty. |
42 | * Since it is not interrupt driven, all system activities are | |
43 | * suspended. Printf should not be used for chit-chat. | |
44 | * | |
45 | * One additional format: %b is supported to decode error registers. | |
46 | * Usage is: | |
47 | * printf("reg=%b\n", regval, "<base><arg>*"); | |
48 | * Where <base> is the output base expressed as a control character, | |
49 | * e.g. \10 gives octal; \20 gives hex. Each arg is a sequence of | |
50 | * characters, the first of which gives the bit number to be inspected | |
51 | * (origin 1), and the next characters (up to a control character, i.e. | |
52 | * a character <= 32), give the name of the register. Thus | |
53 | * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); | |
54 | * would produce output: | |
8d907ccf | 55 | * reg=3<BITTWO,BITONE> |
8cbb423c BJ |
56 | */ |
57 | /*VARARGS1*/ | |
58 | printf(fmt, x1) | |
b725a0ca BJ |
59 | char *fmt; |
60 | unsigned x1; | |
96d38f03 BJ |
61 | { |
62 | ||
34ef3482 RC |
63 | prf(fmt, &x1, TOCONS | TOLOG, (struct tty *)0); |
64 | logwakeup(); | |
96d38f03 BJ |
65 | } |
66 | ||
843267b1 | 67 | /* |
6f71a9f6 MK |
68 | * Uprintf prints to the current user's terminal. |
69 | * It may block if the tty queue is overfull. | |
70 | * Should determine whether current terminal user is related | |
71 | * to this process. | |
843267b1 BJ |
72 | */ |
73 | /*VARARGS1*/ | |
74 | uprintf(fmt, x1) | |
b725a0ca | 75 | char *fmt; |
843267b1 | 76 | unsigned x1; |
96d38f03 | 77 | { |
c359fb80 | 78 | #ifdef notdef |
6f71a9f6 | 79 | register struct proc *p; |
c359fb80 | 80 | #endif |
6f71a9f6 | 81 | register struct tty *tp; |
96d38f03 | 82 | |
6f71a9f6 MK |
83 | if ((tp = u.u_ttyp) == NULL) |
84 | return; | |
85 | #ifdef notdef | |
86 | if (tp->t_pgrp && (p = pfind(tp->t_pgrp))) | |
c359fb80 | 87 | if (p->p_uid != u.u_uid) /* doesn't account for setuid */ |
6f71a9f6 MK |
88 | return; |
89 | #endif | |
90 | (void)ttycheckoutq(tp, 1); | |
91 | prf(fmt, &x1, TOTTY, tp); | |
34ef3482 RC |
92 | } |
93 | ||
bd10af3f MK |
94 | /* |
95 | * tprintf prints on the specified terminal (console if none) | |
96 | * and logs the message. It is designed for error messages from | |
6f71a9f6 MK |
97 | * single-open devices, and may be called from interrupt level |
98 | * (does not sleep). | |
bd10af3f | 99 | */ |
34ef3482 | 100 | /*VARARGS2*/ |
6f71a9f6 MK |
101 | tprintf(tp, fmt, x1) |
102 | register struct tty *tp; | |
34ef3482 RC |
103 | char *fmt; |
104 | unsigned x1; | |
105 | { | |
6f71a9f6 MK |
106 | int flags = TOTTY | TOLOG; |
107 | extern struct tty cons; | |
34ef3482 | 108 | |
6f71a9f6 MK |
109 | logpri(LOG_INFO); |
110 | if (tp == (struct tty *)NULL) | |
111 | tp = &cons; | |
112 | if (ttycheckoutq(tp, 0) == 0) | |
113 | flags = TOLOG; | |
114 | prf(fmt, &x1, flags, tp); | |
115 | logwakeup(); | |
34ef3482 RC |
116 | } |
117 | ||
118 | /* | |
119 | * Log writes to the log buffer, | |
8d907ccf | 120 | * and guarantees not to sleep (so can be called by interrupt routines). |
bd10af3f | 121 | * If there is no process reading the log yet, it writes to the console also. |
34ef3482 RC |
122 | */ |
123 | /*VARARGS2*/ | |
124 | log(level, fmt, x1) | |
125 | char *fmt; | |
126 | unsigned x1; | |
127 | { | |
128 | register s = splhigh(); | |
bd10af3f | 129 | extern int log_open; |
34ef3482 | 130 | |
6f71a9f6 | 131 | logpri(level); |
34ef3482 RC |
132 | prf(fmt, &x1, TOLOG, (struct tty *)0); |
133 | splx(s); | |
bd10af3f MK |
134 | if (!log_open) |
135 | prf(fmt, &x1, TOCONS, (struct tty *)0); | |
34ef3482 | 136 | logwakeup(); |
96d38f03 BJ |
137 | } |
138 | ||
6f71a9f6 MK |
139 | logpri(level) |
140 | int level; | |
141 | { | |
142 | ||
143 | putchar('<', TOLOG, (struct tty *)0); | |
8011f5df | 144 | printn((u_long)level, 10, TOLOG, (struct tty *)0); |
6f71a9f6 MK |
145 | putchar('>', TOLOG, (struct tty *)0); |
146 | } | |
147 | ||
34ef3482 | 148 | prf(fmt, adx, flags, ttyp) |
b725a0ca BJ |
149 | register char *fmt; |
150 | register u_int *adx; | |
34ef3482 | 151 | struct tty *ttyp; |
8cbb423c | 152 | { |
d5726689 | 153 | register int b, c, i; |
8cbb423c | 154 | char *s; |
3c79e4ff | 155 | int any; |
8cbb423c | 156 | |
8cbb423c | 157 | loop: |
843267b1 | 158 | while ((c = *fmt++) != '%') { |
34ef3482 | 159 | if (c == '\0') |
8cbb423c | 160 | return; |
34ef3482 | 161 | putchar(c, flags, ttyp); |
8cbb423c | 162 | } |
843267b1 | 163 | again: |
8cbb423c | 164 | c = *fmt++; |
b725a0ca | 165 | /* THIS CODE IS VAX DEPENDENT IN HANDLING %l? AND %c */ |
843267b1 BJ |
166 | switch (c) { |
167 | ||
168 | case 'l': | |
169 | goto again; | |
170 | case 'x': case 'X': | |
171 | b = 16; | |
172 | goto number; | |
173 | case 'd': case 'D': | |
174 | case 'u': /* what a joke */ | |
175 | b = 10; | |
176 | goto number; | |
177 | case 'o': case 'O': | |
178 | b = 8; | |
179 | number: | |
34ef3482 | 180 | printn((u_long)*adx, b, flags, ttyp); |
843267b1 BJ |
181 | break; |
182 | case 'c': | |
d5726689 BJ |
183 | b = *adx; |
184 | for (i = 24; i >= 0; i -= 8) | |
185 | if (c = (b >> i) & 0x7f) | |
34ef3482 | 186 | putchar(c, flags, ttyp); |
843267b1 | 187 | break; |
3c79e4ff BJ |
188 | case 'b': |
189 | b = *adx++; | |
190 | s = (char *)*adx; | |
34ef3482 | 191 | printn((u_long)b, *s++, flags, ttyp); |
3c79e4ff BJ |
192 | any = 0; |
193 | if (b) { | |
3c79e4ff BJ |
194 | while (i = *s++) { |
195 | if (b & (1 << (i-1))) { | |
8d907ccf | 196 | putchar(any? ',' : '<', flags, ttyp); |
3c79e4ff BJ |
197 | any = 1; |
198 | for (; (c = *s) > 32; s++) | |
34ef3482 | 199 | putchar(c, flags, ttyp); |
3c79e4ff BJ |
200 | } else |
201 | for (; *s > 32; s++) | |
202 | ; | |
203 | } | |
1ce587f2 | 204 | if (any) |
34ef3482 | 205 | putchar('>', flags, ttyp); |
3c79e4ff BJ |
206 | } |
207 | break; | |
208 | ||
843267b1 | 209 | case 's': |
8cbb423c | 210 | s = (char *)*adx; |
96d38f03 | 211 | while (c = *s++) |
34ef3482 | 212 | putchar(c, flags, ttyp); |
843267b1 | 213 | break; |
2bb8d359 BJ |
214 | |
215 | case '%': | |
34ef3482 | 216 | putchar('%', flags, ttyp); |
2bb8d359 | 217 | break; |
8cbb423c BJ |
218 | } |
219 | adx++; | |
220 | goto loop; | |
221 | } | |
222 | ||
b725a0ca BJ |
223 | /* |
224 | * Printn prints a number n in base b. | |
225 | * We don't use recursion to avoid deep kernel stacks. | |
226 | */ | |
34ef3482 | 227 | printn(n, b, flags, ttyp) |
a0eab615 | 228 | u_long n; |
34ef3482 | 229 | struct tty *ttyp; |
8cbb423c | 230 | { |
d5726689 | 231 | char prbuf[11]; |
843267b1 | 232 | register char *cp; |
8cbb423c | 233 | |
843267b1 | 234 | if (b == 10 && (int)n < 0) { |
34ef3482 | 235 | putchar('-', flags, ttyp); |
843267b1 | 236 | n = (unsigned)(-(int)n); |
8cbb423c | 237 | } |
d5726689 | 238 | cp = prbuf; |
843267b1 BJ |
239 | do { |
240 | *cp++ = "0123456789abcdef"[n%b]; | |
241 | n /= b; | |
242 | } while (n); | |
243 | do | |
34ef3482 | 244 | putchar(*--cp, flags, ttyp); |
d5726689 | 245 | while (cp > prbuf); |
8cbb423c BJ |
246 | } |
247 | ||
248 | /* | |
0dc06be8 | 249 | * Panic is called on unresolvable fatal errors. |
b725a0ca BJ |
250 | * It prints "panic: mesg", and then reboots. |
251 | * If we are called twice, then we avoid trying to | |
252 | * sync the disks as this often leads to recursive panics. | |
8cbb423c BJ |
253 | */ |
254 | panic(s) | |
b725a0ca | 255 | char *s; |
8cbb423c | 256 | { |
68503f9a | 257 | int bootopt = RB_AUTOBOOT; |
843267b1 | 258 | |
68503f9a BJ |
259 | if (panicstr) |
260 | bootopt |= RB_NOSYNC; | |
cddce008 | 261 | else { |
961945a8 | 262 | panicstr = s; |
961945a8 | 263 | } |
a9c526c1 | 264 | printf("panic: %s\n", s); |
b725a0ca | 265 | boot(RB_PANIC, bootopt); |
8cbb423c BJ |
266 | } |
267 | ||
fdd11a14 BJ |
268 | /* |
269 | * Warn that a system table is full. | |
270 | */ | |
271 | tablefull(tab) | |
272 | char *tab; | |
273 | { | |
274 | ||
283ffc90 | 275 | log(LOG_ERR, "%s: table is full\n", tab); |
fdd11a14 BJ |
276 | } |
277 | ||
b725a0ca BJ |
278 | /* |
279 | * Hard error is the preface to plaintive error messages | |
fdd11a14 | 280 | * about failing disk transfers. |
b725a0ca | 281 | */ |
fdd11a14 | 282 | harderr(bp, cp) |
3c79e4ff | 283 | struct buf *bp; |
fdd11a14 | 284 | char *cp; |
8cbb423c BJ |
285 | { |
286 | ||
fdd11a14 | 287 | printf("%s%d%c: hard error sn%d ", cp, |
c852160f | 288 | minor(bp->b_dev) >> 3, 'a'+(minor(bp->b_dev)&07), bp->b_blkno); |
8cbb423c | 289 | } |
b725a0ca | 290 | |
96d38f03 | 291 | /* |
843267b1 | 292 | * Print a character on console or users terminal. |
96d38f03 BJ |
293 | * If destination is console then the last MSGBUFS characters |
294 | * are saved in msgbuf for inspection later. | |
295 | */ | |
49c84d3f | 296 | /*ARGSUSED*/ |
8d907ccf | 297 | putchar(c, flags, tp) |
843267b1 | 298 | register int c; |
8d907ccf | 299 | struct tty *tp; |
96d38f03 | 300 | { |
96d38f03 | 301 | |
34ef3482 | 302 | if (flags & TOTTY) { |
6f71a9f6 MK |
303 | register s = spltty(); |
304 | ||
305 | if (tp && (tp->t_state & (TS_CARR_ON | TS_ISOPEN)) == | |
306 | (TS_CARR_ON | TS_ISOPEN)) { | |
843267b1 | 307 | if (c == '\n') |
2752c877 BJ |
308 | (void) ttyoutput('\r', tp); |
309 | (void) ttyoutput(c, tp); | |
d11b28dc | 310 | ttstart(tp); |
d11b28dc | 311 | } |
6f71a9f6 | 312 | splx(s); |
d11b28dc | 313 | } |
34ef3482 | 314 | if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177 |
b4e32d36 | 315 | #ifdef vax |
cddce008 BJ |
316 | && mfpr(MAPEN) |
317 | #endif | |
318 | ) { | |
90f8d91f | 319 | if (msgbuf.msg_magic != MSG_MAGIC) { |
76db4195 SL |
320 | register int i; |
321 | ||
90f8d91f | 322 | msgbuf.msg_magic = MSG_MAGIC; |
34ef3482 | 323 | msgbuf.msg_bufx = msgbuf.msg_bufr = 0; |
76db4195 SL |
324 | for (i=0; i < MSG_BSIZE; i++) |
325 | msgbuf.msg_bufc[i] = 0; | |
90f8d91f | 326 | } |
7e401e0e | 327 | msgbuf.msg_bufc[msgbuf.msg_bufx++] = c; |
90f8d91f BJ |
328 | if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE) |
329 | msgbuf.msg_bufx = 0; | |
96d38f03 | 330 | } |
34ef3482 RC |
331 | if ((flags & TOCONS) && c != '\0') |
332 | cnputc(c); | |
96d38f03 | 333 | } |