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$
   40  */
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/kernel.h>
   45 #include <sys/msgbuf.h>
   46 #include <sys/malloc.h>
   47 #include <sys/proc.h>
   48 #include <sys/tty.h>
   49 #include <sys/tprintf.h>
   50 #include <sys/syslog.h>
   51 #include <sys/cons.h>
   52 #include <sys/uio.h>
   53 #include <sys/sysctl.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 /* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */
   66 #define MAXNBUF (sizeof(quad_t) * NBBY + 1)
   67 
   68 struct putchar_arg {
   69         int     flags;
   70         int     pri;
   71         struct  tty *tty;
   72 };
   73 
   74 struct snprintf_arg {
   75         char    *str;
   76         size_t  remain;
   77 };
   78 
   79 extern  int log_open;
   80 
   81 struct  tty *constty;                   /* pointer to console "window" tty */
   82 
   83 static void (*v_putc)(int) = cnputc;    /* routine to putc on virtual console */
   84 static void  msglogchar(int c, int pri);
   85 static void  msgaddchar(int c, void *dummy);
   86 static void  putchar __P((int ch, void *arg));
   87 static char *ksprintn __P((char *nbuf, u_long num, int base, int *len));
   88 static char *ksprintqn __P((char *nbuf, u_quad_t num, int base, int *len));
   89 static void  snprintf_func __P((int ch, void *arg));
   90 
   91 static int consintr = 1;                /* Ok to handle console interrupts? */
   92 static int msgbufmapped;                /* Set when safe to use msgbuf */
   93 int msgbuftrigger;
   94 
   95 static int      log_console_output = 1;
   96 TUNABLE_INT("kern.log_console_output", &log_console_output);
   97 SYSCTL_INT(_kern, OID_AUTO, log_console_output, CTLFLAG_RW,
   98     &log_console_output, 0, "");
   99 
  100 /*
  101  * Warn that a system table is full.
  102  */
  103 void
  104 tablefull(const char *tab)
  105 {
  106 
  107         log(LOG_ERR, "%s: table is full\n", tab);
  108 }
  109 
  110 /*
  111  * Uprintf prints to the controlling terminal for the current process.
  112  * It may block if the tty queue is overfull.  No message is printed if
  113  * the queue does not clear in a reasonable time.
  114  */
  115 int
  116 uprintf(const char *fmt, ...)
  117 {
  118         struct proc *p = curproc;
  119         va_list ap;
  120         struct putchar_arg pca;
  121         int retval = 0;
  122 
  123         if (p && p->p_flag & P_CONTROLT &&
  124             p->p_session->s_ttyvp) {
  125                 va_start(ap, fmt);
  126                 pca.tty = p->p_session->s_ttyp;
  127                 pca.flags = TOTTY;
  128                 retval = kvprintf(fmt, putchar, &pca, 10, ap);
  129                 va_end(ap);
  130         }
  131         return retval;
  132 }
  133 
  134 tpr_t
  135 tprintf_open(p)
  136         register struct proc *p;
  137 {
  138 
  139         if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
  140                 SESSHOLD(p->p_session);
  141                 return ((tpr_t) p->p_session);
  142         }
  143         return ((tpr_t) NULL);
  144 }
  145 
  146 void
  147 tprintf_close(sess)
  148         tpr_t sess;
  149 {
  150 
  151         if (sess)
  152                 SESSRELE((struct session *) sess);
  153 }
  154 
  155 /*
  156  * tprintf prints on the controlling terminal associated
  157  * with the given session.
  158  */
  159 int
  160 tprintf(tpr_t tpr, const char *fmt, ...)
  161 {
  162         register struct session *sess = (struct session *)tpr;
  163         struct tty *tp = NULL;
  164         int flags = TOLOG;
  165         va_list ap;
  166         struct putchar_arg pca;
  167         int retval;
  168 
  169         if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) {
  170                 flags |= TOTTY;
  171                 tp = sess->s_ttyp;
  172         }
  173         va_start(ap, fmt);
  174         pca.tty = tp;
  175         pca.flags = flags;
  176         pca.pri = LOG_INFO;
  177         retval = kvprintf(fmt, putchar, &pca, 10, ap);
  178         va_end(ap);
  179         msgbuftrigger = 1;
  180         return retval;
  181 }
  182 
  183 /*
  184  * Ttyprintf displays a message on a tty; it should be used only by
  185  * the tty driver, or anything that knows the underlying tty will not
  186  * be revoke(2)'d away.  Other callers should use tprintf.
  187  */
  188 int
  189 ttyprintf(struct tty *tp, const char *fmt, ...)
  190 {
  191         va_list ap;
  192         struct putchar_arg pca;
  193         int retval;
  194 
  195         va_start(ap, fmt);
  196         pca.tty = tp;
  197         pca.flags = TOTTY;
  198         retval = kvprintf(fmt, putchar, &pca, 10, ap);
  199         va_end(ap);
  200         return retval;
  201 }
  202 
  203 /*
  204  * Log writes to the log buffer, and guarantees not to sleep (so can be
  205  * called by interrupt routines).  If there is no process reading the
  206  * log yet, it writes to the console also.
  207  */
  208 int
  209 log(int level, const char *fmt, ...)
  210 {
  211         va_list ap;
  212         int retval;
  213         struct putchar_arg pca;
  214 
  215         pca.tty = NULL;
  216         pca.pri = level;
  217         pca.flags = log_open ? TOLOG : TOCONS;
  218 
  219         va_start(ap, fmt);
  220         retval = kvprintf(fmt, putchar, &pca, 10, ap);
  221         va_end(ap);
  222 
  223         msgbuftrigger = 1;
  224         return (retval);
  225 }
  226 
  227 int
  228 addlog(const char *fmt, ...)
  229 {
  230         va_list ap;
  231         int retval;
  232         struct putchar_arg pca;
  233 
  234         pca.tty = NULL;
  235         pca.pri = -1;
  236         pca.flags = log_open ? TOLOG : TOCONS;
  237 
  238         va_start(ap, fmt);
  239         retval = kvprintf(fmt, putchar, &pca, 10, ap);
  240         va_end(ap);
  241 
  242         msgbuftrigger = 1;
  243         return (retval);
  244 }
  245 
  246 #define CONSCHUNK 128
  247 
  248 void
  249 log_console(struct uio *uio)
  250 {
  251         int c, i, error, iovlen, nl;
  252         struct uio muio;
  253         struct iovec *miov = NULL;
  254         char *consbuffer;
  255         int pri;
  256 
  257         if (!log_console_output)
  258                 return;
  259 
  260         pri = LOG_INFO | LOG_CONSOLE;
  261         muio = *uio;
  262         iovlen = uio->uio_iovcnt * sizeof (struct iovec);
  263         MALLOC(miov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
  264         MALLOC(consbuffer, char *, CONSCHUNK, M_TEMP, M_WAITOK);
  265         bcopy((caddr_t)muio.uio_iov, (caddr_t)miov, iovlen);
  266         muio.uio_iov = miov;
  267         uio = &muio;
  268 
  269         nl = 0;
  270         while (uio->uio_resid > 0) {
  271                 c = imin(uio->uio_resid, CONSCHUNK);
  272                 error = uiomove(consbuffer, c, uio);
  273                 if (error != 0)
  274                         return;
  275                 for (i = 0; i < c; i++) {
  276                         msglogchar(consbuffer[i], pri);
  277                         if (consbuffer[i] == '\n')
  278                                 nl = 1;
  279                         else
  280                                 nl = 0;
  281                 }
  282         }
  283         if (!nl)
  284                 msglogchar('\n', pri);
  285         msgbuftrigger = 1;
  286         FREE(miov, M_TEMP);
  287         FREE(consbuffer, M_TEMP);
  288         return;
  289 }
  290 
  291 int
  292 printf(const char *fmt, ...)
  293 {
  294         va_list ap;
  295         int savintr;
  296         struct putchar_arg pca;
  297         int retval;
  298 
  299         savintr = consintr;             /* disable interrupts */
  300         consintr = 0;
  301         va_start(ap, fmt);
  302         pca.tty = NULL;
  303         pca.flags = TOCONS | TOLOG;
  304         pca.pri = -1;
  305         retval = kvprintf(fmt, putchar, &pca, 10, ap);
  306         va_end(ap);
  307         if (!panicstr)
  308                 msgbuftrigger = 1;
  309         consintr = savintr;             /* reenable interrupts */
  310         return retval;
  311 }
  312 
  313 int
  314 vprintf(const char *fmt, va_list ap)
  315 {
  316         int savintr;
  317         struct putchar_arg pca;
  318         int retval;
  319 
  320         savintr = consintr;             /* disable interrupts */
  321         consintr = 0;
  322         pca.tty = NULL;
  323         pca.flags = TOCONS | TOLOG;
  324         pca.pri = -1;
  325         retval = kvprintf(fmt, putchar, &pca, 10, ap);
  326         if (!panicstr)
  327                 msgbuftrigger = 1;
  328         consintr = savintr;             /* reenable interrupts */
  329         return retval;
  330 }
  331 
  332 /*
  333  * Print a character on console or users terminal.  If destination is
  334  * the console then the last bunch of characters are saved in msgbuf for
  335  * inspection later.
  336  */
  337 static void
  338 putchar(int c, void *arg)
  339 {
  340         struct putchar_arg *ap = (struct putchar_arg*) arg;
  341         int flags = ap->flags;
  342         struct tty *tp = ap->tty;
  343         if (panicstr)
  344                 constty = NULL;
  345         if ((flags & TOCONS) && tp == NULL && constty) {
  346                 tp = constty;
  347                 flags |= TOTTY;
  348         }
  349         if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 &&
  350             (flags & TOCONS) && tp == constty)
  351                 constty = NULL;
  352         if ((flags & TOLOG))
  353                 msglogchar(c, ap->pri);
  354         if ((flags & TOCONS) && constty == NULL && c != '\0')
  355                 (*v_putc)(c);
  356 }
  357 
  358 /*
  359  * Scaled down version of sprintf(3).
  360  */
  361 int
  362 sprintf(char *buf, const char *cfmt, ...)
  363 {
  364         int retval;
  365         va_list ap;
  366 
  367         va_start(ap, cfmt);
  368         retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
  369         buf[retval] = '\0';
  370         va_end(ap);
  371         return retval;
  372 }
  373 
  374 /*
  375  * Scaled down version of vsprintf(3).
  376  */
  377 int
  378 vsprintf(char *buf, const char *cfmt, va_list ap)
  379 {
  380         int retval;
  381 
  382         retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
  383         buf[retval] = '\0';
  384         return retval;
  385 }
  386 
  387 /*
  388  * Scaled down version of snprintf(3).
  389  */
  390 int
  391 snprintf(char *str, size_t size, const char *format, ...)
  392 {
  393         int retval;
  394         va_list ap;
  395 
  396         va_start(ap, format);
  397         retval = vsnprintf(str, size, format, ap);
  398         va_end(ap);
  399         return(retval);
  400 }
  401 
  402 /*
  403  * Scaled down version of vsnprintf(3).
  404  */
  405 int
  406 vsnprintf(char *str, size_t size, const char *format, va_list ap)
  407 {
  408         struct snprintf_arg info;
  409         int retval;
  410 
  411         info.str = str;
  412         info.remain = size;
  413         retval = kvprintf(format, snprintf_func, &info, 10, ap);
  414         if (info.remain >= 1)
  415                 *info.str++ = '\0';
  416         return retval;
  417 }
  418 
  419 static void
  420 snprintf_func(int ch, void *arg)
  421 {
  422         struct snprintf_arg *const info = arg;
  423 
  424         if (info->remain >= 2) {
  425                 *info->str++ = ch;
  426                 info->remain--;
  427         }
  428 }
  429 
  430 /*
  431  * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
  432  * order; return an optional length and a pointer to the last character
  433  * written in the buffer (i.e., the first character of the string).
  434  * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
  435  */
  436 static char *
  437 ksprintn(nbuf, ul, base, lenp)
  438         char *nbuf;
  439         u_long ul;
  440         int base, *lenp;
  441 {
  442         char *p;
  443 
  444         p = nbuf;
  445         *p = '\0';
  446         do {
  447                 *++p = hex2ascii(ul % base);
  448         } while (ul /= base);
  449         if (lenp)
  450                 *lenp = p - nbuf;
  451         return (p);
  452 }
  453 /* ksprintn, but for a quad_t. */
  454 static char *
  455 ksprintqn(nbuf, uq, base, lenp)
  456         char *nbuf;
  457         u_quad_t uq;
  458         int base, *lenp;
  459 {
  460         char *p;
  461 
  462         p = nbuf;
  463         *p = '\0';
  464         do {
  465                 *++p = hex2ascii(uq % base);
  466         } while (uq /= base);
  467         if (lenp)
  468                 *lenp = p - nbuf;
  469         return (p);
  470 }
  471 
  472 /*
  473  * Scaled down version of printf(3).
  474  *
  475  * Two additional formats:
  476  *
  477  * The format %b is supported to decode error registers.
  478  * Its usage is:
  479  *
  480  *      printf("reg=%b\n", regval, "<base><arg>*");
  481  *
  482  * where <base> is the output base expressed as a control character, e.g.
  483  * \10 gives octal; \20 gives hex.  Each arg is a sequence of characters,
  484  * the first of which gives the bit number to be inspected (origin 1), and
  485  * the next characters (up to a control character, i.e. a character <= 32),
  486  * give the name of the register.  Thus:
  487  *
  488  *      kvprintf("reg=%b\n", 3, "\1\2BITTWO\1BITONE\n");
  489  *
  490  * would produce output:
  491  *
  492  *      reg=3<BITTWO,BITONE>
  493  *
  494  * XXX:  %D  -- Hexdump, takes pointer and separator string:
  495  *              ("%6D", ptr, ":")   -> XX:XX:XX:XX:XX:XX
  496  *              ("%*D", len, ptr, " " -> XX XX XX XX ...
  497  */
  498 int
  499 kvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap)
  500 {
  501 #define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; }
  502         char nbuf[MAXNBUF];
  503         char *p, *q, *d;
  504         u_char *up;
  505         int ch, n;
  506         u_long ul;
  507         u_quad_t uq;
  508         int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
  509         int dwidth;
  510         char padc;
  511         int retval = 0;
  512 
  513         ul = 0;
  514         uq = 0;
  515         if (!func)
  516                 d = (char *) arg;
  517         else
  518                 d = NULL;
  519 
  520         if (fmt == NULL)
  521                 fmt = "(fmt null)\n";
  522 
  523         if (radix < 2 || radix > 36)
  524                 radix = 10;
  525 
  526         for (;;) {
  527                 padc = ' ';
  528                 width = 0;
  529                 while ((ch = (u_char)*fmt++) != '%') {
  530                         if (ch == '\0') 
  531                                 return retval;
  532                         PCHAR(ch);
  533                 }
  534                 qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
  535                 sign = 0; dot = 0; dwidth = 0;
  536 reswitch:       switch (ch = (u_char)*fmt++) {
  537                 case '.':
  538                         dot = 1;
  539                         goto reswitch;
  540                 case '#':
  541                         sharpflag = 1;
  542                         goto reswitch;
  543                 case '+':
  544                         sign = 1;
  545                         goto reswitch;
  546                 case '-':
  547                         ladjust = 1;
  548                         goto reswitch;
  549                 case '%':
  550                         PCHAR(ch);
  551                         break;
  552                 case '*':
  553                         if (!dot) {
  554                                 width = va_arg(ap, int);
  555                                 if (width < 0) {
  556                                         ladjust = !ladjust;
  557                                         width = -width;
  558                                 }
  559                         } else {
  560                                 dwidth = va_arg(ap, int);
  561                         }
  562                         goto reswitch;
  563                 case '':
  564                         if (!dot) {
  565                                 padc = '';
  566                                 goto reswitch;
  567                         }
  568                 case '1': case '2': case '3': case '4':
  569                 case '5': case '6': case '7': case '8': case '9':
  570                                 for (n = 0;; ++fmt) {
  571                                         n = n * 10 + ch - '';
  572                                         ch = *fmt;
  573                                         if (ch < '' || ch > '9')
  574                                                 break;
  575                                 }
  576                         if (dot)
  577                                 dwidth = n;
  578                         else
  579                                 width = n;
  580                         goto reswitch;
  581                 case 'b':
  582                         ul = va_arg(ap, int);
  583                         p = va_arg(ap, char *);
  584                         for (q = ksprintn(nbuf, ul, *p++, NULL); *q;)
  585                                 PCHAR(*q--);
  586 
  587                         if (!ul)
  588                                 break;
  589 
  590                         for (tmp = 0; *p;) {
  591                                 n = *p++;
  592                                 if (ul & (1 << (n - 1))) {
  593                                         PCHAR(tmp ? ',' : '<');
  594                                         for (; (n = *p) > ' '; ++p)
  595                                                 PCHAR(n);
  596                                         tmp = 1;
  597                                 } else
  598                                         for (; *p > ' '; ++p)
  599                                                 continue;
  600                         }
  601                         if (tmp)
  602                                 PCHAR('>');
  603                         break;
  604                 case 'c':
  605                         PCHAR(va_arg(ap, int));
  606                         break;
  607                 case 'D':
  608                         up = va_arg(ap, u_char *);
  609                         p = va_arg(ap, char *);
  610                         if (!width)
  611                                 width = 16;
  612                         while(width--) {
  613                                 PCHAR(hex2ascii(*up >> 4));
  614                                 PCHAR(hex2ascii(*up & 0x0f));
  615                                 up++;
  616                                 if (width)
  617                                         for (q=p;*q;q++)
  618                                                 PCHAR(*q);
  619                         }
  620                         break;
  621                 case 'd':
  622                         if (qflag)
  623                                 uq = va_arg(ap, quad_t);
  624                         else if (lflag)
  625                                 ul = va_arg(ap, long);
  626                         else
  627                                 ul = va_arg(ap, int);
  628                         sign = 1;
  629                         base = 10;
  630                         goto number;
  631                 case 'l':
  632                         if (lflag) {
  633                                 lflag = 0;
  634                                 qflag = 1;
  635                         } else
  636                                 lflag = 1;
  637                         goto reswitch;
  638                 case 'o':
  639                         if (qflag)
  640                                 uq = va_arg(ap, u_quad_t);
  641                         else if (lflag)
  642                                 ul = va_arg(ap, u_long);
  643                         else
  644                                 ul = va_arg(ap, u_int);
  645                         base = 8;
  646                         goto nosign;
  647                 case 'p':
  648                         ul = (uintptr_t)va_arg(ap, void *);
  649                         base = 16;
  650                         sharpflag = (width == 0);
  651                         goto nosign;
  652                 case 'q':
  653                         qflag = 1;
  654                         goto reswitch;
  655                 case 'n':
  656                 case 'r':
  657                         if (qflag)
  658                                 uq = va_arg(ap, u_quad_t);
  659                         else if (lflag)
  660                                 ul = va_arg(ap, u_long);
  661                         else
  662                                 ul = sign ?
  663                                     (u_long)va_arg(ap, int) : va_arg(ap, u_int);
  664                         base = radix;
  665                         goto number;
  666                 case 's':
  667                         p = va_arg(ap, char *);
  668                         if (p == NULL)
  669                                 p = "(null)";
  670                         if (!dot)
  671                                 n = strlen (p);
  672                         else
  673                                 for (n = 0; n < dwidth && p[n]; n++)
  674                                         continue;
  675 
  676                         width -= n;
  677 
  678                         if (!ladjust && width > 0)
  679                                 while (width--)
  680                                         PCHAR(padc);
  681                         while (n--)
  682                                 PCHAR(*p++);
  683                         if (ladjust && width > 0)
  684                                 while (width--)
  685                                         PCHAR(padc);
  686                         break;
  687                 case 'u':
  688                         if (qflag)
  689                                 uq = va_arg(ap, u_quad_t);
  690                         else if (lflag)
  691                                 ul = va_arg(ap, u_long);
  692                         else
  693                                 ul = va_arg(ap, u_int);
  694                         base = 10;
  695                         goto nosign;
  696                 case 'x':
  697                 case 'X':
  698                         if (qflag)
  699                                 uq = va_arg(ap, u_quad_t);
  700                         else if (lflag)
  701                                 ul = va_arg(ap, u_long);
  702                         else
  703                                 ul = va_arg(ap, u_int);
  704                         base = 16;
  705                         goto nosign;
  706                 case 'z':
  707                         if (qflag)
  708                                 uq = va_arg(ap, u_quad_t);
  709                         else if (lflag)
  710                                 ul = va_arg(ap, u_long);
  711                         else
  712                                 ul = sign ?
  713                                     (u_long)va_arg(ap, int) : va_arg(ap, u_int);
  714                         base = 16;
  715                         goto number;
  716 nosign:                 sign = 0;
  717 number:                 
  718                         if (qflag) {
  719                                 if (sign && (quad_t)uq < 0) {
  720                                         neg = 1;
  721                                         uq = -(quad_t)uq;
  722                                 }
  723                                 p = ksprintqn(nbuf, uq, base, &tmp);
  724                         } else {
  725                                 if (sign && (long)ul < 0) {
  726                                         neg = 1;
  727                                         ul = -(long)ul;
  728                                 }
  729                                 p = ksprintn(nbuf, ul, base, &tmp);
  730                         }
  731                         if (sharpflag && (qflag ? uq != 0 : ul != 0)) {
  732                                 if (base == 8)
  733                                         tmp++;
  734                                 else if (base == 16)
  735                                         tmp += 2;
  736                         }
  737                         if (neg)
  738                                 tmp++;
  739 
  740                         if (!ladjust && width && (width -= tmp) > 0)
  741                                 while (width--)
  742                                         PCHAR(padc);
  743                         if (neg)
  744                                 PCHAR('-');
  745                         if (sharpflag && (qflag ? uq != 0 : ul != 0)) {
  746                                 if (base == 8) {
  747                                         PCHAR('');
  748                                 } else if (base == 16) {
  749                                         PCHAR('');
  750                                         PCHAR('x');
  751                                 }
  752                         }
  753 
  754                         while (*p)
  755                                 PCHAR(*p--);
  756 
  757                         if (ladjust && width && (width -= tmp) > 0)
  758                                 while (width--)
  759                                         PCHAR(padc);
  760 
  761                         break;
  762                 default:
  763                         PCHAR('%');
  764                         if (lflag)
  765                                 PCHAR('l');
  766                         PCHAR(ch);
  767                         break;
  768                 }
  769         }
  770 #undef PCHAR
  771 }
  772 
  773 /*
  774  * Put character in log buffer with a particular priority.
  775  */
  776 static void
  777 msglogchar(int c, int pri)
  778 {
  779         static int lastpri = -1;
  780         static int dangling;
  781         char nbuf[MAXNBUF];
  782         char *p;
  783 
  784         if (!msgbufmapped)
  785                 return;
  786         if (c == '\0' || c == '\r')
  787                 return;
  788         if (pri != -1 && pri != lastpri) {
  789                 if (dangling) {
  790                         msgaddchar('\n', NULL);
  791                         dangling = 0;
  792                 }
  793                 msgaddchar('<', NULL);
  794                 for (p = ksprintn(nbuf, (u_long)pri, 10, NULL); *p;)
  795                         msgaddchar(*p--, NULL);
  796                 msgaddchar('>', NULL);
  797                 lastpri = pri;
  798         }
  799         msgaddchar(c, NULL);
  800         if (c == '\n') {
  801                 dangling = 0;
  802                 lastpri = -1;
  803         } else {
  804                 dangling = 1;
  805         }
  806 }
  807 
  808 /*
  809  * Put char in log buffer
  810  */
  811 static void
  812 msgaddchar(int c, void *dummy)
  813 {
  814         struct msgbuf *mbp;
  815 
  816         if (!msgbufmapped)
  817                 return;
  818         mbp = msgbufp;
  819         mbp->msg_ptr[mbp->msg_bufx++] = c;
  820         if (mbp->msg_bufx >= mbp->msg_size)
  821                 mbp->msg_bufx = 0;
  822         /* If the buffer is full, keep the most recent data. */
  823         if (mbp->msg_bufr == mbp->msg_bufx) {
  824                 if (++mbp->msg_bufr >= mbp->msg_size)
  825                         mbp->msg_bufr = 0;
  826         }
  827 }
  828 
  829 static void
  830 msgbufcopy(struct msgbuf *oldp)
  831 {
  832         int pos;
  833 
  834         pos = oldp->msg_bufr;
  835         while (pos != oldp->msg_bufx) {
  836                 msglogchar(oldp->msg_ptr[pos], -1);
  837                 if (++pos >= oldp->msg_size)
  838                         pos = 0;
  839         }
  840 }
  841 
  842 void
  843 msgbufinit(void *ptr, size_t size)
  844 {
  845         char *cp;
  846         static struct msgbuf *oldp = NULL;
  847 
  848         size -= sizeof(*msgbufp);
  849         cp = (char *)ptr;
  850         msgbufp = (struct msgbuf *) (cp + size);
  851         if (msgbufp->msg_magic != MSG_MAGIC || msgbufp->msg_size != size ||
  852             msgbufp->msg_bufx >= size || msgbufp->msg_bufr >= size) {
  853                 bzero(cp, size);
  854                 bzero(msgbufp, sizeof(*msgbufp));
  855                 msgbufp->msg_magic = MSG_MAGIC;
  856                 msgbufp->msg_size = (char *)msgbufp - cp;
  857         }
  858         msgbufp->msg_ptr = cp;
  859         if (msgbufmapped && oldp != msgbufp)
  860                 msgbufcopy(oldp);
  861         msgbufmapped = 1;
  862         oldp = msgbufp;
  863 }
  864 
  865 /* Sysctls for accessing/clearing the msgbuf */
  866 static int
  867 sysctl_kern_msgbuf(SYSCTL_HANDLER_ARGS)
  868 {
  869         int error;
  870 
  871         /*
  872          * Unwind the buffer, so that it's linear (possibly starting with
  873          * some initial nulls).
  874          */
  875         error = sysctl_handle_opaque(oidp, msgbufp->msg_ptr + msgbufp->msg_bufx,
  876             msgbufp->msg_size - msgbufp->msg_bufx, req);
  877         if (error)
  878                 return (error);
  879         if (msgbufp->msg_bufx > 0) {
  880                 error = sysctl_handle_opaque(oidp, msgbufp->msg_ptr,
  881                     msgbufp->msg_bufx, req);
  882         }
  883         return (error);
  884 }
  885 
  886 SYSCTL_PROC(_kern, OID_AUTO, msgbuf, CTLTYPE_STRING | CTLFLAG_RD,
  887     0, 0, sysctl_kern_msgbuf, "A", "Contents of kernel message buffer");
  888 
  889 static int msgbuf_clear;
  890 
  891 static int
  892 sysctl_kern_msgbuf_clear(SYSCTL_HANDLER_ARGS)
  893 {
  894         int error;
  895         error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
  896         if (!error && req->newptr) {
  897                 /* Clear the buffer and reset write pointer */
  898                 bzero(msgbufp->msg_ptr, msgbufp->msg_size);
  899                 msgbufp->msg_bufr = msgbufp->msg_bufx = 0;
  900                 msgbuf_clear = 0;
  901         }
  902         return (error);
  903 }
  904 
  905 SYSCTL_PROC(_kern, OID_AUTO, msgbuf_clear,
  906     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE, &msgbuf_clear, 0, 
  907     sysctl_kern_msgbuf_clear, "I", "Clear kernel message buffer");
  908 
  909 #include "opt_ddb.h"
  910 #ifdef DDB
  911 #include <ddb/ddb.h>
  912 
  913 DB_SHOW_COMMAND(msgbuf, db_show_msgbuf)
  914 {
  915         int i, j;
  916 
  917         if (!msgbufmapped) {
  918                 db_printf("msgbuf not mapped yet\n");
  919                 return;
  920         }
  921         db_printf("msgbufp = %p\n", msgbufp);
  922         db_printf("magic = %x, size = %d, r= %d, w = %d, ptr = %p\n",
  923             msgbufp->msg_magic, msgbufp->msg_size, msgbufp->msg_bufr,
  924             msgbufp->msg_bufx, msgbufp->msg_ptr);
  925         for (i = 0; i < msgbufp->msg_size; i++) {
  926                 j = (i + msgbufp->msg_bufr) % msgbufp->msg_size;
  927                 db_printf("%c", msgbufp->msg_ptr[j]);
  928         }
  929         db_printf("\n");
  930 }
  931 
  932 #endif /* DDB */

Cache object: 6c8598cd0aab690099654a0138ddca44


[ 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.