1: /* 2: * Copyright (c) 1982, 1986 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.1 (Berkeley) 6/5/86 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 "dir.h" 18: #include "user.h" 19: #include "proc.h" 20: #include "ioctl.h" 21: #include "tty.h" 22: #include "syslog.h" 23: 24: #ifdef vax 25: #include "../vax/mtpr.h" 26: #endif 27: 28: #define TOCONS 0x1 29: #define TOTTY 0x2 30: #define TOLOG 0x4 31: 32: /* 33: * In case console is off, 34: * panicstr contains argument to last 35: * call to panic. 36: */ 37: char *panicstr; 38: 39: /* 40: * Scaled down version of C Library printf. 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: 55: * reg=3<BITTWO,BITONE> 56: */ 57: /*VARARGS1*/ 58: printf(fmt, x1) 59: char *fmt; 60: unsigned x1; 61: { 62: 63: prf(fmt, &x1, TOCONS | TOLOG, (struct tty *)0); 64: logwakeup(); 65: } 66: 67: /* 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. 72: */ 73: /*VARARGS1*/ 74: uprintf(fmt, x1) 75: char *fmt; 76: unsigned x1; 77: { 78: #ifdef notdef 79: register struct proc *p; 80: #endif 81: register struct tty *tp; 82: 83: if ((tp = u.u_ttyp) == NULL) 84: return; 85: #ifdef notdef 86: if (tp->t_pgrp && (p = pfind(tp->t_pgrp))) 87: if (p->p_uid != u.u_uid) /* doesn't account for setuid */ 88: return; 89: #endif 90: (void)ttycheckoutq(tp, 1); 91: prf(fmt, &x1, TOTTY, tp); 92: } 93: 94: /* 95: * tprintf prints on the specified terminal (console if none) 96: * and logs the message. It is designed for error messages from 97: * single-open devices, and may be called from interrupt level 98: * (does not sleep). 99: */ 100: /*VARARGS2*/ 101: tprintf(tp, fmt, x1) 102: register struct tty *tp; 103: char *fmt; 104: unsigned x1; 105: { 106: int flags = TOTTY | TOLOG; 107: extern struct tty cons; 108: 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(); 116: } 117: 118: /* 119: * Log writes to the log buffer, 120: * and guarantees not to sleep (so can be called by interrupt routines). 121: * If there is no process reading the log yet, it writes to the console also. 122: */ 123: /*VARARGS2*/ 124: log(level, fmt, x1) 125: char *fmt; 126: unsigned x1; 127: { 128: register s = splhigh(); 129: extern int log_open; 130: 131: logpri(level); 132: prf(fmt, &x1, TOLOG, (struct tty *)0); 133: splx(s); 134: if (!log_open) 135: prf(fmt, &x1, TOCONS, (struct tty *)0); 136: logwakeup(); 137: } 138: 139: logpri(level) 140: int level; 141: { 142: 143: putchar('<', TOLOG, (struct tty *)0); 144: printn((u_long)level, 10, TOLOG, (struct tty *)0); 145: putchar('>', TOLOG, (struct tty *)0); 146: } 147: 148: prf(fmt, adx, flags, ttyp) 149: register char *fmt; 150: register u_int *adx; 151: struct tty *ttyp; 152: { 153: register int b, c, i; 154: char *s; 155: int any; 156: 157: loop: 158: while ((c = *fmt++) != '%') { 159: if (c == '\0') 160: return; 161: putchar(c, flags, ttyp); 162: } 163: again: 164: c = *fmt++; 165: /* THIS CODE IS VAX DEPENDENT IN HANDLING %l? AND %c */ 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: 180: printn((u_long)*adx, b, flags, ttyp); 181: break; 182: case 'c': 183: b = *adx; 184: for (i = 24; i >= 0; i -= 8) 185: if (c = (b >> i) & 0x7f) 186: putchar(c, flags, ttyp); 187: break; 188: case 'b': 189: b = *adx++; 190: s = (char *)*adx; 191: printn((u_long)b, *s++, flags, ttyp); 192: any = 0; 193: if (b) { 194: while (i = *s++) { 195: if (b & (1 << (i-1))) { 196: putchar(any? ',' : '<', flags, ttyp); 197: any = 1; 198: for (; (c = *s) > 32; s++) 199: putchar(c, flags, ttyp); 200: } else 201: for (; *s > 32; s++) 202: ; 203: } 204: if (any) 205: putchar('>', flags, ttyp); 206: } 207: break; 208: 209: case 's': 210: s = (char *)*adx; 211: while (c = *s++) 212: putchar(c, flags, ttyp); 213: break; 214: 215: case '%': 216: putchar('%', flags, ttyp); 217: break; 218: } 219: adx++; 220: goto loop; 221: } 222: 223: /* 224: * Printn prints a number n in base b. 225: * We don't use recursion to avoid deep kernel stacks. 226: */ 227: printn(n, b, flags, ttyp) 228: u_long n; 229: struct tty *ttyp; 230: { 231: char prbuf[11]; 232: register char *cp; 233: 234: if (b == 10 && (int)n < 0) { 235: putchar('-', flags, ttyp); 236: n = (unsigned)(-(int)n); 237: } 238: cp = prbuf; 239: do { 240: *cp++ = "0123456789abcdef"[n%b]; 241: n /= b; 242: } while (n); 243: do 244: putchar(*--cp, flags, ttyp); 245: while (cp > prbuf); 246: } 247: 248: /* 249: * Panic is called on unresolvable fatal errors. 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. 253: */ 254: panic(s) 255: char *s; 256: { 257: int bootopt = RB_AUTOBOOT; 258: 259: if (panicstr) 260: bootopt |= RB_NOSYNC; 261: else { 262: panicstr = s; 263: } 264: printf("panic: %s\n", s); 265: boot(RB_PANIC, bootopt); 266: } 267: 268: /* 269: * Warn that a system table is full. 270: */ 271: tablefull(tab) 272: char *tab; 273: { 274: 275: log(LOG_ERR, "%s: table is full\n", tab); 276: } 277: 278: /* 279: * Hard error is the preface to plaintive error messages 280: * about failing disk transfers. 281: */ 282: harderr(bp, cp) 283: struct buf *bp; 284: char *cp; 285: { 286: 287: printf("%s%d%c: hard error sn%d ", cp, 288: minor(bp->b_dev) >> 3, 'a'+(minor(bp->b_dev)&07), bp->b_blkno); 289: } 290: 291: /* 292: * Print a character on console or users terminal. 293: * If destination is console then the last MSGBUFS characters 294: * are saved in msgbuf for inspection later. 295: */ 296: /*ARGSUSED*/ 297: putchar(c, flags, tp) 298: register int c; 299: struct tty *tp; 300: { 301: 302: if (flags & TOTTY) { 303: register s = spltty(); 304: 305: if (tp && (tp->t_state & (TS_CARR_ON | TS_ISOPEN)) == 306: (TS_CARR_ON | TS_ISOPEN)) { 307: if (c == '\n') 308: (void) ttyoutput('\r', tp); 309: (void) ttyoutput(c, tp); 310: ttstart(tp); 311: } 312: splx(s); 313: } 314: if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177 315: #ifdef vax 316: && mfpr(MAPEN) 317: #endif 318: ) { 319: if (msgbuf.msg_magic != MSG_MAGIC) { 320: register int i; 321: 322: msgbuf.msg_magic = MSG_MAGIC; 323: msgbuf.msg_bufx = msgbuf.msg_bufr = 0; 324: for (i=0; i < MSG_BSIZE; i++) 325: msgbuf.msg_bufc[i] = 0; 326: } 327: msgbuf.msg_bufc[msgbuf.msg_bufx++] = c; 328: if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE) 329: msgbuf.msg_bufx = 0; 330: } 331: if ((flags & TOCONS) && c != '\0') 332: cnputc(c); 333: }