|
|
1.1 ! root 1: /*- ! 2: * Copyright (c) 1986, 1988, 1991 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms, with or without ! 6: * modification, are permitted provided that the following conditions ! 7: * are met: ! 8: * 1. Redistributions of source code must retain the above copyright ! 9: * notice, this list of conditions and the following disclaimer. ! 10: * 2. Redistributions in binary form must reproduce the above copyright ! 11: * notice, this list of conditions and the following disclaimer in the ! 12: * documentation and/or other materials provided with the distribution. ! 13: * 3. All advertising materials mentioning features or use of this software ! 14: * must display the following acknowledgement: ! 15: * This product includes software developed by the University of ! 16: * California, Berkeley and its contributors. ! 17: * 4. Neither the name of the University nor the names of its contributors ! 18: * may be used to endorse or promote products derived from this software ! 19: * without specific prior written permission. ! 20: * ! 21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 31: * SUCH DAMAGE. ! 32: * ! 33: * @(#)subr_prf.c 7.30 (Berkeley) 6/29/91 ! 34: */ ! 35: ! 36: #include "param.h" ! 37: #include "systm.h" ! 38: #include "buf.h" ! 39: #include "conf.h" ! 40: #include "reboot.h" ! 41: #include "msgbuf.h" ! 42: #include "proc.h" ! 43: #include "ioctl.h" ! 44: #include "vnode.h" ! 45: #include "file.h" ! 46: #include "tty.h" ! 47: #include "tprintf.h" ! 48: #include "syslog.h" ! 49: #include "malloc.h" ! 50: ! 51: /* ! 52: * Note that stdarg.h and the ANSI style va_start macro is used for both ! 53: * ANSI and traditional C compilers. ! 54: */ ! 55: #include <machine/stdarg.h> ! 56: ! 57: #ifdef KADB ! 58: #include "machine/kdbparam.h" ! 59: #endif ! 60: ! 61: #define TOCONS 0x01 ! 62: #define TOTTY 0x02 ! 63: #define TOLOG 0x04 ! 64: ! 65: struct tty *constty; /* pointer to console "window" tty */ ! 66: ! 67: #ifdef KADB ! 68: extern cngetc(); /* standard console getc */ ! 69: int (*v_getc)() = cngetc; /* "" getc from virtual console */ ! 70: extern cnpoll(); ! 71: int (*v_poll)() = cnpoll; /* kdb hook to enable input polling */ ! 72: #endif ! 73: extern cnputc(); /* standard console putc */ ! 74: int (*v_putc)() = cnputc; /* routine to putc on virtual console */ ! 75: ! 76: static void logpri __P((int level)); ! 77: static void putchar __P((int ch, int flags, struct tty *tp)); ! 78: static char *ksprintn __P((u_long num, int base, int *len)); ! 79: void kprintf __P((const char *fmt, int flags, struct tty *tp, va_list)); ! 80: ! 81: /* ! 82: * Variable panicstr contains argument to first call to panic; used ! 83: * as flag to indicate that the kernel has already called panic. ! 84: */ ! 85: char *panicstr; ! 86: ! 87: /* ! 88: * Panic is called on unresolvable fatal errors. It prints "panic: mesg", ! 89: * and then reboots. If we are called twice, then we avoid trying to sync ! 90: * the disks as this often leads to recursive panics. ! 91: */ ! 92: void ! 93: panic(msg) ! 94: char *msg; ! 95: { ! 96: int bootopt = RB_AUTOBOOT | RB_DUMP; ! 97: ! 98: if (panicstr) ! 99: bootopt |= RB_NOSYNC; ! 100: else ! 101: panicstr = msg; ! 102: printf("panic: %s\n", msg); ! 103: #ifdef KGDB ! 104: kgdb_panic(); ! 105: #endif ! 106: #ifdef KADB ! 107: if (boothowto & RB_KDB) { ! 108: int s; ! 109: ! 110: s = splnet(); /* below kdb pri */ ! 111: setsoftkdb(); ! 112: splx(s); ! 113: } ! 114: #endif ! 115: boot(bootopt); ! 116: } ! 117: ! 118: /* ! 119: * Warn that a system table is full. ! 120: */ ! 121: void ! 122: tablefull(tab) ! 123: char *tab; ! 124: { ! 125: ! 126: log(LOG_ERR, "%s: table is full\n", tab); ! 127: } ! 128: ! 129: /* ! 130: * Uprintf prints to the controlling terminal for the current process. ! 131: * It may block if the tty queue is overfull. No message is printed if ! 132: * the queue does not clear in a reasonable time. ! 133: */ ! 134: void ! 135: #ifdef __STDC__ ! 136: uprintf(const char *fmt, ...) ! 137: #else ! 138: uprintf(fmt /*, va_alist */) ! 139: char *fmt; ! 140: #endif ! 141: { ! 142: register struct proc *p = curproc; ! 143: va_list ap; ! 144: ! 145: if (p->p_flag & SCTTY && p->p_session->s_ttyvp) { ! 146: va_start(ap, fmt); ! 147: kprintf(fmt, TOTTY, p->p_session->s_ttyp, ap); ! 148: va_end(ap); ! 149: } ! 150: } ! 151: ! 152: tpr_t ! 153: tprintf_open(p) ! 154: register struct proc *p; ! 155: { ! 156: ! 157: if (p->p_flag & SCTTY && p->p_session->s_ttyvp) { ! 158: SESSHOLD(p->p_session); ! 159: return ((tpr_t) p->p_session); ! 160: } ! 161: return ((tpr_t) NULL); ! 162: } ! 163: ! 164: void ! 165: tprintf_close(sess) ! 166: tpr_t sess; ! 167: { ! 168: ! 169: if (sess) ! 170: SESSRELE((struct session *) sess); ! 171: } ! 172: ! 173: /* ! 174: * tprintf prints on the controlling terminal associated ! 175: * with the given session. ! 176: */ ! 177: void ! 178: #ifdef __STDC__ ! 179: tprintf(tpr_t tpr, const char *fmt, ...) ! 180: #else ! 181: tprintf(tpr, fmt /*, va_alist */) ! 182: tpr_t tpr; ! 183: char *fmt; ! 184: #endif ! 185: { ! 186: register struct session *sess = (struct session *)tpr; ! 187: struct tty *tp = NULL; ! 188: int flags = TOLOG; ! 189: va_list ap; ! 190: ! 191: logpri(LOG_INFO); ! 192: if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) { ! 193: flags |= TOTTY; ! 194: tp = sess->s_ttyp; ! 195: } ! 196: va_start(ap, fmt); ! 197: kprintf(fmt, flags, tp, ap); ! 198: va_end(ap); ! 199: logwakeup(); ! 200: } ! 201: ! 202: /* ! 203: * Ttyprintf displays a message on a tty; it should be used only by ! 204: * the tty driver, or anything that knows the underlying tty will not ! 205: * be revoke(2)'d away. Other callers should use tprintf. ! 206: */ ! 207: void ! 208: #ifdef __STDC__ ! 209: ttyprintf(struct tty *tp, const char *fmt, ...) ! 210: #else ! 211: ttyprintf(tp, fmt /*, va_alist */) ! 212: struct tty *tp; ! 213: char *fmt; ! 214: #endif ! 215: { ! 216: va_list ap; ! 217: ! 218: va_start(ap, fmt); ! 219: kprintf(fmt, TOTTY, tp, ap); ! 220: va_end(ap); ! 221: } ! 222: ! 223: extern int log_open; ! 224: ! 225: /* ! 226: * Log writes to the log buffer, and guarantees not to sleep (so can be ! 227: * called by interrupt routines). If there is no process reading the ! 228: * log yet, it writes to the console also. ! 229: */ ! 230: void ! 231: #ifdef __STDC__ ! 232: log(int level, const char *fmt, ...) ! 233: #else ! 234: log(level, fmt /*, va_alist */) ! 235: int level; ! 236: char *fmt; ! 237: #endif ! 238: { ! 239: register int s; ! 240: va_list ap; ! 241: ! 242: s = splhigh(); ! 243: logpri(level); ! 244: va_start(ap, fmt); ! 245: kprintf(fmt, TOLOG, NULL, ap); ! 246: splx(s); ! 247: va_end(ap); ! 248: if (!log_open) { ! 249: va_start(ap, fmt); ! 250: kprintf(fmt, TOCONS, NULL, ap); ! 251: va_end(ap); ! 252: } ! 253: logwakeup(); ! 254: } ! 255: ! 256: static void ! 257: logpri(level) ! 258: int level; ! 259: { ! 260: register int ch; ! 261: register char *p; ! 262: ! 263: putchar('<', TOLOG, NULL); ! 264: for (p = ksprintn((u_long)level, 10, NULL); ch = *p--;) ! 265: putchar(ch, TOLOG, NULL); ! 266: putchar('>', TOLOG, NULL); ! 267: } ! 268: ! 269: void ! 270: #ifdef __STDC__ ! 271: addlog(const char *fmt, ...) ! 272: #else ! 273: addlog(fmt /*, va_alist */) ! 274: char *fmt; ! 275: #endif ! 276: { ! 277: register int s; ! 278: va_list ap; ! 279: ! 280: s = splhigh(); ! 281: va_start(ap, fmt); ! 282: kprintf(fmt, TOLOG, NULL, ap); ! 283: splx(s); ! 284: va_end(ap); ! 285: if (!log_open) { ! 286: va_start(ap, fmt); ! 287: kprintf(fmt, TOCONS, NULL, ap); ! 288: va_end(ap); ! 289: } ! 290: logwakeup(); ! 291: } ! 292: ! 293: int consintr = 1; /* ok to handle console interrupts? */ ! 294: ! 295: void ! 296: #ifdef __STDC__ ! 297: printf(const char *fmt, ...) ! 298: #else ! 299: printf(fmt /*, va_alist */) ! 300: char *fmt; ! 301: #endif ! 302: { ! 303: va_list ap; ! 304: register int savintr; ! 305: ! 306: savintr = consintr; /* disable interrupts */ ! 307: consintr = 0; ! 308: va_start(ap, fmt); ! 309: kprintf(fmt, TOCONS | TOLOG, NULL, ap); ! 310: va_end(ap); ! 311: if (!panicstr) ! 312: logwakeup(); ! 313: consintr = savintr; /* reenable interrupts */ ! 314: } ! 315: ! 316: /* ! 317: * Scaled down version of printf(3). ! 318: * ! 319: * Two additional formats: ! 320: * ! 321: * The format %b is supported to decode error registers. ! 322: * Its usage is: ! 323: * ! 324: * printf("reg=%b\n", regval, "<base><arg>*"); ! 325: * ! 326: * where <base> is the output base expressed as a control character, e.g. ! 327: * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, ! 328: * the first of which gives the bit number to be inspected (origin 1), and ! 329: * the next characters (up to a control character, i.e. a character <= 32), ! 330: * give the name of the register. Thus: ! 331: * ! 332: * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); ! 333: * ! 334: * would produce output: ! 335: * ! 336: * reg=3<BITTWO,BITONE> ! 337: * ! 338: * The format %r is supposed to pass an additional format string and argument ! 339: * list recursively. ! 340: * Its usage is: ! 341: * ! 342: * fn(otherstuff, char *fmt, ...) ! 343: * { ! 344: * va_list ap; ! 345: * va_start(ap, fmt); ! 346: * printf("prefix: %r, other stuff\n", fmt, ap); ! 347: * va_end(ap); ! 348: * ! 349: * Space or zero padding and a field width are supported for the numeric ! 350: * formats only. ! 351: */ ! 352: void ! 353: kprintf(fmt, flags, tp, ap) ! 354: register const char *fmt; ! 355: int flags; ! 356: struct tty *tp; ! 357: va_list ap; ! 358: { ! 359: register char *p; ! 360: register int ch, n; ! 361: u_long ul; ! 362: int base, lflag, tmp, width; ! 363: char padc; ! 364: ! 365: for (;;) { ! 366: padc = ' '; ! 367: width = 0; ! 368: while ((ch = *(u_char *)fmt++) != '%') { ! 369: if (ch == '\0') ! 370: return; ! 371: putchar(ch, flags, tp); ! 372: } ! 373: lflag = 0; ! 374: reswitch: switch (ch = *(u_char *)fmt++) { ! 375: case '0': ! 376: padc = '0'; ! 377: goto reswitch; ! 378: case '1': case '2': case '3': case '4': ! 379: case '5': case '6': case '7': case '8': case '9': ! 380: for (width = 0;; ++fmt) { ! 381: width = width * 10 + ch - '0'; ! 382: ch = *fmt; ! 383: if (ch < '0' || ch > '9') ! 384: break; ! 385: } ! 386: goto reswitch; ! 387: case 'l': ! 388: lflag = 1; ! 389: goto reswitch; ! 390: case 'b': ! 391: ul = va_arg(ap, int); ! 392: p = va_arg(ap, char *); ! 393: for (p = ksprintn(ul, *p++, NULL); ch = *p--;) ! 394: putchar(ch, flags, tp); ! 395: ! 396: if (!ul) ! 397: break; ! 398: ! 399: for (tmp = 0; n = *p++;) { ! 400: if (ul & (1 << (n - 1))) { ! 401: putchar(tmp ? ',' : '<', flags, tp); ! 402: for (; (n = *p) > ' '; ++p) ! 403: putchar(n, flags, tp); ! 404: tmp = 1; ! 405: } else ! 406: for (; *p > ' '; ++p); ! 407: } ! 408: if (tmp) ! 409: putchar('>', flags, tp); ! 410: break; ! 411: case 'c': ! 412: putchar(va_arg(ap, int), flags, tp); ! 413: break; ! 414: case 'r': ! 415: p = va_arg(ap, char *); ! 416: kprintf(p, flags, tp, va_arg(ap, va_list)); ! 417: break; ! 418: case 's': ! 419: p = va_arg(ap, char *); ! 420: while (ch = *p++) ! 421: putchar(ch, flags, tp); ! 422: break; ! 423: case 'd': ! 424: ul = lflag ? va_arg(ap, long) : va_arg(ap, int); ! 425: if ((long)ul < 0) { ! 426: putchar('-', flags, tp); ! 427: ul = -(long)ul; ! 428: } ! 429: base = 10; ! 430: goto number; ! 431: case 'o': ! 432: ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); ! 433: base = 8; ! 434: goto number; ! 435: case 'u': ! 436: ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); ! 437: base = 10; ! 438: goto number; ! 439: case 'x': ! 440: ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); ! 441: base = 16; ! 442: number: p = ksprintn(ul, base, &tmp); ! 443: if (width && (width -= tmp) > 0) ! 444: while (width--) ! 445: putchar(padc, flags, tp); ! 446: while (ch = *p--) ! 447: putchar(ch, flags, tp); ! 448: break; ! 449: default: ! 450: putchar('%', flags, tp); ! 451: if (lflag) ! 452: putchar('l', flags, tp); ! 453: /* FALLTHROUGH */ ! 454: case '%': ! 455: putchar(ch, flags, tp); ! 456: } ! 457: } ! 458: } ! 459: ! 460: /* ! 461: * Print a character on console or users terminal. If destination is ! 462: * the console then the last MSGBUFS characters are saved in msgbuf for ! 463: * inspection later. ! 464: */ ! 465: static void ! 466: putchar(c, flags, tp) ! 467: register int c; ! 468: int flags; ! 469: struct tty *tp; ! 470: { ! 471: extern int msgbufmapped; ! 472: register struct msgbuf *mbp; ! 473: ! 474: if (panicstr) ! 475: constty = NULL; ! 476: if ((flags & TOCONS) && tp == NULL && constty) { ! 477: tp = constty; ! 478: flags |= TOTTY; ! 479: } ! 480: if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 && ! 481: (flags & TOCONS) && tp == constty) ! 482: constty = NULL; ! 483: if ((flags & TOLOG) && ! 484: c != '\0' && c != '\r' && c != 0177 && msgbufmapped) { ! 485: mbp = msgbufp; ! 486: if (mbp->msg_magic != MSG_MAGIC) { ! 487: bzero((caddr_t)mbp, sizeof(*mbp)); ! 488: mbp->msg_magic = MSG_MAGIC; ! 489: } ! 490: mbp->msg_bufc[mbp->msg_bufx++] = c; ! 491: if (mbp->msg_bufx < 0 || mbp->msg_bufx >= MSG_BSIZE) ! 492: mbp->msg_bufx = 0; ! 493: } ! 494: if ((flags & TOCONS) && constty == NULL && c != '\0') ! 495: (*v_putc)(c); ! 496: } ! 497: ! 498: /* ! 499: * Scaled down version of sprintf(3). ! 500: */ ! 501: #ifdef __STDC__ ! 502: sprintf(char *buf, const char *cfmt, ...) ! 503: #else ! 504: sprintf(buf, cfmt /*, va_alist */) ! 505: char *buf, *cfmt; ! 506: #endif ! 507: { ! 508: register const char *fmt = cfmt; ! 509: register char *p, *bp; ! 510: register int ch, base; ! 511: u_long ul; ! 512: int lflag; ! 513: va_list ap; ! 514: ! 515: va_start(ap, cfmt); ! 516: for (bp = buf; ; ) { ! 517: while ((ch = *(u_char *)fmt++) != '%') ! 518: if ((*bp++ = ch) == '\0') ! 519: return ((bp - buf) - 1); ! 520: ! 521: lflag = 0; ! 522: reswitch: switch (ch = *(u_char *)fmt++) { ! 523: case 'l': ! 524: lflag = 1; ! 525: goto reswitch; ! 526: case 'c': ! 527: *bp++ = va_arg(ap, int); ! 528: break; ! 529: case 's': ! 530: p = va_arg(ap, char *); ! 531: while (*bp++ = *p++) ! 532: ; ! 533: --bp; ! 534: break; ! 535: case 'd': ! 536: ul = lflag ? va_arg(ap, long) : va_arg(ap, int); ! 537: if ((long)ul < 0) { ! 538: *bp++ = '-'; ! 539: ul = -(long)ul; ! 540: } ! 541: base = 10; ! 542: goto number; ! 543: break; ! 544: case 'o': ! 545: ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); ! 546: base = 8; ! 547: goto number; ! 548: break; ! 549: case 'u': ! 550: ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); ! 551: base = 10; ! 552: goto number; ! 553: break; ! 554: case 'x': ! 555: ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); ! 556: base = 16; ! 557: number: for (p = ksprintn(ul, base, NULL); ch = *p--;) ! 558: *bp++ = ch; ! 559: break; ! 560: default: ! 561: *bp++ = '%'; ! 562: if (lflag) ! 563: *bp++ = 'l'; ! 564: /* FALLTHROUGH */ ! 565: case '%': ! 566: *bp++ = ch; ! 567: } ! 568: } ! 569: va_end(ap); ! 570: } ! 571: ! 572: /* ! 573: * Put a number (base <= 16) in a buffer in reverse order; return an ! 574: * optional length and a pointer to the NULL terminated (preceded?) ! 575: * buffer. ! 576: */ ! 577: static char * ! 578: ksprintn(ul, base, lenp) ! 579: register u_long ul; ! 580: register int base, *lenp; ! 581: { /* A long in base 8, plus NULL. */ ! 582: static char buf[sizeof(long) * NBBY / 3 + 2]; ! 583: register char *p; ! 584: ! 585: p = buf; ! 586: do { ! 587: *++p = "0123456789abcdef"[ul % base]; ! 588: } while (ul /= base); ! 589: if (lenp) ! 590: *lenp = p - buf; ! 591: return (p); ! 592: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.