1: /* 2: * Copyright (c) 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 1.2 (2.11BSD) 1998/12/5 7: */ 8: 9: #include "param.h" 10: #include "user.h" 11: #include "machine/seg.h" 12: #include "buf.h" 13: #include "msgbuf.h" 14: #include "conf.h" 15: #include "ioctl.h" 16: #include "tty.h" 17: #include "reboot.h" 18: #include "systm.h" 19: #include "syslog.h" 20: 21: #define TOCONS 0x1 22: #define TOTTY 0x2 23: #define TOLOG 0x4 24: 25: /* 26: * In case console is off, 27: * panicstr contains argument to last 28: * call to panic. 29: */ 30: char *panicstr; 31: 32: /* 33: * Scaled down version of C Library printf. 34: * Used to print diagnostic information directly on console tty. 35: * Since it is not interrupt driven, all system activities are 36: * suspended. Printf should not be used for chit-chat. 37: * 38: * One additional format: %b is supported to decode error registers. 39: * Usage is: 40: * printf("reg=%b\n", regval, "<base><arg>*"); 41: * Where <base> is the output base expressed as a control character, 42: * e.g. \10 gives octal; \20 gives hex. Each arg is a sequence of 43: * characters, the first of which gives the bit number to be inspected 44: * (origin 1), and the next characters (up to a control character, i.e. 45: * a character <= 32), give the name of the register. Thus 46: * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 47: * would produce output: 48: * reg=3<BITTWO,BITONE> 49: */ 50: 51: /*VARARGS1*/ 52: printf(fmt, x1) 53: char *fmt; 54: unsigned x1; 55: { 56: prf(fmt, &x1, TOCONS | TOLOG, (struct tty *)0); 57: } 58: 59: /* 60: * Uprintf prints to the current user's terminal, 61: * guarantees not to sleep (so could be called by interrupt routines; 62: * but prints on the tty of the current process) 63: * and does no watermark checking - (so no verbose messages). 64: * NOTE: with current kernel mapping scheme, the user structure is 65: * not guaranteed to be accessible at interrupt level (see seg.h); 66: * a savemap/restormap would be needed here or in putchar if uprintf 67: * was to be used at interrupt time. 68: */ 69: /*VARARGS1*/ 70: uprintf(fmt, x1) 71: char *fmt; 72: unsigned x1; 73: { 74: register struct tty *tp; 75: 76: if ((tp = u.u_ttyp) == NULL) 77: return; 78: 79: if (ttycheckoutq(tp, 1)) 80: prf(fmt, &x1, TOTTY, tp); 81: } 82: 83: /* 84: * tprintf prints on the specified terminal (console if none) 85: * and logs the message. It is designed for error messages from 86: * single-open devices, and may be called from interrupt level 87: * (does not sleep). 88: */ 89: /*VARARGS2*/ 90: tprintf(tp, fmt, x1) 91: register struct tty *tp; 92: char *fmt; 93: unsigned x1; 94: { 95: int flags = TOTTY | TOLOG; 96: extern struct tty cons; 97: 98: logpri(LOG_INFO); 99: if (tp == (struct tty *)NULL) 100: tp = &cons; 101: if (ttycheckoutq(tp, 0) == 0) 102: flags = TOLOG; 103: prf(fmt, &x1, flags, tp); 104: logwakeup(logMSG); 105: } 106: 107: /* 108: * Log writes to the log buffer, 109: * and guarantees not to sleep (so can be called by interrupt routines). 110: * If there is no process reading the log yet, it writes to the console also. 111: */ 112: /*VARARGS2*/ 113: log(level, fmt, x1) 114: char *fmt; 115: unsigned x1; 116: { 117: register s = splhigh(); 118: 119: logpri(level); 120: prf(fmt, &x1, TOLOG, (struct tty *)0); 121: splx(s); 122: if (!logisopen(logMSG)) 123: prf(fmt, &x1, TOCONS, (struct tty *)0); 124: logwakeup(logMSG); 125: } 126: 127: logpri(level) 128: int level; 129: { 130: 131: putchar('<', TOLOG, (struct tty *)0); 132: printn((u_long)level, 10, TOLOG, (struct tty *)0); 133: putchar('>', TOLOG, (struct tty *)0); 134: } 135: 136: prf(fmt, adx, flags, ttyp) 137: register char *fmt; 138: register u_int *adx; 139: int flags; 140: struct tty *ttyp; 141: { 142: register int c; 143: u_int b; 144: char *s; 145: int i, any; 146: 147: loop: 148: while ((c = *fmt++) != '%') { 149: if (c == '\0') 150: return; 151: putchar(c, flags, ttyp); 152: } 153: c = *fmt++; 154: switch (c) { 155: 156: case 'l': 157: c = *fmt++; 158: switch(c) { 159: case 'x': 160: b = 16; 161: goto lnumber; 162: case 'd': 163: b = 10; 164: goto lnumber; 165: case 'o': 166: b = 8; 167: goto lnumber; 168: default: 169: putchar('%', flags, ttyp); 170: putchar('l', flags, ttyp); 171: putchar(c, flags, ttyp); 172: } 173: break; 174: case 'X': 175: b = 16; 176: goto lnumber; 177: case 'D': 178: b = 10; 179: goto lnumber; 180: case 'O': 181: b = 8; 182: lnumber: printn(*(long *)adx, b, flags, ttyp); 183: adx += (sizeof(long) / sizeof(int)) - 1; 184: break; 185: case 'x': 186: b = 16; 187: goto number; 188: case 'd': 189: case 'u': /* what a joke */ 190: b = 10; 191: goto number; 192: case 'o': 193: b = 8; 194: number: printn((long)*adx, b, flags, ttyp); 195: break; 196: case 'c': 197: putchar(*adx, flags, ttyp); 198: break; 199: case 'b': 200: b = *adx++; 201: s = (char *)*adx; 202: printn((long)b, *s++, flags, ttyp); 203: any = 0; 204: if (b) { 205: while (i = *s++) { 206: if (b & (1 << (i - 1))) { 207: putchar(any? ',' : '<', flags, ttyp); 208: any = 1; 209: for (; (c = *s) > 32; s++) 210: putchar(c, flags, ttyp); 211: } else 212: for (; *s > 32; s++) 213: ; 214: } 215: if (any) 216: putchar('>', flags, ttyp); 217: } 218: break; 219: case 's': 220: s = (char *)*adx; 221: while (c = *s++) 222: putchar(c, flags, ttyp); 223: break; 224: case '%': 225: putchar(c, flags, ttyp); 226: break; 227: default: 228: putchar('%', flags, ttyp); 229: putchar(c, flags, ttyp); 230: break; 231: } 232: adx++; 233: goto loop; 234: } 235: 236: /* 237: * Printn prints a number n in base b. 238: * We don't use recursion to avoid deep kernels stacks. 239: */ 240: printn(n, b, flags, ttyp) 241: long n; 242: u_int b; 243: struct tty *ttyp; 244: { 245: char prbuf[12]; 246: register char *cp = prbuf; 247: register int offset = 0; 248: 249: if (n<0) 250: switch(b) { 251: case 8: /* unchecked, but should be like hex case */ 252: case 16: 253: offset = b-1; 254: n++; 255: break; 256: case 10: 257: putchar('-', flags, ttyp); 258: n = -n; 259: break; 260: } 261: do { 262: *cp++ = "0123456789ABCDEF"[offset + n%b]; 263: } while (n = n/b); /* Avoid n /= b, since that requires alrem */ 264: do 265: putchar(*--cp, flags, ttyp); 266: while (cp > prbuf); 267: } 268: 269: /* 270: * Panic is called on unresolvable fatal errors. 271: * It prints "panic: mesg", and then reboots. 272: * If we are called twice, then we avoid trying to 273: * sync the disks as this often leads to recursive panics. 274: */ 275: panic(s) 276: char *s; 277: { 278: int bootopt = RB_AUTOBOOT|RB_DUMP; 279: 280: if (panicstr) 281: bootopt |= RB_NOSYNC; 282: else { 283: panicstr = s; 284: } 285: printf("panic: %s\n", s); 286: boot(rootdev, bootopt); 287: } 288: 289: /* 290: * Warn that a system table is full. 291: */ 292: tablefull(tab) 293: char *tab; 294: { 295: log(LOG_ERR, "%s: table full\n", tab); 296: } 297: 298: /* 299: * Hard error is the preface to plaintive error messages 300: * about failing disk tranfers. 301: */ 302: harderr(bp, cp) 303: struct buf *bp; 304: char *cp; 305: { 306: printf("%s%d%c: hard error sn%D ", cp, 307: minor(bp->b_dev) >> 3, 'a'+(minor(bp->b_dev) & 07), bp->b_blkno); 308: } 309: 310: /* 311: * Print a character on console or users terminal. 312: * If destination is console then the last MSGBUFS characters 313: * are saved in msgbuf for inspection later. 314: */ 315: putchar(c, flags, tp) 316: int c, flags; 317: register struct tty *tp; 318: { 319: 320: if (flags & TOTTY) { 321: register int s = spltty(); 322: 323: if (tp && (tp->t_state & (TS_CARR_ON | TS_ISOPEN)) == 324: (TS_CARR_ON | TS_ISOPEN)) { 325: if (c == '\n') 326: (void) ttyoutput('\r', tp); 327: (void) ttyoutput(c, tp); 328: ttstart(tp); 329: } 330: splx(s); 331: } 332: if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177) 333: logwrt(&c, 1, logMSG); 334: if ((flags & TOCONS) && c != '\0') 335: cnputc(c); 336: }