123381Smckusick /* 229101Smckusick * Copyright (c) 1982, 1986 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*29946Skarels * @(#)subr_prf.c 7.3 (Berkeley) 11/03/86 723381Smckusick */ 8*29946Skarels #include "../machine/mtpr.h" 931Sbill 1017094Sbloom #include "param.h" 1117094Sbloom #include "systm.h" 1217094Sbloom #include "seg.h" 1317094Sbloom #include "buf.h" 1417094Sbloom #include "conf.h" 1517094Sbloom #include "reboot.h" 1617094Sbloom #include "vm.h" 1717094Sbloom #include "msgbuf.h" 1817094Sbloom #include "dir.h" 1917094Sbloom #include "user.h" 2017094Sbloom #include "proc.h" 2117577Sbloom #include "ioctl.h" 2217094Sbloom #include "tty.h" 2318364Skarels #include "syslog.h" 2431Sbill 2516724Sralph #define TOCONS 0x1 2616724Sralph #define TOTTY 0x2 2716724Sralph #define TOLOG 0x4 2816724Sralph 2931Sbill /* 3031Sbill * In case console is off, 3131Sbill * panicstr contains argument to last 3231Sbill * call to panic. 3331Sbill */ 3431Sbill char *panicstr; 3531Sbill 3631Sbill /* 3731Sbill * Scaled down version of C Library printf. 382781Swnj * Used to print diagnostic information directly on console tty. 392781Swnj * Since it is not interrupt driven, all system activities are 402781Swnj * suspended. Printf should not be used for chit-chat. 412781Swnj * 422781Swnj * One additional format: %b is supported to decode error registers. 432781Swnj * Usage is: 442781Swnj * printf("reg=%b\n", regval, "<base><arg>*"); 452781Swnj * Where <base> is the output base expressed as a control character, 462781Swnj * e.g. \10 gives octal; \20 gives hex. Each arg is a sequence of 472781Swnj * characters, the first of which gives the bit number to be inspected 482781Swnj * (origin 1), and the next characters (up to a control character, i.e. 492781Swnj * a character <= 32), give the name of the register. Thus 502781Swnj * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 512781Swnj * would produce output: 5217594Skarels * reg=3<BITTWO,BITONE> 5331Sbill */ 54*29946Skarels #if defined(tahoe) 55*29946Skarels int consintr; 56*29946Skarels #endif 57*29946Skarels 5831Sbill /*VARARGS1*/ 5931Sbill printf(fmt, x1) 602781Swnj char *fmt; 612781Swnj unsigned x1; 6231Sbill { 63*29946Skarels #if defined(tahoe) 64*29946Skarels register int savintr; 65285Sbill 66*29946Skarels savintr = consintr, consintr = 0; /* disable interrupts */ 67*29946Skarels #endif 6816724Sralph prf(fmt, &x1, TOCONS | TOLOG, (struct tty *)0); 6916724Sralph logwakeup(); 70*29946Skarels #if defined(tahoe) 71*29946Skarels consintr = savintr; /* reenable interrupts */ 72*29946Skarels #endif 73285Sbill } 74285Sbill 752377Swnj /* 7625389Skarels * Uprintf prints to the current user's terminal. 7725389Skarels * It may block if the tty queue is overfull. 7825389Skarels * Should determine whether current terminal user is related 7925389Skarels * to this process. 802377Swnj */ 812377Swnj /*VARARGS1*/ 822377Swnj uprintf(fmt, x1) 832781Swnj char *fmt; 842377Swnj unsigned x1; 85285Sbill { 8626250Skarels #ifdef notdef 8725389Skarels register struct proc *p; 8826250Skarels #endif 8925389Skarels register struct tty *tp; 90285Sbill 9125389Skarels if ((tp = u.u_ttyp) == NULL) 9225389Skarels return; 9325389Skarels #ifdef notdef 9425389Skarels if (tp->t_pgrp && (p = pfind(tp->t_pgrp))) 9526250Skarels if (p->p_uid != u.u_uid) /* doesn't account for setuid */ 9625389Skarels return; 9725389Skarels #endif 9825389Skarels (void)ttycheckoutq(tp, 1); 9925389Skarels prf(fmt, &x1, TOTTY, tp); 100285Sbill } 101285Sbill 10218364Skarels /* 10318364Skarels * tprintf prints on the specified terminal (console if none) 10418364Skarels * and logs the message. It is designed for error messages from 10525389Skarels * single-open devices, and may be called from interrupt level 10625389Skarels * (does not sleep). 10718364Skarels */ 10816724Sralph /*VARARGS2*/ 10925389Skarels tprintf(tp, fmt, x1) 11025389Skarels register struct tty *tp; 11116724Sralph char *fmt; 11216724Sralph unsigned x1; 11316724Sralph { 11425389Skarels int flags = TOTTY | TOLOG; 115*29946Skarels extern struct tty cons; 11616724Sralph 11725389Skarels logpri(LOG_INFO); 118*29946Skarels if (tp == (struct tty *)NULL) 119*29946Skarels tp = &cons; 12025389Skarels if (ttycheckoutq(tp, 0) == 0) 12125389Skarels flags = TOLOG; 12225389Skarels prf(fmt, &x1, flags, tp); 12325389Skarels logwakeup(); 12416724Sralph } 12516724Sralph 12616724Sralph /* 12716724Sralph * Log writes to the log buffer, 12817594Skarels * and guarantees not to sleep (so can be called by interrupt routines). 12918364Skarels * If there is no process reading the log yet, it writes to the console also. 13016724Sralph */ 13116724Sralph /*VARARGS2*/ 13216724Sralph log(level, fmt, x1) 13316724Sralph char *fmt; 13416724Sralph unsigned x1; 13516724Sralph { 13616724Sralph register s = splhigh(); 13718364Skarels extern int log_open; 13816724Sralph 13925389Skarels logpri(level); 14016724Sralph prf(fmt, &x1, TOLOG, (struct tty *)0); 14116724Sralph splx(s); 14218364Skarels if (!log_open) 14318364Skarels prf(fmt, &x1, TOCONS, (struct tty *)0); 14416724Sralph logwakeup(); 14516724Sralph } 14616724Sralph 14725389Skarels logpri(level) 14825389Skarels int level; 14925389Skarels { 15025389Skarels 15125389Skarels putchar('<', TOLOG, (struct tty *)0); 15226356Skarels printn((u_long)level, 10, TOLOG, (struct tty *)0); 15325389Skarels putchar('>', TOLOG, (struct tty *)0); 15425389Skarels } 15525389Skarels 15616724Sralph prf(fmt, adx, flags, ttyp) 1572781Swnj register char *fmt; 1582781Swnj register u_int *adx; 15916724Sralph struct tty *ttyp; 160285Sbill { 1612434Swnj register int b, c, i; 16231Sbill char *s; 1632678Swnj int any; 16431Sbill 16531Sbill loop: 1662377Swnj while ((c = *fmt++) != '%') { 16716724Sralph if (c == '\0') 16831Sbill return; 16916724Sralph putchar(c, flags, ttyp); 17031Sbill } 1712377Swnj again: 17231Sbill c = *fmt++; 173*29946Skarels /* THIS CODE IS MACHINE DEPENDENT IN HANDLING %l? AND %c */ 1742377Swnj switch (c) { 1752377Swnj 1762377Swnj case 'l': 1772377Swnj goto again; 1782377Swnj case 'x': case 'X': 1792377Swnj b = 16; 1802377Swnj goto number; 1812377Swnj case 'd': case 'D': 182*29946Skarels b = -10; 183*29946Skarels goto number; 184*29946Skarels case 'u': 1852377Swnj b = 10; 1862377Swnj goto number; 1872377Swnj case 'o': case 'O': 1882377Swnj b = 8; 1892377Swnj number: 19016724Sralph printn((u_long)*adx, b, flags, ttyp); 1912377Swnj break; 1922377Swnj case 'c': 1932434Swnj b = *adx; 194*29946Skarels #if ENDIAN == LITTLE 1952434Swnj for (i = 24; i >= 0; i -= 8) 1962434Swnj if (c = (b >> i) & 0x7f) 19716724Sralph putchar(c, flags, ttyp); 198*29946Skarels #endif 199*29946Skarels #if ENDIAN == BIG 200*29946Skarels if (c = (b & 0x7f)) 201*29946Skarels putchar(c, flags, ttyp); 202*29946Skarels #endif 2032377Swnj break; 2042678Swnj case 'b': 2052678Swnj b = *adx++; 2062678Swnj s = (char *)*adx; 20716724Sralph printn((u_long)b, *s++, flags, ttyp); 2082678Swnj any = 0; 2092678Swnj if (b) { 2102678Swnj while (i = *s++) { 2112678Swnj if (b & (1 << (i-1))) { 212*29946Skarels putchar(any ? ',' : '<', flags, ttyp); 2132678Swnj any = 1; 2142678Swnj for (; (c = *s) > 32; s++) 21516724Sralph putchar(c, flags, ttyp); 2162678Swnj } else 2172678Swnj for (; *s > 32; s++) 2182678Swnj ; 2192678Swnj } 2203878Swnj if (any) 22116724Sralph putchar('>', flags, ttyp); 2222678Swnj } 2232678Swnj break; 2242678Swnj 2252377Swnj case 's': 22631Sbill s = (char *)*adx; 227285Sbill while (c = *s++) 22816724Sralph putchar(c, flags, ttyp); 2292377Swnj break; 2303736Sroot 2313736Sroot case '%': 23216724Sralph putchar('%', flags, ttyp); 2333736Sroot break; 23431Sbill } 23531Sbill adx++; 23631Sbill goto loop; 23731Sbill } 23831Sbill 2392781Swnj /* 2402781Swnj * Printn prints a number n in base b. 2412781Swnj * We don't use recursion to avoid deep kernel stacks. 2422781Swnj */ 24316724Sralph printn(n, b, flags, ttyp) 2443101Swnj u_long n; 24516724Sralph struct tty *ttyp; 24631Sbill { 2472434Swnj char prbuf[11]; 2482377Swnj register char *cp; 24931Sbill 250*29946Skarels if (b == -10) { 251*29946Skarels if ((int)n < 0) { 252*29946Skarels putchar('-', flags, ttyp); 253*29946Skarels n = (unsigned)(-(int)n); 254*29946Skarels } 255*29946Skarels b = -b; 25631Sbill } 2572434Swnj cp = prbuf; 2582377Swnj do { 2592377Swnj *cp++ = "0123456789abcdef"[n%b]; 2602377Swnj n /= b; 2612377Swnj } while (n); 2622377Swnj do 26316724Sralph putchar(*--cp, flags, ttyp); 2642434Swnj while (cp > prbuf); 26531Sbill } 26631Sbill 26731Sbill /* 2681184Sbill * Panic is called on unresolvable fatal errors. 2692781Swnj * It prints "panic: mesg", and then reboots. 2702781Swnj * If we are called twice, then we avoid trying to 2712781Swnj * sync the disks as this often leads to recursive panics. 27231Sbill */ 27331Sbill panic(s) 2742781Swnj char *s; 27531Sbill { 2765416Swnj int bootopt = RB_AUTOBOOT; 2772377Swnj 2785416Swnj if (panicstr) 2795416Swnj bootopt |= RB_NOSYNC; 2809758Ssam else { 2819758Ssam panicstr = s; 2828950Sroot } 2833285Swnj printf("panic: %s\n", s); 2842781Swnj boot(RB_PANIC, bootopt); 28531Sbill } 28631Sbill 28731Sbill /* 2882941Swnj * Warn that a system table is full. 2892941Swnj */ 2902941Swnj tablefull(tab) 2912941Swnj char *tab; 2922941Swnj { 2932941Swnj 29424839Seric log(LOG_ERR, "%s: table is full\n", tab); 2952941Swnj } 2962941Swnj 2972941Swnj /* 2982781Swnj * Hard error is the preface to plaintive error messages 2992941Swnj * about failing disk transfers. 3002781Swnj */ 3012941Swnj harderr(bp, cp) 3022678Swnj struct buf *bp; 3032941Swnj char *cp; 30431Sbill { 30531Sbill 3062941Swnj printf("%s%d%c: hard error sn%d ", cp, 30724759Skarels minor(bp->b_dev) >> 3, 'a'+(minor(bp->b_dev)&07), bp->b_blkno); 30831Sbill } 3092781Swnj 310285Sbill /* 3112377Swnj * Print a character on console or users terminal. 312285Sbill * If destination is console then the last MSGBUFS characters 313285Sbill * are saved in msgbuf for inspection later. 314285Sbill */ 3151785Sbill /*ARGSUSED*/ 31617594Skarels putchar(c, flags, tp) 3172377Swnj register int c; 31817594Skarels struct tty *tp; 319285Sbill { 320285Sbill 32116724Sralph if (flags & TOTTY) { 32225389Skarels register s = spltty(); 32325389Skarels 32425389Skarels if (tp && (tp->t_state & (TS_CARR_ON | TS_ISOPEN)) == 32525389Skarels (TS_CARR_ON | TS_ISOPEN)) { 3262377Swnj if (c == '\n') 3274970Swnj (void) ttyoutput('\r', tp); 3284970Swnj (void) ttyoutput(c, tp); 3292360Skre ttstart(tp); 330*29946Skarels } 33125389Skarels splx(s); 3322360Skre } 333*29946Skarels /* 334*29946Skarels * Can send to log only after memory management enabled: 335*29946Skarels * this has happened by the time maxmem is set. 336*29946Skarels */ 337*29946Skarels if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177 && maxmem) { 3382172Swnj if (msgbuf.msg_magic != MSG_MAGIC) { 33912494Ssam register int i; 34012494Ssam 3412172Swnj msgbuf.msg_magic = MSG_MAGIC; 34216724Sralph msgbuf.msg_bufx = msgbuf.msg_bufr = 0; 34312494Ssam for (i=0; i < MSG_BSIZE; i++) 34412494Ssam msgbuf.msg_bufc[i] = 0; 3452172Swnj } 34626427Sbloom msgbuf.msg_bufc[msgbuf.msg_bufx++] = c; 3472172Swnj if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE) 3482172Swnj msgbuf.msg_bufx = 0; 349285Sbill } 35016724Sralph if ((flags & TOCONS) && c != '\0') 351*29946Skarels cnputc(c); 352285Sbill } 353