123381Smckusick /* 2*34420Skarels * 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*34420Skarels * @(#)subr_prf.c 7.9 (Berkeley) 05/22/88 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 2430625Skarels #include "../machine/mtpr.h" 2530625Skarels #ifdef KDB 2630625Skarels #include "../machine/kdbparam.h" 2730625Skarels #endif 2830625Skarels 2916724Sralph #define TOCONS 0x1 3016724Sralph #define TOTTY 0x2 3116724Sralph #define TOLOG 0x4 3216724Sralph 3331Sbill /* 3431Sbill * In case console is off, 3531Sbill * panicstr contains argument to last 3631Sbill * call to panic. 3731Sbill */ 3831Sbill char *panicstr; 3931Sbill 4030549Skarels extern cnputc(); /* standard console putc */ 4130549Skarels extern struct tty cons; /* standard console tty */ 4230549Skarels struct tty *constty; /* pointer to console "window" tty */ 4330549Skarels int (*v_putc)() = cnputc; /* routine to putc on virtual console */ 4430549Skarels 4531Sbill /* 4631Sbill * Scaled down version of C Library printf. 472781Swnj * Used to print diagnostic information directly on console tty. 482781Swnj * Since it is not interrupt driven, all system activities are 492781Swnj * suspended. Printf should not be used for chit-chat. 502781Swnj * 512781Swnj * One additional format: %b is supported to decode error registers. 522781Swnj * Usage is: 532781Swnj * printf("reg=%b\n", regval, "<base><arg>*"); 542781Swnj * Where <base> is the output base expressed as a control character, 552781Swnj * e.g. \10 gives octal; \20 gives hex. Each arg is a sequence of 562781Swnj * characters, the first of which gives the bit number to be inspected 572781Swnj * (origin 1), and the next characters (up to a control character, i.e. 582781Swnj * a character <= 32), give the name of the register. Thus 592781Swnj * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 602781Swnj * would produce output: 6117594Skarels * reg=3<BITTWO,BITONE> 6231Sbill */ 6329946Skarels #if defined(tahoe) 6429946Skarels int consintr; 6529946Skarels #endif 6629946Skarels 6731Sbill /*VARARGS1*/ 6831Sbill printf(fmt, x1) 692781Swnj char *fmt; 702781Swnj unsigned x1; 7131Sbill { 7229946Skarels #if defined(tahoe) 7329946Skarels register int savintr; 74285Sbill 7529946Skarels savintr = consintr, consintr = 0; /* disable interrupts */ 7629946Skarels #endif 7716724Sralph prf(fmt, &x1, TOCONS | TOLOG, (struct tty *)0); 7816724Sralph logwakeup(); 7929946Skarels #if defined(tahoe) 8029946Skarels consintr = savintr; /* reenable interrupts */ 8129946Skarels #endif 82285Sbill } 83285Sbill 842377Swnj /* 8525389Skarels * Uprintf prints to the current user's terminal. 8625389Skarels * It may block if the tty queue is overfull. 8730695Skarels * No message is printed if the queue does not clear 8830695Skarels * in a reasonable time. 8925389Skarels * Should determine whether current terminal user is related 9025389Skarels * to this process. 912377Swnj */ 922377Swnj /*VARARGS1*/ 932377Swnj uprintf(fmt, x1) 942781Swnj char *fmt; 952377Swnj unsigned x1; 96285Sbill { 9726250Skarels #ifdef notdef 9825389Skarels register struct proc *p; 9926250Skarels #endif 10025389Skarels register struct tty *tp; 101285Sbill 10225389Skarels if ((tp = u.u_ttyp) == NULL) 10325389Skarels return; 10425389Skarels #ifdef notdef 10525389Skarels if (tp->t_pgrp && (p = pfind(tp->t_pgrp))) 10626250Skarels if (p->p_uid != u.u_uid) /* doesn't account for setuid */ 10725389Skarels return; 10825389Skarels #endif 10930695Skarels if (ttycheckoutq(tp, 1)) 11030695Skarels prf(fmt, &x1, TOTTY, tp); 111285Sbill } 112285Sbill 11318364Skarels /* 11418364Skarels * tprintf prints on the specified terminal (console if none) 11518364Skarels * and logs the message. It is designed for error messages from 11625389Skarels * single-open devices, and may be called from interrupt level 11725389Skarels * (does not sleep). 11818364Skarels */ 11916724Sralph /*VARARGS2*/ 12025389Skarels tprintf(tp, fmt, x1) 12125389Skarels register struct tty *tp; 12216724Sralph char *fmt; 12316724Sralph unsigned x1; 12416724Sralph { 12525389Skarels int flags = TOTTY | TOLOG; 12616724Sralph 12725389Skarels logpri(LOG_INFO); 12829946Skarels if (tp == (struct tty *)NULL) 12929946Skarels tp = &cons; 13025389Skarels if (ttycheckoutq(tp, 0) == 0) 13125389Skarels flags = TOLOG; 13225389Skarels prf(fmt, &x1, flags, tp); 13325389Skarels logwakeup(); 13416724Sralph } 13516724Sralph 13616724Sralph /* 13716724Sralph * Log writes to the log buffer, 13817594Skarels * and guarantees not to sleep (so can be called by interrupt routines). 13918364Skarels * If there is no process reading the log yet, it writes to the console also. 14016724Sralph */ 14116724Sralph /*VARARGS2*/ 14216724Sralph log(level, fmt, x1) 14316724Sralph char *fmt; 14416724Sralph unsigned x1; 14516724Sralph { 14616724Sralph register s = splhigh(); 14718364Skarels extern int log_open; 14816724Sralph 14925389Skarels logpri(level); 15016724Sralph prf(fmt, &x1, TOLOG, (struct tty *)0); 15116724Sralph splx(s); 15218364Skarels if (!log_open) 15318364Skarels prf(fmt, &x1, TOCONS, (struct tty *)0); 15416724Sralph logwakeup(); 15516724Sralph } 15616724Sralph 15725389Skarels logpri(level) 15825389Skarels int level; 15925389Skarels { 16025389Skarels 16125389Skarels putchar('<', TOLOG, (struct tty *)0); 16226356Skarels printn((u_long)level, 10, TOLOG, (struct tty *)0); 16325389Skarels putchar('>', TOLOG, (struct tty *)0); 16425389Skarels } 16525389Skarels 16633479Skarels /*VARARGS1*/ 16733479Skarels addlog(fmt, x1) 16833479Skarels char *fmt; 16933479Skarels unsigned x1; 17033479Skarels { 17133479Skarels register s = splhigh(); 17233479Skarels 17333479Skarels prf(fmt, &x1, TOLOG, (struct tty *)0); 17433479Skarels splx(s); 17533479Skarels if (!log_open) 17633479Skarels prf(fmt, &x1, TOCONS, (struct tty *)0); 17733479Skarels logwakeup(); 17833479Skarels } 17933479Skarels 18016724Sralph prf(fmt, adx, flags, ttyp) 1812781Swnj register char *fmt; 1822781Swnj register u_int *adx; 18316724Sralph struct tty *ttyp; 184285Sbill { 1852434Swnj register int b, c, i; 18631Sbill char *s; 1872678Swnj int any; 18831Sbill 18931Sbill loop: 1902377Swnj while ((c = *fmt++) != '%') { 19116724Sralph if (c == '\0') 19231Sbill return; 19316724Sralph putchar(c, flags, ttyp); 19431Sbill } 1952377Swnj again: 19631Sbill c = *fmt++; 19729946Skarels /* THIS CODE IS MACHINE DEPENDENT IN HANDLING %l? AND %c */ 1982377Swnj switch (c) { 1992377Swnj 2002377Swnj case 'l': 2012377Swnj goto again; 2022377Swnj case 'x': case 'X': 2032377Swnj b = 16; 2042377Swnj goto number; 2052377Swnj case 'd': case 'D': 20629946Skarels b = -10; 20729946Skarels goto number; 20829946Skarels case 'u': 2092377Swnj b = 10; 2102377Swnj goto number; 2112377Swnj case 'o': case 'O': 2122377Swnj b = 8; 2132377Swnj number: 21416724Sralph printn((u_long)*adx, b, flags, ttyp); 2152377Swnj break; 2162377Swnj case 'c': 2172434Swnj b = *adx; 21833479Skarels #if BYTE_ORDER == LITTLE_ENDIAN 2192434Swnj for (i = 24; i >= 0; i -= 8) 2202434Swnj if (c = (b >> i) & 0x7f) 22116724Sralph putchar(c, flags, ttyp); 22229946Skarels #endif 22333479Skarels #if BYTE_ORDER == BIG_ENDIAN 22429946Skarels if (c = (b & 0x7f)) 22529946Skarels putchar(c, flags, ttyp); 22629946Skarels #endif 2272377Swnj break; 2282678Swnj case 'b': 2292678Swnj b = *adx++; 2302678Swnj s = (char *)*adx; 23116724Sralph printn((u_long)b, *s++, flags, ttyp); 2322678Swnj any = 0; 2332678Swnj if (b) { 2342678Swnj while (i = *s++) { 2352678Swnj if (b & (1 << (i-1))) { 23629946Skarels putchar(any ? ',' : '<', flags, ttyp); 2372678Swnj any = 1; 2382678Swnj for (; (c = *s) > 32; s++) 23916724Sralph putchar(c, flags, ttyp); 2402678Swnj } else 2412678Swnj for (; *s > 32; s++) 2422678Swnj ; 2432678Swnj } 2443878Swnj if (any) 24516724Sralph putchar('>', flags, ttyp); 2462678Swnj } 2472678Swnj break; 2482678Swnj 2492377Swnj case 's': 25031Sbill s = (char *)*adx; 251285Sbill while (c = *s++) 25216724Sralph putchar(c, flags, ttyp); 2532377Swnj break; 2543736Sroot 25533479Skarels case 'r': 25633479Skarels s = (char *)*adx++; 25733479Skarels prf(s, *adx, flags, ttyp); 25833479Skarels break; 25933479Skarels 2603736Sroot case '%': 26116724Sralph putchar('%', flags, ttyp); 2623736Sroot break; 26331Sbill } 26431Sbill adx++; 26531Sbill goto loop; 26631Sbill } 26731Sbill 2682781Swnj /* 2692781Swnj * Printn prints a number n in base b. 2702781Swnj * We don't use recursion to avoid deep kernel stacks. 2712781Swnj */ 27216724Sralph printn(n, b, flags, ttyp) 2733101Swnj u_long n; 27416724Sralph struct tty *ttyp; 27531Sbill { 2762434Swnj char prbuf[11]; 2772377Swnj register char *cp; 27831Sbill 27929946Skarels if (b == -10) { 28029946Skarels if ((int)n < 0) { 28129946Skarels putchar('-', flags, ttyp); 28229946Skarels n = (unsigned)(-(int)n); 28329946Skarels } 28429946Skarels b = -b; 28531Sbill } 2862434Swnj cp = prbuf; 2872377Swnj do { 2882377Swnj *cp++ = "0123456789abcdef"[n%b]; 2892377Swnj n /= b; 2902377Swnj } while (n); 2912377Swnj do 29216724Sralph putchar(*--cp, flags, ttyp); 2932434Swnj while (cp > prbuf); 29431Sbill } 29531Sbill 29631Sbill /* 2971184Sbill * Panic is called on unresolvable fatal errors. 2982781Swnj * It prints "panic: mesg", and then reboots. 2992781Swnj * If we are called twice, then we avoid trying to 3002781Swnj * sync the disks as this often leads to recursive panics. 30131Sbill */ 30231Sbill panic(s) 3032781Swnj char *s; 30431Sbill { 30530566Skarels int bootopt = RB_AUTOBOOT | RB_DUMP; 3062377Swnj 3075416Swnj if (panicstr) 3085416Swnj bootopt |= RB_NOSYNC; 3099758Ssam else { 3109758Ssam panicstr = s; 3118950Sroot } 3123285Swnj printf("panic: %s\n", s); 31330625Skarels #ifdef KDB 31430625Skarels if (boothowto & RB_KDB) { 315*34420Skarels int x = splnet(); /* below kdb pri */ 31630625Skarels 31730625Skarels setsoftkdb(); 318*34420Skarels splx(x); 31930625Skarels } 32030625Skarels #endif 32130566Skarels boot(bootopt); 32231Sbill } 32331Sbill 32431Sbill /* 3252941Swnj * Warn that a system table is full. 3262941Swnj */ 3272941Swnj tablefull(tab) 3282941Swnj char *tab; 3292941Swnj { 3302941Swnj 33124839Seric log(LOG_ERR, "%s: table is full\n", tab); 3322941Swnj } 3332941Swnj 3342941Swnj /* 3352781Swnj * Hard error is the preface to plaintive error messages 3362941Swnj * about failing disk transfers. 3372781Swnj */ 3382941Swnj harderr(bp, cp) 3392678Swnj struct buf *bp; 3402941Swnj char *cp; 34131Sbill { 34231Sbill 3432941Swnj printf("%s%d%c: hard error sn%d ", cp, 34424759Skarels minor(bp->b_dev) >> 3, 'a'+(minor(bp->b_dev)&07), bp->b_blkno); 34531Sbill } 3462781Swnj 347285Sbill /* 3482377Swnj * Print a character on console or users terminal. 349285Sbill * If destination is console then the last MSGBUFS characters 350285Sbill * are saved in msgbuf for inspection later. 351285Sbill */ 3521785Sbill /*ARGSUSED*/ 35317594Skarels putchar(c, flags, tp) 3542377Swnj register int c; 35517594Skarels struct tty *tp; 356285Sbill { 35733479Skarels extern int msgbufmapped; 358285Sbill 35930549Skarels if (panicstr) 36030549Skarels constty = 0; 36130549Skarels if ((flags & TOCONS) && tp == 0 && constty) { 36230549Skarels tp = constty; 36330549Skarels flags |= TOTTY; 36430549Skarels } 36516724Sralph if (flags & TOTTY) { 36625389Skarels register s = spltty(); 36725389Skarels 36825389Skarels if (tp && (tp->t_state & (TS_CARR_ON | TS_ISOPEN)) == 36925389Skarels (TS_CARR_ON | TS_ISOPEN)) { 3702377Swnj if (c == '\n') 3714970Swnj (void) ttyoutput('\r', tp); 3724970Swnj (void) ttyoutput(c, tp); 3732360Skre ttstart(tp); 37430549Skarels } else if ((flags & TOCONS) && tp == constty) 37530549Skarels constty = 0; 37625389Skarels splx(s); 3772360Skre } 37833479Skarels if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177 && 37933479Skarels msgbufmapped) { 3802172Swnj if (msgbuf.msg_magic != MSG_MAGIC) { 38112494Ssam register int i; 38212494Ssam 3832172Swnj msgbuf.msg_magic = MSG_MAGIC; 38416724Sralph msgbuf.msg_bufx = msgbuf.msg_bufr = 0; 38512494Ssam for (i=0; i < MSG_BSIZE; i++) 38612494Ssam msgbuf.msg_bufc[i] = 0; 3872172Swnj } 38826427Sbloom msgbuf.msg_bufc[msgbuf.msg_bufx++] = c; 3892172Swnj if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE) 3902172Swnj msgbuf.msg_bufx = 0; 391285Sbill } 39230549Skarels if ((flags & TOCONS) && constty == 0 && c != '\0') 39330549Skarels (*v_putc)(c); 394285Sbill } 395