The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/subr_prf.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 79930d86fc6679a4d74284e8a3ba125a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.