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*34478Skarels * @(#)subr_prf.c 7.10 (Berkeley) 05/25/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> 62*34478Skarels * 63*34478Skarels * Another additional format: %r is used to pass an additional format string 64*34478Skarels * and argument list recursively. Usage is typically: 65*34478Skarels * 66*34478Skarels * fn(otherstuff, fmt [, arg1, ... ] ) 67*34478Skarels * char *fmt; 68*34478Skarels * u_int arg1, ...; 69*34478Skarels * 70*34478Skarels * printf("prefix: %r, other stuff\n", fmt, &arg1); 7131Sbill */ 7229946Skarels #if defined(tahoe) 7329946Skarels int consintr; 7429946Skarels #endif 7529946Skarels 7631Sbill /*VARARGS1*/ 7731Sbill printf(fmt, x1) 782781Swnj char *fmt; 792781Swnj unsigned x1; 8031Sbill { 8129946Skarels #if defined(tahoe) 8229946Skarels register int savintr; 83285Sbill 8429946Skarels savintr = consintr, consintr = 0; /* disable interrupts */ 8529946Skarels #endif 8616724Sralph prf(fmt, &x1, TOCONS | TOLOG, (struct tty *)0); 8716724Sralph logwakeup(); 8829946Skarels #if defined(tahoe) 8929946Skarels consintr = savintr; /* reenable interrupts */ 9029946Skarels #endif 91285Sbill } 92285Sbill 932377Swnj /* 9425389Skarels * Uprintf prints to the current user's terminal. 9525389Skarels * It may block if the tty queue is overfull. 9630695Skarels * No message is printed if the queue does not clear 9730695Skarels * in a reasonable time. 9825389Skarels * Should determine whether current terminal user is related 9925389Skarels * to this process. 1002377Swnj */ 1012377Swnj /*VARARGS1*/ 1022377Swnj uprintf(fmt, x1) 1032781Swnj char *fmt; 1042377Swnj unsigned x1; 105285Sbill { 10626250Skarels #ifdef notdef 10725389Skarels register struct proc *p; 10826250Skarels #endif 10925389Skarels register struct tty *tp; 110285Sbill 11125389Skarels if ((tp = u.u_ttyp) == NULL) 11225389Skarels return; 11325389Skarels #ifdef notdef 11425389Skarels if (tp->t_pgrp && (p = pfind(tp->t_pgrp))) 11526250Skarels if (p->p_uid != u.u_uid) /* doesn't account for setuid */ 11625389Skarels return; 11725389Skarels #endif 11830695Skarels if (ttycheckoutq(tp, 1)) 11930695Skarels prf(fmt, &x1, TOTTY, tp); 120285Sbill } 121285Sbill 12218364Skarels /* 12318364Skarels * tprintf prints on the specified terminal (console if none) 12418364Skarels * and logs the message. It is designed for error messages from 12525389Skarels * single-open devices, and may be called from interrupt level 12625389Skarels * (does not sleep). 12718364Skarels */ 12816724Sralph /*VARARGS2*/ 12925389Skarels tprintf(tp, fmt, x1) 13025389Skarels register struct tty *tp; 13116724Sralph char *fmt; 13216724Sralph unsigned x1; 13316724Sralph { 13425389Skarels int flags = TOTTY | TOLOG; 13516724Sralph 13625389Skarels logpri(LOG_INFO); 13729946Skarels if (tp == (struct tty *)NULL) 13829946Skarels tp = &cons; 13925389Skarels if (ttycheckoutq(tp, 0) == 0) 14025389Skarels flags = TOLOG; 14125389Skarels prf(fmt, &x1, flags, tp); 14225389Skarels logwakeup(); 14316724Sralph } 14416724Sralph 14516724Sralph /* 14616724Sralph * Log writes to the log buffer, 14717594Skarels * and guarantees not to sleep (so can be called by interrupt routines). 14818364Skarels * If there is no process reading the log yet, it writes to the console also. 14916724Sralph */ 15016724Sralph /*VARARGS2*/ 15116724Sralph log(level, fmt, x1) 15216724Sralph char *fmt; 15316724Sralph unsigned x1; 15416724Sralph { 15516724Sralph register s = splhigh(); 15618364Skarels extern int log_open; 15716724Sralph 15825389Skarels logpri(level); 15916724Sralph prf(fmt, &x1, TOLOG, (struct tty *)0); 16016724Sralph splx(s); 16118364Skarels if (!log_open) 16218364Skarels prf(fmt, &x1, TOCONS, (struct tty *)0); 16316724Sralph logwakeup(); 16416724Sralph } 16516724Sralph 16625389Skarels logpri(level) 16725389Skarels int level; 16825389Skarels { 16925389Skarels 17025389Skarels putchar('<', TOLOG, (struct tty *)0); 17126356Skarels printn((u_long)level, 10, TOLOG, (struct tty *)0); 17225389Skarels putchar('>', TOLOG, (struct tty *)0); 17325389Skarels } 17425389Skarels 17533479Skarels /*VARARGS1*/ 17633479Skarels addlog(fmt, x1) 17733479Skarels char *fmt; 17833479Skarels unsigned x1; 17933479Skarels { 18033479Skarels register s = splhigh(); 18133479Skarels 18233479Skarels prf(fmt, &x1, TOLOG, (struct tty *)0); 18333479Skarels splx(s); 18433479Skarels if (!log_open) 18533479Skarels prf(fmt, &x1, TOCONS, (struct tty *)0); 18633479Skarels logwakeup(); 18733479Skarels } 18833479Skarels 18916724Sralph prf(fmt, adx, flags, ttyp) 1902781Swnj register char *fmt; 1912781Swnj register u_int *adx; 19216724Sralph struct tty *ttyp; 193285Sbill { 1942434Swnj register int b, c, i; 19531Sbill char *s; 1962678Swnj int any; 19731Sbill 19831Sbill loop: 1992377Swnj while ((c = *fmt++) != '%') { 20016724Sralph if (c == '\0') 20131Sbill return; 20216724Sralph putchar(c, flags, ttyp); 20331Sbill } 2042377Swnj again: 20531Sbill c = *fmt++; 20629946Skarels /* THIS CODE IS MACHINE DEPENDENT IN HANDLING %l? AND %c */ 2072377Swnj switch (c) { 2082377Swnj 2092377Swnj case 'l': 2102377Swnj goto again; 2112377Swnj case 'x': case 'X': 2122377Swnj b = 16; 2132377Swnj goto number; 2142377Swnj case 'd': case 'D': 21529946Skarels b = -10; 21629946Skarels goto number; 21729946Skarels case 'u': 2182377Swnj b = 10; 2192377Swnj goto number; 2202377Swnj case 'o': case 'O': 2212377Swnj b = 8; 2222377Swnj number: 22316724Sralph printn((u_long)*adx, b, flags, ttyp); 2242377Swnj break; 2252377Swnj case 'c': 2262434Swnj b = *adx; 22733479Skarels #if BYTE_ORDER == LITTLE_ENDIAN 2282434Swnj for (i = 24; i >= 0; i -= 8) 2292434Swnj if (c = (b >> i) & 0x7f) 23016724Sralph putchar(c, flags, ttyp); 23129946Skarels #endif 23233479Skarels #if BYTE_ORDER == BIG_ENDIAN 23329946Skarels if (c = (b & 0x7f)) 23429946Skarels putchar(c, flags, ttyp); 23529946Skarels #endif 2362377Swnj break; 2372678Swnj case 'b': 2382678Swnj b = *adx++; 2392678Swnj s = (char *)*adx; 24016724Sralph printn((u_long)b, *s++, flags, ttyp); 2412678Swnj any = 0; 2422678Swnj if (b) { 2432678Swnj while (i = *s++) { 2442678Swnj if (b & (1 << (i-1))) { 24529946Skarels putchar(any ? ',' : '<', flags, ttyp); 2462678Swnj any = 1; 2472678Swnj for (; (c = *s) > 32; s++) 24816724Sralph putchar(c, flags, ttyp); 2492678Swnj } else 2502678Swnj for (; *s > 32; s++) 2512678Swnj ; 2522678Swnj } 2533878Swnj if (any) 25416724Sralph putchar('>', flags, ttyp); 2552678Swnj } 2562678Swnj break; 2572678Swnj 2582377Swnj case 's': 25931Sbill s = (char *)*adx; 260285Sbill while (c = *s++) 26116724Sralph putchar(c, flags, ttyp); 2622377Swnj break; 2633736Sroot 26433479Skarels case 'r': 26533479Skarels s = (char *)*adx++; 266*34478Skarels prf(s, (u_int *)*adx, flags, ttyp); 26733479Skarels break; 26833479Skarels 2693736Sroot case '%': 27016724Sralph putchar('%', flags, ttyp); 2713736Sroot break; 27231Sbill } 27331Sbill adx++; 27431Sbill goto loop; 27531Sbill } 27631Sbill 2772781Swnj /* 2782781Swnj * Printn prints a number n in base b. 2792781Swnj * We don't use recursion to avoid deep kernel stacks. 2802781Swnj */ 28116724Sralph printn(n, b, flags, ttyp) 2823101Swnj u_long n; 28316724Sralph struct tty *ttyp; 28431Sbill { 2852434Swnj char prbuf[11]; 2862377Swnj register char *cp; 28731Sbill 28829946Skarels if (b == -10) { 28929946Skarels if ((int)n < 0) { 29029946Skarels putchar('-', flags, ttyp); 29129946Skarels n = (unsigned)(-(int)n); 29229946Skarels } 29329946Skarels b = -b; 29431Sbill } 2952434Swnj cp = prbuf; 2962377Swnj do { 2972377Swnj *cp++ = "0123456789abcdef"[n%b]; 2982377Swnj n /= b; 2992377Swnj } while (n); 3002377Swnj do 30116724Sralph putchar(*--cp, flags, ttyp); 3022434Swnj while (cp > prbuf); 30331Sbill } 30431Sbill 30531Sbill /* 3061184Sbill * Panic is called on unresolvable fatal errors. 3072781Swnj * It prints "panic: mesg", and then reboots. 3082781Swnj * If we are called twice, then we avoid trying to 3092781Swnj * sync the disks as this often leads to recursive panics. 31031Sbill */ 31131Sbill panic(s) 3122781Swnj char *s; 31331Sbill { 31430566Skarels int bootopt = RB_AUTOBOOT | RB_DUMP; 3152377Swnj 3165416Swnj if (panicstr) 3175416Swnj bootopt |= RB_NOSYNC; 3189758Ssam else { 3199758Ssam panicstr = s; 3208950Sroot } 3213285Swnj printf("panic: %s\n", s); 32230625Skarels #ifdef KDB 32330625Skarels if (boothowto & RB_KDB) { 32434420Skarels int x = splnet(); /* below kdb pri */ 32530625Skarels 32630625Skarels setsoftkdb(); 32734420Skarels splx(x); 32830625Skarels } 32930625Skarels #endif 33030566Skarels boot(bootopt); 33131Sbill } 33231Sbill 33331Sbill /* 3342941Swnj * Warn that a system table is full. 3352941Swnj */ 3362941Swnj tablefull(tab) 3372941Swnj char *tab; 3382941Swnj { 3392941Swnj 34024839Seric log(LOG_ERR, "%s: table is full\n", tab); 3412941Swnj } 3422941Swnj 3432941Swnj /* 3442781Swnj * Hard error is the preface to plaintive error messages 3452941Swnj * about failing disk transfers. 3462781Swnj */ 3472941Swnj harderr(bp, cp) 3482678Swnj struct buf *bp; 3492941Swnj char *cp; 35031Sbill { 35131Sbill 3522941Swnj printf("%s%d%c: hard error sn%d ", cp, 35324759Skarels minor(bp->b_dev) >> 3, 'a'+(minor(bp->b_dev)&07), bp->b_blkno); 35431Sbill } 3552781Swnj 356285Sbill /* 3572377Swnj * Print a character on console or users terminal. 358285Sbill * If destination is console then the last MSGBUFS characters 359285Sbill * are saved in msgbuf for inspection later. 360285Sbill */ 3611785Sbill /*ARGSUSED*/ 36217594Skarels putchar(c, flags, tp) 3632377Swnj register int c; 36417594Skarels struct tty *tp; 365285Sbill { 36633479Skarels extern int msgbufmapped; 367285Sbill 36830549Skarels if (panicstr) 36930549Skarels constty = 0; 37030549Skarels if ((flags & TOCONS) && tp == 0 && constty) { 37130549Skarels tp = constty; 37230549Skarels flags |= TOTTY; 37330549Skarels } 37416724Sralph if (flags & TOTTY) { 37525389Skarels register s = spltty(); 37625389Skarels 37725389Skarels if (tp && (tp->t_state & (TS_CARR_ON | TS_ISOPEN)) == 37825389Skarels (TS_CARR_ON | TS_ISOPEN)) { 3792377Swnj if (c == '\n') 3804970Swnj (void) ttyoutput('\r', tp); 3814970Swnj (void) ttyoutput(c, tp); 3822360Skre ttstart(tp); 38330549Skarels } else if ((flags & TOCONS) && tp == constty) 38430549Skarels constty = 0; 38525389Skarels splx(s); 3862360Skre } 38733479Skarels if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177 && 38833479Skarels msgbufmapped) { 3892172Swnj if (msgbuf.msg_magic != MSG_MAGIC) { 39012494Ssam register int i; 39112494Ssam 3922172Swnj msgbuf.msg_magic = MSG_MAGIC; 39316724Sralph msgbuf.msg_bufx = msgbuf.msg_bufr = 0; 39412494Ssam for (i=0; i < MSG_BSIZE; i++) 39512494Ssam msgbuf.msg_bufc[i] = 0; 3962172Swnj } 39726427Sbloom msgbuf.msg_bufc[msgbuf.msg_bufx++] = c; 3982172Swnj if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE) 3992172Swnj msgbuf.msg_bufx = 0; 400285Sbill } 40130549Skarels if ((flags & TOCONS) && constty == 0 && c != '\0') 40230549Skarels (*v_putc)(c); 403285Sbill } 404