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

Cache object: 8b88f26bebc6f202544f450015633633


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