|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: *
6: * @(#)subr_prf.c 7.18 (Berkeley) 6/28/90
7: */
8:
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 "user.h"
18: #include "proc.h"
19: #include "ioctl.h"
20: #include "vnode.h"
21: #include "file.h"
22: #include "tty.h"
23: #include "tprintf.h"
24: #include "syslog.h"
25: #include "malloc.h"
26:
27: #include "machine/mtpr.h"
28: #ifdef KADB
29: #include "machine/kdbparam.h"
30: #endif
31:
32: #define TOCONS 0x1
33: #define TOTTY 0x2
34: #define TOLOG 0x4
35:
36: /*
37: * In case console is off,
38: * panicstr contains argument to last
39: * call to panic.
40: */
41: char *panicstr;
42:
43: extern cnputc(); /* standard console putc */
44: int (*v_putc)() = cnputc; /* routine to putc on virtual console */
45: extern struct tty cons; /* standard console tty */
46: struct tty *constty; /* pointer to console "window" tty */
47:
48: #ifdef KADB
49: extern cngetc(); /* standard console getc */
50: extern cnpoll();
51: int (*v_getc)() = cngetc; /* "" getc from virtual console */
52: int (*v_poll)() = cnpoll; /* kdb hook to enable input polling */
53: #endif
54:
55: /*
56: * Scaled down version of C Library printf.
57: * Used to print diagnostic information directly on console tty.
58: * Since it is not interrupt driven, all system activities are
59: * suspended. Printf should not be used for chit-chat.
60: *
61: * One additional format: %b is supported to decode error registers.
62: * Usage is:
63: * printf("reg=%b\n", regval, "<base><arg>*");
64: * Where <base> is the output base expressed as a control character,
65: * e.g. \10 gives octal; \20 gives hex. Each arg is a sequence of
66: * characters, the first of which gives the bit number to be inspected
67: * (origin 1), and the next characters (up to a control character, i.e.
68: * a character <= 32), give the name of the register. Thus
69: * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
70: * would produce output:
71: * reg=3<BITTWO,BITONE>
72: *
73: * Another additional format: %r is used to pass an additional format string
74: * and argument list recursively. Usage is typically:
75: *
76: * fn(otherstuff, fmt [, arg1, ... ] )
77: * char *fmt;
78: * u_int arg1, ...;
79: *
80: * printf("prefix: %r, other stuff\n", fmt, &arg1);
81: */
82: #if defined(tahoe)
83: int consintr;
84: #endif
85:
86: /*VARARGS1*/
87: printf(fmt, x1)
88: char *fmt;
89: unsigned x1;
90: {
91: #if defined(tahoe)
92: register int savintr;
93:
94: savintr = consintr, consintr = 0; /* disable interrupts */
95: #endif
96: prf(fmt, &x1, TOCONS | TOLOG, (struct tty *)NULL);
97: if (!panicstr)
98: logwakeup();
99: #if defined(tahoe)
100: consintr = savintr; /* reenable interrupts */
101: #endif
102: }
103:
104: /*
105: * Uprintf prints to the controlling terminal for the current process.
106: * It may block if the tty queue is overfull.
107: * No message is printed if the queue does not clear
108: * in a reasonable time.
109: */
110: /*VARARGS1*/
111: uprintf(fmt, x1)
112: char *fmt;
113: unsigned x1;
114: {
115: register struct proc *p = u.u_procp;
116:
117: if (p->p_flag & SCTTY && p->p_session->s_ttyvp)
118: prf(fmt, &x1, TOTTY, p->p_session->s_ttyp);
119: }
120:
121: tpr_t
122: tprintf_open()
123: {
124: register struct proc *p = u.u_procp;
125:
126: if (p->p_flag & SCTTY && p->p_session->s_ttyvp) {
127: SESSHOLD(p->p_session);
128: return ((tpr_t)p->p_session);
129: } else
130: return ((tpr_t)NULL);
131: }
132:
133: tprintf_close(sess)
134: tpr_t sess;
135: {
136: if (sess)
137: SESSRELE(sess);
138: }
139:
140: /*
141: * tprintf prints on the controlling terminal associated
142: * with the given session.
143: */
144: /*VARARGS2*/
145: tprintf(sess, fmt, x1)
146: register tpr_t sess;
147: char *fmt;
148: unsigned x1;
149: {
150: int flags = TOLOG;
151:
152: logpri(LOG_INFO);
153:
154: if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0))
155: flags |= TOTTY;
156: prf(fmt, &x1, flags, sess->s_ttyp);
157: logwakeup();
158: }
159:
160:
161: /*
162: * Log writes to the log buffer,
163: * and guarantees not to sleep (so can be called by interrupt routines).
164: * If there is no process reading the log yet, it writes to the console also.
165: */
166: /*VARARGS2*/
167: log(level, fmt, x1)
168: char *fmt;
169: unsigned x1;
170: {
171: register s = splhigh();
172: extern int log_open;
173:
174: logpri(level);
175: prf(fmt, &x1, TOLOG, (struct tty *)NULL);
176: splx(s);
177: if (!log_open)
178: prf(fmt, &x1, TOCONS, (struct tty *)NULL);
179: logwakeup();
180: }
181:
182: logpri(level)
183: int level;
184: {
185:
186: putchar('<', TOLOG, (struct tty *)NULL);
187: printn((u_long)level, 10, TOLOG, (struct tty *)NULL);
188: putchar('>', TOLOG, (struct tty *)NULL);
189: }
190:
191: /*VARARGS1*/
192: addlog(fmt, x1)
193: char *fmt;
194: unsigned x1;
195: {
196: register s = splhigh();
197:
198: prf(fmt, &x1, TOLOG, (struct tty *)NULL);
199: splx(s);
200: if (!log_open)
201: prf(fmt, &x1, TOCONS, (struct tty *)NULL);
202: logwakeup();
203: }
204:
205: prf(fmt, adx, flags, ttyp)
206: register char *fmt;
207: register u_int *adx;
208: struct tty *ttyp;
209: {
210: register int b, c, i;
211: char *s;
212: int any;
213:
214: loop:
215: while ((c = *fmt++) != '%') {
216: if (c == '\0')
217: return;
218: putchar(c, flags, ttyp);
219: }
220: again:
221: c = *fmt++;
222: /* THIS CODE IS MACHINE DEPENDENT IN HANDLING %l? AND %c */
223: switch (c) {
224:
225: case 'l':
226: goto again;
227: case 'x': case 'X':
228: b = 16;
229: goto number;
230: case 'd': case 'D':
231: b = -10;
232: goto number;
233: case 'u':
234: b = 10;
235: goto number;
236: case 'o': case 'O':
237: b = 8;
238: number:
239: printn((u_long)*adx, b, flags, ttyp);
240: break;
241: case 'c':
242: b = *adx;
243: #if BYTE_ORDER == LITTLE_ENDIAN
244: for (i = 24; i >= 0; i -= 8)
245: if (c = (b >> i) & 0x7f)
246: putchar(c, flags, ttyp);
247: #endif
248: #if BYTE_ORDER == BIG_ENDIAN
249: if (c = (b & 0x7f))
250: putchar(c, flags, ttyp);
251: #endif
252: break;
253: case 'b':
254: b = *adx++;
255: s = (char *)*adx;
256: printn((u_long)b, *s++, flags, ttyp);
257: any = 0;
258: if (b) {
259: while (i = *s++) {
260: if (b & (1 << (i-1))) {
261: putchar(any ? ',' : '<', flags, ttyp);
262: any = 1;
263: for (; (c = *s) > 32; s++)
264: putchar(c, flags, ttyp);
265: } else
266: for (; *s > 32; s++)
267: ;
268: }
269: if (any)
270: putchar('>', flags, ttyp);
271: }
272: break;
273:
274: case 's':
275: s = (char *)*adx;
276: while (c = *s++)
277: putchar(c, flags, ttyp);
278: break;
279:
280: case 'r':
281: s = (char *)*adx++;
282: prf(s, (u_int *)*adx, flags, ttyp);
283: break;
284:
285: case '%':
286: putchar('%', flags, ttyp);
287: break;
288: }
289: adx++;
290: goto loop;
291: }
292:
293: /*
294: * Printn prints a number n in base b.
295: * We don't use recursion to avoid deep kernel stacks.
296: */
297: printn(n, b, flags, ttyp)
298: u_long n;
299: struct tty *ttyp;
300: {
301: char prbuf[11];
302: register char *cp;
303:
304: if (b == -10) {
305: if ((int)n < 0) {
306: putchar('-', flags, ttyp);
307: n = (unsigned)(-(int)n);
308: }
309: b = -b;
310: }
311: cp = prbuf;
312: do {
313: *cp++ = "0123456789abcdef"[n%b];
314: n /= b;
315: } while (n);
316: do
317: putchar(*--cp, flags, ttyp);
318: while (cp > prbuf);
319: }
320:
321: /*
322: * Panic is called on unresolvable fatal errors.
323: * It prints "panic: mesg", and then reboots.
324: * If we are called twice, then we avoid trying to
325: * sync the disks as this often leads to recursive panics.
326: */
327: panic(s)
328: char *s;
329: {
330: int bootopt = RB_AUTOBOOT | RB_DUMP;
331:
332: if (panicstr)
333: bootopt |= RB_NOSYNC;
334: else {
335: panicstr = s;
336: }
337: printf("panic: %s\n", s);
338: #ifdef KADB
339: if (boothowto & RB_KDB) {
340: int x = splnet(); /* below kdb pri */
341:
342: setsoftkdb();
343: splx(x);
344: }
345: #endif
346: boot(bootopt);
347: }
348:
349: /*
350: * Warn that a system table is full.
351: */
352: tablefull(tab)
353: char *tab;
354: {
355:
356: log(LOG_ERR, "%s: table is full\n", tab);
357: }
358:
359: /*
360: * Print a character on console or users terminal.
361: * If destination is console then the last MSGBUFS characters
362: * are saved in msgbuf for inspection later.
363: */
364: /*ARGSUSED*/
365: putchar(c, flags, ttyp)
366: register int c;
367: struct tty *ttyp;
368: {
369: extern int msgbufmapped;
370:
371: if (panicstr)
372: constty = 0;
373: if ((flags & TOCONS) && ttyp == NULL && constty) {
374: ttyp = constty;
375: flags |= TOTTY;
376: }
377: if ((flags & TOTTY) && ttyp && tputchar(c, ttyp) < 0 &&
378: (flags & TOCONS) && ttyp == constty)
379: constty = 0;
380: if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177 &&
381: msgbufmapped) {
382: if (msgbuf.msg_magic != MSG_MAGIC) {
383: register int i;
384:
385: msgbuf.msg_magic = MSG_MAGIC;
386: msgbuf.msg_bufx = msgbuf.msg_bufr = 0;
387: for (i=0; i < MSG_BSIZE; i++)
388: msgbuf.msg_bufc[i] = 0;
389: }
390: msgbuf.msg_bufc[msgbuf.msg_bufx++] = c;
391: if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE)
392: msgbuf.msg_bufx = 0;
393: }
394: if ((flags & TOCONS) && constty == 0 && c != '\0')
395: (*v_putc)(c);
396: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.