123381Smckusick /* 223381Smckusick * Copyright (c) 1982 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*25389Skarels * @(#)subr_prf.c 6.10 (Berkeley) 11/04/85 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 "dir.h" 1817094Sbloom #include "user.h" 1917094Sbloom #include "proc.h" 2017577Sbloom #include "ioctl.h" 2117094Sbloom #include "tty.h" 2218364Skarels #include "syslog.h" 2331Sbill 2413531Ssam #ifdef vax 2513531Ssam #include "../vax/mtpr.h" 2613531Ssam #endif 2713531Ssam 2816724Sralph #define TOCONS 0x1 2916724Sralph #define TOTTY 0x2 3016724Sralph #define TOLOG 0x4 3116724Sralph 3231Sbill /* 3331Sbill * In case console is off, 3431Sbill * panicstr contains argument to last 3531Sbill * call to panic. 3631Sbill */ 3731Sbill char *panicstr; 3831Sbill 3931Sbill /* 4031Sbill * Scaled down version of C Library printf. 412781Swnj * Used to print diagnostic information directly on console tty. 422781Swnj * Since it is not interrupt driven, all system activities are 432781Swnj * suspended. Printf should not be used for chit-chat. 442781Swnj * 452781Swnj * One additional format: %b is supported to decode error registers. 462781Swnj * Usage is: 472781Swnj * printf("reg=%b\n", regval, "<base><arg>*"); 482781Swnj * Where <base> is the output base expressed as a control character, 492781Swnj * e.g. \10 gives octal; \20 gives hex. Each arg is a sequence of 502781Swnj * characters, the first of which gives the bit number to be inspected 512781Swnj * (origin 1), and the next characters (up to a control character, i.e. 522781Swnj * a character <= 32), give the name of the register. Thus 532781Swnj * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 542781Swnj * would produce output: 5517594Skarels * reg=3<BITTWO,BITONE> 5631Sbill */ 5731Sbill /*VARARGS1*/ 5831Sbill printf(fmt, x1) 592781Swnj char *fmt; 602781Swnj unsigned x1; 6131Sbill { 62285Sbill 6316724Sralph prf(fmt, &x1, TOCONS | TOLOG, (struct tty *)0); 6416724Sralph logwakeup(); 65285Sbill } 66285Sbill 672377Swnj /* 68*25389Skarels * Uprintf prints to the current user's terminal. 69*25389Skarels * It may block if the tty queue is overfull. 70*25389Skarels * Should determine whether current terminal user is related 71*25389Skarels * to this process. 722377Swnj */ 732377Swnj /*VARARGS1*/ 742377Swnj uprintf(fmt, x1) 752781Swnj char *fmt; 762377Swnj unsigned x1; 77285Sbill { 78*25389Skarels register struct proc *p; 79*25389Skarels register struct tty *tp; 80285Sbill 81*25389Skarels if ((tp = u.u_ttyp) == NULL) 82*25389Skarels return; 83*25389Skarels #ifdef notdef 84*25389Skarels if (tp->t_pgrp && (p = pfind(tp->t_pgrp))) 85*25389Skarels if (p->p_uid != u.u_uid) 86*25389Skarels return; 87*25389Skarels #endif 88*25389Skarels (void)ttycheckoutq(tp, 1); 89*25389Skarels prf(fmt, &x1, TOTTY, tp); 90285Sbill } 91285Sbill 9218364Skarels /* 9318364Skarels * tprintf prints on the specified terminal (console if none) 9418364Skarels * and logs the message. It is designed for error messages from 95*25389Skarels * single-open devices, and may be called from interrupt level 96*25389Skarels * (does not sleep). 9718364Skarels */ 9816724Sralph /*VARARGS2*/ 99*25389Skarels tprintf(tp, fmt, x1) 100*25389Skarels register struct tty *tp; 10116724Sralph char *fmt; 10216724Sralph unsigned x1; 10316724Sralph { 104*25389Skarels int flags = TOTTY | TOLOG; 105*25389Skarels extern struct tty cons; 10616724Sralph 107*25389Skarels logpri(LOG_INFO); 108*25389Skarels if (tp == (struct tty *)NULL) 109*25389Skarels tp = &cons; 110*25389Skarels if (ttycheckoutq(tp, 0) == 0) 111*25389Skarels flags = TOLOG; 112*25389Skarels prf(fmt, &x1, flags, tp); 113*25389Skarels logwakeup(); 11416724Sralph } 11516724Sralph 11616724Sralph /* 11716724Sralph * Log writes to the log buffer, 11817594Skarels * and guarantees not to sleep (so can be called by interrupt routines). 11918364Skarels * If there is no process reading the log yet, it writes to the console also. 12016724Sralph */ 12116724Sralph /*VARARGS2*/ 12216724Sralph log(level, fmt, x1) 12316724Sralph char *fmt; 12416724Sralph unsigned x1; 12516724Sralph { 12616724Sralph register s = splhigh(); 12718364Skarels extern int log_open; 12816724Sralph 129*25389Skarels logpri(level); 13016724Sralph prf(fmt, &x1, TOLOG, (struct tty *)0); 13116724Sralph splx(s); 13218364Skarels if (!log_open) 13318364Skarels prf(fmt, &x1, TOCONS, (struct tty *)0); 13416724Sralph logwakeup(); 13516724Sralph } 13616724Sralph 137*25389Skarels logpri(level) 138*25389Skarels int level; 139*25389Skarels { 140*25389Skarels 141*25389Skarels putchar('<', TOLOG, (struct tty *)0); 142*25389Skarels printn(level, 10, TOLOG, (struct tty *)0); 143*25389Skarels putchar('>', TOLOG, (struct tty *)0); 144*25389Skarels } 145*25389Skarels 14616724Sralph prf(fmt, adx, flags, ttyp) 1472781Swnj register char *fmt; 1482781Swnj register u_int *adx; 14916724Sralph struct tty *ttyp; 150285Sbill { 1512434Swnj register int b, c, i; 15231Sbill char *s; 1532678Swnj int any; 15431Sbill 15531Sbill loop: 1562377Swnj while ((c = *fmt++) != '%') { 15716724Sralph if (c == '\0') 15831Sbill return; 15916724Sralph putchar(c, flags, ttyp); 16031Sbill } 1612377Swnj again: 16231Sbill c = *fmt++; 1632781Swnj /* THIS CODE IS VAX DEPENDENT IN HANDLING %l? AND %c */ 1642377Swnj switch (c) { 1652377Swnj 1662377Swnj case 'l': 1672377Swnj goto again; 1682377Swnj case 'x': case 'X': 1692377Swnj b = 16; 1702377Swnj goto number; 1712377Swnj case 'd': case 'D': 1722377Swnj case 'u': /* what a joke */ 1732377Swnj b = 10; 1742377Swnj goto number; 1752377Swnj case 'o': case 'O': 1762377Swnj b = 8; 1772377Swnj number: 17816724Sralph printn((u_long)*adx, b, flags, ttyp); 1792377Swnj break; 1802377Swnj case 'c': 1812434Swnj b = *adx; 1822434Swnj for (i = 24; i >= 0; i -= 8) 1832434Swnj if (c = (b >> i) & 0x7f) 18416724Sralph putchar(c, flags, ttyp); 1852377Swnj break; 1862678Swnj case 'b': 1872678Swnj b = *adx++; 1882678Swnj s = (char *)*adx; 18916724Sralph printn((u_long)b, *s++, flags, ttyp); 1902678Swnj any = 0; 1912678Swnj if (b) { 1922678Swnj while (i = *s++) { 1932678Swnj if (b & (1 << (i-1))) { 19417594Skarels putchar(any? ',' : '<', flags, ttyp); 1952678Swnj any = 1; 1962678Swnj for (; (c = *s) > 32; s++) 19716724Sralph putchar(c, flags, ttyp); 1982678Swnj } else 1992678Swnj for (; *s > 32; s++) 2002678Swnj ; 2012678Swnj } 2023878Swnj if (any) 20316724Sralph putchar('>', flags, ttyp); 2042678Swnj } 2052678Swnj break; 2062678Swnj 2072377Swnj case 's': 20831Sbill s = (char *)*adx; 209285Sbill while (c = *s++) 21016724Sralph putchar(c, flags, ttyp); 2112377Swnj break; 2123736Sroot 2133736Sroot case '%': 21416724Sralph putchar('%', flags, ttyp); 2153736Sroot break; 21631Sbill } 21731Sbill adx++; 21831Sbill goto loop; 21931Sbill } 22031Sbill 2212781Swnj /* 2222781Swnj * Printn prints a number n in base b. 2232781Swnj * We don't use recursion to avoid deep kernel stacks. 2242781Swnj */ 22516724Sralph printn(n, b, flags, ttyp) 2263101Swnj u_long n; 22716724Sralph struct tty *ttyp; 22831Sbill { 2292434Swnj char prbuf[11]; 2302377Swnj register char *cp; 23131Sbill 2322377Swnj if (b == 10 && (int)n < 0) { 23316724Sralph putchar('-', flags, ttyp); 2342377Swnj n = (unsigned)(-(int)n); 23531Sbill } 2362434Swnj cp = prbuf; 2372377Swnj do { 2382377Swnj *cp++ = "0123456789abcdef"[n%b]; 2392377Swnj n /= b; 2402377Swnj } while (n); 2412377Swnj do 24216724Sralph putchar(*--cp, flags, ttyp); 2432434Swnj while (cp > prbuf); 24431Sbill } 24531Sbill 24631Sbill /* 2471184Sbill * Panic is called on unresolvable fatal errors. 2482781Swnj * It prints "panic: mesg", and then reboots. 2492781Swnj * If we are called twice, then we avoid trying to 2502781Swnj * sync the disks as this often leads to recursive panics. 25131Sbill */ 25231Sbill panic(s) 2532781Swnj char *s; 25431Sbill { 2555416Swnj int bootopt = RB_AUTOBOOT; 2562377Swnj 2575416Swnj if (panicstr) 2585416Swnj bootopt |= RB_NOSYNC; 2599758Ssam else { 2609758Ssam panicstr = s; 2618950Sroot } 2623285Swnj printf("panic: %s\n", s); 2632781Swnj boot(RB_PANIC, bootopt); 26431Sbill } 26531Sbill 26631Sbill /* 2672941Swnj * Warn that a system table is full. 2682941Swnj */ 2692941Swnj tablefull(tab) 2702941Swnj char *tab; 2712941Swnj { 2722941Swnj 27324839Seric log(LOG_ERR, "%s: table is full\n", tab); 2742941Swnj } 2752941Swnj 2762941Swnj /* 2772781Swnj * Hard error is the preface to plaintive error messages 2782941Swnj * about failing disk transfers. 2792781Swnj */ 2802941Swnj harderr(bp, cp) 2812678Swnj struct buf *bp; 2822941Swnj char *cp; 28331Sbill { 28431Sbill 2852941Swnj printf("%s%d%c: hard error sn%d ", cp, 28624759Skarels minor(bp->b_dev) >> 3, 'a'+(minor(bp->b_dev)&07), bp->b_blkno); 28731Sbill } 2882781Swnj 289285Sbill /* 2902377Swnj * Print a character on console or users terminal. 291285Sbill * If destination is console then the last MSGBUFS characters 292285Sbill * are saved in msgbuf for inspection later. 293285Sbill */ 2941785Sbill /*ARGSUSED*/ 29517594Skarels putchar(c, flags, tp) 2962377Swnj register int c; 29717594Skarels struct tty *tp; 298285Sbill { 299285Sbill 30016724Sralph if (flags & TOTTY) { 301*25389Skarels register s = spltty(); 302*25389Skarels 303*25389Skarels if (tp && (tp->t_state & (TS_CARR_ON | TS_ISOPEN)) == 304*25389Skarels (TS_CARR_ON | TS_ISOPEN)) { 3052377Swnj if (c == '\n') 3064970Swnj (void) ttyoutput('\r', tp); 3074970Swnj (void) ttyoutput(c, tp); 3082360Skre ttstart(tp); 3092360Skre } 310*25389Skarels splx(s); 3112360Skre } 31216724Sralph if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177 3138966Sroot #ifdef vax 3148950Sroot && mfpr(MAPEN) 3158950Sroot #endif 3168950Sroot ) { 3172172Swnj if (msgbuf.msg_magic != MSG_MAGIC) { 31812494Ssam register int i; 31912494Ssam 3202172Swnj msgbuf.msg_magic = MSG_MAGIC; 32116724Sralph msgbuf.msg_bufx = msgbuf.msg_bufr = 0; 32212494Ssam for (i=0; i < MSG_BSIZE; i++) 32312494Ssam msgbuf.msg_bufc[i] = 0; 3242172Swnj } 3252172Swnj if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE) 3262172Swnj msgbuf.msg_bufx = 0; 3272172Swnj msgbuf.msg_bufc[msgbuf.msg_bufx++] = c; 328285Sbill } 32916724Sralph if ((flags & TOCONS) && c != '\0') 33016724Sralph cnputc(c); 331285Sbill } 332