123381Smckusick /* 2*48426Skarels * Copyright (c) 1982, 1986, 1988, 1991 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*48426Skarels * @(#)subr_prf.c 7.21 (Berkeley) 04/20/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 "proc.h" 1617577Sbloom #include "ioctl.h" 1739560Smarc #include "vnode.h" 1839560Smarc #include "file.h" 1917094Sbloom #include "tty.h" 2044386Smarc #include "tprintf.h" 2118364Skarels #include "syslog.h" 2244386Smarc #include "malloc.h" 2331Sbill 2435282Skarels #ifdef KADB 2537496Smckusick #include "machine/kdbparam.h" 2630625Skarels #endif 2730625Skarels 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 3930549Skarels extern cnputc(); /* standard console putc */ 4040808Smarc int (*v_putc)() = cnputc; /* routine to putc on virtual console */ 4130549Skarels extern struct tty cons; /* standard console tty */ 4230549Skarels struct tty *constty; /* pointer to console "window" tty */ 4330549Skarels 4440808Smarc #ifdef KADB 4540808Smarc extern cngetc(); /* standard console getc */ 4640808Smarc extern cnpoll(); 4740808Smarc int (*v_getc)() = cngetc; /* "" getc from virtual console */ 4840808Smarc int (*v_poll)() = cnpoll; /* kdb hook to enable input polling */ 4940808Smarc #endif 5040808Smarc 5131Sbill /* 5231Sbill * Scaled down version of C Library printf. 532781Swnj * Used to print diagnostic information directly on console tty. 542781Swnj * Since it is not interrupt driven, all system activities are 552781Swnj * suspended. Printf should not be used for chit-chat. 562781Swnj * 572781Swnj * One additional format: %b is supported to decode error registers. 582781Swnj * Usage is: 592781Swnj * printf("reg=%b\n", regval, "<base><arg>*"); 602781Swnj * Where <base> is the output base expressed as a control character, 612781Swnj * e.g. \10 gives octal; \20 gives hex. Each arg is a sequence of 622781Swnj * characters, the first of which gives the bit number to be inspected 632781Swnj * (origin 1), and the next characters (up to a control character, i.e. 642781Swnj * a character <= 32), give the name of the register. Thus 652781Swnj * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 662781Swnj * would produce output: 6717594Skarels * reg=3<BITTWO,BITONE> 6834478Skarels * 6934478Skarels * Another additional format: %r is used to pass an additional format string 7034478Skarels * and argument list recursively. Usage is typically: 7134478Skarels * 7234478Skarels * fn(otherstuff, fmt [, arg1, ... ] ) 7334478Skarels * char *fmt; 7434478Skarels * u_int arg1, ...; 7534478Skarels * 7634478Skarels * printf("prefix: %r, other stuff\n", fmt, &arg1); 7731Sbill */ 7829946Skarels 79*48426Skarels int consintr = 1; /* ok to handle console interrupts? */ 80*48426Skarels 8131Sbill /*VARARGS1*/ 8247540Skarels printf(fmt, args) 832781Swnj char *fmt; 8447540Skarels unsigned args; 8531Sbill { 8629946Skarels register int savintr; 87285Sbill 8829946Skarels savintr = consintr, consintr = 0; /* disable interrupts */ 8947540Skarels prf(fmt, &args, TOCONS | TOLOG, (struct tty *)NULL); 9041972Smckusick if (!panicstr) 9141972Smckusick logwakeup(); 9229946Skarels consintr = savintr; /* reenable interrupts */ 93285Sbill } 94285Sbill 952377Swnj /* 9639560Smarc * Uprintf prints to the controlling terminal for the current process. 9725389Skarels * It may block if the tty queue is overfull. 9830695Skarels * No message is printed if the queue does not clear 9930695Skarels * in a reasonable time. 1002377Swnj */ 1012377Swnj /*VARARGS1*/ 10247540Skarels uprintf(fmt, args) 1032781Swnj char *fmt; 10447540Skarels unsigned args; 105285Sbill { 10647540Skarels register struct proc *p = curproc; 107285Sbill 10844386Smarc if (p->p_flag & SCTTY && p->p_session->s_ttyvp) 10947540Skarels prf(fmt, &args, TOTTY, p->p_session->s_ttyp); 110285Sbill } 111285Sbill 11244386Smarc tpr_t 113*48426Skarels tprintf_open(p) 114*48426Skarels register struct proc *p; 11544386Smarc { 11644386Smarc 11744386Smarc if (p->p_flag & SCTTY && p->p_session->s_ttyvp) { 11844386Smarc SESSHOLD(p->p_session); 119*48426Skarels return ((tpr_t) p->p_session); 12044386Smarc } else 121*48426Skarels return ((tpr_t) NULL); 12244386Smarc } 12344386Smarc 124*48426Skarels void 12544386Smarc tprintf_close(sess) 12644386Smarc tpr_t sess; 12744386Smarc { 12844386Smarc if (sess) 129*48426Skarels SESSRELE((struct session *) sess); 13044386Smarc } 13144386Smarc 13218364Skarels /* 13344386Smarc * tprintf prints on the controlling terminal associated 13444386Smarc * with the given session. 13518364Skarels */ 13616724Sralph /*VARARGS2*/ 137*48426Skarels tprintf(tpr, fmt, args) 138*48426Skarels tpr_t tpr; 13916724Sralph char *fmt; 14047540Skarels unsigned args; 14116724Sralph { 142*48426Skarels register struct session *sess = (struct session *)tpr; 143*48426Skarels struct tty *tp = NULL; 14444386Smarc int flags = TOLOG; 14516724Sralph 14625389Skarels logpri(LOG_INFO); 14739560Smarc 148*48426Skarels if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) { 14944386Smarc flags |= TOTTY; 150*48426Skarels tp = sess->s_ttyp; 151*48426Skarels } 152*48426Skarels prf(fmt, &args, flags, tp); 15325389Skarels logwakeup(); 15416724Sralph } 15516724Sralph 156*48426Skarels extern int log_open; 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*/ 16447540Skarels log(level, fmt, args) 16516724Sralph char *fmt; 16647540Skarels unsigned args; 16716724Sralph { 16816724Sralph register s = splhigh(); 16916724Sralph 17025389Skarels logpri(level); 17147540Skarels prf(fmt, &args, TOLOG, (struct tty *)NULL); 17216724Sralph splx(s); 17318364Skarels if (!log_open) 17447540Skarels prf(fmt, &args, TOCONS, (struct tty *)NULL); 17516724Sralph logwakeup(); 17616724Sralph } 17716724Sralph 17825389Skarels logpri(level) 17925389Skarels int level; 18025389Skarels { 18125389Skarels 18244386Smarc putchar('<', TOLOG, (struct tty *)NULL); 18344386Smarc printn((u_long)level, 10, TOLOG, (struct tty *)NULL); 18444386Smarc putchar('>', TOLOG, (struct tty *)NULL); 18525389Skarels } 18625389Skarels 18733479Skarels /*VARARGS1*/ 18847540Skarels addlog(fmt, args) 18933479Skarels char *fmt; 19047540Skarels unsigned args; 19133479Skarels { 19233479Skarels register s = splhigh(); 19333479Skarels 19447540Skarels prf(fmt, &args, TOLOG, (struct tty *)NULL); 19533479Skarels splx(s); 19633479Skarels if (!log_open) 19747540Skarels prf(fmt, &args, TOCONS, (struct tty *)NULL); 19833479Skarels logwakeup(); 19933479Skarels } 20033479Skarels 20147540Skarels prf(fmt, argp, flags, ttyp) 2022781Swnj register char *fmt; 20347540Skarels register u_int *argp; 20444386Smarc struct tty *ttyp; 205285Sbill { 2062434Swnj register int b, c, i; 20731Sbill char *s; 2082678Swnj int any; 20931Sbill 21031Sbill loop: 2112377Swnj while ((c = *fmt++) != '%') { 21216724Sralph if (c == '\0') 21331Sbill return; 21444386Smarc putchar(c, flags, ttyp); 21531Sbill } 2162377Swnj again: 21731Sbill c = *fmt++; 21829946Skarels /* THIS CODE IS MACHINE DEPENDENT IN HANDLING %l? AND %c */ 2192377Swnj switch (c) { 2202377Swnj 2212377Swnj case 'l': 2222377Swnj goto again; 2232377Swnj case 'x': case 'X': 2242377Swnj b = 16; 2252377Swnj goto number; 2262377Swnj case 'd': case 'D': 22729946Skarels b = -10; 22829946Skarels goto number; 22929946Skarels case 'u': 2302377Swnj b = 10; 2312377Swnj goto number; 2322377Swnj case 'o': case 'O': 2332377Swnj b = 8; 2342377Swnj number: 23547540Skarels printn((u_long)*argp, b, flags, ttyp); 2362377Swnj break; 2372377Swnj case 'c': 23847540Skarels b = *argp; 23933479Skarels #if BYTE_ORDER == LITTLE_ENDIAN 2402434Swnj for (i = 24; i >= 0; i -= 8) 2412434Swnj if (c = (b >> i) & 0x7f) 24244386Smarc putchar(c, flags, ttyp); 24329946Skarels #endif 24433479Skarels #if BYTE_ORDER == BIG_ENDIAN 24529946Skarels if (c = (b & 0x7f)) 24644386Smarc putchar(c, flags, ttyp); 24729946Skarels #endif 2482377Swnj break; 2492678Swnj case 'b': 25047540Skarels b = *argp++; 25147540Skarels s = (char *)*argp; 25244386Smarc printn((u_long)b, *s++, flags, ttyp); 2532678Swnj any = 0; 2542678Swnj if (b) { 2552678Swnj while (i = *s++) { 2562678Swnj if (b & (1 << (i-1))) { 25744386Smarc putchar(any ? ',' : '<', flags, ttyp); 2582678Swnj any = 1; 2592678Swnj for (; (c = *s) > 32; s++) 26044386Smarc putchar(c, flags, ttyp); 2612678Swnj } else 2622678Swnj for (; *s > 32; s++) 2632678Swnj ; 2642678Swnj } 2653878Swnj if (any) 26644386Smarc putchar('>', flags, ttyp); 2672678Swnj } 2682678Swnj break; 2692678Swnj 2702377Swnj case 's': 27147540Skarels s = (char *)*argp; 272285Sbill while (c = *s++) 27344386Smarc putchar(c, flags, ttyp); 2742377Swnj break; 2753736Sroot 27633479Skarels case 'r': 27747540Skarels s = (char *)*argp++; 27847540Skarels prf(s, (u_int *)*argp, flags, ttyp); 27933479Skarels break; 28033479Skarels 2813736Sroot case '%': 28244386Smarc putchar('%', flags, ttyp); 2833736Sroot break; 28431Sbill } 28547540Skarels argp++; 28631Sbill goto loop; 28731Sbill } 28831Sbill 2892781Swnj /* 2902781Swnj * Printn prints a number n in base b. 29147540Skarels * We avoid recursion to avoid deep kernel stacks. 2922781Swnj */ 29344386Smarc printn(n, b, flags, ttyp) 2943101Swnj u_long n; 29544386Smarc struct tty *ttyp; 29631Sbill { 2972434Swnj char prbuf[11]; 2982377Swnj register char *cp; 29931Sbill 30029946Skarels if (b == -10) { 30129946Skarels if ((int)n < 0) { 30244386Smarc putchar('-', flags, ttyp); 30329946Skarels n = (unsigned)(-(int)n); 30429946Skarels } 30529946Skarels b = -b; 30631Sbill } 3072434Swnj cp = prbuf; 3082377Swnj do { 3092377Swnj *cp++ = "0123456789abcdef"[n%b]; 3102377Swnj n /= b; 3112377Swnj } while (n); 3122377Swnj do 31344386Smarc putchar(*--cp, flags, ttyp); 3142434Swnj while (cp > prbuf); 31531Sbill } 31631Sbill 31731Sbill /* 3181184Sbill * Panic is called on unresolvable fatal errors. 3192781Swnj * It prints "panic: mesg", and then reboots. 3202781Swnj * If we are called twice, then we avoid trying to 3212781Swnj * sync the disks as this often leads to recursive panics. 32231Sbill */ 32331Sbill panic(s) 3242781Swnj char *s; 32531Sbill { 32630566Skarels int bootopt = RB_AUTOBOOT | RB_DUMP; 3272377Swnj 3285416Swnj if (panicstr) 3295416Swnj bootopt |= RB_NOSYNC; 33047540Skarels else 3319758Ssam panicstr = s; 3323285Swnj printf("panic: %s\n", s); 33347540Skarels #ifdef KGDB 33447540Skarels kgdb_panic(); 33547540Skarels #endif 33635282Skarels #ifdef KADB 33730625Skarels if (boothowto & RB_KDB) { 33834420Skarels int x = splnet(); /* below kdb pri */ 33930625Skarels 34030625Skarels setsoftkdb(); 34134420Skarels splx(x); 34230625Skarels } 34330625Skarels #endif 34430566Skarels boot(bootopt); 34531Sbill } 34631Sbill 34731Sbill /* 3482941Swnj * Warn that a system table is full. 3492941Swnj */ 3502941Swnj tablefull(tab) 3512941Swnj char *tab; 3522941Swnj { 3532941Swnj 35424839Seric log(LOG_ERR, "%s: table is full\n", tab); 3552941Swnj } 3562941Swnj 3572941Swnj /* 3582377Swnj * Print a character on console or users terminal. 359285Sbill * If destination is console then the last MSGBUFS characters 360285Sbill * are saved in msgbuf for inspection later. 361285Sbill */ 3621785Sbill /*ARGSUSED*/ 36344386Smarc putchar(c, flags, ttyp) 3642377Swnj register int c; 36544386Smarc struct tty *ttyp; 366285Sbill { 36745733Smckusick register struct msgbuf *mbp = msgbufp; 36833479Skarels extern int msgbufmapped; 369285Sbill 37030549Skarels if (panicstr) 37130549Skarels constty = 0; 37244386Smarc if ((flags & TOCONS) && ttyp == NULL && constty) { 37344386Smarc ttyp = constty; 37430549Skarels flags |= TOTTY; 37530549Skarels } 37644386Smarc if ((flags & TOTTY) && ttyp && tputchar(c, ttyp) < 0 && 37744386Smarc (flags & TOCONS) && ttyp == constty) 37839560Smarc constty = 0; 37933479Skarels if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177 && 38033479Skarels msgbufmapped) { 38145733Smckusick if (mbp->msg_magic != MSG_MAGIC) { 38212494Ssam register int i; 38312494Ssam 38445733Smckusick mbp->msg_magic = MSG_MAGIC; 38545733Smckusick mbp->msg_bufx = mbp->msg_bufr = 0; 38612494Ssam for (i=0; i < MSG_BSIZE; i++) 38745733Smckusick mbp->msg_bufc[i] = 0; 3882172Swnj } 38945733Smckusick mbp->msg_bufc[mbp->msg_bufx++] = c; 39045733Smckusick if (mbp->msg_bufx < 0 || mbp->msg_bufx >= MSG_BSIZE) 39145733Smckusick mbp->msg_bufx = 0; 392285Sbill } 39330549Skarels if ((flags & TOCONS) && constty == 0 && c != '\0') 39430549Skarels (*v_putc)(c); 395285Sbill } 396