|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ ! 26: /*- ! 27: * Copyright (c) 1986, 1988, 1991, 1993 ! 28: * The Regents of the University of California. All rights reserved. ! 29: * (c) UNIX System Laboratories, Inc. ! 30: * All or some portions of this file are derived from material licensed ! 31: * to the University of California by American Telephone and Telegraph ! 32: * Co. or Unix System Laboratories, Inc. and are reproduced herein with ! 33: * the permission of UNIX System Laboratories, Inc. ! 34: * ! 35: * Redistribution and use in source and binary forms, with or without ! 36: * modification, are permitted provided that the following conditions ! 37: * are met: ! 38: * 1. Redistributions of source code must retain the above copyright ! 39: * notice, this list of conditions and the following disclaimer. ! 40: * 2. Redistributions in binary form must reproduce the above copyright ! 41: * notice, this list of conditions and the following disclaimer in the ! 42: * documentation and/or other materials provided with the distribution. ! 43: * 3. All advertising materials mentioning features or use of this software ! 44: * must display the following acknowledgement: ! 45: * This product includes software developed by the University of ! 46: * California, Berkeley and its contributors. ! 47: * 4. Neither the name of the University nor the names of its contributors ! 48: * may be used to endorse or promote products derived from this software ! 49: * without specific prior written permission. ! 50: * ! 51: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 52: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 53: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 54: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 55: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 56: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 57: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 58: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 59: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 60: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 61: * SUCH DAMAGE. ! 62: * ! 63: * @(#)subr_prf.c 8.4 (Berkeley) 5/4/95 ! 64: */ ! 65: /* HISTORY ! 66: * 22-Sep-1997 Umesh Vaishampayan ([email protected]) ! 67: * Cleaned up m68k crud. Fixed vlog() to do logpri() for ppc, too. ! 68: * ! 69: * 17-July-97 Umesh Vaishampayan ([email protected]) ! 70: * Eliminated multiple definition of constty which is defined ! 71: * in bsd/dev/XXX/cons.c ! 72: * ! 73: * 26-MAR-1997 Umesh Vaishampayan ([email protected] ! 74: * Fixed tharshing format in many functions. Cleanup. ! 75: * ! 76: * 17-Jun-1995 Mac Gillon (mgillon) at NeXT ! 77: * Purged old history ! 78: * New version based on 4.4 and NS3.3 ! 79: */ ! 80: ! 81: #include <cpus.h> ! 82: #include <cputypes.h> ! 83: ! 84: #include <sys/param.h> ! 85: #include <sys/systm.h> ! 86: #include <sys/buf.h> ! 87: #include <sys/conf.h> ! 88: #include <sys/reboot.h> ! 89: #include <sys/msgbuf.h> ! 90: #include <sys/proc.h> ! 91: #include <sys/ioctl.h> ! 92: #include <sys/tty.h> ! 93: #include <sys/file.h> ! 94: #include <sys/tprintf.h> ! 95: #include <sys/syslog.h> ! 96: #include <stdarg.h> ! 97: #include <sys/malloc.h> ! 98: #include <kern/lock.h> ! 99: #include <kern/parallel.h> ! 100: #import <sys/subr_prf.h> ! 101: ! 102: #include <machine/cpu.h> /* for cpu_number() */ ! 103: #include <machine/spl.h> ! 104: ! 105: /* ! 106: * In case console is off, ! 107: * panicstr contains argument to last ! 108: * call to panic. ! 109: */ ! 110: const char *panicstr; ! 111: ! 112: extern cnputc(); /* standard console putc */ ! 113: int (*v_putc)() = cnputc; /* routine to putc on virtual console */ ! 114: ! 115: extern struct tty cons; /* standard console tty */ ! 116: extern struct tty *constty; /* pointer to console "window" tty */ ! 117: ! 118: /* ! 119: * Record cpu that panic'd and lock around panic data ! 120: */ ! 121: decl_simple_lock_data(,panic_lock) ! 122: int paniccpu; ! 123: ! 124: static void puts(const char *s, int flags, struct tty *ttyp); ! 125: static void printn(u_long n, int b, int flags, struct tty *ttyp, int zf, int fld_size); ! 126: ! 127: /* MP printf stuff */ ! 128: decl_simple_lock_data(,printf_lock) ! 129: #if NCPUS > 1 ! 130: boolean_t new_printf_cpu_number; /* do we need to output who we are */ ! 131: #endif ! 132: ! 133: extern void logwakeup(); ! 134: extern void halt_cpu(); ! 135: #if NeXT ! 136: extern void mini_mon(); ! 137: #endif /* NeXT */ ! 138: extern boot(); ! 139: int putchar(); ! 140: ! 141: ! 142: /* ! 143: * Scaled down version of C Library printf. ! 144: * Used to print diagnostic information directly on console tty. ! 145: * Since it is not interrupt driven, all system activities are ! 146: * suspended. Printf should not be used for chit-chat. ! 147: * ! 148: * One additional format: %b is supported to decode error registers. ! 149: * Usage is: ! 150: * printf("reg=%b\n", regval, "<base><arg>*"); ! 151: * Where <base> is the output base expressed as a control character, ! 152: * e.g. \10 gives octal; \20 gives hex. Each arg is a sequence of ! 153: * characters, the first of which gives the bit number to be inspected ! 154: * (origin 1), and the next characters (up to a control character, i.e. ! 155: * a character <= 32), give the name of the register. Thus ! 156: * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); ! 157: * would produce output: ! 158: * reg=3<BITTWO,BITONE> ! 159: * ! 160: */ ! 161: ! 162: void printf(const char *format, ...) ! 163: { ! 164: va_list ap; ! 165: ! 166: va_start(ap, format); ! 167: prf(format, ap, TOCONS | TOLOG, (struct tty *)0); ! 168: va_end(ap); ! 169: ! 170: if (!panicstr) ! 171: logwakeup(); ! 172: } ! 173: ! 174: int sprintf(char *s, const char *format, ...) ! 175: { ! 176: char *sptr = s; ! 177: char *s0 = s; ! 178: va_list ap; ! 179: ! 180: va_start(ap, format); ! 181: prf(format, ap, TOSTR, (struct tty *)&sptr); ! 182: va_end(ap); ! 183: *sptr = 0; ! 184: return sptr - s0; ! 185: } ! 186: ! 187: /* ! 188: * Uprintf prints to the controlling terminal for the current process. ! 189: * It may block if the tty queue is overfull. No message is printed if ! 190: * the queue does not clear in a reasonable time. ! 191: */ ! 192: void ! 193: uprintf(const char *fmt, ...) ! 194: { ! 195: register struct proc *p = current_proc(); ! 196: va_list ap; ! 197: ! 198: unix_master(); /* sessions, sigh */ ! 199: if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) { ! 200: va_start(ap, fmt); ! 201: prf(fmt, ap, TOTTY, (struct tty *)p->p_session->s_ttyvp); ! 202: va_end(ap); ! 203: } ! 204: unix_release(); ! 205: } ! 206: ! 207: tpr_t ! 208: tprintf_open(p) ! 209: register struct proc *p; ! 210: { ! 211: unix_master(); /* sessions, sigh */ ! 212: if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) { ! 213: SESSHOLD(p->p_session); ! 214: unix_release(); ! 215: return ((tpr_t) p->p_session); ! 216: } ! 217: unix_release(); ! 218: return ((tpr_t) NULL); ! 219: } ! 220: ! 221: void ! 222: tprintf_close(sess) ! 223: tpr_t sess; ! 224: { ! 225: unix_master(); /* sessions, sigh */ ! 226: if (sess) ! 227: SESSRELE((struct session *) sess); ! 228: unix_release(); ! 229: } ! 230: ! 231: /* ! 232: * tprintf prints on the controlling terminal associated ! 233: * with the given session. ! 234: */ ! 235: void ! 236: tprintf(tpr_t tpr, const char *fmt, ...) ! 237: { ! 238: register struct session *sess = (struct session *)tpr; ! 239: struct tty *tp = NULL; ! 240: int flags = TOLOG; ! 241: va_list ap; ! 242: ! 243: logpri(LOG_INFO); ! 244: unix_master(); /* sessions, sigh */ ! 245: if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) { ! 246: flags |= TOTTY; ! 247: tp = sess->s_ttyp; ! 248: } ! 249: if (tp != NULL) { ! 250: va_start(ap, fmt); ! 251: prf(fmt, ap, TOTTY, tp); ! 252: va_end(ap); ! 253: } ! 254: unix_release(); ! 255: logwakeup(); ! 256: } ! 257: ! 258: /* ! 259: * Ttyprintf displays a message on a tty; it should be used only by ! 260: * the tty driver, or anything that knows the underlying tty will not ! 261: * be revoke(2)'d away. Other callers should use tprintf. ! 262: */ ! 263: void ! 264: ttyprintf(struct tty *tp, const char *fmt, ...) ! 265: { ! 266: va_list ap; ! 267: ! 268: if (tp != NULL) { ! 269: va_start(ap, fmt); ! 270: prf(fmt, ap, TOTTY, tp); ! 271: va_end(ap); ! 272: } ! 273: } ! 274: ! 275: extern int log_open; ! 276: ! 277: /* ! 278: * Log writes to the log buffer, ! 279: * and guarantees not to sleep (so can be called by interrupt routines). ! 280: * If there is no process reading the log yet, it writes to the console also. ! 281: */ ! 282: void ! 283: log(int level, const char *fmt, ...) ! 284: { ! 285: extern void vlog(); ! 286: va_list ap; ! 287: ! 288: va_start(ap, fmt); ! 289: vlog(level, fmt, ap); ! 290: va_end(ap); ! 291: } ! 292: ! 293: /* ! 294: * driverkit needs vlog to be called from IOLog ! 295: */ ! 296: void ! 297: vlog(int level, const char *fmt, va_list ap) ! 298: { ! 299: register s = splhigh(); ! 300: ! 301: #if !NeXT ! 302: logpri(level); ! 303: #endif ! 304: prf(fmt, ap, TOLOG, (struct tty *)0); ! 305: splx(s); ! 306: if (!log_open) ! 307: prf(fmt, ap, TOCONS, (struct tty *)0); ! 308: logwakeup(); ! 309: } ! 310: ! 311: void ! 312: logpri(level) ! 313: int level; ! 314: { ! 315: ! 316: putchar('<', TOLOG, (struct tty *)0); ! 317: printn((u_long)level, 10, TOLOG, (struct tty *)0, 0, 0); ! 318: putchar('>', TOLOG, (struct tty *)0); ! 319: } ! 320: ! 321: void ! 322: addlog(const char *fmt, ...) ! 323: { ! 324: register s = splhigh(); ! 325: va_list ap; ! 326: ! 327: va_start(ap, fmt); ! 328: prf(fmt, ap, TOLOG, (struct tty *)0); ! 329: splx(s); ! 330: if (!log_open) ! 331: prf(fmt, ap, TOCONS, (struct tty *)0); ! 332: va_end(ap); ! 333: logwakeup(); ! 334: } ! 335: #warning pulled in from mksparc check encumbered or not ! 336: void _printf(int flags, struct tty *ttyp, const char *format, ...) ! 337: { ! 338: va_list ap; ! 339: ! 340: va_start(ap, format); ! 341: prf(format, ap, flags, ttyp); ! 342: va_end(ap); ! 343: } ! 344: ! 345: int prf(const char *fmt, va_list ap, int flags, struct tty *ttyp) ! 346: { ! 347: register int b, c, i; ! 348: char *s; ! 349: int any; ! 350: int zf = 0, fld_size; ! 351: ! 352: #if NCPUS > 1 ! 353: int cpun = cpu_number(); ! 354: ! 355: if(ttyp == 0) { ! 356: simple_lock(&printf_lock); ! 357: } else ! 358: TTY_LOCK(ttyp); ! 359: ! 360: if (cpun != master_cpu) ! 361: new_printf_cpu_number = TRUE; ! 362: ! 363: if (new_printf_cpu_number) { ! 364: putchar('{', flags, ttyp); ! 365: printn((u_long)cpun, 10, flags, ttyp, 0, 0); ! 366: putchar('}', flags, ttyp); ! 367: } ! 368: #endif /* NCPUS > 1 */ ! 369: loop: ! 370: while ((c = *fmt++) != '%') { ! 371: if (c == '\0') { ! 372: #if NCPUS > 1 ! 373: if(ttyp == 0) { ! 374: simple_unlock(&printf_lock); ! 375: } else ! 376: TTY_UNLOCK(ttyp); ! 377: #endif ! 378: return 0; ! 379: } ! 380: putchar(c, flags, ttyp); ! 381: } ! 382: again: ! 383: zf = 0; ! 384: fld_size = 0; ! 385: c = *fmt++; ! 386: if (c == '0') ! 387: zf = '0'; ! 388: fld_size = 0; ! 389: for (;c <= '9' && c >= '0'; c = *fmt++) ! 390: fld_size = fld_size * 10 + c - '0'; ! 391: ! 392: /* THIS CODE IS VAX DEPENDENT IN HANDLING %l? AND %c */ ! 393: switch (c) { ! 394: ! 395: case 'l': ! 396: goto again; ! 397: case 'x': case 'X': ! 398: b = 16; ! 399: goto number; ! 400: case 'd': case 'D': ! 401: case 'u': /* what a joke */ ! 402: b = 10; ! 403: goto number; ! 404: case 'o': case 'O': ! 405: b = 8; ! 406: number: ! 407: printn(va_arg(ap, unsigned), b, flags, ttyp, zf, fld_size); ! 408: break; ! 409: case 'c': ! 410: b = va_arg(ap, unsigned); ! 411: #if BYTE_ORDER == LITTLE_ENDIAN ! 412: for (i = 24; i >= 0; i -= 8) ! 413: if (c = (b >> i) & 0x7f) ! 414: putchar(c, flags, ttyp); ! 415: #endif ! 416: #if BYTE_ORDER == BIG_ENDIAN ! 417: if ((c = (b & 0x7f))) ! 418: putchar(c, flags, ttyp); ! 419: #endif ! 420: break; ! 421: case 'b': ! 422: b = va_arg(ap, unsigned); ! 423: s = va_arg(ap, char *); ! 424: printn((u_long)b, *s++, flags, ttyp, 0, 0); ! 425: any = 0; ! 426: if (b) { ! 427: while ((i = *s++)) { ! 428: if (*s <= 32) { ! 429: register int j; ! 430: ! 431: if (any++) ! 432: putchar(',', flags, ttyp); ! 433: j = *s++ ; ! 434: for (; (c = *s) > 32 ; s++) ! 435: putchar(c, flags, ttyp); ! 436: printn( (u_long)( (b >> (j-1)) & ! 437: ( (2 << (i-j)) -1)), ! 438: 8, flags, ttyp, 0, 0); ! 439: } else if (b & (1 << (i-1))) { ! 440: putchar(any? ',' : '<', flags, ttyp); ! 441: any = 1; ! 442: for (; (c = *s) > 32; s++) ! 443: putchar(c, flags, ttyp); ! 444: } else ! 445: for (; *s > 32; s++) ! 446: ; ! 447: } ! 448: putchar('>', flags, ttyp); ! 449: } ! 450: break; ! 451: ! 452: case 's': ! 453: s = va_arg(ap, char *); ! 454: #ifdef DEBUG ! 455: if (fld_size) { ! 456: while (fld_size-- > 0) ! 457: putchar((c = *s++)? c : '_', flags, ttyp); ! 458: } else { ! 459: while ((c = *s++)) ! 460: putchar(c, flags, ttyp); ! 461: } ! 462: #else ! 463: while (c = *s++) ! 464: putchar(c, flags, ttyp); ! 465: #endif ! 466: break; ! 467: ! 468: case '%': ! 469: putchar('%', flags, ttyp); ! 470: goto loop; ! 471: case 'C': ! 472: b = va_arg(ap, unsigned); ! 473: #if BYTE_ORDER == LITTLE_ENDIAN ! 474: for (i = 24; i >= 0; i -= 8) ! 475: if (c = (b >> i) & 0x7f) ! 476: putchar(c, flags, ttyp); ! 477: #endif ! 478: #if BYTE_ORDER == BIG_ENDIAN ! 479: if ((c = (b & 0x7f))) ! 480: putchar(c, flags, ttyp); ! 481: #endif ! 482: ! 483: case 'r': ! 484: case 'R': ! 485: b = va_arg(ap, unsigned); ! 486: s = va_arg(ap, char *); ! 487: if (c == 'R') { ! 488: puts("0x", flags, ttyp); ! 489: printn((u_long)b, 16, flags, ttyp, 0, 0); ! 490: } ! 491: any = 0; ! 492: if (c == 'r' || b) { ! 493: register struct reg_desc *rd; ! 494: register struct reg_values *rv; ! 495: unsigned field; ! 496: ! 497: putchar('<', flags, ttyp); ! 498: for (rd = (struct reg_desc *)s; rd->rd_mask; rd++) { ! 499: field = b & rd->rd_mask; ! 500: field = (rd->rd_shift > 0) ! 501: ? field << rd->rd_shift ! 502: : field >> -rd->rd_shift; ! 503: if (any && ! 504: (rd->rd_format || rd->rd_values ! 505: || (rd->rd_name && field) ! 506: ) ! 507: ) ! 508: putchar(',', flags, ttyp); ! 509: if (rd->rd_name) { ! 510: if (rd->rd_format || rd->rd_values ! 511: || field) { ! 512: puts(rd->rd_name, flags, ttyp); ! 513: any = 1; ! 514: } ! 515: if (rd->rd_format || rd->rd_values) { ! 516: putchar('=', flags, ttyp); ! 517: any = 1; ! 518: } ! 519: } ! 520: if (rd->rd_format) { ! 521: _printf(flags, ttyp, rd->rd_format, ! 522: field); ! 523: any = 1; ! 524: if (rd->rd_values) ! 525: putchar(':', flags, ttyp); ! 526: } ! 527: if (rd->rd_values) { ! 528: any = 1; ! 529: for (rv = rd->rd_values; ! 530: rv->rv_name; ! 531: rv++) { ! 532: if (field == rv->rv_value) { ! 533: puts(rv->rv_name, flags, ! 534: ttyp); ! 535: break; ! 536: } ! 537: } ! 538: if (rv->rv_name == NULL) ! 539: puts("???", flags, ttyp); ! 540: } ! 541: } ! 542: putchar('>', flags, ttyp); ! 543: } ! 544: break; ! 545: ! 546: case 'n': ! 547: case 'N': ! 548: { ! 549: register struct reg_values *rv; ! 550: ! 551: b = va_arg(ap, unsigned); ! 552: s = va_arg(ap,char *); ! 553: for (rv = (struct reg_values *)s; rv->rv_name; rv++) { ! 554: if (b == rv->rv_value) { ! 555: puts(rv->rv_name, flags, ttyp); ! 556: break; ! 557: } ! 558: } ! 559: if (rv->rv_name == NULL) ! 560: puts("???", flags, ttyp); ! 561: if (c == 'N' || rv->rv_name == NULL) { ! 562: putchar(':', flags, ttyp); ! 563: printn((u_long)b, 10, flags, ttyp, 0, 0); ! 564: } ! 565: } ! 566: break; ! 567: } ! 568: goto loop; ! 569: } ! 570: ! 571: static void puts(const char *s, int flags, struct tty *ttyp) ! 572: { ! 573: register char c; ! 574: ! 575: while ((c = *s++)) ! 576: putchar(c, flags, ttyp); ! 577: } ! 578: ! 579: /* ! 580: * Printn prints a number n in base b. ! 581: * We don't use recursion to avoid deep kernel stacks. ! 582: */ ! 583: static void printn(u_long n, int b, int flags, struct tty *ttyp, int zf, int fld_size) ! 584: { ! 585: char prbuf[11]; ! 586: register char *cp; ! 587: ! 588: if (b == 10 && (int)n < 0) { ! 589: putchar('-', flags, ttyp); ! 590: n = (unsigned)(-(int)n); ! 591: } ! 592: cp = prbuf; ! 593: do { ! 594: *cp++ = "0123456789abcdef"[n%b]; ! 595: n /= b; ! 596: } while (n); ! 597: if (fld_size) { ! 598: for (fld_size -= cp - prbuf; fld_size > 0; fld_size--) ! 599: if (zf) ! 600: putchar('0', flags, ttyp); ! 601: else ! 602: putchar(' ', flags, ttyp); ! 603: } ! 604: do ! 605: putchar(*--cp, flags, ttyp); ! 606: while (cp > prbuf); ! 607: } ! 608: ! 609: void panic_init() ! 610: { ! 611: simple_lock_init(&panic_lock); ! 612: } ! 613: ! 614: /* ! 615: * Panic is called on unresolvable fatal errors. It prints "panic: mesg", ! 616: * and then reboots. If we are called twice, then we avoid trying to sync ! 617: * the disks as this often leads to recursive panics. ! 618: */ ! 619: #ifdef __GNUC__ ! 620: volatile ! 621: #endif ! 622: void ! 623: panic(const char *fmt, ...) ! 624: { ! 625: #if MACH_LDEBUG ! 626: extern int mach_ldebug; ! 627: #endif /* MACH_LDEBUG */ ! 628: int bootopt; ! 629: va_list ap; ! 630: char buffer[256]; ! 631: ! 632: simple_lock(&panic_lock); ! 633: bootopt = RB_AUTOBOOT; ! 634: if (panicstr) { ! 635: if (cpu_number() == paniccpu) { ! 636: bootopt |= RB_NOSYNC; ! 637: } else { ! 638: simple_unlock(&panic_lock); ! 639: halt_cpu(); ! 640: /* NOTREACHED */ ! 641: } ! 642: } else { ! 643: panicstr = fmt; ! 644: paniccpu = cpu_number(); ! 645: } ! 646: ! 647: simple_unlock(&panic_lock); ! 648: ! 649: #if MACH_LDEBUG ! 650: mach_ldebug = 0; // turn off simple lock debugging. ! 651: #endif /* MACH_LDEBUG */ ! 652: ! 653: va_start(ap, fmt); ! 654: sprintf(buffer, "panic: %s", fmt); ! 655: prf(buffer, ap, TOCONS, (struct tty *)0); ! 656: va_end(ap); ! 657: ! 658: #if NeXT ! 659: if( panicstr == fmt) { ! 660: // make panicstr for minimon ! 661: char * strOut = buffer; ! 662: va_start(ap, fmt); ! 663: prf(fmt, ap, TOSTR, (struct tty *)&strOut ); ! 664: va_end(ap); ! 665: *strOut = 0; ! 666: panicstr = buffer; ! 667: } ! 668: mini_mon ("panic", "System Panic", current_thread()->pcb); ! 669: #endif /* NeXT */ ! 670: boot(RB_PANIC, bootopt, ""); ! 671: } ! 672: ! 673: /* ! 674: * Warn that a system table is full. ! 675: */ ! 676: void tablefull(const char *tab) ! 677: { ! 678: log(LOG_ERR, "%s: table is full\n", tab); ! 679: } ! 680: ! 681: /* ! 682: * Hard error is the preface to plaintive error messages ! 683: * about failing disk transfers. ! 684: */ ! 685: void harderr(struct buf *bp, const char *cp) ! 686: { ! 687: ! 688: printf("%s%d%c: hard error sn%d ", cp, ! 689: minor(bp->b_dev) >> 3, 'a'+(minor(bp->b_dev)&07), bp->b_blkno); ! 690: } ! 691: ! 692: /* ! 693: * Print a character on console or users terminal. ! 694: * If destination is console then the last MSGBUFS characters ! 695: * are saved in msgbuf for inspection later. ! 696: */ ! 697: /*ARGSUSED*/ ! 698: int ! 699: putchar(c, flags, tp) ! 700: register int c; ! 701: struct tty *tp; ! 702: { ! 703: register struct msgbuf *mbp; ! 704: char **sp = (char**) tp; ! 705: ! 706: if (panicstr) ! 707: constty = 0; ! 708: if ((flags & TOCONS) && tp == NULL && constty) { ! 709: tp = constty; ! 710: flags |= TOTTY; ! 711: } ! 712: if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 && ! 713: (flags & TOCONS) && tp == constty) ! 714: constty = 0; ! 715: if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177) { ! 716: mbp = msgbufp; ! 717: if (mbp-> msg_magic != MSG_MAGIC) { ! 718: register int i; ! 719: ! 720: mbp->msg_magic = MSG_MAGIC; ! 721: mbp->msg_bufx = mbp->msg_bufr = 0; ! 722: for (i=0; i < MSG_BSIZE; i++) ! 723: mbp->msg_bufc[i] = 0; ! 724: } ! 725: mbp->msg_bufc[mbp->msg_bufx++] = c; ! 726: if (mbp->msg_bufx < 0 || mbp->msg_bufx >= MSG_BSIZE) ! 727: mbp->msg_bufx = 0; ! 728: } ! 729: if ((flags & TOCONS) && constty == 0 && c != '\0') ! 730: (*v_putc)(c); ! 731: if (flags & TOSTR) { ! 732: **sp = c; ! 733: (*sp)++; ! 734: } ! 735: return 0; ! 736: } ! 737:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.