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

Cache object: e73c9ed5a25b3e6189364b0dcbaa084e


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