1*49062Sbostic /*- 2*49062Sbostic * Copyright (c) 1986, 1988, 1991 The Regents of the University of California. 3*49062Sbostic * All rights reserved. 423381Smckusick * 5*49062Sbostic * %sccs.include.redist.c% 6*49062Sbostic * 7*49062Sbostic * @(#)subr_prf.c 7.22 (Berkeley) 05/04/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 25*49062Sbostic /* 26*49062Sbostic * Note that stdarg.h and the ANSI style va_start macro is used for both 27*49062Sbostic * ANSI and traditional C compilers. 28*49062Sbostic */ 29*49062Sbostic #include <machine/stdarg.h> 30*49062Sbostic 3135282Skarels #ifdef KADB 3237496Smckusick #include "machine/kdbparam.h" 3330625Skarels #endif 3430625Skarels 35*49062Sbostic #define TOCONS 0x01 36*49062Sbostic #define TOTTY 0x02 37*49062Sbostic #define TOLOG 0x04 3816724Sralph 3930549Skarels struct tty *constty; /* pointer to console "window" tty */ 4030549Skarels 4140808Smarc #ifdef KADB 4240808Smarc extern cngetc(); /* standard console getc */ 43*49062Sbostic int (*v_getc)() = cngetc; /* "" getc from virtual console */ 4440808Smarc extern cnpoll(); 4540808Smarc int (*v_poll)() = cnpoll; /* kdb hook to enable input polling */ 4640808Smarc #endif 47*49062Sbostic extern cnputc(); /* standard console putc */ 48*49062Sbostic int (*v_putc)() = cnputc; /* routine to putc on virtual console */ 4940808Smarc 50*49062Sbostic static void logpri __P((int)); 51*49062Sbostic static void putchar __P((int, int, struct tty *)); 52*49062Sbostic static void kprintf __P((const char *, int, struct tty *, ...)); 53*49062Sbostic static void kprintn __P((u_long, int)); 54*49062Sbostic 5531Sbill /* 56*49062Sbostic * Variable panicstr contains argument to first call to panic; used 57*49062Sbostic * as flag to indicate that the kernel has already called panic. 5831Sbill */ 59*49062Sbostic char *panicstr; 6029946Skarels 61*49062Sbostic /* 62*49062Sbostic * Panic is called on unresolvable fatal errors. It prints "panic: mesg", 63*49062Sbostic * and then reboots. If we are called twice, then we avoid trying to sync 64*49062Sbostic * the disks as this often leads to recursive panics. 65*49062Sbostic */ 66*49062Sbostic void 67*49062Sbostic panic(msg) 68*49062Sbostic char *msg; 69*49062Sbostic { 70*49062Sbostic int bootopt = RB_AUTOBOOT | RB_DUMP; 71*49062Sbostic int s; 7248426Skarels 73*49062Sbostic if (panicstr) 74*49062Sbostic bootopt |= RB_NOSYNC; 75*49062Sbostic else 76*49062Sbostic panicstr = msg; 77*49062Sbostic printf("panic: %s\n", msg); 78*49062Sbostic #ifdef KGDB 79*49062Sbostic kgdb_panic(); 80*49062Sbostic #endif 81*49062Sbostic #ifdef KADB 82*49062Sbostic if (boothowto & RB_KDB) { 83*49062Sbostic s = splnet(); /* below kdb pri */ 84*49062Sbostic setsoftkdb(); 85*49062Sbostic splx(s); 86*49062Sbostic } 87*49062Sbostic #endif 88*49062Sbostic boot(bootopt); 89*49062Sbostic } 90*49062Sbostic 91*49062Sbostic /* 92*49062Sbostic * Warn that a system table is full. 93*49062Sbostic */ 94*49062Sbostic void 95*49062Sbostic tablefull(tab) 96*49062Sbostic char *tab; 9731Sbill { 98285Sbill 99*49062Sbostic log(LOG_ERR, "%s: table is full\n", tab); 100285Sbill } 101285Sbill 1022377Swnj /* 10339560Smarc * Uprintf prints to the controlling terminal for the current process. 104*49062Sbostic * It may block if the tty queue is overfull. No message is printed if 105*49062Sbostic * the queue does not clear in a reasonable time. 1062377Swnj */ 107*49062Sbostic void 108*49062Sbostic #ifdef __STDC__ 109*49062Sbostic uprintf(const char *fmt, ...) 110*49062Sbostic #else 111*49062Sbostic uprintf(fmt /*, va_alist */) 1122781Swnj char *fmt; 113*49062Sbostic #endif 114285Sbill { 11547540Skarels register struct proc *p = curproc; 116*49062Sbostic va_list ap; 117285Sbill 118*49062Sbostic va_start(ap, fmt); 11944386Smarc if (p->p_flag & SCTTY && p->p_session->s_ttyvp) 120*49062Sbostic kprintf(fmt, TOTTY, p->p_session->s_ttyp, ap); 121*49062Sbostic 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); 131*49062Sbostic } 132*49062Sbostic 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 145*49062Sbostic * with the given session. 14618364Skarels */ 147*49062Sbostic void 148*49062Sbostic #ifdef __STDC__ 149*49062Sbostic tprintf(tpr_t tpr, const char *fmt, ...) 150*49062Sbostic #else 151*49062Sbostic tprintf(tpr, fmt /*, va_alist */) 15248426Skarels tpr_t tpr; 15316724Sralph char *fmt; 154*49062Sbostic #endif 15516724Sralph { 15648426Skarels register struct session *sess = (struct session *)tpr; 15748426Skarels struct tty *tp = NULL; 15844386Smarc int flags = TOLOG; 159*49062Sbostic 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 } 166*49062Sbostic va_start(ap, fmt); 167*49062Sbostic kprintf(fmt, flags, tp, ap); 168*49062Sbostic va_end(ap); 16925389Skarels logwakeup(); 17016724Sralph } 17116724Sralph 172*49062Sbostic /* 173*49062Sbostic * Ttyprintf displays a message on a tty; it should be used only by 174*49062Sbostic * the tty driver, or anything that knows the underlying tty will not 175*49062Sbostic * be revoke(2)'d away. Other callers should use tprintf. 176*49062Sbostic */ 177*49062Sbostic void 178*49062Sbostic #ifdef __STDC__ 179*49062Sbostic ttyprintf(struct tty *tp, const char *fmt, ...) 180*49062Sbostic #else 181*49062Sbostic ttyprintf(tp, fmt /*, va_alist */) 182*49062Sbostic struct tty *tp; 183*49062Sbostic char *fmt; 184*49062Sbostic #endif 185*49062Sbostic { 186*49062Sbostic va_list ap; 187*49062Sbostic 188*49062Sbostic va_start(ap, fmt); 189*49062Sbostic kprintf(fmt, TOTTY, tp, ap); 190*49062Sbostic va_end(ap); 191*49062Sbostic } 192*49062Sbostic 19348426Skarels extern int log_open; 19444386Smarc 19516724Sralph /* 196*49062Sbostic * Log writes to the log buffer, and guarantees not to sleep (so can be 197*49062Sbostic * called by interrupt routines). If there is no process reading the 198*49062Sbostic * log yet, it writes to the console also. 19916724Sralph */ 200*49062Sbostic void 201*49062Sbostic #ifdef __STDC__ 202*49062Sbostic log(int level, const char *fmt, ...) 203*49062Sbostic #else 204*49062Sbostic log(level, fmt /*, va_alist */) 205*49062Sbostic int level; 20616724Sralph char *fmt; 207*49062Sbostic #endif 20816724Sralph { 20916724Sralph register s = splhigh(); 210*49062Sbostic va_list ap; 21116724Sralph 21225389Skarels logpri(level); 213*49062Sbostic va_start(ap, fmt); 214*49062Sbostic kprintf(fmt, TOLOG, NULL, ap); 21516724Sralph splx(s); 21618364Skarels if (!log_open) 217*49062Sbostic kprintf(fmt, TOCONS, NULL, ap); 218*49062Sbostic va_end(ap); 21916724Sralph logwakeup(); 22016724Sralph } 22116724Sralph 222*49062Sbostic static void 22325389Skarels logpri(level) 22425389Skarels int level; 22525389Skarels { 22625389Skarels 227*49062Sbostic putchar('<', TOLOG, NULL); 228*49062Sbostic kprintn((u_long)level, 10, TOLOG, NULL); 229*49062Sbostic putchar('>', TOLOG, NULL); 23025389Skarels } 23125389Skarels 232*49062Sbostic void 233*49062Sbostic #ifdef __STDC__ 234*49062Sbostic addlog(const char *fmt, ...) 235*49062Sbostic #else 236*49062Sbostic addlog(fmt /*, va_alist */) 23733479Skarels char *fmt; 238*49062Sbostic #endif 23933479Skarels { 24033479Skarels register s = splhigh(); 241*49062Sbostic va_list ap; 24233479Skarels 243*49062Sbostic va_start(ap, fmt); 244*49062Sbostic kprintf(fmt, TOLOG, NULL, ap); 24533479Skarels splx(s); 24633479Skarels if (!log_open) 247*49062Sbostic kprintf(fmt, TOCONS, NULL, ap); 248*49062Sbostic va_end(ap); 24933479Skarels logwakeup(); 25033479Skarels } 25133479Skarels 252*49062Sbostic int consintr = 1; /* ok to handle console interrupts? */ 25331Sbill 254*49062Sbostic void 255*49062Sbostic #ifdef __STDC__ 256*49062Sbostic printf(const char *fmt, ...) 257*49062Sbostic #else 258*49062Sbostic printf(fmt /*, va_alist */) 259*49062Sbostic char *fmt; 26029946Skarels #endif 261*49062Sbostic { 262*49062Sbostic register int savintr; 263*49062Sbostic va_list ap; 2642678Swnj 265*49062Sbostic savintr = consintr; /* disable interrupts */ 266*49062Sbostic consintr = 0; 267*49062Sbostic va_start(ap, fmt); 268*49062Sbostic kprintf(fmt, TOCONS | TOLOG, NULL, ap); 269*49062Sbostic va_end(ap); 270*49062Sbostic if (!panicstr) 271*49062Sbostic logwakeup(); 272*49062Sbostic consintr = savintr; /* reenable interrupts */ 27331Sbill } 27431Sbill 2752781Swnj /* 276*49062Sbostic * Scaled down version of printf(3). 277*49062Sbostic * 278*49062Sbostic * Two additional formats: 279*49062Sbostic * 280*49062Sbostic * The format %b is supported to decode error registers. 281*49062Sbostic * Its usage is: 282*49062Sbostic * 283*49062Sbostic * kprintf("reg=%b\n", regval, "<base><arg>*"); 284*49062Sbostic * 285*49062Sbostic * where <base> is the output base expressed as a control character, e.g. 286*49062Sbostic * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, 287*49062Sbostic * the first of which gives the bit number to be inspected (origin 1), and 288*49062Sbostic * the next characters (up to a control character, i.e. a character <= 32), 289*49062Sbostic * give the name of the register. Thus: 290*49062Sbostic * 291*49062Sbostic * kprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 292*49062Sbostic * 293*49062Sbostic * would produce output: 294*49062Sbostic * 295*49062Sbostic * reg=3<BITTWO,BITONE> 296*49062Sbostic * 297*49062Sbostic * The format %r is supposed to pass an additional format string and argument 298*49062Sbostic * list recursively. 299*49062Sbostic * Its usage is: 300*49062Sbostic * 301*49062Sbostic * fn(otherstuff, fmt [, arg1, ... ]) 302*49062Sbostic * char *fmt; 303*49062Sbostic * u_int arg1, ...; 304*49062Sbostic * 305*49062Sbostic * kprintf("prefix: %r, other stuff\n", fmt, ap); 3062781Swnj */ 307*49062Sbostic static void 308*49062Sbostic kprintf(fmt, flags, ttyp, ap) 309*49062Sbostic register char *fmt; 310*49062Sbostic int flags; 31144386Smarc struct tty *ttyp; 312*49062Sbostic va_list ap; 31331Sbill { 314*49062Sbostic register char *p; 315*49062Sbostic register int ch, n; 316*49062Sbostic unsigned long ul; 317*49062Sbostic int lflag, set; 31831Sbill 319*49062Sbostic for (;;) { 320*49062Sbostic while ((ch = *fmt++) != '%') { 321*49062Sbostic if (ch == '\0') 322*49062Sbostic return; 323*49062Sbostic putchar(ch, flags, ttyp); 32429946Skarels } 325*49062Sbostic lflag = 0; 326*49062Sbostic reswitch: switch (ch = *fmt++) { 327*49062Sbostic case 'l': 328*49062Sbostic lflag = 1; 329*49062Sbostic goto reswitch; 330*49062Sbostic case 'b': 331*49062Sbostic ul = va_arg(ap, int); 332*49062Sbostic p = va_arg(ap, char *); 333*49062Sbostic kprintn(ul, *p++); 33431Sbill 335*49062Sbostic if (!ul) 336*49062Sbostic break; 3372377Swnj 338*49062Sbostic for (set = 0; n = *p++;) { 339*49062Sbostic if (ul & (1 << (n - 1))) { 340*49062Sbostic putchar(set ? ',' : '<', flags, ttyp); 341*49062Sbostic for (; (n = *p) > ' '; ++p) 342*49062Sbostic putchar(n, flags, ttyp); 343*49062Sbostic set = 1; 344*49062Sbostic } else 345*49062Sbostic for (; *p > ' '; ++p); 346*49062Sbostic } 347*49062Sbostic if (set) 348*49062Sbostic putchar('>', flags, ttyp); 349*49062Sbostic break; 350*49062Sbostic case 'c': 351*49062Sbostic putchar(va_arg(ap, int), flags, ttyp); 352*49062Sbostic break; 353*49062Sbostic case 'r': 354*49062Sbostic p = va_arg(ap, char *); 355*49062Sbostic kprintf(p, flags, ttyp, va_arg(ap, va_list)); 356*49062Sbostic break; 357*49062Sbostic case 's': 358*49062Sbostic p = va_arg(ap, char *); 359*49062Sbostic while (ch = *p++) 360*49062Sbostic putchar(ch, flags, ttyp); 361*49062Sbostic break; 362*49062Sbostic case 'D': 363*49062Sbostic lflag = 1; 364*49062Sbostic /* FALLTHROUGH */ 365*49062Sbostic case 'd': 366*49062Sbostic ul = lflag ? 367*49062Sbostic va_arg(ap, long) : va_arg(ap, int); 368*49062Sbostic if ((long)ul < 0) { 369*49062Sbostic putchar('-', flags, ttyp); 370*49062Sbostic ul = -(long)ul; 371*49062Sbostic } 372*49062Sbostic kprintn(ul, 10); 373*49062Sbostic break; 374*49062Sbostic case 'O': 375*49062Sbostic lflag = 1; 376*49062Sbostic /* FALLTHROUGH */ 377*49062Sbostic case 'o': 378*49062Sbostic ul = lflag ? 379*49062Sbostic va_arg(ap, u_long) : va_arg(ap, u_int); 380*49062Sbostic kprintn(ul, 8); 381*49062Sbostic break; 382*49062Sbostic case 'U': 383*49062Sbostic lflag = 1; 384*49062Sbostic /* FALLTHROUGH */ 385*49062Sbostic case 'u': 386*49062Sbostic ul = lflag ? 387*49062Sbostic va_arg(ap, u_long) : va_arg(ap, u_int); 388*49062Sbostic kprintn(ul, 10); 389*49062Sbostic break; 390*49062Sbostic case 'X': 391*49062Sbostic lflag = 1; 392*49062Sbostic /* FALLTHROUGH */ 393*49062Sbostic case 'x': 394*49062Sbostic ul = lflag ? 395*49062Sbostic va_arg(ap, u_long) : va_arg(ap, u_int); 396*49062Sbostic kprintn(ul, 16); 397*49062Sbostic break; 398*49062Sbostic default: 399*49062Sbostic putchar('%', flags, ttyp); 400*49062Sbostic if (lflag) 401*49062Sbostic putchar('l', flags, ttyp); 402*49062Sbostic putchar(ch, flags, ttyp); 403*49062Sbostic } 40430625Skarels } 405*49062Sbostic va_end(ap); 40631Sbill } 40731Sbill 408*49062Sbostic static void 409*49062Sbostic kprintn(ul, base) 410*49062Sbostic u_long ul; 411*49062Sbostic int base; 4122941Swnj { 413*49062Sbostic /* hold a long in base 8 */ 414*49062Sbostic char *p, buf[(sizeof(long) * NBBY >> 3) + 1]; 4152941Swnj 416*49062Sbostic p = buf; 417*49062Sbostic do { 418*49062Sbostic *p++ = "0123456789abcdef"[ul % base]; 419*49062Sbostic } while (ul /= base); 420*49062Sbostic do { 421*49062Sbostic putchar(*--p); 422*49062Sbostic } while (p > buf); 4232941Swnj } 4242941Swnj 4252941Swnj /* 426*49062Sbostic * Print a character on console or users terminal. If destination is 427*49062Sbostic * the console then the last MSGBUFS characters are saved in msgbuf for 428*49062Sbostic * inspection later. 429285Sbill */ 430*49062Sbostic static void 43144386Smarc putchar(c, flags, ttyp) 4322377Swnj register int c; 433*49062Sbostic int flags; 43444386Smarc struct tty *ttyp; 435285Sbill { 43633479Skarels extern int msgbufmapped; 437*49062Sbostic register struct msgbuf *mbp; 438285Sbill 43930549Skarels if (panicstr) 440*49062Sbostic constty = NULL; 44144386Smarc if ((flags & TOCONS) && ttyp == NULL && constty) { 44244386Smarc ttyp = constty; 44330549Skarels flags |= TOTTY; 44430549Skarels } 44544386Smarc if ((flags & TOTTY) && ttyp && tputchar(c, ttyp) < 0 && 44644386Smarc (flags & TOCONS) && ttyp == constty) 447*49062Sbostic constty = NULL; 448*49062Sbostic if ((flags & TOLOG) && 449*49062Sbostic c != '\0' && c != '\r' && c != 0177 && msgbufmapped) { 450*49062Sbostic mbp = msgbufp; 45145733Smckusick if (mbp->msg_magic != MSG_MAGIC) { 45212494Ssam register int i; 45312494Ssam 45445733Smckusick mbp->msg_magic = MSG_MAGIC; 45545733Smckusick mbp->msg_bufx = mbp->msg_bufr = 0; 456*49062Sbostic for (i = 0; i < MSG_BSIZE; i++) 45745733Smckusick mbp->msg_bufc[i] = 0; 4582172Swnj } 45945733Smckusick mbp->msg_bufc[mbp->msg_bufx++] = c; 46045733Smckusick if (mbp->msg_bufx < 0 || mbp->msg_bufx >= MSG_BSIZE) 46145733Smckusick mbp->msg_bufx = 0; 462285Sbill } 463*49062Sbostic if ((flags & TOCONS) && constty == NULL && c != '\0') 46430549Skarels (*v_putc)(c); 465285Sbill } 466