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*47540Skarels * @(#)subr_prf.c 7.20 (Berkeley) 03/17/91 723381Smckusick */ 831Sbill 917094Sbloom #include "param.h" 1017094Sbloom #include "systm.h" 1117094Sbloom #include "buf.h" 1217094Sbloom #include "conf.h" 1317094Sbloom #include "reboot.h" 1417094Sbloom #include "msgbuf.h" 1517094Sbloom #include "user.h" 1617094Sbloom #include "proc.h" 1717577Sbloom #include "ioctl.h" 1839560Smarc #include "vnode.h" 1939560Smarc #include "file.h" 2017094Sbloom #include "tty.h" 2144386Smarc #include "tprintf.h" 2218364Skarels #include "syslog.h" 2344386Smarc #include "malloc.h" 2431Sbill 2535282Skarels #ifdef KADB 2637496Smckusick #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 */ 4140808Smarc int (*v_putc)() = cnputc; /* routine to putc on virtual console */ 4230549Skarels extern struct tty cons; /* standard console tty */ 4330549Skarels struct tty *constty; /* pointer to console "window" tty */ 4430549Skarels 4540808Smarc #ifdef KADB 4640808Smarc extern cngetc(); /* standard console getc */ 4740808Smarc extern cnpoll(); 4840808Smarc int (*v_getc)() = cngetc; /* "" getc from virtual console */ 4940808Smarc int (*v_poll)() = cnpoll; /* kdb hook to enable input polling */ 5040808Smarc #endif 5140808Smarc 5231Sbill /* 5331Sbill * Scaled down version of C Library printf. 542781Swnj * Used to print diagnostic information directly on console tty. 552781Swnj * Since it is not interrupt driven, all system activities are 562781Swnj * suspended. Printf should not be used for chit-chat. 572781Swnj * 582781Swnj * One additional format: %b is supported to decode error registers. 592781Swnj * Usage is: 602781Swnj * printf("reg=%b\n", regval, "<base><arg>*"); 612781Swnj * Where <base> is the output base expressed as a control character, 622781Swnj * e.g. \10 gives octal; \20 gives hex. Each arg is a sequence of 632781Swnj * characters, the first of which gives the bit number to be inspected 642781Swnj * (origin 1), and the next characters (up to a control character, i.e. 652781Swnj * a character <= 32), give the name of the register. Thus 662781Swnj * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 672781Swnj * would produce output: 6817594Skarels * reg=3<BITTWO,BITONE> 6934478Skarels * 7034478Skarels * Another additional format: %r is used to pass an additional format string 7134478Skarels * and argument list recursively. Usage is typically: 7234478Skarels * 7334478Skarels * fn(otherstuff, fmt [, arg1, ... ] ) 7434478Skarels * char *fmt; 7534478Skarels * u_int arg1, ...; 7634478Skarels * 7734478Skarels * printf("prefix: %r, other stuff\n", fmt, &arg1); 7831Sbill */ 7929946Skarels #if defined(tahoe) 8029946Skarels int consintr; 8129946Skarels #endif 8229946Skarels 8331Sbill /*VARARGS1*/ 84*47540Skarels printf(fmt, args) 852781Swnj char *fmt; 86*47540Skarels unsigned args; 8731Sbill { 8829946Skarels #if defined(tahoe) 8929946Skarels register int savintr; 90285Sbill 9129946Skarels savintr = consintr, consintr = 0; /* disable interrupts */ 9229946Skarels #endif 93*47540Skarels prf(fmt, &args, TOCONS | TOLOG, (struct tty *)NULL); 9441972Smckusick if (!panicstr) 9541972Smckusick logwakeup(); 9629946Skarels #if defined(tahoe) 9729946Skarels consintr = savintr; /* reenable interrupts */ 9829946Skarels #endif 99285Sbill } 100285Sbill 1012377Swnj /* 10239560Smarc * Uprintf prints to the controlling terminal for the current process. 10325389Skarels * It may block if the tty queue is overfull. 10430695Skarels * No message is printed if the queue does not clear 10530695Skarels * in a reasonable time. 1062377Swnj */ 1072377Swnj /*VARARGS1*/ 108*47540Skarels uprintf(fmt, args) 1092781Swnj char *fmt; 110*47540Skarels unsigned args; 111285Sbill { 112*47540Skarels register struct proc *p = curproc; 113285Sbill 11444386Smarc if (p->p_flag & SCTTY && p->p_session->s_ttyvp) 115*47540Skarels prf(fmt, &args, TOTTY, p->p_session->s_ttyp); 116285Sbill } 117285Sbill 11844386Smarc tpr_t 11944386Smarc tprintf_open() 12044386Smarc { 121*47540Skarels register struct proc *p = curproc; 12244386Smarc 12344386Smarc if (p->p_flag & SCTTY && p->p_session->s_ttyvp) { 12444386Smarc SESSHOLD(p->p_session); 12544386Smarc return ((tpr_t)p->p_session); 12644386Smarc } else 12744386Smarc return ((tpr_t)NULL); 12844386Smarc } 12944386Smarc 13044386Smarc tprintf_close(sess) 13144386Smarc tpr_t sess; 13244386Smarc { 13344386Smarc if (sess) 13444386Smarc SESSRELE(sess); 13544386Smarc } 13644386Smarc 13718364Skarels /* 13844386Smarc * tprintf prints on the controlling terminal associated 13944386Smarc * with the given session. 14018364Skarels */ 14116724Sralph /*VARARGS2*/ 142*47540Skarels tprintf(sess, fmt, args) 14344386Smarc register tpr_t sess; 14416724Sralph char *fmt; 145*47540Skarels unsigned args; 14616724Sralph { 14744386Smarc int flags = TOLOG; 14816724Sralph 14925389Skarels logpri(LOG_INFO); 15039560Smarc 15144386Smarc if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) 15244386Smarc flags |= TOTTY; 153*47540Skarels prf(fmt, &args, flags, sess->s_ttyp); 15425389Skarels logwakeup(); 15516724Sralph } 15616724Sralph 15744386Smarc 15816724Sralph /* 15916724Sralph * Log writes to the log buffer, 16017594Skarels * and guarantees not to sleep (so can be called by interrupt routines). 16118364Skarels * If there is no process reading the log yet, it writes to the console also. 16216724Sralph */ 16316724Sralph /*VARARGS2*/ 164*47540Skarels log(level, fmt, args) 16516724Sralph char *fmt; 166*47540Skarels unsigned args; 16716724Sralph { 16816724Sralph register s = splhigh(); 16918364Skarels extern int log_open; 17016724Sralph 17125389Skarels logpri(level); 172*47540Skarels prf(fmt, &args, TOLOG, (struct tty *)NULL); 17316724Sralph splx(s); 17418364Skarels if (!log_open) 175*47540Skarels prf(fmt, &args, TOCONS, (struct tty *)NULL); 17616724Sralph logwakeup(); 17716724Sralph } 17816724Sralph 17925389Skarels logpri(level) 18025389Skarels int level; 18125389Skarels { 18225389Skarels 18344386Smarc putchar('<', TOLOG, (struct tty *)NULL); 18444386Smarc printn((u_long)level, 10, TOLOG, (struct tty *)NULL); 18544386Smarc putchar('>', TOLOG, (struct tty *)NULL); 18625389Skarels } 18725389Skarels 18833479Skarels /*VARARGS1*/ 189*47540Skarels addlog(fmt, args) 19033479Skarels char *fmt; 191*47540Skarels unsigned args; 19233479Skarels { 19333479Skarels register s = splhigh(); 19433479Skarels 195*47540Skarels prf(fmt, &args, TOLOG, (struct tty *)NULL); 19633479Skarels splx(s); 19733479Skarels if (!log_open) 198*47540Skarels prf(fmt, &args, TOCONS, (struct tty *)NULL); 19933479Skarels logwakeup(); 20033479Skarels } 20133479Skarels 202*47540Skarels prf(fmt, argp, flags, ttyp) 2032781Swnj register char *fmt; 204*47540Skarels register u_int *argp; 20544386Smarc struct tty *ttyp; 206285Sbill { 2072434Swnj register int b, c, i; 20831Sbill char *s; 2092678Swnj int any; 21031Sbill 21131Sbill loop: 2122377Swnj while ((c = *fmt++) != '%') { 21316724Sralph if (c == '\0') 21431Sbill return; 21544386Smarc putchar(c, flags, ttyp); 21631Sbill } 2172377Swnj again: 21831Sbill c = *fmt++; 21929946Skarels /* THIS CODE IS MACHINE DEPENDENT IN HANDLING %l? AND %c */ 2202377Swnj switch (c) { 2212377Swnj 2222377Swnj case 'l': 2232377Swnj goto again; 2242377Swnj case 'x': case 'X': 2252377Swnj b = 16; 2262377Swnj goto number; 2272377Swnj case 'd': case 'D': 22829946Skarels b = -10; 22929946Skarels goto number; 23029946Skarels case 'u': 2312377Swnj b = 10; 2322377Swnj goto number; 2332377Swnj case 'o': case 'O': 2342377Swnj b = 8; 2352377Swnj number: 236*47540Skarels printn((u_long)*argp, b, flags, ttyp); 2372377Swnj break; 2382377Swnj case 'c': 239*47540Skarels b = *argp; 24033479Skarels #if BYTE_ORDER == LITTLE_ENDIAN 2412434Swnj for (i = 24; i >= 0; i -= 8) 2422434Swnj if (c = (b >> i) & 0x7f) 24344386Smarc putchar(c, flags, ttyp); 24429946Skarels #endif 24533479Skarels #if BYTE_ORDER == BIG_ENDIAN 24629946Skarels if (c = (b & 0x7f)) 24744386Smarc putchar(c, flags, ttyp); 24829946Skarels #endif 2492377Swnj break; 2502678Swnj case 'b': 251*47540Skarels b = *argp++; 252*47540Skarels s = (char *)*argp; 25344386Smarc printn((u_long)b, *s++, flags, ttyp); 2542678Swnj any = 0; 2552678Swnj if (b) { 2562678Swnj while (i = *s++) { 2572678Swnj if (b & (1 << (i-1))) { 25844386Smarc putchar(any ? ',' : '<', flags, ttyp); 2592678Swnj any = 1; 2602678Swnj for (; (c = *s) > 32; s++) 26144386Smarc putchar(c, flags, ttyp); 2622678Swnj } else 2632678Swnj for (; *s > 32; s++) 2642678Swnj ; 2652678Swnj } 2663878Swnj if (any) 26744386Smarc putchar('>', flags, ttyp); 2682678Swnj } 2692678Swnj break; 2702678Swnj 2712377Swnj case 's': 272*47540Skarels s = (char *)*argp; 273285Sbill while (c = *s++) 27444386Smarc putchar(c, flags, ttyp); 2752377Swnj break; 2763736Sroot 27733479Skarels case 'r': 278*47540Skarels s = (char *)*argp++; 279*47540Skarels prf(s, (u_int *)*argp, flags, ttyp); 28033479Skarels break; 28133479Skarels 2823736Sroot case '%': 28344386Smarc putchar('%', flags, ttyp); 2843736Sroot break; 28531Sbill } 286*47540Skarels argp++; 28731Sbill goto loop; 28831Sbill } 28931Sbill 2902781Swnj /* 2912781Swnj * Printn prints a number n in base b. 292*47540Skarels * We avoid recursion to avoid deep kernel stacks. 2932781Swnj */ 29444386Smarc printn(n, b, flags, ttyp) 2953101Swnj u_long n; 29644386Smarc struct tty *ttyp; 29731Sbill { 2982434Swnj char prbuf[11]; 2992377Swnj register char *cp; 30031Sbill 30129946Skarels if (b == -10) { 30229946Skarels if ((int)n < 0) { 30344386Smarc putchar('-', flags, ttyp); 30429946Skarels n = (unsigned)(-(int)n); 30529946Skarels } 30629946Skarels b = -b; 30731Sbill } 3082434Swnj cp = prbuf; 3092377Swnj do { 3102377Swnj *cp++ = "0123456789abcdef"[n%b]; 3112377Swnj n /= b; 3122377Swnj } while (n); 3132377Swnj do 31444386Smarc putchar(*--cp, flags, ttyp); 3152434Swnj while (cp > prbuf); 31631Sbill } 31731Sbill 31831Sbill /* 3191184Sbill * Panic is called on unresolvable fatal errors. 3202781Swnj * It prints "panic: mesg", and then reboots. 3212781Swnj * If we are called twice, then we avoid trying to 3222781Swnj * sync the disks as this often leads to recursive panics. 32331Sbill */ 32431Sbill panic(s) 3252781Swnj char *s; 32631Sbill { 32730566Skarels int bootopt = RB_AUTOBOOT | RB_DUMP; 3282377Swnj 3295416Swnj if (panicstr) 3305416Swnj bootopt |= RB_NOSYNC; 331*47540Skarels else 3329758Ssam panicstr = s; 3333285Swnj printf("panic: %s\n", s); 334*47540Skarels #ifdef KGDB 335*47540Skarels kgdb_panic(); 336*47540Skarels #endif 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 { 36845733Smckusick 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) { 38245733Smckusick if (mbp->msg_magic != MSG_MAGIC) { 38312494Ssam register int i; 38412494Ssam 38545733Smckusick mbp->msg_magic = MSG_MAGIC; 38645733Smckusick mbp->msg_bufx = mbp->msg_bufr = 0; 38712494Ssam for (i=0; i < MSG_BSIZE; i++) 38845733Smckusick mbp->msg_bufc[i] = 0; 3892172Swnj } 39045733Smckusick mbp->msg_bufc[mbp->msg_bufx++] = c; 39145733Smckusick if (mbp->msg_bufx < 0 || mbp->msg_bufx >= MSG_BSIZE) 39245733Smckusick mbp->msg_bufx = 0; 393285Sbill } 39430549Skarels if ((flags & TOCONS) && constty == 0 && c != '\0') 39530549Skarels (*v_putc)(c); 396285Sbill } 397