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*52911Storek * @(#)subr_prf.c 7.38 (Berkeley) 03/11/92 823381Smckusick */ 931Sbill 1051768Smarc #include <sys/param.h> 1151768Smarc #include <sys/systm.h> 1251768Smarc #include <sys/buf.h> 1351768Smarc #include <sys/conf.h> 1451768Smarc #include <sys/reboot.h> 1551768Smarc #include <sys/msgbuf.h> 1651768Smarc #include <sys/proc.h> 1751768Smarc #include <sys/ioctl.h> 1851768Smarc #include <sys/vnode.h> 1951768Smarc #include <sys/file.h> 2051768Smarc #include <sys/tty.h> 2151768Smarc #include <sys/tprintf.h> 2251768Smarc #include <sys/syslog.h> 2351768Smarc #include <sys/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 4149062Sbostic extern cnputc(); /* standard console putc */ 4249953Sbostic int (*v_putc)() = cnputc; /* routine to putc on virtual console */ 4340808Smarc 4451768Smarc void logpri __P((int level)); 4549908Sbostic static void putchar __P((int ch, int flags, struct tty *tp)); 4649908Sbostic static char *ksprintn __P((u_long num, int base, int *len)); 4752392Smarc void kprintf __P((const char *fmt, int flags, struct tty *tp, va_list ap)); 4849062Sbostic 4951768Smarc int consintr = 1; /* Ok to handle console interrupts? */ 5051768Smarc 5131Sbill /* 5251768Smarc * Variable panicstr contains argument to first call to panic; used as flag 5351768Smarc * to indicate that the kernel has already called panic. 5431Sbill */ 5551768Smarc const char *panicstr; 5629946Skarels 5749062Sbostic /* 5849062Sbostic * Panic is called on unresolvable fatal errors. It prints "panic: mesg", 5949062Sbostic * and then reboots. If we are called twice, then we avoid trying to sync 6049062Sbostic * the disks as this often leads to recursive panics. 6149062Sbostic */ 6252392Smarc #ifdef __GNUC__ 6352406Smckusick volatile void boot(int flags); /* boot() does not return */ 6452392Smarc volatile /* panic() does not return */ 6552392Smarc #endif 6649062Sbostic void 6751768Smarc #ifdef __STDC__ 6851768Smarc panic(const char *fmt, ...) 6951768Smarc #else 7052782Sralph panic(fmt, va_alist) 7151768Smarc char *fmt; 7251768Smarc #endif 7349062Sbostic { 7452392Smarc int bootopt; 7551768Smarc va_list ap; 7648426Skarels 7751768Smarc bootopt = RB_AUTOBOOT | RB_DUMP; 7849062Sbostic if (panicstr) 7949062Sbostic bootopt |= RB_NOSYNC; 8049062Sbostic else 8151768Smarc panicstr = fmt; 8251768Smarc 8351768Smarc va_start(ap, fmt); 8452392Smarc printf("panic: %r\n", fmt, ap); 8551768Smarc va_end(ap); 8651768Smarc 8749062Sbostic #ifdef KGDB 8849062Sbostic kgdb_panic(); 8949062Sbostic #endif 9049062Sbostic #ifdef KADB 9152782Sralph if (boothowto & RB_KDB) 9252782Sralph kdbpanic(); 9349062Sbostic #endif 9449062Sbostic boot(bootopt); 9549062Sbostic } 9649062Sbostic 9749062Sbostic /* 9849062Sbostic * Warn that a system table is full. 9949062Sbostic */ 10049062Sbostic void 10149062Sbostic tablefull(tab) 10252406Smckusick const char *tab; 10331Sbill { 104285Sbill 10549062Sbostic log(LOG_ERR, "%s: table is full\n", tab); 106285Sbill } 107285Sbill 1082377Swnj /* 10939560Smarc * Uprintf prints to the controlling terminal for the current process. 11049062Sbostic * It may block if the tty queue is overfull. No message is printed if 11149062Sbostic * the queue does not clear in a reasonable time. 1122377Swnj */ 11349062Sbostic void 11449062Sbostic #ifdef __STDC__ 11549062Sbostic uprintf(const char *fmt, ...) 11649062Sbostic #else 11751767Smarc uprintf(fmt, va_alist) 1182781Swnj char *fmt; 11949062Sbostic #endif 120285Sbill { 12147540Skarels register struct proc *p = curproc; 12249062Sbostic va_list ap; 123285Sbill 12449953Sbostic if (p->p_flag & SCTTY && p->p_session->s_ttyvp) { 12549953Sbostic va_start(ap, fmt); 12649062Sbostic kprintf(fmt, TOTTY, p->p_session->s_ttyp, ap); 12749953Sbostic va_end(ap); 12849953Sbostic } 129285Sbill } 130285Sbill 13144386Smarc tpr_t 13248426Skarels tprintf_open(p) 13348426Skarels register struct proc *p; 13444386Smarc { 13549953Sbostic 13644386Smarc if (p->p_flag & SCTTY && p->p_session->s_ttyvp) { 13744386Smarc SESSHOLD(p->p_session); 13848426Skarels return ((tpr_t) p->p_session); 13949062Sbostic } 14049062Sbostic return ((tpr_t) NULL); 14144386Smarc } 14244386Smarc 14348426Skarels void 14444386Smarc tprintf_close(sess) 14544386Smarc tpr_t sess; 14644386Smarc { 14749953Sbostic 14844386Smarc if (sess) 14948426Skarels SESSRELE((struct session *) sess); 15044386Smarc } 15144386Smarc 15218364Skarels /* 15344386Smarc * tprintf prints on the controlling terminal associated 15449062Sbostic * with the given session. 15518364Skarels */ 15649062Sbostic void 15749062Sbostic #ifdef __STDC__ 15849062Sbostic tprintf(tpr_t tpr, const char *fmt, ...) 15949062Sbostic #else 16051767Smarc tprintf(tpr, fmt, va_alist) 16148426Skarels tpr_t tpr; 16216724Sralph char *fmt; 16349062Sbostic #endif 16416724Sralph { 16548426Skarels register struct session *sess = (struct session *)tpr; 16648426Skarels struct tty *tp = NULL; 16744386Smarc int flags = TOLOG; 16849062Sbostic va_list ap; 16916724Sralph 17025389Skarels logpri(LOG_INFO); 17148426Skarels if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) { 17244386Smarc flags |= TOTTY; 17348426Skarels tp = sess->s_ttyp; 17448426Skarels } 17549062Sbostic va_start(ap, fmt); 17649062Sbostic kprintf(fmt, flags, tp, ap); 17749062Sbostic va_end(ap); 17825389Skarels logwakeup(); 17916724Sralph } 18016724Sralph 18149062Sbostic /* 18249062Sbostic * Ttyprintf displays a message on a tty; it should be used only by 18349062Sbostic * the tty driver, or anything that knows the underlying tty will not 18449062Sbostic * be revoke(2)'d away. Other callers should use tprintf. 18549062Sbostic */ 18649062Sbostic void 18749062Sbostic #ifdef __STDC__ 18849062Sbostic ttyprintf(struct tty *tp, const char *fmt, ...) 18949062Sbostic #else 19051767Smarc ttyprintf(tp, fmt, va_alist) 19149062Sbostic struct tty *tp; 19249062Sbostic char *fmt; 19349062Sbostic #endif 19449062Sbostic { 19549062Sbostic va_list ap; 19649062Sbostic 19749062Sbostic va_start(ap, fmt); 19849062Sbostic kprintf(fmt, TOTTY, tp, ap); 19949062Sbostic va_end(ap); 20049062Sbostic } 20149062Sbostic 20248426Skarels extern int log_open; 20344386Smarc 20416724Sralph /* 20549062Sbostic * Log writes to the log buffer, and guarantees not to sleep (so can be 20649062Sbostic * called by interrupt routines). If there is no process reading the 20749062Sbostic * log yet, it writes to the console also. 20816724Sralph */ 20949062Sbostic void 21049062Sbostic #ifdef __STDC__ 21149062Sbostic log(int level, const char *fmt, ...) 21249062Sbostic #else 21351767Smarc log(level, fmt, va_alist) 21449062Sbostic int level; 21516724Sralph char *fmt; 21649062Sbostic #endif 21716724Sralph { 21850268Sbostic register int s; 21949062Sbostic va_list ap; 22016724Sralph 22150268Sbostic s = splhigh(); 22225389Skarels logpri(level); 22349062Sbostic va_start(ap, fmt); 22449062Sbostic kprintf(fmt, TOLOG, NULL, ap); 22516724Sralph splx(s); 22649953Sbostic va_end(ap); 22749953Sbostic if (!log_open) { 22849953Sbostic va_start(ap, fmt); 22949062Sbostic kprintf(fmt, TOCONS, NULL, ap); 23049953Sbostic va_end(ap); 23149953Sbostic } 23216724Sralph logwakeup(); 23316724Sralph } 23416724Sralph 23551768Smarc void 23625389Skarels logpri(level) 23725389Skarels int level; 23825389Skarels { 23949908Sbostic register int ch; 24049908Sbostic register char *p; 24125389Skarels 24249062Sbostic putchar('<', TOLOG, NULL); 24349908Sbostic for (p = ksprintn((u_long)level, 10, NULL); ch = *p--;) 24449908Sbostic putchar(ch, TOLOG, NULL); 24549062Sbostic putchar('>', TOLOG, NULL); 24625389Skarels } 24725389Skarels 24849062Sbostic void 24949062Sbostic #ifdef __STDC__ 25049062Sbostic addlog(const char *fmt, ...) 25149062Sbostic #else 25251767Smarc addlog(fmt, va_alist) 25333479Skarels char *fmt; 25449062Sbostic #endif 25533479Skarels { 25650268Sbostic register int s; 25749062Sbostic va_list ap; 25833479Skarels 25950268Sbostic s = splhigh(); 26049062Sbostic va_start(ap, fmt); 26149062Sbostic kprintf(fmt, TOLOG, NULL, ap); 26233479Skarels splx(s); 26349953Sbostic va_end(ap); 26449953Sbostic if (!log_open) { 26549953Sbostic va_start(ap, fmt); 26649062Sbostic kprintf(fmt, TOCONS, NULL, ap); 26749953Sbostic va_end(ap); 26849953Sbostic } 26933479Skarels logwakeup(); 27033479Skarels } 27133479Skarels 27249062Sbostic void 27349062Sbostic #ifdef __STDC__ 27449062Sbostic printf(const char *fmt, ...) 27549062Sbostic #else 27651767Smarc printf(fmt, va_alist) 27749062Sbostic char *fmt; 27829946Skarels #endif 27949062Sbostic { 28049953Sbostic va_list ap; 28149062Sbostic register int savintr; 2822678Swnj 28349062Sbostic savintr = consintr; /* disable interrupts */ 28449062Sbostic consintr = 0; 28549062Sbostic va_start(ap, fmt); 28649062Sbostic kprintf(fmt, TOCONS | TOLOG, NULL, ap); 28749062Sbostic va_end(ap); 28849062Sbostic if (!panicstr) 28949062Sbostic logwakeup(); 29049062Sbostic consintr = savintr; /* reenable interrupts */ 29131Sbill } 29231Sbill 2932781Swnj /* 29449062Sbostic * Scaled down version of printf(3). 29549062Sbostic * 29649062Sbostic * Two additional formats: 29749062Sbostic * 29849062Sbostic * The format %b is supported to decode error registers. 29949062Sbostic * Its usage is: 30049062Sbostic * 30152392Smarc * printf("reg=%b\n", regval, "<base><arg>*"); 30249062Sbostic * 30349062Sbostic * where <base> is the output base expressed as a control character, e.g. 30449062Sbostic * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, 30549062Sbostic * the first of which gives the bit number to be inspected (origin 1), and 30649062Sbostic * the next characters (up to a control character, i.e. a character <= 32), 30749062Sbostic * give the name of the register. Thus: 30849062Sbostic * 30951768Smarc * kprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 31049062Sbostic * 31149062Sbostic * would produce output: 31249062Sbostic * 31349062Sbostic * reg=3<BITTWO,BITONE> 31449062Sbostic * 31551768Smarc * The format %r passes an additional format string and argument list 31651768Smarc * recursively. Its usage is: 31749062Sbostic * 31851768Smarc * fn(char *fmt, ...) 31949953Sbostic * { 32049953Sbostic * va_list ap; 32149953Sbostic * va_start(ap, fmt); 32252392Smarc * printf("prefix: %r: suffix\n", fmt, ap); 32349953Sbostic * va_end(ap); 32451768Smarc * } 32549908Sbostic * 32649908Sbostic * Space or zero padding and a field width are supported for the numeric 32749908Sbostic * formats only. 3282781Swnj */ 32949909Sbostic void 33052392Smarc kprintf(fmt, flags, tp, ap) 33149094Sbostic register const char *fmt; 33249062Sbostic int flags; 33349094Sbostic struct tty *tp; 33449062Sbostic va_list ap; 33531Sbill { 33652877Skarels register char *p, *q; 33749062Sbostic register int ch, n; 33849908Sbostic u_long ul; 33949908Sbostic int base, lflag, tmp, width; 34049908Sbostic char padc; 34131Sbill 34249062Sbostic for (;;) { 34349908Sbostic padc = ' '; 34449908Sbostic width = 0; 34549919Skarels while ((ch = *(u_char *)fmt++) != '%') { 34649062Sbostic if (ch == '\0') 34749062Sbostic return; 34849094Sbostic putchar(ch, flags, tp); 34929946Skarels } 35049062Sbostic lflag = 0; 35149919Skarels reswitch: switch (ch = *(u_char *)fmt++) { 35249908Sbostic case '0': 35349908Sbostic padc = '0'; 35449908Sbostic goto reswitch; 35549908Sbostic case '1': case '2': case '3': case '4': 35649908Sbostic case '5': case '6': case '7': case '8': case '9': 35749908Sbostic for (width = 0;; ++fmt) { 35849908Sbostic width = width * 10 + ch - '0'; 35949908Sbostic ch = *fmt; 36049908Sbostic if (ch < '0' || ch > '9') 36149908Sbostic break; 36249908Sbostic } 36349908Sbostic goto reswitch; 36449062Sbostic case 'l': 36549062Sbostic lflag = 1; 36649062Sbostic goto reswitch; 36749062Sbostic case 'b': 36849062Sbostic ul = va_arg(ap, int); 36949062Sbostic p = va_arg(ap, char *); 37052877Skarels for (q = ksprintn(ul, *p++, NULL); ch = *q--;) 37149908Sbostic putchar(ch, flags, tp); 37231Sbill 37349062Sbostic if (!ul) 37449062Sbostic break; 3752377Swnj 37649908Sbostic for (tmp = 0; n = *p++;) { 37749062Sbostic if (ul & (1 << (n - 1))) { 37849908Sbostic putchar(tmp ? ',' : '<', flags, tp); 37949062Sbostic for (; (n = *p) > ' '; ++p) 38049094Sbostic putchar(n, flags, tp); 38149908Sbostic tmp = 1; 38249062Sbostic } else 383*52911Storek for (; *p > ' '; ++p) 384*52911Storek continue; 38549062Sbostic } 38649908Sbostic if (tmp) 38749094Sbostic putchar('>', flags, tp); 38849062Sbostic break; 38949062Sbostic case 'c': 39049094Sbostic putchar(va_arg(ap, int), flags, tp); 39149062Sbostic break; 39249062Sbostic case 'r': 39349062Sbostic p = va_arg(ap, char *); 39449094Sbostic kprintf(p, flags, tp, va_arg(ap, va_list)); 39549062Sbostic break; 39649062Sbostic case 's': 39749062Sbostic p = va_arg(ap, char *); 39849062Sbostic while (ch = *p++) 39949094Sbostic putchar(ch, flags, tp); 40049062Sbostic break; 40149062Sbostic case 'd': 40249908Sbostic ul = lflag ? va_arg(ap, long) : va_arg(ap, int); 40349062Sbostic if ((long)ul < 0) { 40449094Sbostic putchar('-', flags, tp); 40549062Sbostic ul = -(long)ul; 40649062Sbostic } 40749908Sbostic base = 10; 40849908Sbostic goto number; 40949062Sbostic case 'o': 41049908Sbostic ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 41149908Sbostic base = 8; 41249953Sbostic goto number; 41349062Sbostic case 'u': 41449908Sbostic ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 41549908Sbostic base = 10; 41649908Sbostic goto number; 41749062Sbostic case 'x': 41849908Sbostic ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 41949908Sbostic base = 16; 42049908Sbostic number: p = ksprintn(ul, base, &tmp); 42149908Sbostic if (width && (width -= tmp) > 0) 42249908Sbostic while (width--) 42349908Sbostic putchar(padc, flags, tp); 42449908Sbostic while (ch = *p--) 42549908Sbostic putchar(ch, flags, tp); 42649062Sbostic break; 42749062Sbostic default: 42849094Sbostic putchar('%', flags, tp); 42949062Sbostic if (lflag) 43049094Sbostic putchar('l', flags, tp); 43149908Sbostic /* FALLTHROUGH */ 43249908Sbostic case '%': 43349094Sbostic putchar(ch, flags, tp); 43449062Sbostic } 43530625Skarels } 43631Sbill } 43731Sbill 4382941Swnj /* 43949062Sbostic * Print a character on console or users terminal. If destination is 44049062Sbostic * the console then the last MSGBUFS characters are saved in msgbuf for 44149062Sbostic * inspection later. 442285Sbill */ 44349062Sbostic static void 44449094Sbostic putchar(c, flags, tp) 4452377Swnj register int c; 44649062Sbostic int flags; 44749094Sbostic struct tty *tp; 448285Sbill { 44933479Skarels extern int msgbufmapped; 45050268Sbostic register struct msgbuf *mbp; 451285Sbill 45230549Skarels if (panicstr) 45349062Sbostic constty = NULL; 45449094Sbostic if ((flags & TOCONS) && tp == NULL && constty) { 45549094Sbostic tp = constty; 45630549Skarels flags |= TOTTY; 45730549Skarels } 45849094Sbostic if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 && 45949094Sbostic (flags & TOCONS) && tp == constty) 46049062Sbostic constty = NULL; 46149062Sbostic if ((flags & TOLOG) && 46249062Sbostic c != '\0' && c != '\r' && c != 0177 && msgbufmapped) { 46350268Sbostic mbp = msgbufp; 46445733Smckusick if (mbp->msg_magic != MSG_MAGIC) { 46549953Sbostic bzero((caddr_t)mbp, sizeof(*mbp)); 46645733Smckusick mbp->msg_magic = MSG_MAGIC; 4672172Swnj } 46845733Smckusick mbp->msg_bufc[mbp->msg_bufx++] = c; 46945733Smckusick if (mbp->msg_bufx < 0 || mbp->msg_bufx >= MSG_BSIZE) 47045733Smckusick mbp->msg_bufx = 0; 471285Sbill } 47249062Sbostic if ((flags & TOCONS) && constty == NULL && c != '\0') 47330549Skarels (*v_putc)(c); 474285Sbill } 47549908Sbostic 47649908Sbostic /* 47749908Sbostic * Scaled down version of sprintf(3). 47849908Sbostic */ 47949908Sbostic #ifdef __STDC__ 48049919Skarels sprintf(char *buf, const char *cfmt, ...) 48149908Sbostic #else 48251767Smarc sprintf(buf, cfmt, va_alist) 48349919Skarels char *buf, *cfmt; 48449908Sbostic #endif 48549908Sbostic { 48649919Skarels register const char *fmt = cfmt; 48749908Sbostic register char *p, *bp; 48849908Sbostic register int ch, base; 48949908Sbostic u_long ul; 49049908Sbostic int lflag; 49149908Sbostic va_list ap; 49249908Sbostic 49349919Skarels va_start(ap, cfmt); 49449919Skarels for (bp = buf; ; ) { 49549919Skarels while ((ch = *(u_char *)fmt++) != '%') 49649908Sbostic if ((*bp++ = ch) == '\0') 49749919Skarels return ((bp - buf) - 1); 49849919Skarels 49949908Sbostic lflag = 0; 50049919Skarels reswitch: switch (ch = *(u_char *)fmt++) { 50149908Sbostic case 'l': 50249908Sbostic lflag = 1; 50349908Sbostic goto reswitch; 50449908Sbostic case 'c': 50549908Sbostic *bp++ = va_arg(ap, int); 50649908Sbostic break; 50749908Sbostic case 's': 50849908Sbostic p = va_arg(ap, char *); 50949919Skarels while (*bp++ = *p++) 51052392Smarc continue; 51149908Sbostic --bp; 51249908Sbostic break; 51349908Sbostic case 'd': 51449908Sbostic ul = lflag ? va_arg(ap, long) : va_arg(ap, int); 51549908Sbostic if ((long)ul < 0) { 51649908Sbostic *bp++ = '-'; 51749908Sbostic ul = -(long)ul; 51849908Sbostic } 51949908Sbostic base = 10; 52049908Sbostic goto number; 52149908Sbostic break; 52249908Sbostic case 'o': 52349908Sbostic ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 52449908Sbostic base = 8; 52549908Sbostic goto number; 52649908Sbostic break; 52749908Sbostic case 'u': 52849908Sbostic ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 52949908Sbostic base = 10; 53049908Sbostic goto number; 53149908Sbostic break; 53249908Sbostic case 'x': 53349908Sbostic ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 53449908Sbostic base = 16; 53549908Sbostic number: for (p = ksprintn(ul, base, NULL); ch = *p--;) 53649908Sbostic *bp++ = ch; 53749908Sbostic break; 53849908Sbostic default: 53949908Sbostic *bp++ = '%'; 54049908Sbostic if (lflag) 54149908Sbostic *bp++ = 'l'; 54249908Sbostic /* FALLTHROUGH */ 54349908Sbostic case '%': 54449908Sbostic *bp++ = ch; 54549908Sbostic } 54649908Sbostic } 54749908Sbostic va_end(ap); 54849908Sbostic } 54949908Sbostic 55049908Sbostic /* 55149908Sbostic * Put a number (base <= 16) in a buffer in reverse order; return an 55249908Sbostic * optional length and a pointer to the NULL terminated (preceded?) 55349908Sbostic * buffer. 55449908Sbostic */ 55549908Sbostic static char * 55649908Sbostic ksprintn(ul, base, lenp) 55749908Sbostic register u_long ul; 55849908Sbostic register int base, *lenp; 55949908Sbostic { /* A long in base 8, plus NULL. */ 56049908Sbostic static char buf[sizeof(long) * NBBY / 3 + 2]; 56149908Sbostic register char *p; 56249908Sbostic 56349908Sbostic p = buf; 56449908Sbostic do { 56549908Sbostic *++p = "0123456789abcdef"[ul % base]; 56649908Sbostic } while (ul /= base); 56749908Sbostic if (lenp) 56849908Sbostic *lenp = p - buf; 56949919Skarels return (p); 57049908Sbostic } 571