123381Smckusick /* 234420Skarels * Copyright (c) 1982, 1986, 1988 Regents of the University of California. 323381Smckusick * All rights reserved. The Berkeley software License Agreement 423381Smckusick * specifies the terms and conditions for redistribution. 523381Smckusick * 6*44386Smarc * @(#)subr_prf.c 7.18 (Berkeley) 06/28/90 723381Smckusick */ 831Sbill 917094Sbloom #include "param.h" 1017094Sbloom #include "systm.h" 1117094Sbloom #include "seg.h" 1217094Sbloom #include "buf.h" 1317094Sbloom #include "conf.h" 1417094Sbloom #include "reboot.h" 1517094Sbloom #include "vm.h" 1617094Sbloom #include "msgbuf.h" 1717094Sbloom #include "user.h" 1817094Sbloom #include "proc.h" 1917577Sbloom #include "ioctl.h" 2039560Smarc #include "vnode.h" 2139560Smarc #include "file.h" 2217094Sbloom #include "tty.h" 23*44386Smarc #include "tprintf.h" 2418364Skarels #include "syslog.h" 25*44386Smarc #include "malloc.h" 2631Sbill 2737496Smckusick #include "machine/mtpr.h" 2835282Skarels #ifdef KADB 2937496Smckusick #include "machine/kdbparam.h" 3030625Skarels #endif 3130625Skarels 3216724Sralph #define TOCONS 0x1 3316724Sralph #define TOTTY 0x2 3416724Sralph #define TOLOG 0x4 3516724Sralph 3631Sbill /* 3731Sbill * In case console is off, 3831Sbill * panicstr contains argument to last 3931Sbill * call to panic. 4031Sbill */ 4131Sbill char *panicstr; 4231Sbill 4330549Skarels extern cnputc(); /* standard console putc */ 4440808Smarc int (*v_putc)() = cnputc; /* routine to putc on virtual console */ 4530549Skarels extern struct tty cons; /* standard console tty */ 4630549Skarels struct tty *constty; /* pointer to console "window" tty */ 4730549Skarels 4840808Smarc #ifdef KADB 4940808Smarc extern cngetc(); /* standard console getc */ 5040808Smarc extern cnpoll(); 5140808Smarc int (*v_getc)() = cngetc; /* "" getc from virtual console */ 5240808Smarc int (*v_poll)() = cnpoll; /* kdb hook to enable input polling */ 5340808Smarc #endif 5440808Smarc 5531Sbill /* 5631Sbill * Scaled down version of C Library printf. 572781Swnj * Used to print diagnostic information directly on console tty. 582781Swnj * Since it is not interrupt driven, all system activities are 592781Swnj * suspended. Printf should not be used for chit-chat. 602781Swnj * 612781Swnj * One additional format: %b is supported to decode error registers. 622781Swnj * Usage is: 632781Swnj * printf("reg=%b\n", regval, "<base><arg>*"); 642781Swnj * Where <base> is the output base expressed as a control character, 652781Swnj * e.g. \10 gives octal; \20 gives hex. Each arg is a sequence of 662781Swnj * characters, the first of which gives the bit number to be inspected 672781Swnj * (origin 1), and the next characters (up to a control character, i.e. 682781Swnj * a character <= 32), give the name of the register. Thus 692781Swnj * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 702781Swnj * would produce output: 7117594Skarels * reg=3<BITTWO,BITONE> 7234478Skarels * 7334478Skarels * Another additional format: %r is used to pass an additional format string 7434478Skarels * and argument list recursively. Usage is typically: 7534478Skarels * 7634478Skarels * fn(otherstuff, fmt [, arg1, ... ] ) 7734478Skarels * char *fmt; 7834478Skarels * u_int arg1, ...; 7934478Skarels * 8034478Skarels * printf("prefix: %r, other stuff\n", fmt, &arg1); 8131Sbill */ 8229946Skarels #if defined(tahoe) 8329946Skarels int consintr; 8429946Skarels #endif 8529946Skarels 8631Sbill /*VARARGS1*/ 8731Sbill printf(fmt, x1) 882781Swnj char *fmt; 892781Swnj unsigned x1; 9031Sbill { 9129946Skarels #if defined(tahoe) 9229946Skarels register int savintr; 93285Sbill 9429946Skarels savintr = consintr, consintr = 0; /* disable interrupts */ 9529946Skarels #endif 96*44386Smarc prf(fmt, &x1, TOCONS | TOLOG, (struct tty *)NULL); 9741972Smckusick if (!panicstr) 9841972Smckusick logwakeup(); 9929946Skarels #if defined(tahoe) 10029946Skarels consintr = savintr; /* reenable interrupts */ 10129946Skarels #endif 102285Sbill } 103285Sbill 1042377Swnj /* 10539560Smarc * Uprintf prints to the controlling terminal for the current process. 10625389Skarels * It may block if the tty queue is overfull. 10730695Skarels * No message is printed if the queue does not clear 10830695Skarels * in a reasonable time. 1092377Swnj */ 1102377Swnj /*VARARGS1*/ 1112377Swnj uprintf(fmt, x1) 1122781Swnj char *fmt; 1132377Swnj unsigned x1; 114285Sbill { 115*44386Smarc register struct proc *p = u.u_procp; 116285Sbill 117*44386Smarc if (p->p_flag & SCTTY && p->p_session->s_ttyvp) 118*44386Smarc prf(fmt, &x1, TOTTY, p->p_session->s_ttyp); 119285Sbill } 120285Sbill 121*44386Smarc tpr_t 122*44386Smarc tprintf_open() 123*44386Smarc { 124*44386Smarc register struct proc *p = u.u_procp; 125*44386Smarc 126*44386Smarc if (p->p_flag & SCTTY && p->p_session->s_ttyvp) { 127*44386Smarc SESSHOLD(p->p_session); 128*44386Smarc return ((tpr_t)p->p_session); 129*44386Smarc } else 130*44386Smarc return ((tpr_t)NULL); 131*44386Smarc } 132*44386Smarc 133*44386Smarc tprintf_close(sess) 134*44386Smarc tpr_t sess; 135*44386Smarc { 136*44386Smarc if (sess) 137*44386Smarc SESSRELE(sess); 138*44386Smarc } 139*44386Smarc 14018364Skarels /* 141*44386Smarc * tprintf prints on the controlling terminal associated 142*44386Smarc * with the given session. 14318364Skarels */ 14416724Sralph /*VARARGS2*/ 145*44386Smarc tprintf(sess, fmt, x1) 146*44386Smarc register tpr_t sess; 14716724Sralph char *fmt; 14816724Sralph unsigned x1; 14916724Sralph { 150*44386Smarc int flags = TOLOG; 15116724Sralph 15225389Skarels logpri(LOG_INFO); 15339560Smarc 154*44386Smarc if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) 155*44386Smarc flags |= TOTTY; 156*44386Smarc prf(fmt, &x1, flags, sess->s_ttyp); 15725389Skarels logwakeup(); 15816724Sralph } 15916724Sralph 160*44386Smarc 16116724Sralph /* 16216724Sralph * Log writes to the log buffer, 16317594Skarels * and guarantees not to sleep (so can be called by interrupt routines). 16418364Skarels * If there is no process reading the log yet, it writes to the console also. 16516724Sralph */ 16616724Sralph /*VARARGS2*/ 16716724Sralph log(level, fmt, x1) 16816724Sralph char *fmt; 16916724Sralph unsigned x1; 17016724Sralph { 17116724Sralph register s = splhigh(); 17218364Skarels extern int log_open; 17316724Sralph 17425389Skarels logpri(level); 175*44386Smarc prf(fmt, &x1, TOLOG, (struct tty *)NULL); 17616724Sralph splx(s); 17718364Skarels if (!log_open) 178*44386Smarc prf(fmt, &x1, TOCONS, (struct tty *)NULL); 17916724Sralph logwakeup(); 18016724Sralph } 18116724Sralph 18225389Skarels logpri(level) 18325389Skarels int level; 18425389Skarels { 18525389Skarels 186*44386Smarc putchar('<', TOLOG, (struct tty *)NULL); 187*44386Smarc printn((u_long)level, 10, TOLOG, (struct tty *)NULL); 188*44386Smarc putchar('>', TOLOG, (struct tty *)NULL); 18925389Skarels } 19025389Skarels 19133479Skarels /*VARARGS1*/ 19233479Skarels addlog(fmt, x1) 19333479Skarels char *fmt; 19433479Skarels unsigned x1; 19533479Skarels { 19633479Skarels register s = splhigh(); 19733479Skarels 198*44386Smarc prf(fmt, &x1, TOLOG, (struct tty *)NULL); 19933479Skarels splx(s); 20033479Skarels if (!log_open) 201*44386Smarc prf(fmt, &x1, TOCONS, (struct tty *)NULL); 20233479Skarels logwakeup(); 20333479Skarels } 20433479Skarels 205*44386Smarc prf(fmt, adx, flags, ttyp) 2062781Swnj register char *fmt; 2072781Swnj register u_int *adx; 208*44386Smarc struct tty *ttyp; 209285Sbill { 2102434Swnj register int b, c, i; 21131Sbill char *s; 2122678Swnj int any; 21331Sbill 21431Sbill loop: 2152377Swnj while ((c = *fmt++) != '%') { 21616724Sralph if (c == '\0') 21731Sbill return; 218*44386Smarc putchar(c, flags, ttyp); 21931Sbill } 2202377Swnj again: 22131Sbill c = *fmt++; 22229946Skarels /* THIS CODE IS MACHINE DEPENDENT IN HANDLING %l? AND %c */ 2232377Swnj switch (c) { 2242377Swnj 2252377Swnj case 'l': 2262377Swnj goto again; 2272377Swnj case 'x': case 'X': 2282377Swnj b = 16; 2292377Swnj goto number; 2302377Swnj case 'd': case 'D': 23129946Skarels b = -10; 23229946Skarels goto number; 23329946Skarels case 'u': 2342377Swnj b = 10; 2352377Swnj goto number; 2362377Swnj case 'o': case 'O': 2372377Swnj b = 8; 2382377Swnj number: 239*44386Smarc printn((u_long)*adx, b, flags, ttyp); 2402377Swnj break; 2412377Swnj case 'c': 2422434Swnj b = *adx; 24333479Skarels #if BYTE_ORDER == LITTLE_ENDIAN 2442434Swnj for (i = 24; i >= 0; i -= 8) 2452434Swnj if (c = (b >> i) & 0x7f) 246*44386Smarc putchar(c, flags, ttyp); 24729946Skarels #endif 24833479Skarels #if BYTE_ORDER == BIG_ENDIAN 24929946Skarels if (c = (b & 0x7f)) 250*44386Smarc putchar(c, flags, ttyp); 25129946Skarels #endif 2522377Swnj break; 2532678Swnj case 'b': 2542678Swnj b = *adx++; 2552678Swnj s = (char *)*adx; 256*44386Smarc printn((u_long)b, *s++, flags, ttyp); 2572678Swnj any = 0; 2582678Swnj if (b) { 2592678Swnj while (i = *s++) { 2602678Swnj if (b & (1 << (i-1))) { 261*44386Smarc putchar(any ? ',' : '<', flags, ttyp); 2622678Swnj any = 1; 2632678Swnj for (; (c = *s) > 32; s++) 264*44386Smarc putchar(c, flags, ttyp); 2652678Swnj } else 2662678Swnj for (; *s > 32; s++) 2672678Swnj ; 2682678Swnj } 2693878Swnj if (any) 270*44386Smarc putchar('>', flags, ttyp); 2712678Swnj } 2722678Swnj break; 2732678Swnj 2742377Swnj case 's': 27531Sbill s = (char *)*adx; 276285Sbill while (c = *s++) 277*44386Smarc putchar(c, flags, ttyp); 2782377Swnj break; 2793736Sroot 28033479Skarels case 'r': 28133479Skarels s = (char *)*adx++; 282*44386Smarc prf(s, (u_int *)*adx, flags, ttyp); 28333479Skarels break; 28433479Skarels 2853736Sroot case '%': 286*44386Smarc putchar('%', flags, ttyp); 2873736Sroot break; 28831Sbill } 28931Sbill adx++; 29031Sbill goto loop; 29131Sbill } 29231Sbill 2932781Swnj /* 2942781Swnj * Printn prints a number n in base b. 2952781Swnj * We don't use recursion to avoid deep kernel stacks. 2962781Swnj */ 297*44386Smarc printn(n, b, flags, ttyp) 2983101Swnj u_long n; 299*44386Smarc struct tty *ttyp; 30031Sbill { 3012434Swnj char prbuf[11]; 3022377Swnj register char *cp; 30331Sbill 30429946Skarels if (b == -10) { 30529946Skarels if ((int)n < 0) { 306*44386Smarc putchar('-', flags, ttyp); 30729946Skarels n = (unsigned)(-(int)n); 30829946Skarels } 30929946Skarels b = -b; 31031Sbill } 3112434Swnj cp = prbuf; 3122377Swnj do { 3132377Swnj *cp++ = "0123456789abcdef"[n%b]; 3142377Swnj n /= b; 3152377Swnj } while (n); 3162377Swnj do 317*44386Smarc putchar(*--cp, flags, ttyp); 3182434Swnj while (cp > prbuf); 31931Sbill } 32031Sbill 32131Sbill /* 3221184Sbill * Panic is called on unresolvable fatal errors. 3232781Swnj * It prints "panic: mesg", and then reboots. 3242781Swnj * If we are called twice, then we avoid trying to 3252781Swnj * sync the disks as this often leads to recursive panics. 32631Sbill */ 32731Sbill panic(s) 3282781Swnj char *s; 32931Sbill { 33030566Skarels int bootopt = RB_AUTOBOOT | RB_DUMP; 3312377Swnj 3325416Swnj if (panicstr) 3335416Swnj bootopt |= RB_NOSYNC; 3349758Ssam else { 3359758Ssam panicstr = s; 3368950Sroot } 3373285Swnj printf("panic: %s\n", s); 33835282Skarels #ifdef KADB 33930625Skarels if (boothowto & RB_KDB) { 34034420Skarels int x = splnet(); /* below kdb pri */ 34130625Skarels 34230625Skarels setsoftkdb(); 34334420Skarels splx(x); 34430625Skarels } 34530625Skarels #endif 34630566Skarels boot(bootopt); 34731Sbill } 34831Sbill 34931Sbill /* 3502941Swnj * Warn that a system table is full. 3512941Swnj */ 3522941Swnj tablefull(tab) 3532941Swnj char *tab; 3542941Swnj { 3552941Swnj 35624839Seric log(LOG_ERR, "%s: table is full\n", tab); 3572941Swnj } 3582941Swnj 3592941Swnj /* 3602377Swnj * Print a character on console or users terminal. 361285Sbill * If destination is console then the last MSGBUFS characters 362285Sbill * are saved in msgbuf for inspection later. 363285Sbill */ 3641785Sbill /*ARGSUSED*/ 365*44386Smarc putchar(c, flags, ttyp) 3662377Swnj register int c; 367*44386Smarc struct tty *ttyp; 368285Sbill { 36933479Skarels extern int msgbufmapped; 370285Sbill 37130549Skarels if (panicstr) 37230549Skarels constty = 0; 373*44386Smarc if ((flags & TOCONS) && ttyp == NULL && constty) { 374*44386Smarc ttyp = constty; 37530549Skarels flags |= TOTTY; 37630549Skarels } 377*44386Smarc if ((flags & TOTTY) && ttyp && tputchar(c, ttyp) < 0 && 378*44386Smarc (flags & TOCONS) && ttyp == constty) 37939560Smarc constty = 0; 38033479Skarels if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177 && 38133479Skarels msgbufmapped) { 3822172Swnj if (msgbuf.msg_magic != MSG_MAGIC) { 38312494Ssam register int i; 38412494Ssam 3852172Swnj msgbuf.msg_magic = MSG_MAGIC; 38616724Sralph msgbuf.msg_bufx = msgbuf.msg_bufr = 0; 38712494Ssam for (i=0; i < MSG_BSIZE; i++) 38812494Ssam msgbuf.msg_bufc[i] = 0; 3892172Swnj } 39026427Sbloom msgbuf.msg_bufc[msgbuf.msg_bufx++] = c; 3912172Swnj if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE) 3922172Swnj msgbuf.msg_bufx = 0; 393285Sbill } 39430549Skarels if ((flags & TOCONS) && constty == 0 && c != '\0') 39530549Skarels (*v_putc)(c); 396285Sbill } 397