X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/d11b28dc6e0d0269c4e1ea342e9f9f25c478815b..7bf304e65beb1e282cd098ed53ab9f4999b78280:/usr/src/sys/kern/subr_prf.c diff --git a/usr/src/sys/kern/subr_prf.c b/usr/src/sys/kern/subr_prf.c index 180f7d5c42..b2e04feebe 100644 --- a/usr/src/sys/kern/subr_prf.c +++ b/usr/src/sys/kern/subr_prf.c @@ -1,262 +1,401 @@ -/* subr_prf.c 4.6 %G% */ - -#include "../h/param.h" -#include "../h/systm.h" -#include "../h/seg.h" -#include "../h/buf.h" -#include "../h/conf.h" -#include "../h/mtpr.h" -#include "../h/reboot.h" -#include "../h/vm.h" -#include "../h/msgbuf.h" -#include "../h/dir.h" -#include "../h/user.h" -#include "../h/tty.h" - -#ifdef TRACE -#define TRCBUFS 4096 -char trcbuf[TRCBUFS]; -char *trcbufp = trcbuf; -int trcwrap; -int trcprt = TRCBUFS; +/* + * Copyright (c) 1982, 1986, 1988 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + * + * @(#)subr_prf.c 7.14 (Berkeley) %G% + */ + +#include "param.h" +#include "systm.h" +#include "seg.h" +#include "buf.h" +#include "conf.h" +#include "reboot.h" +#include "vm.h" +#include "msgbuf.h" +#include "user.h" +#include "proc.h" +#include "ioctl.h" +#include "tty.h" +#include "syslog.h" + +#include "machine/mtpr.h" +#ifdef KADB +#include "machine/kdbparam.h" #endif +#define TOCONS 0x1 +#define TOTTY 0x2 +#define TOLOG 0x4 + /* * In case console is off, * panicstr contains argument to last * call to panic. */ - char *panicstr; +extern cnputc(); /* standard console putc */ +extern struct tty cons; /* standard console tty */ +struct tty *constty; /* pointer to console "window" tty */ +int (*v_putc)() = cnputc; /* routine to putc on virtual console */ + +extern cnputc(); /* standard console putc */ +extern struct tty cons; /* standard console tty */ +struct tty *constty; /* pointer to console "window" tty */ +int (*v_console)() = cnputc; /* routine to putc on virtual console */ + /* * Scaled down version of C Library printf. - * Only %s %u %d (==%u) %o %x %D are recognized. - * Used to print diagnostic information - * directly on console tty. - * Since it is not interrupt driven, - * all system activities are pretty much - * suspended. - * Printf should not be used for chit-chat. + * Used to print diagnostic information directly on console tty. + * Since it is not interrupt driven, all system activities are + * suspended. Printf should not be used for chit-chat. + * + * One additional format: %b is supported to decode error registers. + * Usage is: + * printf("reg=%b\n", regval, "*"); + * Where is the output base expressed as a control character, + * e.g. \10 gives octal; \20 gives hex. Each arg is a sequence of + * characters, the first of which gives the bit number to be inspected + * (origin 1), and the next characters (up to a control character, i.e. + * a character <= 32), give the name of the register. Thus + * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); + * would produce output: + * reg=3 + * + * Another additional format: %r is used to pass an additional format string + * and argument list recursively. Usage is typically: + * + * fn(otherstuff, fmt [, arg1, ... ] ) + * char *fmt; + * u_int arg1, ...; + * + * printf("prefix: %r, other stuff\n", fmt, &arg1); */ +#if defined(tahoe) +int consintr; +#endif + /*VARARGS1*/ printf(fmt, x1) -register char *fmt; -unsigned x1; + char *fmt; + unsigned x1; { +#if defined(tahoe) + register int savintr; - prf(fmt, &x1, 0); + savintr = consintr, consintr = 0; /* disable interrupts */ +#endif + prf(fmt, &x1, TOCONS | TOLOG, (struct tty *)0); + logwakeup(); +#if defined(tahoe) + consintr = savintr; /* reenable interrupts */ +#endif } -#ifdef TRACE -trace(fmt, x1) -register char *fmt; -unsigned x1; +/* + * Uprintf prints to the current user's terminal. + * It may block if the tty queue is overfull. + * No message is printed if the queue does not clear + * in a reasonable time. + * Should determine whether current terminal user is related + * to this process. + */ +/*VARARGS1*/ +uprintf(fmt, x1) + char *fmt; + unsigned x1; { +#ifdef notdef + register struct proc *p; +#endif + register struct tty *tp; - prf(fmt, &x1, 1); + if ((tp = u.u_ttyp) == NULL) + return; +#ifdef notdef + if (tp->t_pgrp && (p = pfind(tp->t_pgrp))) + if (p->p_uid != u.u_uid) /* doesn't account for setuid */ + return; +#endif + if (ttycheckoutq(tp, 1)) + prf(fmt, &x1, TOTTY, tp); } -#endif +/* + * tprintf prints on the specified terminal (console if none) + * and logs the message. It is designed for error messages from + * single-open devices, and may be called from interrupt level + * (does not sleep). + */ +/*VARARGS2*/ +tprintf(tp, fmt, x1) + register struct tty *tp; + char *fmt; + unsigned x1; +{ + int flags = TOTTY | TOLOG; + + logpri(LOG_INFO); + if (tp == (struct tty *)NULL) { + tp = constty; + if (tp == (struct tty *)NULL) + tp = &cons; + } + if (ttycheckoutq(tp, 0) == 0) + flags = TOLOG; + prf(fmt, &x1, flags, tp); + logwakeup(); +} -prf(fmt, adx, trace) -register char *fmt; -register unsigned int *adx; +/* + * Log writes to the log buffer, + * and guarantees not to sleep (so can be called by interrupt routines). + * If there is no process reading the log yet, it writes to the console also. + */ +/*VARARGS2*/ +log(level, fmt, x1) + char *fmt; + unsigned x1; +{ + register s = splhigh(); + extern int log_open; + + logpri(level); + prf(fmt, &x1, TOLOG, (struct tty *)0); + splx(s); + if (!log_open) + prf(fmt, &x1, TOCONS, (struct tty *)0); + logwakeup(); +} + +logpri(level) + int level; +{ + + putchar('<', TOLOG, (struct tty *)0); + printn((u_long)level, 10, TOLOG, (struct tty *)0); + putchar('>', TOLOG, (struct tty *)0); +} + +/*VARARGS1*/ +addlog(fmt, x1) + char *fmt; + unsigned x1; { - register c; + register s = splhigh(); + + prf(fmt, &x1, TOLOG, (struct tty *)0); + splx(s); + if (!log_open) + prf(fmt, &x1, TOCONS, (struct tty *)0); + logwakeup(); +} + +prf(fmt, adx, flags, ttyp) + register char *fmt; + register u_int *adx; + struct tty *ttyp; +{ + register int b, c, i; char *s; + int any; loop: - while((c = *fmt++) != '%') { - if(c == '\0') + while ((c = *fmt++) != '%') { + if (c == '\0') return; - putchar(c, trace); + putchar(c, flags, ttyp); } +again: c = *fmt++; - if (c == 'X') - printx((long)*adx, trace); - else if (c == 'd' || c == 'u' || c == 'o' || c == 'x') - printn((long)*adx, c=='o'? 8: (c=='x'? 16:10), trace); - else if (c == 's') { + /* THIS CODE IS MACHINE DEPENDENT IN HANDLING %l? AND %c */ + switch (c) { + + case 'l': + goto again; + case 'x': case 'X': + b = 16; + goto number; + case 'd': case 'D': + b = -10; + goto number; + case 'u': + b = 10; + goto number; + case 'o': case 'O': + b = 8; +number: + printn((u_long)*adx, b, flags, ttyp); + break; + case 'c': + b = *adx; +#if BYTE_ORDER == LITTLE_ENDIAN + for (i = 24; i >= 0; i -= 8) + if (c = (b >> i) & 0x7f) + putchar(c, flags, ttyp); +#endif +#if BYTE_ORDER == BIG_ENDIAN + if (c = (b & 0x7f)) + putchar(c, flags, ttyp); +#endif + break; + case 'b': + b = *adx++; + s = (char *)*adx; + printn((u_long)b, *s++, flags, ttyp); + any = 0; + if (b) { + while (i = *s++) { + if (b & (1 << (i-1))) { + putchar(any ? ',' : '<', flags, ttyp); + any = 1; + for (; (c = *s) > 32; s++) + putchar(c, flags, ttyp); + } else + for (; *s > 32; s++) + ; + } + if (any) + putchar('>', flags, ttyp); + } + break; + + case 's': s = (char *)*adx; while (c = *s++) -#ifdef TRACE - if (trace == 1) { - *trcbufp++ = c; - if (trcbufp >= &trcbuf[TRCBUFS]) { - trcbufp = trcbuf; - trcwrap = 1; - } - } else -#endif - putchar(c, trace); - } else if (c == 'D') { - printn(*(long *)adx, 10, trace); - adx += (sizeof(long) / sizeof(int)) - 1; + putchar(c, flags, ttyp); + break; + + case 'r': + s = (char *)*adx++; + prf(s, (u_int *)*adx, flags, ttyp); + break; + + case '%': + putchar('%', flags, ttyp); + break; } adx++; goto loop; } -printx(x, trace) -long x; -{ - int i; - - for (i = 0; i < 8; i++) - putchar("0123456789ABCDEF"[(x>>((7-i)*4))&0xf], trace); -} - /* - * Print an integer in base b. If the base is ten it is condidered a - * signed integer otherwise it is treated as unsigned. + * Printn prints a number n in base b. + * We don't use recursion to avoid deep kernel stacks. */ -printn(n, b, trace) -unsigned long n; +printn(n, b, flags, ttyp) + u_long n; + struct tty *ttyp; { - register unsigned long a; - register long a1 = n; + char prbuf[11]; + register char *cp; - if (b == 10 && a1 < 0) { - putchar('-', trace); - n = -a1; + if (b == -10) { + if ((int)n < 0) { + putchar('-', flags, ttyp); + n = (unsigned)(-(int)n); + } + b = -b; } - if(a = n/b) - printn(a, b, trace); - putchar("0123456789ABCDEF"[(int)(n%b)], trace); + cp = prbuf; + do { + *cp++ = "0123456789abcdef"[n%b]; + n /= b; + } while (n); + do + putchar(*--cp, flags, ttyp); + while (cp > prbuf); } /* * Panic is called on unresolvable fatal errors. - * It syncs, prints "panic: mesg", and then reboots. + * It prints "panic: mesg", and then reboots. + * If we are called twice, then we avoid trying to + * sync the disks as this often leads to recursive panics. */ panic(s) -char *s; + char *s; { - panicstr = s; - printf("panic: %s\n", s); - (void) spl0(); - for(;;) - boot(RB_PANIC, RB_AUTOBOOT); -} + int bootopt = RB_AUTOBOOT | RB_DUMP; -/* - * prdev prints a warning message of the - * form "mesg on dev x/y". - * x and y are the major and minor parts of - * the device argument. - */ -prdev(str, dev) -char *str; -dev_t dev; -{ + if (panicstr) + bootopt |= RB_NOSYNC; + else { + panicstr = s; + } + printf("panic: %s\n", s); +#ifdef KADB + if (boothowto & RB_KDB) { + int x = splnet(); /* below kdb pri */ - printf("%s on dev %u/%u\n", str, major(dev), minor(dev)); + setsoftkdb(); + splx(x); + } +#endif + boot(bootopt); } /* - * deverr prints a diagnostic from - * a device driver. - * It prints the device, block number, - * and an octal word (usually some error - * status register) passed as argument. + * Warn that a system table is full. */ -deverror(bp, o1, o2) -register struct buf *bp; +tablefull(tab) + char *tab; { - printf("bn=%d er=%x,%x", bp->b_blkno, o1,o2); - prdev("", bp->b_dev); -} - -#ifdef TRACE -dumptrc() -{ - register char *cp; - register int pos, nch; - - nch = trcprt; - if (nch < 0 || nch > TRCBUFS) - nch = TRCBUFS; - pos = (trcbufp - trcbuf) - nch; - if (pos < 0) - if (trcwrap) - pos += TRCBUFS; - else { - nch += pos; - pos = 0; - } - for (cp = &trcbuf[pos]; nch > 0; nch--) { - putchar(*cp++, 0); - if (cp >= &trcbuf[TRCBUFS]) - cp = trcbuf; - } + log(LOG_ERR, "%s: table is full\n", tab); } -#else -/*ARGSUSED*/ -dumptrc(nch) - int nch; -{ - -} -#endif /* - * Print a character on console or in internal trace buffer. + * Print a character on console or users terminal. * If destination is console then the last MSGBUFS characters * are saved in msgbuf for inspection later. */ /*ARGSUSED*/ -putchar(c, trace) -register c; +putchar(c, flags, tp) + register int c; + struct tty *tp; { + extern int msgbufmapped; - if (trace == 2) { - register struct tty *tp; - register s; + if (panicstr) + constty = 0; + if ((flags & TOCONS) && tp == 0 && constty) { + tp = constty; + flags |= TOTTY; + } + if ((flags & TOCONS) && panicstr == 0 && tp == 0 && constty) { + tp = constty; + flags |= TOTTY; + } + if (flags & TOTTY) { + register s = spltty(); - if ((tp = u.u_ttyp) && (tp->t_state&CARR_ON)) { - s = spl7(); - ttyoutput(c, tp); + if (tp && (tp->t_state & (TS_CARR_ON | TS_ISOPEN)) == + (TS_CARR_ON | TS_ISOPEN)) { + if (c == '\n') + (void) ttyoutput('\r', tp); + (void) ttyoutput(c, tp); ttstart(tp); - splx(s); - } - return; - } -#ifdef TRACE - if (trace) { - *trcbufp++ = c; - if (trcbufp >= &trcbuf[TRCBUFS]) { - trcbufp = trcbuf; - trcwrap = 1; - } - return; + flags &= ~TOCONS; + } else if ((flags & TOCONS) && tp == constty) + constty = 0; + splx(s); } -#endif - if (c != '\0' && c != '\r' && c != 0177) { + if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177 && + msgbufmapped) { if (msgbuf.msg_magic != MSG_MAGIC) { - msgbuf.msg_bufx = 0; + register int i; + msgbuf.msg_magic = MSG_MAGIC; + msgbuf.msg_bufx = msgbuf.msg_bufr = 0; + for (i=0; i < MSG_BSIZE; i++) + msgbuf.msg_bufc[i] = 0; } + msgbuf.msg_bufc[msgbuf.msg_bufx++] = c; if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE) msgbuf.msg_bufx = 0; - msgbuf.msg_bufc[msgbuf.msg_bufx++] = c; } - if (c == 0) - return; - cnputc(c); -} - -/* - * print to the current users terminal, - * guarantee not to sleep (so can be called by intr routine) - * no watermark checking - so no verbose messages - */ - -/*VARARGS1*/ -uprintf(fmt, x1) -char *fmt; -unsigned x1; -{ - prf(fmt, &x1, 2); + (*v_console)(c); }