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*45733Smckusick * @(#)subr_prf.c 7.19 (Berkeley) 12/05/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 "msgbuf.h" 1617094Sbloom #include "user.h" 1717094Sbloom #include "proc.h" 1817577Sbloom #include "ioctl.h" 1939560Smarc #include "vnode.h" 2039560Smarc #include "file.h" 2117094Sbloom #include "tty.h" 2244386Smarc #include "tprintf.h" 2318364Skarels #include "syslog.h" 2444386Smarc #include "malloc.h" 2531Sbill 2637496Smckusick #include "machine/mtpr.h" 2735282Skarels #ifdef KADB 2837496Smckusick #include "machine/kdbparam.h" 2930625Skarels #endif 3030625Skarels 3116724Sralph #define TOCONS 0x1 3216724Sralph #define TOTTY 0x2 3316724Sralph #define TOLOG 0x4 3416724Sralph 3531Sbill /* 3631Sbill * In case console is off, 3731Sbill * panicstr contains argument to last 3831Sbill * call to panic. 3931Sbill */ 4031Sbill char *panicstr; 4131Sbill 4230549Skarels extern cnputc(); /* standard console putc */ 4340808Smarc int (*v_putc)() = cnputc; /* routine to putc on virtual console */ 4430549Skarels extern struct tty cons; /* standard console tty */ 4530549Skarels struct tty *constty; /* pointer to console "window" tty */ 4630549Skarels 4740808Smarc #ifdef KADB 4840808Smarc extern cngetc(); /* standard console getc */ 4940808Smarc extern cnpoll(); 5040808Smarc int (*v_getc)() = cngetc; /* "" getc from virtual console */ 5140808Smarc int (*v_poll)() = cnpoll; /* kdb hook to enable input polling */ 5240808Smarc #endif 5340808Smarc 5431Sbill /* 5531Sbill * Scaled down version of C Library printf. 562781Swnj * Used to print diagnostic information directly on console tty. 572781Swnj * Since it is not interrupt driven, all system activities are 582781Swnj * suspended. Printf should not be used for chit-chat. 592781Swnj * 602781Swnj * One additional format: %b is supported to decode error registers. 612781Swnj * Usage is: 622781Swnj * printf("reg=%b\n", regval, "<base><arg>*"); 632781Swnj * Where <base> is the output base expressed as a control character, 642781Swnj * e.g. \10 gives octal; \20 gives hex. Each arg is a sequence of 652781Swnj * characters, the first of which gives the bit number to be inspected 662781Swnj * (origin 1), and the next characters (up to a control character, i.e. 672781Swnj * a character <= 32), give the name of the register. Thus 682781Swnj * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 692781Swnj * would produce output: 7017594Skarels * reg=3<BITTWO,BITONE> 7134478Skarels * 7234478Skarels * Another additional format: %r is used to pass an additional format string 7334478Skarels * and argument list recursively. Usage is typically: 7434478Skarels * 7534478Skarels * fn(otherstuff, fmt [, arg1, ... ] ) 7634478Skarels * char *fmt; 7734478Skarels * u_int arg1, ...; 7834478Skarels * 7934478Skarels * printf("prefix: %r, other stuff\n", fmt, &arg1); 8031Sbill */ 8129946Skarels #if defined(tahoe) 8229946Skarels int consintr; 8329946Skarels #endif 8429946Skarels 8531Sbill /*VARARGS1*/ 8631Sbill printf(fmt, x1) 872781Swnj char *fmt; 882781Swnj unsigned x1; 8931Sbill { 9029946Skarels #if defined(tahoe) 9129946Skarels register int savintr; 92285Sbill 9329946Skarels savintr = consintr, consintr = 0; /* disable interrupts */ 9429946Skarels #endif 9544386Smarc prf(fmt, &x1, TOCONS | TOLOG, (struct tty *)NULL); 9641972Smckusick if (!panicstr) 9741972Smckusick logwakeup(); 9829946Skarels #if defined(tahoe) 9929946Skarels consintr = savintr; /* reenable interrupts */ 10029946Skarels #endif 101285Sbill } 102285Sbill 1032377Swnj /* 10439560Smarc * Uprintf prints to the controlling terminal for the current process. 10525389Skarels * It may block if the tty queue is overfull. 10630695Skarels * No message is printed if the queue does not clear 10730695Skarels * in a reasonable time. 1082377Swnj */ 1092377Swnj /*VARARGS1*/ 1102377Swnj uprintf(fmt, x1) 1112781Swnj char *fmt; 1122377Swnj unsigned x1; 113285Sbill { 11444386Smarc register struct proc *p = u.u_procp; 115285Sbill 11644386Smarc if (p->p_flag & SCTTY && p->p_session->s_ttyvp) 11744386Smarc prf(fmt, &x1, TOTTY, p->p_session->s_ttyp); 118285Sbill } 119285Sbill 12044386Smarc tpr_t 12144386Smarc tprintf_open() 12244386Smarc { 12344386Smarc register struct proc *p = u.u_procp; 12444386Smarc 12544386Smarc if (p->p_flag & SCTTY && p->p_session->s_ttyvp) { 12644386Smarc SESSHOLD(p->p_session); 12744386Smarc return ((tpr_t)p->p_session); 12844386Smarc } else 12944386Smarc return ((tpr_t)NULL); 13044386Smarc } 13144386Smarc 13244386Smarc tprintf_close(sess) 13344386Smarc tpr_t sess; 13444386Smarc { 13544386Smarc if (sess) 13644386Smarc SESSRELE(sess); 13744386Smarc } 13844386Smarc 13918364Skarels /* 14044386Smarc * tprintf prints on the controlling terminal associated 14144386Smarc * with the given session. 14218364Skarels */ 14316724Sralph /*VARARGS2*/ 14444386Smarc tprintf(sess, fmt, x1) 14544386Smarc register tpr_t sess; 14616724Sralph char *fmt; 14716724Sralph unsigned x1; 14816724Sralph { 14944386Smarc int flags = TOLOG; 15016724Sralph 15125389Skarels logpri(LOG_INFO); 15239560Smarc 15344386Smarc if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) 15444386Smarc flags |= TOTTY; 15544386Smarc prf(fmt, &x1, flags, sess->s_ttyp); 15625389Skarels logwakeup(); 15716724Sralph } 15816724Sralph 15944386Smarc 16016724Sralph /* 16116724Sralph * Log writes to the log buffer, 16217594Skarels * and guarantees not to sleep (so can be called by interrupt routines). 16318364Skarels * If there is no process reading the log yet, it writes to the console also. 16416724Sralph */ 16516724Sralph /*VARARGS2*/ 16616724Sralph log(level, fmt, x1) 16716724Sralph char *fmt; 16816724Sralph unsigned x1; 16916724Sralph { 17016724Sralph register s = splhigh(); 17118364Skarels extern int log_open; 17216724Sralph 17325389Skarels logpri(level); 17444386Smarc prf(fmt, &x1, TOLOG, (struct tty *)NULL); 17516724Sralph splx(s); 17618364Skarels if (!log_open) 17744386Smarc prf(fmt, &x1, TOCONS, (struct tty *)NULL); 17816724Sralph logwakeup(); 17916724Sralph } 18016724Sralph 18125389Skarels logpri(level) 18225389Skarels int level; 18325389Skarels { 18425389Skarels 18544386Smarc putchar('<', TOLOG, (struct tty *)NULL); 18644386Smarc printn((u_long)level, 10, TOLOG, (struct tty *)NULL); 18744386Smarc putchar('>', TOLOG, (struct tty *)NULL); 18825389Skarels } 18925389Skarels 19033479Skarels /*VARARGS1*/ 19133479Skarels addlog(fmt, x1) 19233479Skarels char *fmt; 19333479Skarels unsigned x1; 19433479Skarels { 19533479Skarels register s = splhigh(); 19633479Skarels 19744386Smarc prf(fmt, &x1, TOLOG, (struct tty *)NULL); 19833479Skarels splx(s); 19933479Skarels if (!log_open) 20044386Smarc prf(fmt, &x1, TOCONS, (struct tty *)NULL); 20133479Skarels logwakeup(); 20233479Skarels } 20333479Skarels 20444386Smarc prf(fmt, adx, flags, ttyp) 2052781Swnj register char *fmt; 2062781Swnj register u_int *adx; 20744386Smarc struct tty *ttyp; 208285Sbill { 2092434Swnj register int b, c, i; 21031Sbill char *s; 2112678Swnj int any; 21231Sbill 21331Sbill loop: 2142377Swnj while ((c = *fmt++) != '%') { 21516724Sralph if (c == '\0') 21631Sbill return; 21744386Smarc putchar(c, flags, ttyp); 21831Sbill } 2192377Swnj again: 22031Sbill c = *fmt++; 22129946Skarels /* THIS CODE IS MACHINE DEPENDENT IN HANDLING %l? AND %c */ 2222377Swnj switch (c) { 2232377Swnj 2242377Swnj case 'l': 2252377Swnj goto again; 2262377Swnj case 'x': case 'X': 2272377Swnj b = 16; 2282377Swnj goto number; 2292377Swnj case 'd': case 'D': 23029946Skarels b = -10; 23129946Skarels goto number; 23229946Skarels case 'u': 2332377Swnj b = 10; 2342377Swnj goto number; 2352377Swnj case 'o': case 'O': 2362377Swnj b = 8; 2372377Swnj number: 23844386Smarc printn((u_long)*adx, b, flags, ttyp); 2392377Swnj break; 2402377Swnj case 'c': 2412434Swnj b = *adx; 24233479Skarels #if BYTE_ORDER == LITTLE_ENDIAN 2432434Swnj for (i = 24; i >= 0; i -= 8) 2442434Swnj if (c = (b >> i) & 0x7f) 24544386Smarc putchar(c, flags, ttyp); 24629946Skarels #endif 24733479Skarels #if BYTE_ORDER == BIG_ENDIAN 24829946Skarels if (c = (b & 0x7f)) 24944386Smarc putchar(c, flags, ttyp); 25029946Skarels #endif 2512377Swnj break; 2522678Swnj case 'b': 2532678Swnj b = *adx++; 2542678Swnj s = (char *)*adx; 25544386Smarc printn((u_long)b, *s++, flags, ttyp); 2562678Swnj any = 0; 2572678Swnj if (b) { 2582678Swnj while (i = *s++) { 2592678Swnj if (b & (1 << (i-1))) { 26044386Smarc putchar(any ? ',' : '<', flags, ttyp); 2612678Swnj any = 1; 2622678Swnj for (; (c = *s) > 32; s++) 26344386Smarc putchar(c, flags, ttyp); 2642678Swnj } else 2652678Swnj for (; *s > 32; s++) 2662678Swnj ; 2672678Swnj } 2683878Swnj if (any) 26944386Smarc putchar('>', flags, ttyp); 2702678Swnj } 2712678Swnj break; 2722678Swnj 2732377Swnj case 's': 27431Sbill s = (char *)*adx; 275285Sbill while (c = *s++) 27644386Smarc putchar(c, flags, ttyp); 2772377Swnj break; 2783736Sroot 27933479Skarels case 'r': 28033479Skarels s = (char *)*adx++; 28144386Smarc prf(s, (u_int *)*adx, flags, ttyp); 28233479Skarels break; 28333479Skarels 2843736Sroot case '%': 28544386Smarc putchar('%', flags, ttyp); 2863736Sroot break; 28731Sbill } 28831Sbill adx++; 28931Sbill goto loop; 29031Sbill } 29131Sbill 2922781Swnj /* 2932781Swnj * Printn prints a number n in base b. 2942781Swnj * We don't use recursion to avoid deep kernel stacks. 2952781Swnj */ 29644386Smarc printn(n, b, flags, ttyp) 2973101Swnj u_long n; 29844386Smarc struct tty *ttyp; 29931Sbill { 3002434Swnj char prbuf[11]; 3012377Swnj register char *cp; 30231Sbill 30329946Skarels if (b == -10) { 30429946Skarels if ((int)n < 0) { 30544386Smarc putchar('-', flags, ttyp); 30629946Skarels n = (unsigned)(-(int)n); 30729946Skarels } 30829946Skarels b = -b; 30931Sbill } 3102434Swnj cp = prbuf; 3112377Swnj do { 3122377Swnj *cp++ = "0123456789abcdef"[n%b]; 3132377Swnj n /= b; 3142377Swnj } while (n); 3152377Swnj do 31644386Smarc putchar(*--cp, flags, ttyp); 3172434Swnj while (cp > prbuf); 31831Sbill } 31931Sbill 32031Sbill /* 3211184Sbill * Panic is called on unresolvable fatal errors. 3222781Swnj * It prints "panic: mesg", and then reboots. 3232781Swnj * If we are called twice, then we avoid trying to 3242781Swnj * sync the disks as this often leads to recursive panics. 32531Sbill */ 32631Sbill panic(s) 3272781Swnj char *s; 32831Sbill { 32930566Skarels int bootopt = RB_AUTOBOOT | RB_DUMP; 3302377Swnj 3315416Swnj if (panicstr) 3325416Swnj bootopt |= RB_NOSYNC; 3339758Ssam else { 3349758Ssam panicstr = s; 3358950Sroot } 3363285Swnj printf("panic: %s\n", s); 33735282Skarels #ifdef KADB 33830625Skarels if (boothowto & RB_KDB) { 33934420Skarels int x = splnet(); /* below kdb pri */ 34030625Skarels 34130625Skarels setsoftkdb(); 34234420Skarels splx(x); 34330625Skarels } 34430625Skarels #endif 34530566Skarels boot(bootopt); 34631Sbill } 34731Sbill 34831Sbill /* 3492941Swnj * Warn that a system table is full. 3502941Swnj */ 3512941Swnj tablefull(tab) 3522941Swnj char *tab; 3532941Swnj { 3542941Swnj 35524839Seric log(LOG_ERR, "%s: table is full\n", tab); 3562941Swnj } 3572941Swnj 3582941Swnj /* 3592377Swnj * Print a character on console or users terminal. 360285Sbill * If destination is console then the last MSGBUFS characters 361285Sbill * are saved in msgbuf for inspection later. 362285Sbill */ 3631785Sbill /*ARGSUSED*/ 36444386Smarc putchar(c, flags, ttyp) 3652377Swnj register int c; 36644386Smarc struct tty *ttyp; 367285Sbill { 368*45733Smckusick register struct msgbuf *mbp = msgbufp; 36933479Skarels extern int msgbufmapped; 370285Sbill 37130549Skarels if (panicstr) 37230549Skarels constty = 0; 37344386Smarc if ((flags & TOCONS) && ttyp == NULL && constty) { 37444386Smarc ttyp = constty; 37530549Skarels flags |= TOTTY; 37630549Skarels } 37744386Smarc if ((flags & TOTTY) && ttyp && tputchar(c, ttyp) < 0 && 37844386Smarc (flags & TOCONS) && ttyp == constty) 37939560Smarc constty = 0; 38033479Skarels if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177 && 38133479Skarels msgbufmapped) { 382*45733Smckusick if (mbp->msg_magic != MSG_MAGIC) { 38312494Ssam register int i; 38412494Ssam 385*45733Smckusick mbp->msg_magic = MSG_MAGIC; 386*45733Smckusick mbp->msg_bufx = mbp->msg_bufr = 0; 38712494Ssam for (i=0; i < MSG_BSIZE; i++) 388*45733Smckusick mbp->msg_bufc[i] = 0; 3892172Swnj } 390*45733Smckusick mbp->msg_bufc[mbp->msg_bufx++] = c; 391*45733Smckusick if (mbp->msg_bufx < 0 || mbp->msg_bufx >= MSG_BSIZE) 392*45733Smckusick mbp->msg_bufx = 0; 393285Sbill } 39430549Skarels if ((flags & TOCONS) && constty == 0 && c != '\0') 39530549Skarels (*v_putc)(c); 396285Sbill } 397