149062Sbostic /*- 249062Sbostic * Copyright (c) 1986, 1988, 1991 The Regents of the University of California. 349062Sbostic * All rights reserved. 423381Smckusick * 549062Sbostic * %sccs.include.redist.c% 649062Sbostic * 7*49908Sbostic * @(#)subr_prf.c 7.26 (Berkeley) 05/28/91 823381Smckusick */ 931Sbill 1017094Sbloom #include "param.h" 1117094Sbloom #include "systm.h" 1217094Sbloom #include "buf.h" 1317094Sbloom #include "conf.h" 1417094Sbloom #include "reboot.h" 1517094Sbloom #include "msgbuf.h" 1617094Sbloom #include "proc.h" 1717577Sbloom #include "ioctl.h" 1839560Smarc #include "vnode.h" 1939560Smarc #include "file.h" 2017094Sbloom #include "tty.h" 2144386Smarc #include "tprintf.h" 2218364Skarels #include "syslog.h" 2344386Smarc #include "malloc.h" 2431Sbill 2549062Sbostic /* 2649062Sbostic * Note that stdarg.h and the ANSI style va_start macro is used for both 2749062Sbostic * ANSI and traditional C compilers. 2849062Sbostic */ 2949062Sbostic #include <machine/stdarg.h> 3049062Sbostic 3135282Skarels #ifdef KADB 3237496Smckusick #include "machine/kdbparam.h" 3330625Skarels #endif 3430625Skarels 3549062Sbostic #define TOCONS 0x01 3649062Sbostic #define TOTTY 0x02 3749062Sbostic #define TOLOG 0x04 3816724Sralph 3930549Skarels struct tty *constty; /* pointer to console "window" tty */ 4030549Skarels 4140808Smarc #ifdef KADB 4240808Smarc extern cngetc(); /* standard console getc */ 4349062Sbostic int (*v_getc)() = cngetc; /* "" getc from virtual console */ 4440808Smarc extern cnpoll(); 4540808Smarc int (*v_poll)() = cnpoll; /* kdb hook to enable input polling */ 4640808Smarc #endif 4749062Sbostic extern cnputc(); /* standard console putc */ 4849062Sbostic int (*v_putc)() = cnputc; /* routine to putc on virtual console */ 4940808Smarc 50*49908Sbostic static void logpri __P((int level)); 51*49908Sbostic static void putchar __P((int ch, int flags, struct tty *tp)); 52*49908Sbostic static void kprintf __P((const char *fmt, int flags, struct tty *tp, va_list)); 53*49908Sbostic static char *ksprintn __P((u_long num, int base, int *len)); 5449062Sbostic 5531Sbill /* 5649062Sbostic * Variable panicstr contains argument to first call to panic; used 5749062Sbostic * as flag to indicate that the kernel has already called panic. 5831Sbill */ 5949062Sbostic char *panicstr; 6029946Skarels 6149062Sbostic /* 6249062Sbostic * Panic is called on unresolvable fatal errors. It prints "panic: mesg", 6349062Sbostic * and then reboots. If we are called twice, then we avoid trying to sync 6449062Sbostic * the disks as this often leads to recursive panics. 6549062Sbostic */ 6649062Sbostic void 6749062Sbostic panic(msg) 6849062Sbostic char *msg; 6949062Sbostic { 7049062Sbostic int bootopt = RB_AUTOBOOT | RB_DUMP; 7149062Sbostic int s; 7248426Skarels 7349062Sbostic if (panicstr) 7449062Sbostic bootopt |= RB_NOSYNC; 7549062Sbostic else 7649062Sbostic panicstr = msg; 7749062Sbostic printf("panic: %s\n", msg); 7849062Sbostic #ifdef KGDB 7949062Sbostic kgdb_panic(); 8049062Sbostic #endif 8149062Sbostic #ifdef KADB 8249062Sbostic if (boothowto & RB_KDB) { 8349062Sbostic s = splnet(); /* below kdb pri */ 8449062Sbostic setsoftkdb(); 8549062Sbostic splx(s); 8649062Sbostic } 8749062Sbostic #endif 8849062Sbostic boot(bootopt); 8949062Sbostic } 9049062Sbostic 9149062Sbostic /* 9249062Sbostic * Warn that a system table is full. 9349062Sbostic */ 9449062Sbostic void 9549062Sbostic tablefull(tab) 9649062Sbostic char *tab; 9731Sbill { 98285Sbill 9949062Sbostic log(LOG_ERR, "%s: table is full\n", tab); 100285Sbill } 101285Sbill 1022377Swnj /* 10339560Smarc * Uprintf prints to the controlling terminal for the current process. 10449062Sbostic * It may block if the tty queue is overfull. No message is printed if 10549062Sbostic * the queue does not clear in a reasonable time. 1062377Swnj */ 10749062Sbostic void 10849062Sbostic #ifdef __STDC__ 10949062Sbostic uprintf(const char *fmt, ...) 11049062Sbostic #else 11149062Sbostic uprintf(fmt /*, va_alist */) 1122781Swnj char *fmt; 11349062Sbostic #endif 114285Sbill { 11547540Skarels register struct proc *p = curproc; 11649062Sbostic va_list ap; 117285Sbill 11849062Sbostic va_start(ap, fmt); 11944386Smarc if (p->p_flag & SCTTY && p->p_session->s_ttyvp) 12049062Sbostic kprintf(fmt, TOTTY, p->p_session->s_ttyp, ap); 12149062Sbostic va_end(ap); 122285Sbill } 123285Sbill 12444386Smarc tpr_t 12548426Skarels tprintf_open(p) 12648426Skarels register struct proc *p; 12744386Smarc { 12844386Smarc if (p->p_flag & SCTTY && p->p_session->s_ttyvp) { 12944386Smarc SESSHOLD(p->p_session); 13048426Skarels return ((tpr_t) p->p_session); 13149062Sbostic } 13249062Sbostic return ((tpr_t) NULL); 13344386Smarc } 13444386Smarc 13548426Skarels void 13644386Smarc tprintf_close(sess) 13744386Smarc tpr_t sess; 13844386Smarc { 13944386Smarc if (sess) 14048426Skarels SESSRELE((struct session *) sess); 14144386Smarc } 14244386Smarc 14318364Skarels /* 14444386Smarc * tprintf prints on the controlling terminal associated 14549062Sbostic * with the given session. 14618364Skarels */ 14749062Sbostic void 14849062Sbostic #ifdef __STDC__ 14949062Sbostic tprintf(tpr_t tpr, const char *fmt, ...) 15049062Sbostic #else 15149062Sbostic tprintf(tpr, fmt /*, va_alist */) 15248426Skarels tpr_t tpr; 15316724Sralph char *fmt; 15449062Sbostic #endif 15516724Sralph { 15648426Skarels register struct session *sess = (struct session *)tpr; 15748426Skarels struct tty *tp = NULL; 15844386Smarc int flags = TOLOG; 15949062Sbostic va_list ap; 16016724Sralph 16125389Skarels logpri(LOG_INFO); 16248426Skarels if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) { 16344386Smarc flags |= TOTTY; 16448426Skarels tp = sess->s_ttyp; 16548426Skarels } 16649062Sbostic va_start(ap, fmt); 16749062Sbostic kprintf(fmt, flags, tp, ap); 16849062Sbostic va_end(ap); 16925389Skarels logwakeup(); 17016724Sralph } 17116724Sralph 17249062Sbostic /* 17349062Sbostic * Ttyprintf displays a message on a tty; it should be used only by 17449062Sbostic * the tty driver, or anything that knows the underlying tty will not 17549062Sbostic * be revoke(2)'d away. Other callers should use tprintf. 17649062Sbostic */ 17749062Sbostic void 17849062Sbostic #ifdef __STDC__ 17949062Sbostic ttyprintf(struct tty *tp, const char *fmt, ...) 18049062Sbostic #else 18149062Sbostic ttyprintf(tp, fmt /*, va_alist */) 18249062Sbostic struct tty *tp; 18349062Sbostic char *fmt; 18449062Sbostic #endif 18549062Sbostic { 18649062Sbostic va_list ap; 18749062Sbostic 18849062Sbostic va_start(ap, fmt); 18949062Sbostic kprintf(fmt, TOTTY, tp, ap); 19049062Sbostic va_end(ap); 19149062Sbostic } 19249062Sbostic 19348426Skarels extern int log_open; 19444386Smarc 19516724Sralph /* 19649062Sbostic * Log writes to the log buffer, and guarantees not to sleep (so can be 19749062Sbostic * called by interrupt routines). If there is no process reading the 19849062Sbostic * log yet, it writes to the console also. 19916724Sralph */ 20049062Sbostic void 20149062Sbostic #ifdef __STDC__ 20249062Sbostic log(int level, const char *fmt, ...) 20349062Sbostic #else 20449062Sbostic log(level, fmt /*, va_alist */) 20549062Sbostic int level; 20616724Sralph char *fmt; 20749062Sbostic #endif 20816724Sralph { 20916724Sralph register s = splhigh(); 21049062Sbostic va_list ap; 21116724Sralph 21225389Skarels logpri(level); 21349062Sbostic va_start(ap, fmt); 21449062Sbostic kprintf(fmt, TOLOG, NULL, ap); 21516724Sralph splx(s); 21618364Skarels if (!log_open) 21749062Sbostic kprintf(fmt, TOCONS, NULL, ap); 21849062Sbostic va_end(ap); 21916724Sralph logwakeup(); 22016724Sralph } 22116724Sralph 22249062Sbostic static void 22325389Skarels logpri(level) 22425389Skarels int level; 22525389Skarels { 226*49908Sbostic register int ch; 227*49908Sbostic register char *p; 22825389Skarels 22949062Sbostic putchar('<', TOLOG, NULL); 230*49908Sbostic for (p = ksprintn((u_long)level, 10, NULL); ch = *p--;) 231*49908Sbostic putchar(ch, TOLOG, NULL); 23249062Sbostic putchar('>', TOLOG, NULL); 23325389Skarels } 23425389Skarels 23549062Sbostic void 23649062Sbostic #ifdef __STDC__ 23749062Sbostic addlog(const char *fmt, ...) 23849062Sbostic #else 23949062Sbostic addlog(fmt /*, va_alist */) 24033479Skarels char *fmt; 24149062Sbostic #endif 24233479Skarels { 24333479Skarels register s = splhigh(); 24449062Sbostic va_list ap; 24533479Skarels 24649062Sbostic va_start(ap, fmt); 24749062Sbostic kprintf(fmt, TOLOG, NULL, ap); 24833479Skarels splx(s); 24933479Skarels if (!log_open) 25049062Sbostic kprintf(fmt, TOCONS, NULL, ap); 25149062Sbostic va_end(ap); 25233479Skarels logwakeup(); 25333479Skarels } 25433479Skarels 25549062Sbostic int consintr = 1; /* ok to handle console interrupts? */ 25631Sbill 25749062Sbostic void 25849062Sbostic #ifdef __STDC__ 25949062Sbostic printf(const char *fmt, ...) 26049062Sbostic #else 26149062Sbostic printf(fmt /*, va_alist */) 26249062Sbostic char *fmt; 26329946Skarels #endif 26449062Sbostic { 26549062Sbostic register int savintr; 26649062Sbostic va_list ap; 2672678Swnj 26849062Sbostic savintr = consintr; /* disable interrupts */ 26949062Sbostic consintr = 0; 27049062Sbostic va_start(ap, fmt); 27149062Sbostic kprintf(fmt, TOCONS | TOLOG, NULL, ap); 27249062Sbostic va_end(ap); 27349062Sbostic if (!panicstr) 27449062Sbostic logwakeup(); 27549062Sbostic consintr = savintr; /* reenable interrupts */ 27631Sbill } 27731Sbill 2782781Swnj /* 27949062Sbostic * Scaled down version of printf(3). 28049062Sbostic * 28149062Sbostic * Two additional formats: 28249062Sbostic * 28349062Sbostic * The format %b is supported to decode error registers. 28449062Sbostic * Its usage is: 28549062Sbostic * 286*49908Sbostic * printf("reg=%b\n", regval, "<base><arg>*"); 28749062Sbostic * 28849062Sbostic * where <base> is the output base expressed as a control character, e.g. 28949062Sbostic * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, 29049062Sbostic * the first of which gives the bit number to be inspected (origin 1), and 29149062Sbostic * the next characters (up to a control character, i.e. a character <= 32), 29249062Sbostic * give the name of the register. Thus: 29349062Sbostic * 294*49908Sbostic * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 29549062Sbostic * 29649062Sbostic * would produce output: 29749062Sbostic * 29849062Sbostic * reg=3<BITTWO,BITONE> 29949062Sbostic * 30049062Sbostic * The format %r is supposed to pass an additional format string and argument 30149062Sbostic * list recursively. 30249062Sbostic * Its usage is: 30349062Sbostic * 30449062Sbostic * fn(otherstuff, fmt [, arg1, ... ]) 30549062Sbostic * char *fmt; 30649062Sbostic * u_int arg1, ...; 30749062Sbostic * 308*49908Sbostic * printf("prefix: %r, other stuff\n", fmt, ap); 309*49908Sbostic * 310*49908Sbostic * Space or zero padding and a field width are supported for the numeric 311*49908Sbostic * formats only. 3122781Swnj */ 313*49908Sbostic static void 31449094Sbostic kprintf(fmt, flags, tp, ap) 31549094Sbostic register const char *fmt; 31649062Sbostic int flags; 31749094Sbostic struct tty *tp; 31849062Sbostic va_list ap; 31931Sbill { 32049062Sbostic register char *p; 32149062Sbostic register int ch, n; 322*49908Sbostic u_long ul; 323*49908Sbostic int base, lflag, tmp, width; 324*49908Sbostic char padc; 32531Sbill 32649062Sbostic for (;;) { 327*49908Sbostic padc = ' '; 328*49908Sbostic width = 0; 32949062Sbostic while ((ch = *fmt++) != '%') { 33049062Sbostic if (ch == '\0') 33149062Sbostic return; 33249094Sbostic putchar(ch, flags, tp); 33329946Skarels } 33449062Sbostic lflag = 0; 33549062Sbostic reswitch: switch (ch = *fmt++) { 336*49908Sbostic case '0': 337*49908Sbostic padc = '0'; 338*49908Sbostic goto reswitch; 339*49908Sbostic case '1': case '2': case '3': case '4': 340*49908Sbostic case '5': case '6': case '7': case '8': case '9': 341*49908Sbostic for (width = 0;; ++fmt) { 342*49908Sbostic width = width * 10 + ch - '0'; 343*49908Sbostic ch = *fmt; 344*49908Sbostic if (ch < '0' || ch > '9') 345*49908Sbostic break; 346*49908Sbostic } 347*49908Sbostic goto reswitch; 34849062Sbostic case 'l': 34949062Sbostic lflag = 1; 35049062Sbostic goto reswitch; 35149062Sbostic case 'b': 35249062Sbostic ul = va_arg(ap, int); 35349062Sbostic p = va_arg(ap, char *); 354*49908Sbostic for (p = ksprintn(ul, *p++, NULL); ch = *p--;) 355*49908Sbostic putchar(ch, flags, tp); 35631Sbill 35749062Sbostic if (!ul) 35849062Sbostic break; 3592377Swnj 360*49908Sbostic for (tmp = 0; n = *p++;) { 36149062Sbostic if (ul & (1 << (n - 1))) { 362*49908Sbostic putchar(tmp ? ',' : '<', flags, tp); 36349062Sbostic for (; (n = *p) > ' '; ++p) 36449094Sbostic putchar(n, flags, tp); 365*49908Sbostic tmp = 1; 36649062Sbostic } else 36749062Sbostic for (; *p > ' '; ++p); 36849062Sbostic } 369*49908Sbostic if (tmp) 37049094Sbostic putchar('>', flags, tp); 37149062Sbostic break; 37249062Sbostic case 'c': 37349094Sbostic putchar(va_arg(ap, int), flags, tp); 37449062Sbostic break; 37549062Sbostic case 'r': 37649062Sbostic p = va_arg(ap, char *); 37749094Sbostic kprintf(p, flags, tp, va_arg(ap, va_list)); 37849062Sbostic break; 37949062Sbostic case 's': 38049062Sbostic p = va_arg(ap, char *); 38149062Sbostic while (ch = *p++) 38249094Sbostic putchar(ch, flags, tp); 38349062Sbostic break; 38449062Sbostic case 'd': 385*49908Sbostic ul = lflag ? va_arg(ap, long) : va_arg(ap, int); 38649062Sbostic if ((long)ul < 0) { 38749094Sbostic putchar('-', flags, tp); 38849062Sbostic ul = -(long)ul; 38949062Sbostic } 390*49908Sbostic base = 10; 391*49908Sbostic goto number; 39249062Sbostic case 'o': 393*49908Sbostic ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 394*49908Sbostic base = 8; 395*49908Sbostic goto number;; 39649062Sbostic case 'u': 397*49908Sbostic ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 398*49908Sbostic base = 10; 399*49908Sbostic goto number; 40049062Sbostic case 'x': 401*49908Sbostic ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 402*49908Sbostic base = 16; 403*49908Sbostic number: p = ksprintn(ul, base, &tmp); 404*49908Sbostic if (width && (width -= tmp) > 0) 405*49908Sbostic while (width--) 406*49908Sbostic putchar(padc, flags, tp); 407*49908Sbostic while (ch = *p--) 408*49908Sbostic putchar(ch, flags, tp); 40949062Sbostic break; 41049062Sbostic default: 41149094Sbostic putchar('%', flags, tp); 41249062Sbostic if (lflag) 41349094Sbostic putchar('l', flags, tp); 414*49908Sbostic /* FALLTHROUGH */ 415*49908Sbostic case '%': 41649094Sbostic putchar(ch, flags, tp); 41749062Sbostic } 41830625Skarels } 41931Sbill } 42031Sbill 4212941Swnj /* 42249062Sbostic * Print a character on console or users terminal. If destination is 42349062Sbostic * the console then the last MSGBUFS characters are saved in msgbuf for 42449062Sbostic * inspection later. 425285Sbill */ 42649062Sbostic static void 42749094Sbostic putchar(c, flags, tp) 4282377Swnj register int c; 42949062Sbostic int flags; 43049094Sbostic struct tty *tp; 431285Sbill { 43233479Skarels extern int msgbufmapped; 43349062Sbostic register struct msgbuf *mbp; 434285Sbill 43530549Skarels if (panicstr) 43649062Sbostic constty = NULL; 43749094Sbostic if ((flags & TOCONS) && tp == NULL && constty) { 43849094Sbostic tp = constty; 43930549Skarels flags |= TOTTY; 44030549Skarels } 44149094Sbostic if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 && 44249094Sbostic (flags & TOCONS) && tp == constty) 44349062Sbostic constty = NULL; 44449062Sbostic if ((flags & TOLOG) && 44549062Sbostic c != '\0' && c != '\r' && c != 0177 && msgbufmapped) { 44649062Sbostic mbp = msgbufp; 44745733Smckusick if (mbp->msg_magic != MSG_MAGIC) { 44812494Ssam register int i; 44912494Ssam 45045733Smckusick mbp->msg_magic = MSG_MAGIC; 45145733Smckusick mbp->msg_bufx = mbp->msg_bufr = 0; 45249062Sbostic for (i = 0; i < MSG_BSIZE; i++) 45345733Smckusick mbp->msg_bufc[i] = 0; 4542172Swnj } 45545733Smckusick mbp->msg_bufc[mbp->msg_bufx++] = c; 45645733Smckusick if (mbp->msg_bufx < 0 || mbp->msg_bufx >= MSG_BSIZE) 45745733Smckusick mbp->msg_bufx = 0; 458285Sbill } 45949062Sbostic if ((flags & TOCONS) && constty == NULL && c != '\0') 46030549Skarels (*v_putc)(c); 461285Sbill } 462*49908Sbostic 463*49908Sbostic /* 464*49908Sbostic * Scaled down version of sprintf(3). 465*49908Sbostic */ 466*49908Sbostic #ifdef __STDC__ 467*49908Sbostic sprintf(char *buf, const char *fmt, ...) 468*49908Sbostic #else 469*49908Sbostic sprintf(buf, fmt /*, va_alist */) 470*49908Sbostic char *buf, *fmt; 471*49908Sbostic #endif 472*49908Sbostic { 473*49908Sbostic register char *p, *bp; 474*49908Sbostic register int ch, base; 475*49908Sbostic u_long ul; 476*49908Sbostic int lflag; 477*49908Sbostic va_list ap; 478*49908Sbostic 479*49908Sbostic va_start(ap, fmt); 480*49908Sbostic for (bp = buf;;) { 481*49908Sbostic while ((ch = *fmt++) != '%') 482*49908Sbostic if ((*bp++ = ch) == '\0') 483*49908Sbostic return((bp - buf) - 1); 484*49908Sbostic lflag = 0; 485*49908Sbostic reswitch: switch (ch = *fmt++) { 486*49908Sbostic case 'l': 487*49908Sbostic lflag = 1; 488*49908Sbostic goto reswitch; 489*49908Sbostic case 'c': 490*49908Sbostic *bp++ = va_arg(ap, int); 491*49908Sbostic break; 492*49908Sbostic case 's': 493*49908Sbostic p = va_arg(ap, char *); 494*49908Sbostic while (*bp++ = *p++); 495*49908Sbostic --bp; 496*49908Sbostic break; 497*49908Sbostic case 'd': 498*49908Sbostic ul = lflag ? va_arg(ap, long) : va_arg(ap, int); 499*49908Sbostic if ((long)ul < 0) { 500*49908Sbostic *bp++ = '-'; 501*49908Sbostic ul = -(long)ul; 502*49908Sbostic } 503*49908Sbostic base = 10; 504*49908Sbostic goto number; 505*49908Sbostic break; 506*49908Sbostic case 'o': 507*49908Sbostic ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 508*49908Sbostic base = 8; 509*49908Sbostic goto number; 510*49908Sbostic break; 511*49908Sbostic case 'u': 512*49908Sbostic ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 513*49908Sbostic base = 10; 514*49908Sbostic goto number; 515*49908Sbostic break; 516*49908Sbostic case 'x': 517*49908Sbostic ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 518*49908Sbostic base = 16; 519*49908Sbostic number: for (p = ksprintn(ul, base, NULL); ch = *p--;) 520*49908Sbostic *bp++ = ch; 521*49908Sbostic break; 522*49908Sbostic default: 523*49908Sbostic *bp++ = '%'; 524*49908Sbostic if (lflag) 525*49908Sbostic *bp++ = 'l'; 526*49908Sbostic /* FALLTHROUGH */ 527*49908Sbostic case '%': 528*49908Sbostic *bp++ = ch; 529*49908Sbostic } 530*49908Sbostic } 531*49908Sbostic va_end(ap); 532*49908Sbostic } 533*49908Sbostic 534*49908Sbostic /* 535*49908Sbostic * Put a number (base <= 16) in a buffer in reverse order; return an 536*49908Sbostic * optional length and a pointer to the NULL terminated (preceded?) 537*49908Sbostic * buffer. 538*49908Sbostic */ 539*49908Sbostic static char * 540*49908Sbostic ksprintn(ul, base, lenp) 541*49908Sbostic register u_long ul; 542*49908Sbostic register int base, *lenp; 543*49908Sbostic { /* A long in base 8, plus NULL. */ 544*49908Sbostic static char buf[sizeof(long) * NBBY / 3 + 2]; 545*49908Sbostic register char *p; 546*49908Sbostic 547*49908Sbostic p = buf; 548*49908Sbostic do { 549*49908Sbostic *++p = "0123456789abcdef"[ul % base]; 550*49908Sbostic } while (ul /= base); 551*49908Sbostic if (lenp) 552*49908Sbostic *lenp = p - buf; 553*49908Sbostic return(p); 554*49908Sbostic } 555