|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986, 1988 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.18 (Berkeley) 6/28/90 ! 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 "user.h" ! 18: #include "proc.h" ! 19: #include "ioctl.h" ! 20: #include "vnode.h" ! 21: #include "file.h" ! 22: #include "tty.h" ! 23: #include "tprintf.h" ! 24: #include "syslog.h" ! 25: #include "malloc.h" ! 26: ! 27: #include "machine/mtpr.h" ! 28: #ifdef KADB ! 29: #include "machine/kdbparam.h" ! 30: #endif ! 31: ! 32: #define TOCONS 0x1 ! 33: #define TOTTY 0x2 ! 34: #define TOLOG 0x4 ! 35: ! 36: /* ! 37: * In case console is off, ! 38: * panicstr contains argument to last ! 39: * call to panic. ! 40: */ ! 41: char *panicstr; ! 42: ! 43: extern cnputc(); /* standard console putc */ ! 44: int (*v_putc)() = cnputc; /* routine to putc on virtual console */ ! 45: extern struct tty cons; /* standard console tty */ ! 46: struct tty *constty; /* pointer to console "window" tty */ ! 47: ! 48: #ifdef KADB ! 49: extern cngetc(); /* standard console getc */ ! 50: extern cnpoll(); ! 51: int (*v_getc)() = cngetc; /* "" getc from virtual console */ ! 52: int (*v_poll)() = cnpoll; /* kdb hook to enable input polling */ ! 53: #endif ! 54: ! 55: /* ! 56: * Scaled down version of C Library printf. ! 57: * Used to print diagnostic information directly on console tty. ! 58: * Since it is not interrupt driven, all system activities are ! 59: * suspended. Printf should not be used for chit-chat. ! 60: * ! 61: * One additional format: %b is supported to decode error registers. ! 62: * Usage is: ! 63: * printf("reg=%b\n", regval, "<base><arg>*"); ! 64: * Where <base> is the output base expressed as a control character, ! 65: * e.g. \10 gives octal; \20 gives hex. Each arg is a sequence of ! 66: * characters, the first of which gives the bit number to be inspected ! 67: * (origin 1), and the next characters (up to a control character, i.e. ! 68: * a character <= 32), give the name of the register. Thus ! 69: * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); ! 70: * would produce output: ! 71: * reg=3<BITTWO,BITONE> ! 72: * ! 73: * Another additional format: %r is used to pass an additional format string ! 74: * and argument list recursively. Usage is typically: ! 75: * ! 76: * fn(otherstuff, fmt [, arg1, ... ] ) ! 77: * char *fmt; ! 78: * u_int arg1, ...; ! 79: * ! 80: * printf("prefix: %r, other stuff\n", fmt, &arg1); ! 81: */ ! 82: #if defined(tahoe) ! 83: int consintr; ! 84: #endif ! 85: ! 86: /*VARARGS1*/ ! 87: printf(fmt, x1) ! 88: char *fmt; ! 89: unsigned x1; ! 90: { ! 91: #if defined(tahoe) ! 92: register int savintr; ! 93: ! 94: savintr = consintr, consintr = 0; /* disable interrupts */ ! 95: #endif ! 96: prf(fmt, &x1, TOCONS | TOLOG, (struct tty *)NULL); ! 97: if (!panicstr) ! 98: logwakeup(); ! 99: #if defined(tahoe) ! 100: consintr = savintr; /* reenable interrupts */ ! 101: #endif ! 102: } ! 103: ! 104: /* ! 105: * Uprintf prints to the controlling terminal for the current process. ! 106: * It may block if the tty queue is overfull. ! 107: * No message is printed if the queue does not clear ! 108: * in a reasonable time. ! 109: */ ! 110: /*VARARGS1*/ ! 111: uprintf(fmt, x1) ! 112: char *fmt; ! 113: unsigned x1; ! 114: { ! 115: register struct proc *p = u.u_procp; ! 116: ! 117: if (p->p_flag & SCTTY && p->p_session->s_ttyvp) ! 118: prf(fmt, &x1, TOTTY, p->p_session->s_ttyp); ! 119: } ! 120: ! 121: tpr_t ! 122: tprintf_open() ! 123: { ! 124: register struct proc *p = u.u_procp; ! 125: ! 126: if (p->p_flag & SCTTY && p->p_session->s_ttyvp) { ! 127: SESSHOLD(p->p_session); ! 128: return ((tpr_t)p->p_session); ! 129: } else ! 130: return ((tpr_t)NULL); ! 131: } ! 132: ! 133: tprintf_close(sess) ! 134: tpr_t sess; ! 135: { ! 136: if (sess) ! 137: SESSRELE(sess); ! 138: } ! 139: ! 140: /* ! 141: * tprintf prints on the controlling terminal associated ! 142: * with the given session. ! 143: */ ! 144: /*VARARGS2*/ ! 145: tprintf(sess, fmt, x1) ! 146: register tpr_t sess; ! 147: char *fmt; ! 148: unsigned x1; ! 149: { ! 150: int flags = TOLOG; ! 151: ! 152: logpri(LOG_INFO); ! 153: ! 154: if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) ! 155: flags |= TOTTY; ! 156: prf(fmt, &x1, flags, sess->s_ttyp); ! 157: logwakeup(); ! 158: } ! 159: ! 160: ! 161: /* ! 162: * Log writes to the log buffer, ! 163: * and guarantees not to sleep (so can be called by interrupt routines). ! 164: * If there is no process reading the log yet, it writes to the console also. ! 165: */ ! 166: /*VARARGS2*/ ! 167: log(level, fmt, x1) ! 168: char *fmt; ! 169: unsigned x1; ! 170: { ! 171: register s = splhigh(); ! 172: extern int log_open; ! 173: ! 174: logpri(level); ! 175: prf(fmt, &x1, TOLOG, (struct tty *)NULL); ! 176: splx(s); ! 177: if (!log_open) ! 178: prf(fmt, &x1, TOCONS, (struct tty *)NULL); ! 179: logwakeup(); ! 180: } ! 181: ! 182: logpri(level) ! 183: int level; ! 184: { ! 185: ! 186: putchar('<', TOLOG, (struct tty *)NULL); ! 187: printn((u_long)level, 10, TOLOG, (struct tty *)NULL); ! 188: putchar('>', TOLOG, (struct tty *)NULL); ! 189: } ! 190: ! 191: /*VARARGS1*/ ! 192: addlog(fmt, x1) ! 193: char *fmt; ! 194: unsigned x1; ! 195: { ! 196: register s = splhigh(); ! 197: ! 198: prf(fmt, &x1, TOLOG, (struct tty *)NULL); ! 199: splx(s); ! 200: if (!log_open) ! 201: prf(fmt, &x1, TOCONS, (struct tty *)NULL); ! 202: logwakeup(); ! 203: } ! 204: ! 205: prf(fmt, adx, flags, ttyp) ! 206: register char *fmt; ! 207: register u_int *adx; ! 208: struct tty *ttyp; ! 209: { ! 210: register int b, c, i; ! 211: char *s; ! 212: int any; ! 213: ! 214: loop: ! 215: while ((c = *fmt++) != '%') { ! 216: if (c == '\0') ! 217: return; ! 218: putchar(c, flags, ttyp); ! 219: } ! 220: again: ! 221: c = *fmt++; ! 222: /* THIS CODE IS MACHINE DEPENDENT IN HANDLING %l? AND %c */ ! 223: switch (c) { ! 224: ! 225: case 'l': ! 226: goto again; ! 227: case 'x': case 'X': ! 228: b = 16; ! 229: goto number; ! 230: case 'd': case 'D': ! 231: b = -10; ! 232: goto number; ! 233: case 'u': ! 234: b = 10; ! 235: goto number; ! 236: case 'o': case 'O': ! 237: b = 8; ! 238: number: ! 239: printn((u_long)*adx, b, flags, ttyp); ! 240: break; ! 241: case 'c': ! 242: b = *adx; ! 243: #if BYTE_ORDER == LITTLE_ENDIAN ! 244: for (i = 24; i >= 0; i -= 8) ! 245: if (c = (b >> i) & 0x7f) ! 246: putchar(c, flags, ttyp); ! 247: #endif ! 248: #if BYTE_ORDER == BIG_ENDIAN ! 249: if (c = (b & 0x7f)) ! 250: putchar(c, flags, ttyp); ! 251: #endif ! 252: break; ! 253: case 'b': ! 254: b = *adx++; ! 255: s = (char *)*adx; ! 256: printn((u_long)b, *s++, flags, ttyp); ! 257: any = 0; ! 258: if (b) { ! 259: while (i = *s++) { ! 260: if (b & (1 << (i-1))) { ! 261: putchar(any ? ',' : '<', flags, ttyp); ! 262: any = 1; ! 263: for (; (c = *s) > 32; s++) ! 264: putchar(c, flags, ttyp); ! 265: } else ! 266: for (; *s > 32; s++) ! 267: ; ! 268: } ! 269: if (any) ! 270: putchar('>', flags, ttyp); ! 271: } ! 272: break; ! 273: ! 274: case 's': ! 275: s = (char *)*adx; ! 276: while (c = *s++) ! 277: putchar(c, flags, ttyp); ! 278: break; ! 279: ! 280: case 'r': ! 281: s = (char *)*adx++; ! 282: prf(s, (u_int *)*adx, flags, ttyp); ! 283: break; ! 284: ! 285: case '%': ! 286: putchar('%', flags, ttyp); ! 287: break; ! 288: } ! 289: adx++; ! 290: goto loop; ! 291: } ! 292: ! 293: /* ! 294: * Printn prints a number n in base b. ! 295: * We don't use recursion to avoid deep kernel stacks. ! 296: */ ! 297: printn(n, b, flags, ttyp) ! 298: u_long n; ! 299: struct tty *ttyp; ! 300: { ! 301: char prbuf[11]; ! 302: register char *cp; ! 303: ! 304: if (b == -10) { ! 305: if ((int)n < 0) { ! 306: putchar('-', flags, ttyp); ! 307: n = (unsigned)(-(int)n); ! 308: } ! 309: b = -b; ! 310: } ! 311: cp = prbuf; ! 312: do { ! 313: *cp++ = "0123456789abcdef"[n%b]; ! 314: n /= b; ! 315: } while (n); ! 316: do ! 317: putchar(*--cp, flags, ttyp); ! 318: while (cp > prbuf); ! 319: } ! 320: ! 321: /* ! 322: * Panic is called on unresolvable fatal errors. ! 323: * It prints "panic: mesg", and then reboots. ! 324: * If we are called twice, then we avoid trying to ! 325: * sync the disks as this often leads to recursive panics. ! 326: */ ! 327: panic(s) ! 328: char *s; ! 329: { ! 330: int bootopt = RB_AUTOBOOT | RB_DUMP; ! 331: ! 332: if (panicstr) ! 333: bootopt |= RB_NOSYNC; ! 334: else { ! 335: panicstr = s; ! 336: } ! 337: printf("panic: %s\n", s); ! 338: #ifdef KADB ! 339: if (boothowto & RB_KDB) { ! 340: int x = splnet(); /* below kdb pri */ ! 341: ! 342: setsoftkdb(); ! 343: splx(x); ! 344: } ! 345: #endif ! 346: boot(bootopt); ! 347: } ! 348: ! 349: /* ! 350: * Warn that a system table is full. ! 351: */ ! 352: tablefull(tab) ! 353: char *tab; ! 354: { ! 355: ! 356: log(LOG_ERR, "%s: table is full\n", tab); ! 357: } ! 358: ! 359: /* ! 360: * Print a character on console or users terminal. ! 361: * If destination is console then the last MSGBUFS characters ! 362: * are saved in msgbuf for inspection later. ! 363: */ ! 364: /*ARGSUSED*/ ! 365: putchar(c, flags, ttyp) ! 366: register int c; ! 367: struct tty *ttyp; ! 368: { ! 369: extern int msgbufmapped; ! 370: ! 371: if (panicstr) ! 372: constty = 0; ! 373: if ((flags & TOCONS) && ttyp == NULL && constty) { ! 374: ttyp = constty; ! 375: flags |= TOTTY; ! 376: } ! 377: if ((flags & TOTTY) && ttyp && tputchar(c, ttyp) < 0 && ! 378: (flags & TOCONS) && ttyp == constty) ! 379: constty = 0; ! 380: if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177 && ! 381: msgbufmapped) { ! 382: if (msgbuf.msg_magic != MSG_MAGIC) { ! 383: register int i; ! 384: ! 385: msgbuf.msg_magic = MSG_MAGIC; ! 386: msgbuf.msg_bufx = msgbuf.msg_bufr = 0; ! 387: for (i=0; i < MSG_BSIZE; i++) ! 388: msgbuf.msg_bufc[i] = 0; ! 389: } ! 390: msgbuf.msg_bufc[msgbuf.msg_bufx++] = c; ! 391: if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE) ! 392: msgbuf.msg_bufx = 0; ! 393: } ! 394: if ((flags & TOCONS) && constty == 0 && c != '\0') ! 395: (*v_putc)(c); ! 396: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.