home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / kern / subr_prf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-29  |  12.9 KB  |  593 lines

  1. /*-
  2.  * Copyright (c) 1986, 1988, 1991 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  *
  33.  *    @(#)subr_prf.c    7.30 (Berkeley) 6/29/91
  34.  */
  35.  
  36. #include "param.h"
  37. #include "systm.h"
  38. #include "buf.h"
  39. #include "conf.h"
  40. #include "reboot.h"
  41. #include "msgbuf.h"
  42. #include "proc.h"
  43. #include "ioctl.h"
  44. #include "vnode.h"
  45. #include "file.h"
  46. #include "tty.h"
  47. #include "tprintf.h"
  48. #include "syslog.h"
  49. #include "malloc.h"
  50.  
  51. /*
  52.  * Note that stdarg.h and the ANSI style va_start macro is used for both
  53.  * ANSI and traditional C compilers.
  54.  */
  55. #include <machine/stdarg.h>
  56.  
  57. #ifdef KADB
  58. #include "machine/kdbparam.h"
  59. #endif
  60.  
  61. #define TOCONS    0x01
  62. #define TOTTY    0x02
  63. #define TOLOG    0x04
  64.  
  65. struct    tty *constty;            /* pointer to console "window" tty */
  66.  
  67. #ifdef KADB
  68. extern    cngetc();            /* standard console getc */
  69. int    (*v_getc)() = cngetc;        /* "" getc from virtual console */
  70. extern    cnpoll();
  71. int    (*v_poll)() = cnpoll;        /* kdb hook to enable input polling */
  72. #endif
  73. extern    cnputc();            /* standard console putc */
  74. int    (*v_putc)() = cnputc;        /* routine to putc on virtual console */
  75.  
  76. static void  logpri __P((int level));
  77. static void  putchar __P((int ch, int flags, struct tty *tp));
  78. static char *ksprintn __P((u_long num, int base, int *len));
  79. void  kprintf __P((const char *fmt, int flags, struct tty *tp, va_list));
  80.  
  81. /*
  82.  * Variable panicstr contains argument to first call to panic; used
  83.  * as flag to indicate that the kernel has already called panic.
  84.  */
  85. char    *panicstr;
  86.  
  87. /*
  88.  * Panic is called on unresolvable fatal errors.  It prints "panic: mesg",
  89.  * and then reboots.  If we are called twice, then we avoid trying to sync
  90.  * the disks as this often leads to recursive panics.
  91.  */
  92. void
  93. panic(msg)
  94.     char *msg;
  95. {
  96.     int bootopt = RB_AUTOBOOT | RB_DUMP;
  97.  
  98.     if (panicstr)
  99.         bootopt |= RB_NOSYNC;
  100.     else
  101.         panicstr = msg;
  102.     printf("panic: %s\n", msg);
  103. #ifdef KGDB
  104.     kgdb_panic();
  105. #endif
  106. #ifdef KADB
  107.     if (boothowto & RB_KDB) {
  108.         int s;
  109.  
  110.         s = splnet();    /* below kdb pri */
  111.         setsoftkdb();
  112.         splx(s);
  113.     }
  114. #endif
  115.     boot(bootopt);
  116. }
  117.  
  118. /*
  119.  * Warn that a system table is full.
  120.  */
  121. void
  122. tablefull(tab)
  123.     char *tab;
  124. {
  125.  
  126.     log(LOG_ERR, "%s: table is full\n", tab);
  127. }
  128.  
  129. /*
  130.  * Uprintf prints to the controlling terminal for the current process.
  131.  * It may block if the tty queue is overfull.  No message is printed if
  132.  * the queue does not clear in a reasonable time.
  133.  */
  134. void
  135. #ifdef __STDC__
  136. uprintf(const char *fmt, ...)
  137. #else
  138. uprintf(fmt /*, va_alist */)
  139.     char *fmt;
  140. #endif
  141. {
  142.     register struct proc *p = curproc;
  143.     va_list ap;
  144.  
  145.     if (p->p_flag & SCTTY && p->p_session->s_ttyvp) {
  146.         va_start(ap, fmt);
  147.         kprintf(fmt, TOTTY, p->p_session->s_ttyp, ap);
  148.         va_end(ap);
  149.     }
  150. }
  151.  
  152. tpr_t
  153. tprintf_open(p)
  154.     register struct proc *p;
  155. {
  156.  
  157.     if (p->p_flag & SCTTY && p->p_session->s_ttyvp) {
  158.         SESSHOLD(p->p_session);
  159.         return ((tpr_t) p->p_session);
  160.     }
  161.     return ((tpr_t) NULL);
  162. }
  163.  
  164. void
  165. tprintf_close(sess)
  166.     tpr_t sess;
  167. {
  168.  
  169.     if (sess)
  170.         SESSRELE((struct session *) sess);
  171. }
  172.  
  173. /*
  174.  * tprintf prints on the controlling terminal associated
  175.  * with the given session.
  176.  */
  177. void
  178. #ifdef __STDC__
  179. tprintf(tpr_t tpr, const char *fmt, ...)
  180. #else
  181. tprintf(tpr, fmt /*, va_alist */)
  182.     tpr_t tpr;
  183.     char *fmt;
  184. #endif
  185. {
  186.     register struct session *sess = (struct session *)tpr;
  187.     struct tty *tp = NULL;
  188.     int flags = TOLOG;
  189.     va_list ap;
  190.  
  191.     logpri(LOG_INFO);
  192.     if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) {
  193.         flags |= TOTTY;
  194.         tp = sess->s_ttyp;
  195.     }
  196.     va_start(ap, fmt);
  197.     kprintf(fmt, flags, tp, ap);
  198.     va_end(ap);
  199.     logwakeup();
  200. }
  201.  
  202. /*
  203.  * Ttyprintf displays a message on a tty; it should be used only by
  204.  * the tty driver, or anything that knows the underlying tty will not
  205.  * be revoke(2)'d away.  Other callers should use tprintf.
  206.  */
  207. void
  208. #ifdef __STDC__
  209. ttyprintf(struct tty *tp, const char *fmt, ...)
  210. #else
  211. ttyprintf(tp, fmt /*, va_alist */)
  212.     struct tty *tp;
  213.     char *fmt;
  214. #endif
  215. {
  216.     va_list ap;
  217.  
  218.     va_start(ap, fmt);
  219.     kprintf(fmt, TOTTY, tp, ap);
  220.     va_end(ap);
  221. }
  222.  
  223. extern    int log_open;
  224.  
  225. /*
  226.  * Log writes to the log buffer, and guarantees not to sleep (so can be
  227.  * called by interrupt routines).  If there is no process reading the
  228.  * log yet, it writes to the console also.
  229.  */
  230. void
  231. #ifdef __STDC__
  232. log(int level, const char *fmt, ...)
  233. #else
  234. log(level, fmt /*, va_alist */)
  235.     int level;
  236.     char *fmt;
  237. #endif
  238. {
  239.     register int s;
  240.     va_list ap;
  241.  
  242.     s = splhigh();
  243.     logpri(level);
  244.     va_start(ap, fmt);
  245.     kprintf(fmt, TOLOG, NULL, ap);
  246.     splx(s);
  247.     va_end(ap);
  248.     if (!log_open) {
  249.         va_start(ap, fmt);
  250.         kprintf(fmt, TOCONS, NULL, ap);
  251.         va_end(ap);
  252.     }
  253.     logwakeup();
  254. }
  255.  
  256. static void
  257. logpri(level)
  258.     int level;
  259. {
  260.     register int ch;
  261.     register char *p;
  262.  
  263.     putchar('<', TOLOG, NULL);
  264.     for (p = ksprintn((u_long)level, 10, NULL); ch = *p--;)
  265.         putchar(ch, TOLOG, NULL);
  266.     putchar('>', TOLOG, NULL);
  267. }
  268.  
  269. void
  270. #ifdef __STDC__
  271. addlog(const char *fmt, ...)
  272. #else
  273. addlog(fmt /*, va_alist */)
  274.     char *fmt;
  275. #endif
  276. {
  277.     register int s;
  278.     va_list ap;
  279.  
  280.     s = splhigh();
  281.     va_start(ap, fmt);
  282.     kprintf(fmt, TOLOG, NULL, ap);
  283.     splx(s);
  284.     va_end(ap);
  285.     if (!log_open) {
  286.         va_start(ap, fmt);
  287.         kprintf(fmt, TOCONS, NULL, ap);
  288.         va_end(ap);
  289.     }
  290.     logwakeup();
  291. }
  292.  
  293. int    consintr = 1;            /* ok to handle console interrupts? */
  294.  
  295. void
  296. #ifdef __STDC__
  297. printf(const char *fmt, ...)
  298. #else
  299. printf(fmt /*, va_alist */)
  300.     char *fmt;
  301. #endif
  302. {
  303.     va_list ap;
  304.     register int savintr;
  305.  
  306.     savintr = consintr;        /* disable interrupts */
  307.     consintr = 0;
  308.     va_start(ap, fmt);
  309.     kprintf(fmt, TOCONS | TOLOG, NULL, ap);
  310.     va_end(ap);
  311.     if (!panicstr)
  312.         logwakeup();
  313.     consintr = savintr;        /* reenable interrupts */
  314. }
  315.  
  316. /*
  317.  * Scaled down version of printf(3).
  318.  *
  319.  * Two additional formats:
  320.  *
  321.  * The format %b is supported to decode error registers.
  322.  * Its usage is:
  323.  *
  324.  *    printf("reg=%b\n", regval, "<base><arg>*");
  325.  *
  326.  * where <base> is the output base expressed as a control character, e.g.
  327.  * \10 gives octal; \20 gives hex.  Each arg is a sequence of characters,
  328.  * the first of which gives the bit number to be inspected (origin 1), and
  329.  * the next characters (up to a control character, i.e. a character <= 32),
  330.  * give the name of the register.  Thus:
  331.  *
  332.  *    printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
  333.  *
  334.  * would produce output:
  335.  *
  336.  *    reg=3<BITTWO,BITONE>
  337.  *
  338.  * The format %r is supposed to pass an additional format string and argument
  339.  * list recursively.
  340.  * Its usage is:
  341.  *
  342.  * fn(otherstuff, char *fmt, ...)
  343.  * {
  344.  *    va_list ap;
  345.  *    va_start(ap, fmt);
  346.  *    printf("prefix: %r, other stuff\n", fmt, ap);
  347.  *    va_end(ap);
  348.  *
  349.  * Space or zero padding and a field width are supported for the numeric
  350.  * formats only.
  351.  */
  352. void
  353. kprintf(fmt, flags, tp, ap)
  354.     register const char *fmt;
  355.     int flags;
  356.     struct tty *tp;
  357.     va_list ap;
  358. {
  359.     register char *p;
  360.     register int ch, n;
  361.     u_long ul;
  362.     int base, lflag, tmp, width;
  363.     char padc;
  364.  
  365.     for (;;) {
  366.         padc = ' ';
  367.         width = 0;
  368.         while ((ch = *(u_char *)fmt++) != '%') {
  369.             if (ch == '\0')
  370.                 return;
  371.             putchar(ch, flags, tp);
  372.         }
  373.         lflag = 0;
  374. reswitch:    switch (ch = *(u_char *)fmt++) {
  375.         case '0':
  376.             padc = '0';
  377.             goto reswitch;
  378.         case '1': case '2': case '3': case '4':
  379.         case '5': case '6': case '7': case '8': case '9':
  380.             for (width = 0;; ++fmt) {
  381.                 width = width * 10 + ch - '0';
  382.                 ch = *fmt;
  383.                 if (ch < '0' || ch > '9')
  384.                     break;
  385.             }
  386.             goto reswitch;
  387.         case 'l':
  388.             lflag = 1;
  389.             goto reswitch;
  390.         case 'b':
  391.             ul = va_arg(ap, int);
  392.             p = va_arg(ap, char *);
  393.             for (p = ksprintn(ul, *p++, NULL); ch = *p--;)
  394.                 putchar(ch, flags, tp);
  395.  
  396.             if (!ul)
  397.                 break;
  398.  
  399.             for (tmp = 0; n = *p++;) {
  400.                 if (ul & (1 << (n - 1))) {
  401.                     putchar(tmp ? ',' : '<', flags, tp);
  402.                     for (; (n = *p) > ' '; ++p)
  403.                         putchar(n, flags, tp);
  404.                     tmp = 1;
  405.                 } else
  406.                     for (; *p > ' '; ++p);
  407.             }
  408.             if (tmp)
  409.                 putchar('>', flags, tp);
  410.             break;
  411.         case 'c':
  412.             putchar(va_arg(ap, int), flags, tp);
  413.             break;
  414.         case 'r':
  415.             p = va_arg(ap, char *);
  416.             kprintf(p, flags, tp, va_arg(ap, va_list));
  417.             break;
  418.         case 's':
  419.             p = va_arg(ap, char *);
  420.             while (ch = *p++)
  421.                 putchar(ch, flags, tp);
  422.             break;
  423.         case 'd':
  424.             ul = lflag ? va_arg(ap, long) : va_arg(ap, int);
  425.             if ((long)ul < 0) {
  426.                 putchar('-', flags, tp);
  427.                 ul = -(long)ul;
  428.             }
  429.             base = 10;
  430.             goto number;
  431.         case 'o':
  432.             ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
  433.             base = 8;
  434.             goto number;
  435.         case 'u':
  436.             ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
  437.             base = 10;
  438.             goto number;
  439.         case 'x':
  440.             ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
  441.             base = 16;
  442. number:            p = ksprintn(ul, base, &tmp);
  443.             if (width && (width -= tmp) > 0)
  444.                 while (width--)
  445.                     putchar(padc, flags, tp);
  446.             while (ch = *p--)
  447.                 putchar(ch, flags, tp);
  448.             break;
  449.         default:
  450.             putchar('%', flags, tp);
  451.             if (lflag)
  452.                 putchar('l', flags, tp);
  453.             /* FALLTHROUGH */
  454.         case '%':
  455.             putchar(ch, flags, tp);
  456.         }
  457.     }
  458. }
  459.  
  460. /*
  461.  * Print a character on console or users terminal.  If destination is
  462.  * the console then the last MSGBUFS characters are saved in msgbuf for
  463.  * inspection later.
  464.  */
  465. static void
  466. putchar(c, flags, tp)
  467.     register int c;
  468.     int flags;
  469.     struct tty *tp;
  470. {
  471.     extern int msgbufmapped;
  472.     register struct msgbuf *mbp;
  473.  
  474.     if (panicstr)
  475.         constty = NULL;
  476.     if ((flags & TOCONS) && tp == NULL && constty) {
  477.         tp = constty;
  478.         flags |= TOTTY;
  479.     }
  480.     if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 &&
  481.         (flags & TOCONS) && tp == constty)
  482.         constty = NULL;
  483.     if ((flags & TOLOG) &&
  484.         c != '\0' && c != '\r' && c != 0177 && msgbufmapped) {
  485.         mbp = msgbufp;
  486.         if (mbp->msg_magic != MSG_MAGIC) {
  487.             bzero((caddr_t)mbp, sizeof(*mbp));
  488.             mbp->msg_magic = MSG_MAGIC;
  489.         }
  490.         mbp->msg_bufc[mbp->msg_bufx++] = c;
  491.         if (mbp->msg_bufx < 0 || mbp->msg_bufx >= MSG_BSIZE)
  492.             mbp->msg_bufx = 0;
  493.     }
  494.     if ((flags & TOCONS) && constty == NULL && c != '\0')
  495.         (*v_putc)(c);
  496. }
  497.  
  498. /*
  499.  * Scaled down version of sprintf(3).
  500.  */
  501. #ifdef __STDC__
  502. sprintf(char *buf, const char *cfmt, ...)
  503. #else
  504. sprintf(buf, cfmt /*, va_alist */)
  505.     char *buf, *cfmt;
  506. #endif
  507. {
  508.     register const char *fmt = cfmt;
  509.     register char *p, *bp;
  510.     register int ch, base;
  511.     u_long ul;
  512.     int lflag;
  513.     va_list ap;
  514.  
  515.     va_start(ap, cfmt);
  516.     for (bp = buf; ; ) {
  517.         while ((ch = *(u_char *)fmt++) != '%')
  518.             if ((*bp++ = ch) == '\0')
  519.                 return ((bp - buf) - 1);
  520.  
  521.         lflag = 0;
  522. reswitch:    switch (ch = *(u_char *)fmt++) {
  523.         case 'l':
  524.             lflag = 1;
  525.             goto reswitch;
  526.         case 'c':
  527.             *bp++ = va_arg(ap, int);
  528.             break;
  529.         case 's':
  530.             p = va_arg(ap, char *);
  531.             while (*bp++ = *p++)
  532.                 ;
  533.             --bp;
  534.             break;
  535.         case 'd':
  536.             ul = lflag ? va_arg(ap, long) : va_arg(ap, int);
  537.             if ((long)ul < 0) {
  538.                 *bp++ = '-';
  539.                 ul = -(long)ul;
  540.             }
  541.             base = 10;
  542.             goto number;
  543.             break;
  544.         case 'o':
  545.             ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
  546.             base = 8;
  547.             goto number;
  548.             break;
  549.         case 'u':
  550.             ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
  551.             base = 10;
  552.             goto number;
  553.             break;
  554.         case 'x':
  555.             ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
  556.             base = 16;
  557. number:            for (p = ksprintn(ul, base, NULL); ch = *p--;)
  558.                 *bp++ = ch;
  559.             break;
  560.         default:
  561.             *bp++ = '%';
  562.             if (lflag)
  563.                 *bp++ = 'l';
  564.             /* FALLTHROUGH */
  565.         case '%':
  566.             *bp++ = ch;
  567.         }
  568.     }
  569.     va_end(ap);
  570. }
  571.  
  572. /*
  573.  * Put a number (base <= 16) in a buffer in reverse order; return an
  574.  * optional length and a pointer to the NULL terminated (preceded?)
  575.  * buffer.
  576.  */
  577. static char *
  578. ksprintn(ul, base, lenp)
  579.     register u_long ul;
  580.     register int base, *lenp;
  581. {                    /* A long in base 8, plus NULL. */
  582.     static char buf[sizeof(long) * NBBY / 3 + 2];
  583.     register char *p;
  584.  
  585.     p = buf;
  586.     do {
  587.         *++p = "0123456789abcdef"[ul % base];
  588.     } while (ul /= base);
  589.     if (lenp)
  590.         *lenp = p - buf;
  591.     return (p);
  592. }
  593.