|
|
1.1 root 1: /*-
2: * Copyright (c) 1986, 1988, 1991 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. All advertising materials mentioning features or use of this software
14: * must display the following acknowledgement:
15: * This product includes software developed by the University of
16: * California, Berkeley and its contributors.
17: * 4. Neither the name of the University nor the names of its contributors
18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: *
1.1.1.3 ! root 33: * from: @(#)subr_prf.c 7.30 (Berkeley) 6/29/91
! 34: * subr_prf.c,v 1.7 1993/06/27 06:01:53 andrew Exp
1.1 root 35: */
36:
37: #include "param.h"
38: #include "systm.h"
39: #include "buf.h"
40: #include "conf.h"
41: #include "reboot.h"
42: #include "msgbuf.h"
43: #include "proc.h"
44: #include "ioctl.h"
45: #include "vnode.h"
46: #include "file.h"
47: #include "tty.h"
48: #include "tprintf.h"
49: #include "syslog.h"
50: #include "malloc.h"
51:
52: /*
53: * Note that stdarg.h and the ANSI style va_start macro is used for both
54: * ANSI and traditional C compilers.
55: */
56: #include <machine/stdarg.h>
57:
58: #ifdef KADB
59: #include "machine/kdbparam.h"
60: #endif
61:
62: #define TOCONS 0x01
63: #define TOTTY 0x02
64: #define TOLOG 0x04
65:
66: struct tty *constty; /* pointer to console "window" tty */
67:
1.1.1.3 ! root 68: #if defined(KADB) || defined(PANICWAIT)
1.1 root 69: extern cngetc(); /* standard console getc */
1.1.1.3 ! root 70: #endif
! 71: #ifdef KADB
1.1 root 72: int (*v_getc)() = cngetc; /* "" getc from virtual console */
73: extern cnpoll();
74: int (*v_poll)() = cnpoll; /* kdb hook to enable input polling */
75: #endif
76: extern cnputc(); /* standard console putc */
77: int (*v_putc)() = cnputc; /* routine to putc on virtual console */
78:
79: static void logpri __P((int level));
80: static void putchar __P((int ch, int flags, struct tty *tp));
81: static char *ksprintn __P((u_long num, int base, int *len));
82: void kprintf __P((const char *fmt, int flags, struct tty *tp, va_list));
1.1.1.3 ! root 83: volatile void boot(int bootopt);
1.1 root 84:
85: /*
86: * Variable panicstr contains argument to first call to panic; used
87: * as flag to indicate that the kernel has already called panic.
88: */
1.1.1.3 ! root 89: const char *panicstr;
1.1 root 90:
91: /*
92: * Panic is called on unresolvable fatal errors. It prints "panic: mesg",
93: * and then reboots. If we are called twice, then we avoid trying to sync
94: * the disks as this often leads to recursive panics.
95: */
1.1.1.3 ! root 96: #ifdef __STDC__
! 97: volatile void
! 98: panic(const char *msg)
! 99: #else
1.1 root 100: void
101: panic(msg)
102: char *msg;
1.1.1.3 ! root 103: #endif
1.1 root 104: {
105: int bootopt = RB_AUTOBOOT | RB_DUMP;
106:
107: if (panicstr)
108: bootopt |= RB_NOSYNC;
109: else
110: panicstr = msg;
111: printf("panic: %s\n", msg);
112: #ifdef KGDB
113: kgdb_panic();
114: #endif
115: #ifdef KADB
116: if (boothowto & RB_KDB) {
117: int s;
118:
119: s = splnet(); /* below kdb pri */
120: setsoftkdb();
121: splx(s);
122: }
123: #endif
1.1.1.3 ! root 124: #ifdef DDB
1.1.1.2 root 125: Debugger ();
126: #else
1.1.1.3 ! root 127: #ifdef PANICWAIT
! 128: printf("hit any key to boot/dump...\n>");
! 129: cngetc();
! 130: #endif
1.1.1.2 root 131: #endif
1.1 root 132: boot(bootopt);
133: }
134:
135: /*
136: * Warn that a system table is full.
137: */
138: void
139: tablefull(tab)
140: char *tab;
141: {
142:
143: log(LOG_ERR, "%s: table is full\n", tab);
144: }
145:
146: /*
147: * Uprintf prints to the controlling terminal for the current process.
148: * It may block if the tty queue is overfull. No message is printed if
149: * the queue does not clear in a reasonable time.
150: */
151: void
152: #ifdef __STDC__
153: uprintf(const char *fmt, ...)
154: #else
155: uprintf(fmt /*, va_alist */)
156: char *fmt;
157: #endif
158: {
159: register struct proc *p = curproc;
160: va_list ap;
161:
162: if (p->p_flag & SCTTY && p->p_session->s_ttyvp) {
163: va_start(ap, fmt);
164: kprintf(fmt, TOTTY, p->p_session->s_ttyp, ap);
165: va_end(ap);
166: }
167: }
168:
169: tpr_t
170: tprintf_open(p)
171: register struct proc *p;
172: {
173:
174: if (p->p_flag & SCTTY && p->p_session->s_ttyvp) {
175: SESSHOLD(p->p_session);
176: return ((tpr_t) p->p_session);
177: }
178: return ((tpr_t) NULL);
179: }
180:
181: void
182: tprintf_close(sess)
183: tpr_t sess;
184: {
185:
186: if (sess)
187: SESSRELE((struct session *) sess);
188: }
189:
190: /*
191: * tprintf prints on the controlling terminal associated
192: * with the given session.
193: */
194: void
195: #ifdef __STDC__
196: tprintf(tpr_t tpr, const char *fmt, ...)
197: #else
198: tprintf(tpr, fmt /*, va_alist */)
199: tpr_t tpr;
200: char *fmt;
201: #endif
202: {
203: register struct session *sess = (struct session *)tpr;
204: struct tty *tp = NULL;
205: int flags = TOLOG;
206: va_list ap;
207:
208: logpri(LOG_INFO);
209: if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) {
210: flags |= TOTTY;
211: tp = sess->s_ttyp;
212: }
213: va_start(ap, fmt);
214: kprintf(fmt, flags, tp, ap);
215: va_end(ap);
216: logwakeup();
217: }
218:
219: /*
220: * Ttyprintf displays a message on a tty; it should be used only by
221: * the tty driver, or anything that knows the underlying tty will not
222: * be revoke(2)'d away. Other callers should use tprintf.
223: */
224: void
225: #ifdef __STDC__
226: ttyprintf(struct tty *tp, const char *fmt, ...)
227: #else
228: ttyprintf(tp, fmt /*, va_alist */)
229: struct tty *tp;
230: char *fmt;
231: #endif
232: {
233: va_list ap;
234:
235: va_start(ap, fmt);
236: kprintf(fmt, TOTTY, tp, ap);
237: va_end(ap);
238: }
239:
240: extern int log_open;
241:
242: /*
243: * Log writes to the log buffer, and guarantees not to sleep (so can be
244: * called by interrupt routines). If there is no process reading the
245: * log yet, it writes to the console also.
246: */
247: void
248: #ifdef __STDC__
249: log(int level, const char *fmt, ...)
250: #else
251: log(level, fmt /*, va_alist */)
252: int level;
253: char *fmt;
254: #endif
255: {
256: register int s;
257: va_list ap;
258:
259: s = splhigh();
260: logpri(level);
261: va_start(ap, fmt);
262: kprintf(fmt, TOLOG, NULL, ap);
263: splx(s);
264: va_end(ap);
265: if (!log_open) {
266: va_start(ap, fmt);
267: kprintf(fmt, TOCONS, NULL, ap);
268: va_end(ap);
269: }
270: logwakeup();
271: }
272:
273: static void
274: logpri(level)
275: int level;
276: {
277: register int ch;
278: register char *p;
279:
280: putchar('<', TOLOG, NULL);
281: for (p = ksprintn((u_long)level, 10, NULL); ch = *p--;)
282: putchar(ch, TOLOG, NULL);
283: putchar('>', TOLOG, NULL);
284: }
285:
286: void
287: #ifdef __STDC__
288: addlog(const char *fmt, ...)
289: #else
290: addlog(fmt /*, va_alist */)
291: char *fmt;
292: #endif
293: {
294: register int s;
295: va_list ap;
296:
297: s = splhigh();
298: va_start(ap, fmt);
299: kprintf(fmt, TOLOG, NULL, ap);
300: splx(s);
301: va_end(ap);
302: if (!log_open) {
303: va_start(ap, fmt);
304: kprintf(fmt, TOCONS, NULL, ap);
305: va_end(ap);
306: }
307: logwakeup();
308: }
309:
310: int consintr = 1; /* ok to handle console interrupts? */
311:
1.1.1.3 ! root 312: int
1.1 root 313: #ifdef __STDC__
314: printf(const char *fmt, ...)
315: #else
316: printf(fmt /*, va_alist */)
317: char *fmt;
318: #endif
319: {
320: va_list ap;
321: register int savintr;
322:
323: savintr = consintr; /* disable interrupts */
324: consintr = 0;
325: va_start(ap, fmt);
326: kprintf(fmt, TOCONS | TOLOG, NULL, ap);
327: va_end(ap);
328: if (!panicstr)
329: logwakeup();
330: consintr = savintr; /* reenable interrupts */
1.1.1.3 ! root 331:
! 332: return 0; /* for compatibility with libc's printf() */
1.1 root 333: }
334:
335: /*
336: * Scaled down version of printf(3).
337: *
338: * Two additional formats:
339: *
340: * The format %b is supported to decode error registers.
341: * Its usage is:
342: *
343: * printf("reg=%b\n", regval, "<base><arg>*");
344: *
345: * where <base> is the output base expressed as a control character, e.g.
346: * \10 gives octal; \20 gives hex. Each arg is a sequence of characters,
347: * the first of which gives the bit number to be inspected (origin 1), and
348: * the next characters (up to a control character, i.e. a character <= 32),
349: * give the name of the register. Thus:
350: *
351: * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
352: *
353: * would produce output:
354: *
355: * reg=3<BITTWO,BITONE>
356: *
357: * The format %r is supposed to pass an additional format string and argument
358: * list recursively.
359: * Its usage is:
360: *
361: * fn(otherstuff, char *fmt, ...)
362: * {
363: * va_list ap;
364: * va_start(ap, fmt);
365: * printf("prefix: %r, other stuff\n", fmt, ap);
366: * va_end(ap);
367: *
368: * Space or zero padding and a field width are supported for the numeric
369: * formats only.
370: */
371: void
372: kprintf(fmt, flags, tp, ap)
373: register const char *fmt;
374: int flags;
375: struct tty *tp;
376: va_list ap;
377: {
1.1.1.3 ! root 378: register char *p, *p2;
1.1 root 379: register int ch, n;
380: u_long ul;
381: int base, lflag, tmp, width;
382: char padc;
383:
384: for (;;) {
385: padc = ' ';
386: width = 0;
387: while ((ch = *(u_char *)fmt++) != '%') {
388: if (ch == '\0')
389: return;
390: putchar(ch, flags, tp);
391: }
392: lflag = 0;
393: reswitch: switch (ch = *(u_char *)fmt++) {
394: case '0':
395: padc = '0';
396: goto reswitch;
397: case '1': case '2': case '3': case '4':
398: case '5': case '6': case '7': case '8': case '9':
399: for (width = 0;; ++fmt) {
400: width = width * 10 + ch - '0';
401: ch = *fmt;
402: if (ch < '0' || ch > '9')
403: break;
404: }
405: goto reswitch;
406: case 'l':
407: lflag = 1;
408: goto reswitch;
409: case 'b':
410: ul = va_arg(ap, int);
411: p = va_arg(ap, char *);
1.1.1.3 ! root 412: for (p2 = ksprintn(ul, *p++, NULL); ch = *p2--;)
1.1 root 413: putchar(ch, flags, tp);
414:
415: if (!ul)
416: break;
417:
418: for (tmp = 0; n = *p++;) {
419: if (ul & (1 << (n - 1))) {
420: putchar(tmp ? ',' : '<', flags, tp);
421: for (; (n = *p) > ' '; ++p)
422: putchar(n, flags, tp);
423: tmp = 1;
424: } else
425: for (; *p > ' '; ++p);
426: }
427: if (tmp)
428: putchar('>', flags, tp);
429: break;
430: case 'c':
431: putchar(va_arg(ap, int), flags, tp);
432: break;
433: case 'r':
434: p = va_arg(ap, char *);
435: kprintf(p, flags, tp, va_arg(ap, va_list));
436: break;
437: case 's':
438: p = va_arg(ap, char *);
439: while (ch = *p++)
440: putchar(ch, flags, tp);
441: break;
442: case 'd':
443: ul = lflag ? va_arg(ap, long) : va_arg(ap, int);
444: if ((long)ul < 0) {
445: putchar('-', flags, tp);
446: ul = -(long)ul;
447: }
448: base = 10;
449: goto number;
450: case 'o':
451: ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
452: base = 8;
453: goto number;
454: case 'u':
455: ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
456: base = 10;
457: goto number;
458: case 'x':
459: ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
460: base = 16;
461: number: p = ksprintn(ul, base, &tmp);
462: if (width && (width -= tmp) > 0)
463: while (width--)
464: putchar(padc, flags, tp);
465: while (ch = *p--)
466: putchar(ch, flags, tp);
467: break;
468: default:
469: putchar('%', flags, tp);
470: if (lflag)
471: putchar('l', flags, tp);
472: /* FALLTHROUGH */
473: case '%':
474: putchar(ch, flags, tp);
475: }
476: }
477: }
478:
479: /*
480: * Print a character on console or users terminal. If destination is
481: * the console then the last MSGBUFS characters are saved in msgbuf for
482: * inspection later.
483: */
484: static void
485: putchar(c, flags, tp)
486: register int c;
487: int flags;
488: struct tty *tp;
489: {
490: extern int msgbufmapped;
491: register struct msgbuf *mbp;
492:
493: if (panicstr)
494: constty = NULL;
495: if ((flags & TOCONS) && tp == NULL && constty) {
496: tp = constty;
497: flags |= TOTTY;
498: }
499: if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 &&
500: (flags & TOCONS) && tp == constty)
501: constty = NULL;
502: if ((flags & TOLOG) &&
503: c != '\0' && c != '\r' && c != 0177 && msgbufmapped) {
504: mbp = msgbufp;
505: if (mbp->msg_magic != MSG_MAGIC) {
506: bzero((caddr_t)mbp, sizeof(*mbp));
507: mbp->msg_magic = MSG_MAGIC;
508: }
509: mbp->msg_bufc[mbp->msg_bufx++] = c;
510: if (mbp->msg_bufx < 0 || mbp->msg_bufx >= MSG_BSIZE)
511: mbp->msg_bufx = 0;
512: }
513: if ((flags & TOCONS) && constty == NULL && c != '\0')
514: (*v_putc)(c);
515: }
516:
517: /*
518: * Scaled down version of sprintf(3).
519: */
520: #ifdef __STDC__
1.1.1.3 ! root 521: int
1.1 root 522: sprintf(char *buf, const char *cfmt, ...)
523: #else
1.1.1.3 ! root 524: int
1.1 root 525: sprintf(buf, cfmt /*, va_alist */)
526: char *buf, *cfmt;
527: #endif
528: {
529: register const char *fmt = cfmt;
530: register char *p, *bp;
531: register int ch, base;
532: u_long ul;
533: int lflag;
534: va_list ap;
535:
536: va_start(ap, cfmt);
537: for (bp = buf; ; ) {
538: while ((ch = *(u_char *)fmt++) != '%')
539: if ((*bp++ = ch) == '\0')
540: return ((bp - buf) - 1);
541:
542: lflag = 0;
543: reswitch: switch (ch = *(u_char *)fmt++) {
544: case 'l':
545: lflag = 1;
546: goto reswitch;
547: case 'c':
548: *bp++ = va_arg(ap, int);
549: break;
550: case 's':
551: p = va_arg(ap, char *);
552: while (*bp++ = *p++)
553: ;
554: --bp;
555: break;
556: case 'd':
557: ul = lflag ? va_arg(ap, long) : va_arg(ap, int);
558: if ((long)ul < 0) {
559: *bp++ = '-';
560: ul = -(long)ul;
561: }
562: base = 10;
563: goto number;
564: break;
565: case 'o':
566: ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
567: base = 8;
568: goto number;
569: break;
570: case 'u':
571: ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
572: base = 10;
573: goto number;
574: break;
575: case 'x':
576: ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
577: base = 16;
578: number: for (p = ksprintn(ul, base, NULL); ch = *p--;)
579: *bp++ = ch;
580: break;
581: default:
582: *bp++ = '%';
583: if (lflag)
584: *bp++ = 'l';
585: /* FALLTHROUGH */
586: case '%':
587: *bp++ = ch;
588: }
589: }
590: va_end(ap);
591: }
592:
593: /*
594: * Put a number (base <= 16) in a buffer in reverse order; return an
595: * optional length and a pointer to the NULL terminated (preceded?)
596: * buffer.
597: */
598: static char *
599: ksprintn(ul, base, lenp)
600: register u_long ul;
601: register int base, *lenp;
602: { /* A long in base 8, plus NULL. */
603: static char buf[sizeof(long) * NBBY / 3 + 2];
604: register char *p;
605:
606: p = buf;
607: do {
608: *++p = "0123456789abcdef"[ul % base];
609: } while (ul /= base);
610: if (lenp)
611: *lenp = p - buf;
612: return (p);
613: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.