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*49953Sbostic * @(#)subr_prf.c 7.29 (Berkeley) 05/30/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 */ 48*49953Sbostic int (*v_putc)() = cnputc; /* routine to putc on virtual console */ 4940808Smarc 5049908Sbostic static void logpri __P((int level)); 5149908Sbostic static void putchar __P((int ch, int flags, struct tty *tp)); 5249908Sbostic static char *ksprintn __P((u_long num, int base, int *len)); 5349909Sbostic void kprintf __P((const char *fmt, int flags, struct tty *tp, va_list)); 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; 7148426Skarels 7249062Sbostic if (panicstr) 7349062Sbostic bootopt |= RB_NOSYNC; 7449062Sbostic else 7549062Sbostic panicstr = msg; 7649062Sbostic printf("panic: %s\n", msg); 7749062Sbostic #ifdef KGDB 7849062Sbostic kgdb_panic(); 7949062Sbostic #endif 8049062Sbostic #ifdef KADB 8149062Sbostic if (boothowto & RB_KDB) { 82*49953Sbostic int s = splnet(); /* below kdb pri */ 8349062Sbostic setsoftkdb(); 8449062Sbostic splx(s); 8549062Sbostic } 8649062Sbostic #endif 8749062Sbostic boot(bootopt); 8849062Sbostic } 8949062Sbostic 9049062Sbostic /* 9149062Sbostic * Warn that a system table is full. 9249062Sbostic */ 9349062Sbostic void 9449062Sbostic tablefull(tab) 9549062Sbostic char *tab; 9631Sbill { 97285Sbill 9849062Sbostic log(LOG_ERR, "%s: table is full\n", tab); 99285Sbill } 100285Sbill 1012377Swnj /* 10239560Smarc * Uprintf prints to the controlling terminal for the current process. 10349062Sbostic * It may block if the tty queue is overfull. No message is printed if 10449062Sbostic * the queue does not clear in a reasonable time. 1052377Swnj */ 10649062Sbostic void 10749062Sbostic #ifdef __STDC__ 10849062Sbostic uprintf(const char *fmt, ...) 10949062Sbostic #else 11049062Sbostic uprintf(fmt /*, va_alist */) 1112781Swnj char *fmt; 11249062Sbostic #endif 113285Sbill { 11447540Skarels register struct proc *p = curproc; 11549062Sbostic va_list ap; 116285Sbill 117*49953Sbostic if (p->p_flag & SCTTY && p->p_session->s_ttyvp) { 118*49953Sbostic va_start(ap, fmt); 11949062Sbostic kprintf(fmt, TOTTY, p->p_session->s_ttyp, ap); 120*49953Sbostic va_end(ap); 121*49953Sbostic } 122285Sbill } 123285Sbill 12444386Smarc tpr_t 12548426Skarels tprintf_open(p) 12648426Skarels register struct proc *p; 12744386Smarc { 128*49953Sbostic 12944386Smarc if (p->p_flag & SCTTY && p->p_session->s_ttyvp) { 13044386Smarc SESSHOLD(p->p_session); 13148426Skarels return ((tpr_t) p->p_session); 13249062Sbostic } 13349062Sbostic return ((tpr_t) NULL); 13444386Smarc } 13544386Smarc 13648426Skarels void 13744386Smarc tprintf_close(sess) 13844386Smarc tpr_t sess; 13944386Smarc { 140*49953Sbostic 14144386Smarc if (sess) 14248426Skarels SESSRELE((struct session *) sess); 14344386Smarc } 14444386Smarc 14518364Skarels /* 14644386Smarc * tprintf prints on the controlling terminal associated 14749062Sbostic * with the given session. 14818364Skarels */ 14949062Sbostic void 15049062Sbostic #ifdef __STDC__ 15149062Sbostic tprintf(tpr_t tpr, const char *fmt, ...) 15249062Sbostic #else 15349062Sbostic tprintf(tpr, fmt /*, va_alist */) 15448426Skarels tpr_t tpr; 15516724Sralph char *fmt; 15649062Sbostic #endif 15716724Sralph { 15848426Skarels register struct session *sess = (struct session *)tpr; 15948426Skarels struct tty *tp = NULL; 16044386Smarc int flags = TOLOG; 16149062Sbostic va_list ap; 16216724Sralph 16325389Skarels logpri(LOG_INFO); 16448426Skarels if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) { 16544386Smarc flags |= TOTTY; 16648426Skarels tp = sess->s_ttyp; 16748426Skarels } 16849062Sbostic va_start(ap, fmt); 16949062Sbostic kprintf(fmt, flags, tp, ap); 17049062Sbostic va_end(ap); 17125389Skarels logwakeup(); 17216724Sralph } 17316724Sralph 17449062Sbostic /* 17549062Sbostic * Ttyprintf displays a message on a tty; it should be used only by 17649062Sbostic * the tty driver, or anything that knows the underlying tty will not 17749062Sbostic * be revoke(2)'d away. Other callers should use tprintf. 17849062Sbostic */ 17949062Sbostic void 18049062Sbostic #ifdef __STDC__ 18149062Sbostic ttyprintf(struct tty *tp, const char *fmt, ...) 18249062Sbostic #else 18349062Sbostic ttyprintf(tp, fmt /*, va_alist */) 18449062Sbostic struct tty *tp; 18549062Sbostic char *fmt; 18649062Sbostic #endif 18749062Sbostic { 18849062Sbostic va_list ap; 18949062Sbostic 19049062Sbostic va_start(ap, fmt); 19149062Sbostic kprintf(fmt, TOTTY, tp, ap); 19249062Sbostic va_end(ap); 19349062Sbostic } 19449062Sbostic 19548426Skarels extern int log_open; 19644386Smarc 19716724Sralph /* 19849062Sbostic * Log writes to the log buffer, and guarantees not to sleep (so can be 19949062Sbostic * called by interrupt routines). If there is no process reading the 20049062Sbostic * log yet, it writes to the console also. 20116724Sralph */ 20249062Sbostic void 20349062Sbostic #ifdef __STDC__ 20449062Sbostic log(int level, const char *fmt, ...) 20549062Sbostic #else 20649062Sbostic log(level, fmt /*, va_alist */) 20749062Sbostic int level; 20816724Sralph char *fmt; 20949062Sbostic #endif 21016724Sralph { 211*49953Sbostic register int s = splhigh(); 21249062Sbostic va_list ap; 21316724Sralph 21425389Skarels logpri(level); 21549062Sbostic va_start(ap, fmt); 21649062Sbostic kprintf(fmt, TOLOG, NULL, ap); 21716724Sralph splx(s); 218*49953Sbostic va_end(ap); 219*49953Sbostic if (!log_open) { 220*49953Sbostic va_start(ap, fmt); 22149062Sbostic kprintf(fmt, TOCONS, NULL, ap); 222*49953Sbostic va_end(ap); 223*49953Sbostic } 22416724Sralph logwakeup(); 22516724Sralph } 22616724Sralph 22749062Sbostic static void 22825389Skarels logpri(level) 22925389Skarels int level; 23025389Skarels { 23149908Sbostic register int ch; 23249908Sbostic register char *p; 23325389Skarels 23449062Sbostic putchar('<', TOLOG, NULL); 23549908Sbostic for (p = ksprintn((u_long)level, 10, NULL); ch = *p--;) 23649908Sbostic putchar(ch, TOLOG, NULL); 23749062Sbostic putchar('>', TOLOG, NULL); 23825389Skarels } 23925389Skarels 24049062Sbostic void 24149062Sbostic #ifdef __STDC__ 24249062Sbostic addlog(const char *fmt, ...) 24349062Sbostic #else 24449062Sbostic addlog(fmt /*, va_alist */) 24533479Skarels char *fmt; 24649062Sbostic #endif 24733479Skarels { 248*49953Sbostic register int s = splhigh(); 24949062Sbostic va_list ap; 25033479Skarels 25149062Sbostic va_start(ap, fmt); 25249062Sbostic kprintf(fmt, TOLOG, NULL, ap); 25333479Skarels splx(s); 254*49953Sbostic va_end(ap); 255*49953Sbostic if (!log_open) { 256*49953Sbostic va_start(ap, fmt); 25749062Sbostic kprintf(fmt, TOCONS, NULL, ap); 258*49953Sbostic va_end(ap); 259*49953Sbostic } 26033479Skarels logwakeup(); 26133479Skarels } 26233479Skarels 263*49953Sbostic #if defined(tahoe) 26449062Sbostic int consintr = 1; /* ok to handle console interrupts? */ 265*49953Sbostic #endif 26631Sbill 26749062Sbostic void 26849062Sbostic #ifdef __STDC__ 26949062Sbostic printf(const char *fmt, ...) 27049062Sbostic #else 27149062Sbostic printf(fmt /*, va_alist */) 27249062Sbostic char *fmt; 27329946Skarels #endif 27449062Sbostic { 275*49953Sbostic va_list ap; 276*49953Sbostic #ifdef tahoe 27749062Sbostic register int savintr; 2782678Swnj 27949062Sbostic savintr = consintr; /* disable interrupts */ 28049062Sbostic consintr = 0; 281*49953Sbostic #endif 28249062Sbostic va_start(ap, fmt); 28349062Sbostic kprintf(fmt, TOCONS | TOLOG, NULL, ap); 28449062Sbostic va_end(ap); 28549062Sbostic if (!panicstr) 28649062Sbostic logwakeup(); 287*49953Sbostic #ifdef tahoe 28849062Sbostic consintr = savintr; /* reenable interrupts */ 289*49953Sbostic #endif 29031Sbill } 29131Sbill 2922781Swnj /* 29349062Sbostic * Scaled down version of printf(3). 29449062Sbostic * 29549062Sbostic * Two additional formats: 29649062Sbostic * 29749062Sbostic * The format %b is supported to decode error registers. 29849062Sbostic * Its usage is: 29949062Sbostic * 30049908Sbostic * printf("reg=%b\n", regval, "<base><arg>*"); 30149062Sbostic * 30249062Sbostic * where <base> is the output base expressed as a control character, e.g. 30349062Sbostic * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, 30449062Sbostic * the first of which gives the bit number to be inspected (origin 1), and 30549062Sbostic * the next characters (up to a control character, i.e. a character <= 32), 30649062Sbostic * give the name of the register. Thus: 30749062Sbostic * 30849908Sbostic * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 30949062Sbostic * 31049062Sbostic * would produce output: 31149062Sbostic * 31249062Sbostic * reg=3<BITTWO,BITONE> 31349062Sbostic * 31449062Sbostic * The format %r is supposed to pass an additional format string and argument 31549062Sbostic * list recursively. 31649062Sbostic * Its usage is: 31749062Sbostic * 318*49953Sbostic * fn(otherstuff, char *fmt, ...) 319*49953Sbostic * { 320*49953Sbostic * va_list ap; 321*49953Sbostic * va_start(ap, fmt); 32249908Sbostic * printf("prefix: %r, other stuff\n", fmt, ap); 323*49953Sbostic * va_end(ap); 32449908Sbostic * 32549908Sbostic * Space or zero padding and a field width are supported for the numeric 32649908Sbostic * formats only. 3272781Swnj */ 32849909Sbostic void 32949094Sbostic kprintf(fmt, flags, tp, ap) 33049094Sbostic register const char *fmt; 33149062Sbostic int flags; 33249094Sbostic struct tty *tp; 33349062Sbostic va_list ap; 33431Sbill { 33549062Sbostic register char *p; 33649062Sbostic register int ch, n; 33749908Sbostic u_long ul; 33849908Sbostic int base, lflag, tmp, width; 33949908Sbostic char padc; 34031Sbill 34149062Sbostic for (;;) { 34249908Sbostic padc = ' '; 34349908Sbostic width = 0; 34449919Skarels while ((ch = *(u_char *)fmt++) != '%') { 34549062Sbostic if (ch == '\0') 34649062Sbostic return; 34749094Sbostic putchar(ch, flags, tp); 34829946Skarels } 34949062Sbostic lflag = 0; 35049919Skarels reswitch: switch (ch = *(u_char *)fmt++) { 35149908Sbostic case '0': 35249908Sbostic padc = '0'; 35349908Sbostic goto reswitch; 35449908Sbostic case '1': case '2': case '3': case '4': 35549908Sbostic case '5': case '6': case '7': case '8': case '9': 35649908Sbostic for (width = 0;; ++fmt) { 35749908Sbostic width = width * 10 + ch - '0'; 35849908Sbostic ch = *fmt; 35949908Sbostic if (ch < '0' || ch > '9') 36049908Sbostic break; 36149908Sbostic } 36249908Sbostic goto reswitch; 36349062Sbostic case 'l': 36449062Sbostic lflag = 1; 36549062Sbostic goto reswitch; 36649062Sbostic case 'b': 36749062Sbostic ul = va_arg(ap, int); 36849062Sbostic p = va_arg(ap, char *); 36949908Sbostic for (p = ksprintn(ul, *p++, NULL); ch = *p--;) 37049908Sbostic putchar(ch, flags, tp); 37131Sbill 37249062Sbostic if (!ul) 37349062Sbostic break; 3742377Swnj 37549908Sbostic for (tmp = 0; n = *p++;) { 37649062Sbostic if (ul & (1 << (n - 1))) { 37749908Sbostic putchar(tmp ? ',' : '<', flags, tp); 37849062Sbostic for (; (n = *p) > ' '; ++p) 37949094Sbostic putchar(n, flags, tp); 38049908Sbostic tmp = 1; 38149062Sbostic } else 38249062Sbostic for (; *p > ' '; ++p); 38349062Sbostic } 38449908Sbostic if (tmp) 38549094Sbostic putchar('>', flags, tp); 38649062Sbostic break; 38749062Sbostic case 'c': 38849094Sbostic putchar(va_arg(ap, int), flags, tp); 38949062Sbostic break; 39049062Sbostic case 'r': 39149062Sbostic p = va_arg(ap, char *); 39249094Sbostic kprintf(p, flags, tp, va_arg(ap, va_list)); 39349062Sbostic break; 39449062Sbostic case 's': 39549062Sbostic p = va_arg(ap, char *); 39649062Sbostic while (ch = *p++) 39749094Sbostic putchar(ch, flags, tp); 39849062Sbostic break; 39949062Sbostic case 'd': 40049908Sbostic ul = lflag ? va_arg(ap, long) : va_arg(ap, int); 40149062Sbostic if ((long)ul < 0) { 40249094Sbostic putchar('-', flags, tp); 40349062Sbostic ul = -(long)ul; 40449062Sbostic } 40549908Sbostic base = 10; 40649908Sbostic goto number; 40749062Sbostic case 'o': 40849908Sbostic ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 40949908Sbostic base = 8; 410*49953Sbostic goto number; 41149062Sbostic case 'u': 41249908Sbostic ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 41349908Sbostic base = 10; 41449908Sbostic goto number; 41549062Sbostic case 'x': 41649908Sbostic ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 41749908Sbostic base = 16; 41849908Sbostic number: p = ksprintn(ul, base, &tmp); 41949908Sbostic if (width && (width -= tmp) > 0) 42049908Sbostic while (width--) 42149908Sbostic putchar(padc, flags, tp); 42249908Sbostic while (ch = *p--) 42349908Sbostic putchar(ch, flags, tp); 42449062Sbostic break; 42549062Sbostic default: 42649094Sbostic putchar('%', flags, tp); 42749062Sbostic if (lflag) 42849094Sbostic putchar('l', flags, tp); 42949908Sbostic /* FALLTHROUGH */ 43049908Sbostic case '%': 43149094Sbostic putchar(ch, flags, tp); 43249062Sbostic } 43330625Skarels } 43431Sbill } 43531Sbill 4362941Swnj /* 43749062Sbostic * Print a character on console or users terminal. If destination is 43849062Sbostic * the console then the last MSGBUFS characters are saved in msgbuf for 43949062Sbostic * inspection later. 440285Sbill */ 44149062Sbostic static void 44249094Sbostic putchar(c, flags, tp) 4432377Swnj register int c; 44449062Sbostic int flags; 44549094Sbostic struct tty *tp; 446285Sbill { 44733479Skarels extern int msgbufmapped; 448*49953Sbostic register struct msgbuf *mbp = msgbufp; 449285Sbill 45030549Skarels if (panicstr) 45149062Sbostic constty = NULL; 45249094Sbostic if ((flags & TOCONS) && tp == NULL && constty) { 45349094Sbostic tp = constty; 45430549Skarels flags |= TOTTY; 45530549Skarels } 45649094Sbostic if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 && 45749094Sbostic (flags & TOCONS) && tp == constty) 45849062Sbostic constty = NULL; 45949062Sbostic if ((flags & TOLOG) && 46049062Sbostic c != '\0' && c != '\r' && c != 0177 && msgbufmapped) { 46145733Smckusick if (mbp->msg_magic != MSG_MAGIC) { 462*49953Sbostic bzero((caddr_t)mbp, sizeof(*mbp)); 46345733Smckusick mbp->msg_magic = MSG_MAGIC; 4642172Swnj } 46545733Smckusick mbp->msg_bufc[mbp->msg_bufx++] = c; 46645733Smckusick if (mbp->msg_bufx < 0 || mbp->msg_bufx >= MSG_BSIZE) 46745733Smckusick mbp->msg_bufx = 0; 468285Sbill } 46949062Sbostic if ((flags & TOCONS) && constty == NULL && c != '\0') 47030549Skarels (*v_putc)(c); 471285Sbill } 47249908Sbostic 47349908Sbostic /* 47449908Sbostic * Scaled down version of sprintf(3). 47549908Sbostic */ 47649908Sbostic #ifdef __STDC__ 47749919Skarels sprintf(char *buf, const char *cfmt, ...) 47849908Sbostic #else 47949919Skarels sprintf(buf, cfmt /*, va_alist */) 48049919Skarels char *buf, *cfmt; 48149908Sbostic #endif 48249908Sbostic { 48349919Skarels register const char *fmt = cfmt; 48449908Sbostic register char *p, *bp; 48549908Sbostic register int ch, base; 48649908Sbostic u_long ul; 48749908Sbostic int lflag; 48849908Sbostic va_list ap; 48949908Sbostic 49049919Skarels va_start(ap, cfmt); 49149919Skarels for (bp = buf; ; ) { 49249919Skarels while ((ch = *(u_char *)fmt++) != '%') 49349908Sbostic if ((*bp++ = ch) == '\0') 49449919Skarels return ((bp - buf) - 1); 49549919Skarels 49649908Sbostic lflag = 0; 49749919Skarels reswitch: switch (ch = *(u_char *)fmt++) { 49849908Sbostic case 'l': 49949908Sbostic lflag = 1; 50049908Sbostic goto reswitch; 50149908Sbostic case 'c': 50249908Sbostic *bp++ = va_arg(ap, int); 50349908Sbostic break; 50449908Sbostic case 's': 50549908Sbostic p = va_arg(ap, char *); 50649919Skarels while (*bp++ = *p++) 50749919Skarels ; 50849908Sbostic --bp; 50949908Sbostic break; 51049908Sbostic case 'd': 51149908Sbostic ul = lflag ? va_arg(ap, long) : va_arg(ap, int); 51249908Sbostic if ((long)ul < 0) { 51349908Sbostic *bp++ = '-'; 51449908Sbostic ul = -(long)ul; 51549908Sbostic } 51649908Sbostic base = 10; 51749908Sbostic goto number; 51849908Sbostic break; 51949908Sbostic case 'o': 52049908Sbostic ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 52149908Sbostic base = 8; 52249908Sbostic goto number; 52349908Sbostic break; 52449908Sbostic case 'u': 52549908Sbostic ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 52649908Sbostic base = 10; 52749908Sbostic goto number; 52849908Sbostic break; 52949908Sbostic case 'x': 53049908Sbostic ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 53149908Sbostic base = 16; 53249908Sbostic number: for (p = ksprintn(ul, base, NULL); ch = *p--;) 53349908Sbostic *bp++ = ch; 53449908Sbostic break; 53549908Sbostic default: 53649908Sbostic *bp++ = '%'; 53749908Sbostic if (lflag) 53849908Sbostic *bp++ = 'l'; 53949908Sbostic /* FALLTHROUGH */ 54049908Sbostic case '%': 54149908Sbostic *bp++ = ch; 54249908Sbostic } 54349908Sbostic } 54449908Sbostic va_end(ap); 54549908Sbostic } 54649908Sbostic 54749908Sbostic /* 54849908Sbostic * Put a number (base <= 16) in a buffer in reverse order; return an 54949908Sbostic * optional length and a pointer to the NULL terminated (preceded?) 55049908Sbostic * buffer. 55149908Sbostic */ 55249908Sbostic static char * 55349908Sbostic ksprintn(ul, base, lenp) 55449908Sbostic register u_long ul; 55549908Sbostic register int base, *lenp; 55649908Sbostic { /* A long in base 8, plus NULL. */ 55749908Sbostic static char buf[sizeof(long) * NBBY / 3 + 2]; 55849908Sbostic register char *p; 55949908Sbostic 56049908Sbostic p = buf; 56149908Sbostic do { 56249908Sbostic *++p = "0123456789abcdef"[ul % base]; 56349908Sbostic } while (ul /= base); 56449908Sbostic if (lenp) 56549908Sbostic *lenp = p - buf; 56649919Skarels return (p); 56749908Sbostic } 568