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