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  * 4. Neither the name of the University nor the names of its contributors
   19  *    may be used to endorse or promote products derived from this software
   20  *    without specific prior written permission.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32  * SUCH DAMAGE.
   33  *
   34  *      @(#)subr_prf.c  8.3 (Berkeley) 1/21/94
   35  */
   36 
   37 #include <sys/cdefs.h>
   38 __FBSDID("$FreeBSD: releng/11.2/sys/kern/subr_prf.c 331722 2018-03-29 02:50:57Z eadler $");
   39 
   40 #ifdef _KERNEL
   41 #include "opt_ddb.h"
   42 #include "opt_printf.h"
   43 #endif  /* _KERNEL */
   44 
   45 #include <sys/param.h>
   46 #ifdef _KERNEL
   47 #include <sys/systm.h>
   48 #include <sys/lock.h>
   49 #include <sys/kdb.h>
   50 #include <sys/mutex.h>
   51 #include <sys/sx.h>
   52 #include <sys/kernel.h>
   53 #include <sys/msgbuf.h>
   54 #include <sys/malloc.h>
   55 #include <sys/priv.h>
   56 #include <sys/proc.h>
   57 #include <sys/stddef.h>
   58 #include <sys/sysctl.h>
   59 #include <sys/tty.h>
   60 #include <sys/syslog.h>
   61 #include <sys/cons.h>
   62 #include <sys/uio.h>
   63 #endif
   64 #include <sys/ctype.h>
   65 #include <sys/sbuf.h>
   66 
   67 #ifdef DDB
   68 #include <ddb/ddb.h>
   69 #endif
   70 
   71 /*
   72  * Note that stdarg.h and the ANSI style va_start macro is used for both
   73  * ANSI and traditional C compilers.
   74  */
   75 #ifdef _KERNEL
   76 #include <machine/stdarg.h>
   77 #else
   78 #include <stdarg.h>
   79 #endif
   80 
   81 /*
   82  * This is needed for sbuf_putbuf() when compiled into userland.  Due to the
   83  * shared nature of this file, it's the only place to put it.
   84  */
   85 #ifndef _KERNEL
   86 #include <stdio.h>
   87 #endif
   88 
   89 #ifdef _KERNEL
   90 
   91 #define TOCONS  0x01
   92 #define TOTTY   0x02
   93 #define TOLOG   0x04
   94 
   95 /* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */
   96 #define MAXNBUF (sizeof(intmax_t) * NBBY + 1)
   97 
   98 struct putchar_arg {
   99         int     flags;
  100         int     pri;
  101         struct  tty *tty;
  102         char    *p_bufr;
  103         size_t  n_bufr;
  104         char    *p_next;
  105         size_t  remain;
  106 };
  107 
  108 struct snprintf_arg {
  109         char    *str;
  110         size_t  remain;
  111 };
  112 
  113 extern  int log_open;
  114 
  115 static void  msglogchar(int c, int pri);
  116 static void  msglogstr(char *str, int pri, int filter_cr);
  117 static void  putchar(int ch, void *arg);
  118 static char *ksprintn(char *nbuf, uintmax_t num, int base, int *len, int upper);
  119 static void  snprintf_func(int ch, void *arg);
  120 
  121 static int msgbufmapped;                /* Set when safe to use msgbuf */
  122 int msgbuftrigger;
  123 
  124 static int log_console_output = 1;
  125 SYSCTL_INT(_kern, OID_AUTO, log_console_output, CTLFLAG_RWTUN,
  126     &log_console_output, 0, "Duplicate console output to the syslog");
  127 
  128 /*
  129  * See the comment in log_console() below for more explanation of this.
  130  */
  131 static int log_console_add_linefeed;
  132 SYSCTL_INT(_kern, OID_AUTO, log_console_add_linefeed, CTLFLAG_RWTUN,
  133     &log_console_add_linefeed, 0, "log_console() adds extra newlines");
  134 
  135 static int always_console_output;
  136 SYSCTL_INT(_kern, OID_AUTO, always_console_output, CTLFLAG_RWTUN,
  137     &always_console_output, 0, "Always output to console despite TIOCCONS");
  138 
  139 /*
  140  * Warn that a system table is full.
  141  */
  142 void
  143 tablefull(const char *tab)
  144 {
  145 
  146         log(LOG_ERR, "%s: table is full\n", tab);
  147 }
  148 
  149 /*
  150  * Uprintf prints to the controlling terminal for the current process.
  151  */
  152 int
  153 uprintf(const char *fmt, ...)
  154 {
  155         va_list ap;
  156         struct putchar_arg pca;
  157         struct proc *p;
  158         struct thread *td;
  159         int retval;
  160 
  161         td = curthread;
  162         if (TD_IS_IDLETHREAD(td))
  163                 return (0);
  164 
  165         sx_slock(&proctree_lock);
  166         p = td->td_proc;
  167         PROC_LOCK(p);
  168         if ((p->p_flag & P_CONTROLT) == 0) {
  169                 PROC_UNLOCK(p);
  170                 sx_sunlock(&proctree_lock);
  171                 return (0);
  172         }
  173         SESS_LOCK(p->p_session);
  174         pca.tty = p->p_session->s_ttyp;
  175         SESS_UNLOCK(p->p_session);
  176         PROC_UNLOCK(p);
  177         if (pca.tty == NULL) {
  178                 sx_sunlock(&proctree_lock);
  179                 return (0);
  180         }
  181         pca.flags = TOTTY;
  182         pca.p_bufr = NULL;
  183         va_start(ap, fmt);
  184         tty_lock(pca.tty);
  185         sx_sunlock(&proctree_lock);
  186         retval = kvprintf(fmt, putchar, &pca, 10, ap);
  187         tty_unlock(pca.tty);
  188         va_end(ap);
  189         return (retval);
  190 }
  191 
  192 /*
  193  * tprintf and vtprintf print on the controlling terminal associated with the
  194  * given session, possibly to the log as well.
  195  */
  196 void
  197 tprintf(struct proc *p, int pri, const char *fmt, ...)
  198 {
  199         va_list ap;
  200 
  201         va_start(ap, fmt);
  202         vtprintf(p, pri, fmt, ap);
  203         va_end(ap);
  204 }
  205 
  206 void
  207 vtprintf(struct proc *p, int pri, const char *fmt, va_list ap)
  208 {
  209         struct tty *tp = NULL;
  210         int flags = 0;
  211         struct putchar_arg pca;
  212         struct session *sess = NULL;
  213 
  214         sx_slock(&proctree_lock);
  215         if (pri != -1)
  216                 flags |= TOLOG;
  217         if (p != NULL) {
  218                 PROC_LOCK(p);
  219                 if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
  220                         sess = p->p_session;
  221                         sess_hold(sess);
  222                         PROC_UNLOCK(p);
  223                         tp = sess->s_ttyp;
  224                         if (tp != NULL && tty_checkoutq(tp))
  225                                 flags |= TOTTY;
  226                         else
  227                                 tp = NULL;
  228                 } else
  229                         PROC_UNLOCK(p);
  230         }
  231         pca.pri = pri;
  232         pca.tty = tp;
  233         pca.flags = flags;
  234         pca.p_bufr = NULL;
  235         if (pca.tty != NULL)
  236                 tty_lock(pca.tty);
  237         sx_sunlock(&proctree_lock);
  238         kvprintf(fmt, putchar, &pca, 10, ap);
  239         if (pca.tty != NULL)
  240                 tty_unlock(pca.tty);
  241         if (sess != NULL)
  242                 sess_release(sess);
  243         msgbuftrigger = 1;
  244 }
  245 
  246 /*
  247  * Ttyprintf displays a message on a tty; it should be used only by
  248  * the tty driver, or anything that knows the underlying tty will not
  249  * be revoke(2)'d away.  Other callers should use tprintf.
  250  */
  251 int
  252 ttyprintf(struct tty *tp, const char *fmt, ...)
  253 {
  254         va_list ap;
  255         struct putchar_arg pca;
  256         int retval;
  257 
  258         va_start(ap, fmt);
  259         pca.tty = tp;
  260         pca.flags = TOTTY;
  261         pca.p_bufr = NULL;
  262         retval = kvprintf(fmt, putchar, &pca, 10, ap);
  263         va_end(ap);
  264         return (retval);
  265 }
  266 
  267 static int
  268 _vprintf(int level, int flags, const char *fmt, va_list ap)
  269 {
  270         struct putchar_arg pca;
  271         int retval;
  272 #ifdef PRINTF_BUFR_SIZE
  273         char bufr[PRINTF_BUFR_SIZE];
  274 #endif
  275 
  276         pca.tty = NULL;
  277         pca.pri = level;
  278         pca.flags = flags;
  279 #ifdef PRINTF_BUFR_SIZE
  280         pca.p_bufr = bufr;
  281         pca.p_next = pca.p_bufr;
  282         pca.n_bufr = sizeof(bufr);
  283         pca.remain = sizeof(bufr);
  284         *pca.p_next = '\0';
  285 #else
  286         /* Don't buffer console output. */
  287         pca.p_bufr = NULL;
  288 #endif
  289 
  290         retval = kvprintf(fmt, putchar, &pca, 10, ap);
  291 
  292 #ifdef PRINTF_BUFR_SIZE
  293         /* Write any buffered console/log output: */
  294         if (*pca.p_bufr != '\0') {
  295                 if (pca.flags & TOLOG)
  296                         msglogstr(pca.p_bufr, level, /*filter_cr*/1);
  297 
  298                 if (pca.flags & TOCONS)
  299                         cnputs(pca.p_bufr);
  300         }
  301 #endif
  302 
  303         return (retval);
  304 }
  305 
  306 /*
  307  * Log writes to the log buffer, and guarantees not to sleep (so can be
  308  * called by interrupt routines).  If there is no process reading the
  309  * log yet, it writes to the console also.
  310  */
  311 void
  312 log(int level, const char *fmt, ...)
  313 {
  314         va_list ap;
  315 
  316         va_start(ap, fmt);
  317         vlog(level, fmt, ap);
  318         va_end(ap);
  319 }
  320 
  321 void
  322 vlog(int level, const char *fmt, va_list ap)
  323 {
  324 
  325         (void)_vprintf(level, log_open ? TOLOG : TOCONS | TOLOG, fmt, ap);
  326         msgbuftrigger = 1;
  327 }
  328 
  329 #define CONSCHUNK 128
  330 
  331 void
  332 log_console(struct uio *uio)
  333 {
  334         int c, error, nl;
  335         char *consbuffer;
  336         int pri;
  337 
  338         if (!log_console_output)
  339                 return;
  340 
  341         pri = LOG_INFO | LOG_CONSOLE;
  342         uio = cloneuio(uio);
  343         consbuffer = malloc(CONSCHUNK, M_TEMP, M_WAITOK);
  344 
  345         nl = 0;
  346         while (uio->uio_resid > 0) {
  347                 c = imin(uio->uio_resid, CONSCHUNK - 1);
  348                 error = uiomove(consbuffer, c, uio);
  349                 if (error != 0)
  350                         break;
  351                 /* Make sure we're NUL-terminated */
  352                 consbuffer[c] = '\0';
  353                 if (consbuffer[c - 1] == '\n')
  354                         nl = 1;
  355                 else
  356                         nl = 0;
  357                 msglogstr(consbuffer, pri, /*filter_cr*/ 1);
  358         }
  359         /*
  360          * The previous behavior in log_console() is preserved when
  361          * log_console_add_linefeed is non-zero.  For that behavior, if an
  362          * individual console write came in that was not terminated with a
  363          * line feed, it would add a line feed.
  364          *
  365          * This results in different data in the message buffer than
  366          * appears on the system console (which doesn't add extra line feed
  367          * characters).
  368          *
  369          * A number of programs and rc scripts write a line feed, or a period
  370          * and a line feed when they have completed their operation.  On
  371          * the console, this looks seamless, but when displayed with
  372          * 'dmesg -a', you wind up with output that looks like this:
  373          *
  374          * Updating motd:
  375          * .
  376          *
  377          * On the console, it looks like this:
  378          * Updating motd:.
  379          *
  380          * We could add logic to detect that situation, or just not insert
  381          * the extra newlines.  Set the kern.log_console_add_linefeed
  382          * sysctl/tunable variable to get the old behavior.
  383          */
  384         if (!nl && log_console_add_linefeed) {
  385                 consbuffer[0] = '\n';
  386                 consbuffer[1] = '\0';
  387                 msglogstr(consbuffer, pri, /*filter_cr*/ 1);
  388         }
  389         msgbuftrigger = 1;
  390         free(uio, M_IOV);
  391         free(consbuffer, M_TEMP);
  392 }
  393 
  394 int
  395 printf(const char *fmt, ...)
  396 {
  397         va_list ap;
  398         int retval;
  399 
  400         va_start(ap, fmt);
  401         retval = vprintf(fmt, ap);
  402         va_end(ap);
  403 
  404         return (retval);
  405 }
  406 
  407 int
  408 vprintf(const char *fmt, va_list ap)
  409 {
  410         int retval;
  411 
  412         retval = _vprintf(-1, TOCONS | TOLOG, fmt, ap);
  413 
  414         if (!panicstr)
  415                 msgbuftrigger = 1;
  416 
  417         return (retval);
  418 }
  419 
  420 static void
  421 prf_putbuf(char *bufr, int flags, int pri)
  422 {
  423 
  424         if (flags & TOLOG)
  425                 msglogstr(bufr, pri, /*filter_cr*/1);
  426 
  427         if (flags & TOCONS) {
  428                 if ((panicstr == NULL) && (constty != NULL))
  429                         msgbuf_addstr(&consmsgbuf, -1,
  430                             bufr, /*filter_cr*/ 0);
  431 
  432                 if ((constty == NULL) ||(always_console_output))
  433                         cnputs(bufr);
  434         }
  435 }
  436 
  437 static void
  438 putbuf(int c, struct putchar_arg *ap)
  439 {
  440         /* Check if no console output buffer was provided. */
  441         if (ap->p_bufr == NULL) {
  442                 /* Output direct to the console. */
  443                 if (ap->flags & TOCONS)
  444                         cnputc(c);
  445 
  446                 if (ap->flags & TOLOG)
  447                         msglogchar(c, ap->pri);
  448         } else {
  449                 /* Buffer the character: */
  450                 *ap->p_next++ = c;
  451                 ap->remain--;
  452 
  453                 /* Always leave the buffer zero terminated. */
  454                 *ap->p_next = '\0';
  455 
  456                 /* Check if the buffer needs to be flushed. */
  457                 if (ap->remain == 2 || c == '\n') {
  458                         prf_putbuf(ap->p_bufr, ap->flags, ap->pri);
  459 
  460                         ap->p_next = ap->p_bufr;
  461                         ap->remain = ap->n_bufr;
  462                         *ap->p_next = '\0';
  463                 }
  464 
  465                 /*
  466                  * Since we fill the buffer up one character at a time,
  467                  * this should not happen.  We should always catch it when
  468                  * ap->remain == 2 (if not sooner due to a newline), flush
  469                  * the buffer and move on.  One way this could happen is
  470                  * if someone sets PRINTF_BUFR_SIZE to 1 or something
  471                  * similarly silly.
  472                  */
  473                 KASSERT(ap->remain > 2, ("Bad buffer logic, remain = %zd",
  474                     ap->remain));
  475         }
  476 }
  477 
  478 /*
  479  * Print a character on console or users terminal.  If destination is
  480  * the console then the last bunch of characters are saved in msgbuf for
  481  * inspection later.
  482  */
  483 static void
  484 putchar(int c, void *arg)
  485 {
  486         struct putchar_arg *ap = (struct putchar_arg*) arg;
  487         struct tty *tp = ap->tty;
  488         int flags = ap->flags;
  489 
  490         /* Don't use the tty code after a panic or while in ddb. */
  491         if (kdb_active) {
  492                 if (c != '\0')
  493                         cnputc(c);
  494                 return;
  495         }
  496 
  497         if ((flags & TOTTY) && tp != NULL && panicstr == NULL)
  498                 tty_putchar(tp, c);
  499 
  500         if ((flags & (TOCONS | TOLOG)) && c != '\0')
  501                 putbuf(c, ap);
  502 }
  503 
  504 /*
  505  * Scaled down version of sprintf(3).
  506  */
  507 int
  508 sprintf(char *buf, const char *cfmt, ...)
  509 {
  510         int retval;
  511         va_list ap;
  512 
  513         va_start(ap, cfmt);
  514         retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
  515         buf[retval] = '\0';
  516         va_end(ap);
  517         return (retval);
  518 }
  519 
  520 /*
  521  * Scaled down version of vsprintf(3).
  522  */
  523 int
  524 vsprintf(char *buf, const char *cfmt, va_list ap)
  525 {
  526         int retval;
  527 
  528         retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
  529         buf[retval] = '\0';
  530         return (retval);
  531 }
  532 
  533 /*
  534  * Scaled down version of snprintf(3).
  535  */
  536 int
  537 snprintf(char *str, size_t size, const char *format, ...)
  538 {
  539         int retval;
  540         va_list ap;
  541 
  542         va_start(ap, format);
  543         retval = vsnprintf(str, size, format, ap);
  544         va_end(ap);
  545         return(retval);
  546 }
  547 
  548 /*
  549  * Scaled down version of vsnprintf(3).
  550  */
  551 int
  552 vsnprintf(char *str, size_t size, const char *format, va_list ap)
  553 {
  554         struct snprintf_arg info;
  555         int retval;
  556 
  557         info.str = str;
  558         info.remain = size;
  559         retval = kvprintf(format, snprintf_func, &info, 10, ap);
  560         if (info.remain >= 1)
  561                 *info.str++ = '\0';
  562         return (retval);
  563 }
  564 
  565 /*
  566  * Kernel version which takes radix argument vsnprintf(3).
  567  */
  568 int
  569 vsnrprintf(char *str, size_t size, int radix, const char *format, va_list ap)
  570 {
  571         struct snprintf_arg info;
  572         int retval;
  573 
  574         info.str = str;
  575         info.remain = size;
  576         retval = kvprintf(format, snprintf_func, &info, radix, ap);
  577         if (info.remain >= 1)
  578                 *info.str++ = '\0';
  579         return (retval);
  580 }
  581 
  582 static void
  583 snprintf_func(int ch, void *arg)
  584 {
  585         struct snprintf_arg *const info = arg;
  586 
  587         if (info->remain >= 2) {
  588                 *info->str++ = ch;
  589                 info->remain--;
  590         }
  591 }
  592 
  593 /*
  594  * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
  595  * order; return an optional length and a pointer to the last character
  596  * written in the buffer (i.e., the first character of the string).
  597  * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
  598  */
  599 static char *
  600 ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
  601 {
  602         char *p, c;
  603 
  604         p = nbuf;
  605         *p = '\0';
  606         do {
  607                 c = hex2ascii(num % base);
  608                 *++p = upper ? toupper(c) : c;
  609         } while (num /= base);
  610         if (lenp)
  611                 *lenp = p - nbuf;
  612         return (p);
  613 }
  614 
  615 /*
  616  * Scaled down version of printf(3).
  617  *
  618  * Two additional formats:
  619  *
  620  * The format %b is supported to decode error registers.
  621  * Its usage is:
  622  *
  623  *      printf("reg=%b\n", regval, "<base><arg>*");
  624  *
  625  * where <base> is the output base expressed as a control character, e.g.
  626  * \10 gives octal; \20 gives hex.  Each arg is a sequence of characters,
  627  * the first of which gives the bit number to be inspected (origin 1), and
  628  * the next characters (up to a control character, i.e. a character <= 32),
  629  * give the name of the register.  Thus:
  630  *
  631  *      kvprintf("reg=%b\n", 3, "\1\2BITTWO\1BITONE");
  632  *
  633  * would produce output:
  634  *
  635  *      reg=3<BITTWO,BITONE>
  636  *
  637  * XXX:  %D  -- Hexdump, takes pointer and separator string:
  638  *              ("%6D", ptr, ":")   -> XX:XX:XX:XX:XX:XX
  639  *              ("%*D", len, ptr, " " -> XX XX XX XX ...
  640  */
  641 int
  642 kvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap)
  643 {
  644 #define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; }
  645         char nbuf[MAXNBUF];
  646         char *d;
  647         const char *p, *percent, *q;
  648         u_char *up;
  649         int ch, n;
  650         uintmax_t num;
  651         int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
  652         int cflag, hflag, jflag, tflag, zflag;
  653         int dwidth, upper;
  654         char padc;
  655         int stop = 0, retval = 0;
  656 
  657         num = 0;
  658         if (!func)
  659                 d = (char *) arg;
  660         else
  661                 d = NULL;
  662 
  663         if (fmt == NULL)
  664                 fmt = "(fmt null)\n";
  665 
  666         if (radix < 2 || radix > 36)
  667                 radix = 10;
  668 
  669         for (;;) {
  670                 padc = ' ';
  671                 width = 0;
  672                 while ((ch = (u_char)*fmt++) != '%' || stop) {
  673                         if (ch == '\0')
  674                                 return (retval);
  675                         PCHAR(ch);
  676                 }
  677                 percent = fmt - 1;
  678                 qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
  679                 sign = 0; dot = 0; dwidth = 0; upper = 0;
  680                 cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
  681 reswitch:       switch (ch = (u_char)*fmt++) {
  682                 case '.':
  683                         dot = 1;
  684                         goto reswitch;
  685                 case '#':
  686                         sharpflag = 1;
  687                         goto reswitch;
  688                 case '+':
  689                         sign = 1;
  690                         goto reswitch;
  691                 case '-':
  692                         ladjust = 1;
  693                         goto reswitch;
  694                 case '%':
  695                         PCHAR(ch);
  696                         break;
  697                 case '*':
  698                         if (!dot) {
  699                                 width = va_arg(ap, int);
  700                                 if (width < 0) {
  701                                         ladjust = !ladjust;
  702                                         width = -width;
  703                                 }
  704                         } else {
  705                                 dwidth = va_arg(ap, int);
  706                         }
  707                         goto reswitch;
  708                 case '':
  709                         if (!dot) {
  710                                 padc = '';
  711                                 goto reswitch;
  712                         }
  713                 case '1': case '2': case '3': case '4':
  714                 case '5': case '6': case '7': case '8': case '9':
  715                                 for (n = 0;; ++fmt) {
  716                                         n = n * 10 + ch - '';
  717                                         ch = *fmt;
  718                                         if (ch < '' || ch > '9')
  719                                                 break;
  720                                 }
  721                         if (dot)
  722                                 dwidth = n;
  723                         else
  724                                 width = n;
  725                         goto reswitch;
  726                 case 'b':
  727                         num = (u_int)va_arg(ap, int);
  728                         p = va_arg(ap, char *);
  729                         for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;)
  730                                 PCHAR(*q--);
  731 
  732                         if (num == 0)
  733                                 break;
  734 
  735                         for (tmp = 0; *p;) {
  736                                 n = *p++;
  737                                 if (num & (1 << (n - 1))) {
  738                                         PCHAR(tmp ? ',' : '<');
  739                                         for (; (n = *p) > ' '; ++p)
  740                                                 PCHAR(n);
  741                                         tmp = 1;
  742                                 } else
  743                                         for (; *p > ' '; ++p)
  744                                                 continue;
  745                         }
  746                         if (tmp)
  747                                 PCHAR('>');
  748                         break;
  749                 case 'c':
  750                         width -= 1;
  751 
  752                         if (!ladjust && width > 0)
  753                                 while (width--)
  754                                         PCHAR(padc);
  755                         PCHAR(va_arg(ap, int));
  756                         if (ladjust && width > 0)
  757                                 while (width--)
  758                                         PCHAR(padc);
  759                         break;
  760                 case 'D':
  761                         up = va_arg(ap, u_char *);
  762                         p = va_arg(ap, char *);
  763                         if (!width)
  764                                 width = 16;
  765                         while(width--) {
  766                                 PCHAR(hex2ascii(*up >> 4));
  767                                 PCHAR(hex2ascii(*up & 0x0f));
  768                                 up++;
  769                                 if (width)
  770                                         for (q=p;*q;q++)
  771                                                 PCHAR(*q);
  772                         }
  773                         break;
  774                 case 'd':
  775                 case 'i':
  776                         base = 10;
  777                         sign = 1;
  778                         goto handle_sign;
  779                 case 'h':
  780                         if (hflag) {
  781                                 hflag = 0;
  782                                 cflag = 1;
  783                         } else
  784                                 hflag = 1;
  785                         goto reswitch;
  786                 case 'j':
  787                         jflag = 1;
  788                         goto reswitch;
  789                 case 'l':
  790                         if (lflag) {
  791                                 lflag = 0;
  792                                 qflag = 1;
  793                         } else
  794                                 lflag = 1;
  795                         goto reswitch;
  796                 case 'n':
  797                         if (jflag)
  798                                 *(va_arg(ap, intmax_t *)) = retval;
  799                         else if (qflag)
  800                                 *(va_arg(ap, quad_t *)) = retval;
  801                         else if (lflag)
  802                                 *(va_arg(ap, long *)) = retval;
  803                         else if (zflag)
  804                                 *(va_arg(ap, size_t *)) = retval;
  805                         else if (hflag)
  806                                 *(va_arg(ap, short *)) = retval;
  807                         else if (cflag)
  808                                 *(va_arg(ap, char *)) = retval;
  809                         else
  810                                 *(va_arg(ap, int *)) = retval;
  811                         break;
  812                 case 'o':
  813                         base = 8;
  814                         goto handle_nosign;
  815                 case 'p':
  816                         base = 16;
  817                         sharpflag = (width == 0);
  818                         sign = 0;
  819                         num = (uintptr_t)va_arg(ap, void *);
  820                         goto number;
  821                 case 'q':
  822                         qflag = 1;
  823                         goto reswitch;
  824                 case 'r':
  825                         base = radix;
  826                         if (sign)
  827                                 goto handle_sign;
  828                         goto handle_nosign;
  829                 case 's':
  830                         p = va_arg(ap, char *);
  831                         if (p == NULL)
  832                                 p = "(null)";
  833                         if (!dot)
  834                                 n = strlen (p);
  835                         else
  836                                 for (n = 0; n < dwidth && p[n]; n++)
  837                                         continue;
  838 
  839                         width -= n;
  840 
  841                         if (!ladjust && width > 0)
  842                                 while (width--)
  843                                         PCHAR(padc);
  844                         while (n--)
  845                                 PCHAR(*p++);
  846                         if (ladjust && width > 0)
  847                                 while (width--)
  848                                         PCHAR(padc);
  849                         break;
  850                 case 't':
  851                         tflag = 1;
  852                         goto reswitch;
  853                 case 'u':
  854                         base = 10;
  855                         goto handle_nosign;
  856                 case 'X':
  857                         upper = 1;
  858                 case 'x':
  859                         base = 16;
  860                         goto handle_nosign;
  861                 case 'y':
  862                         base = 16;
  863                         sign = 1;
  864                         goto handle_sign;
  865                 case 'z':
  866                         zflag = 1;
  867                         goto reswitch;
  868 handle_nosign:
  869                         sign = 0;
  870                         if (jflag)
  871                                 num = va_arg(ap, uintmax_t);
  872                         else if (qflag)
  873                                 num = va_arg(ap, u_quad_t);
  874                         else if (tflag)
  875                                 num = va_arg(ap, ptrdiff_t);
  876                         else if (lflag)
  877                                 num = va_arg(ap, u_long);
  878                         else if (zflag)
  879                                 num = va_arg(ap, size_t);
  880                         else if (hflag)
  881                                 num = (u_short)va_arg(ap, int);
  882                         else if (cflag)
  883                                 num = (u_char)va_arg(ap, int);
  884                         else
  885                                 num = va_arg(ap, u_int);
  886                         goto number;
  887 handle_sign:
  888                         if (jflag)
  889                                 num = va_arg(ap, intmax_t);
  890                         else if (qflag)
  891                                 num = va_arg(ap, quad_t);
  892                         else if (tflag)
  893                                 num = va_arg(ap, ptrdiff_t);
  894                         else if (lflag)
  895                                 num = va_arg(ap, long);
  896                         else if (zflag)
  897                                 num = va_arg(ap, ssize_t);
  898                         else if (hflag)
  899                                 num = (short)va_arg(ap, int);
  900                         else if (cflag)
  901                                 num = (char)va_arg(ap, int);
  902                         else
  903                                 num = va_arg(ap, int);
  904 number:
  905                         if (sign && (intmax_t)num < 0) {
  906                                 neg = 1;
  907                                 num = -(intmax_t)num;
  908                         }
  909                         p = ksprintn(nbuf, num, base, &n, upper);
  910                         tmp = 0;
  911                         if (sharpflag && num != 0) {
  912                                 if (base == 8)
  913                                         tmp++;
  914                                 else if (base == 16)
  915                                         tmp += 2;
  916                         }
  917                         if (neg)
  918                                 tmp++;
  919 
  920                         if (!ladjust && padc == '')
  921                                 dwidth = width - tmp;
  922                         width -= tmp + imax(dwidth, n);
  923                         dwidth -= n;
  924                         if (!ladjust)
  925                                 while (width-- > 0)
  926                                         PCHAR(' ');
  927                         if (neg)
  928                                 PCHAR('-');
  929                         if (sharpflag && num != 0) {
  930                                 if (base == 8) {
  931                                         PCHAR('');
  932                                 } else if (base == 16) {
  933                                         PCHAR('');
  934                                         PCHAR('x');
  935                                 }
  936                         }
  937                         while (dwidth-- > 0)
  938                                 PCHAR('');
  939 
  940                         while (*p)
  941                                 PCHAR(*p--);
  942 
  943                         if (ladjust)
  944                                 while (width-- > 0)
  945                                         PCHAR(' ');
  946 
  947                         break;
  948                 default:
  949                         while (percent < fmt)
  950                                 PCHAR(*percent++);
  951                         /*
  952                          * Since we ignore a formatting argument it is no
  953                          * longer safe to obey the remaining formatting
  954                          * arguments as the arguments will no longer match
  955                          * the format specs.
  956                          */
  957                         stop = 1;
  958                         break;
  959                 }
  960         }
  961 #undef PCHAR
  962 }
  963 
  964 /*
  965  * Put character in log buffer with a particular priority.
  966  */
  967 static void
  968 msglogchar(int c, int pri)
  969 {
  970         static int lastpri = -1;
  971         static int dangling;
  972         char nbuf[MAXNBUF];
  973         char *p;
  974 
  975         if (!msgbufmapped)
  976                 return;
  977         if (c == '\0' || c == '\r')
  978                 return;
  979         if (pri != -1 && pri != lastpri) {
  980                 if (dangling) {
  981                         msgbuf_addchar(msgbufp, '\n');
  982                         dangling = 0;
  983                 }
  984                 msgbuf_addchar(msgbufp, '<');
  985                 for (p = ksprintn(nbuf, (uintmax_t)pri, 10, NULL, 0); *p;)
  986                         msgbuf_addchar(msgbufp, *p--);
  987                 msgbuf_addchar(msgbufp, '>');
  988                 lastpri = pri;
  989         }
  990         msgbuf_addchar(msgbufp, c);
  991         if (c == '\n') {
  992                 dangling = 0;
  993                 lastpri = -1;
  994         } else {
  995                 dangling = 1;
  996         }
  997 }
  998 
  999 static void
 1000 msglogstr(char *str, int pri, int filter_cr)
 1001 {
 1002         if (!msgbufmapped)
 1003                 return;
 1004 
 1005         msgbuf_addstr(msgbufp, pri, str, filter_cr);
 1006 }
 1007 
 1008 void
 1009 msgbufinit(void *ptr, int size)
 1010 {
 1011         char *cp;
 1012         static struct msgbuf *oldp = NULL;
 1013 
 1014         size -= sizeof(*msgbufp);
 1015         cp = (char *)ptr;
 1016         msgbufp = (struct msgbuf *)(cp + size);
 1017         msgbuf_reinit(msgbufp, cp, size);
 1018         if (msgbufmapped && oldp != msgbufp)
 1019                 msgbuf_copy(oldp, msgbufp);
 1020         msgbufmapped = 1;
 1021         oldp = msgbufp;
 1022 }
 1023 
 1024 static int unprivileged_read_msgbuf = 1;
 1025 SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_read_msgbuf,
 1026     CTLFLAG_RW, &unprivileged_read_msgbuf, 0,
 1027     "Unprivileged processes may read the kernel message buffer");
 1028 
 1029 /* Sysctls for accessing/clearing the msgbuf */
 1030 static int
 1031 sysctl_kern_msgbuf(SYSCTL_HANDLER_ARGS)
 1032 {
 1033         char buf[128];
 1034         u_int seq;
 1035         int error, len;
 1036 
 1037         if (!unprivileged_read_msgbuf) {
 1038                 error = priv_check(req->td, PRIV_MSGBUF);
 1039                 if (error)
 1040                         return (error);
 1041         }
 1042 
 1043         /* Read the whole buffer, one chunk at a time. */
 1044         mtx_lock(&msgbuf_lock);
 1045         msgbuf_peekbytes(msgbufp, NULL, 0, &seq);
 1046         for (;;) {
 1047                 len = msgbuf_peekbytes(msgbufp, buf, sizeof(buf), &seq);
 1048                 mtx_unlock(&msgbuf_lock);
 1049                 if (len == 0)
 1050                         return (SYSCTL_OUT(req, "", 1)); /* add nulterm */
 1051 
 1052                 error = sysctl_handle_opaque(oidp, buf, len, req);
 1053                 if (error)
 1054                         return (error);
 1055 
 1056                 mtx_lock(&msgbuf_lock);
 1057         }
 1058 }
 1059 
 1060 SYSCTL_PROC(_kern, OID_AUTO, msgbuf,
 1061     CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
 1062     NULL, 0, sysctl_kern_msgbuf, "A", "Contents of kernel message buffer");
 1063 
 1064 static int msgbuf_clearflag;
 1065 
 1066 static int
 1067 sysctl_kern_msgbuf_clear(SYSCTL_HANDLER_ARGS)
 1068 {
 1069         int error;
 1070         error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
 1071         if (!error && req->newptr) {
 1072                 mtx_lock(&msgbuf_lock);
 1073                 msgbuf_clear(msgbufp);
 1074                 mtx_unlock(&msgbuf_lock);
 1075                 msgbuf_clearflag = 0;
 1076         }
 1077         return (error);
 1078 }
 1079 
 1080 SYSCTL_PROC(_kern, OID_AUTO, msgbuf_clear,
 1081     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE | CTLFLAG_MPSAFE,
 1082     &msgbuf_clearflag, 0, sysctl_kern_msgbuf_clear, "I",
 1083     "Clear kernel message buffer");
 1084 
 1085 #ifdef DDB
 1086 
 1087 DB_SHOW_COMMAND(msgbuf, db_show_msgbuf)
 1088 {
 1089         int i, j;
 1090 
 1091         if (!msgbufmapped) {
 1092                 db_printf("msgbuf not mapped yet\n");
 1093                 return;
 1094         }
 1095         db_printf("msgbufp = %p\n", msgbufp);
 1096         db_printf("magic = %x, size = %d, r= %u, w = %u, ptr = %p, cksum= %u\n",
 1097             msgbufp->msg_magic, msgbufp->msg_size, msgbufp->msg_rseq,
 1098             msgbufp->msg_wseq, msgbufp->msg_ptr, msgbufp->msg_cksum);
 1099         for (i = 0; i < msgbufp->msg_size && !db_pager_quit; i++) {
 1100                 j = MSGBUF_SEQ_TO_POS(msgbufp, i + msgbufp->msg_rseq);
 1101                 db_printf("%c", msgbufp->msg_ptr[j]);
 1102         }
 1103         db_printf("\n");
 1104 }
 1105 
 1106 #endif /* DDB */
 1107 
 1108 void
 1109 hexdump(const void *ptr, int length, const char *hdr, int flags)
 1110 {
 1111         int i, j, k;
 1112         int cols;
 1113         const unsigned char *cp;
 1114         char delim;
 1115 
 1116         if ((flags & HD_DELIM_MASK) != 0)
 1117                 delim = (flags & HD_DELIM_MASK) >> 8;
 1118         else
 1119                 delim = ' ';
 1120 
 1121         if ((flags & HD_COLUMN_MASK) != 0)
 1122                 cols = flags & HD_COLUMN_MASK;
 1123         else
 1124                 cols = 16;
 1125 
 1126         cp = ptr;
 1127         for (i = 0; i < length; i+= cols) {
 1128                 if (hdr != NULL)
 1129                         printf("%s", hdr);
 1130 
 1131                 if ((flags & HD_OMIT_COUNT) == 0)
 1132                         printf("%04x  ", i);
 1133 
 1134                 if ((flags & HD_OMIT_HEX) == 0) {
 1135                         for (j = 0; j < cols; j++) {
 1136                                 k = i + j;
 1137                                 if (k < length)
 1138                                         printf("%c%02x", delim, cp[k]);
 1139                                 else
 1140                                         printf("   ");
 1141                         }
 1142                 }
 1143 
 1144                 if ((flags & HD_OMIT_CHARS) == 0) {
 1145                         printf("  |");
 1146                         for (j = 0; j < cols; j++) {
 1147                                 k = i + j;
 1148                                 if (k >= length)
 1149                                         printf(" ");
 1150                                 else if (cp[k] >= ' ' && cp[k] <= '~')
 1151                                         printf("%c", cp[k]);
 1152                                 else
 1153                                         printf(".");
 1154                         }
 1155                         printf("|");
 1156                 }
 1157                 printf("\n");
 1158         }
 1159 }
 1160 #endif /* _KERNEL */
 1161 
 1162 void
 1163 sbuf_hexdump(struct sbuf *sb, const void *ptr, int length, const char *hdr,
 1164              int flags)
 1165 {
 1166         int i, j, k;
 1167         int cols;
 1168         const unsigned char *cp;
 1169         char delim;
 1170 
 1171         if ((flags & HD_DELIM_MASK) != 0)
 1172                 delim = (flags & HD_DELIM_MASK) >> 8;
 1173         else
 1174                 delim = ' ';
 1175 
 1176         if ((flags & HD_COLUMN_MASK) != 0)
 1177                 cols = flags & HD_COLUMN_MASK;
 1178         else
 1179                 cols = 16;
 1180 
 1181         cp = ptr;
 1182         for (i = 0; i < length; i+= cols) {
 1183                 if (hdr != NULL)
 1184                         sbuf_printf(sb, "%s", hdr);
 1185 
 1186                 if ((flags & HD_OMIT_COUNT) == 0)
 1187                         sbuf_printf(sb, "%04x  ", i);
 1188 
 1189                 if ((flags & HD_OMIT_HEX) == 0) {
 1190                         for (j = 0; j < cols; j++) {
 1191                                 k = i + j;
 1192                                 if (k < length)
 1193                                         sbuf_printf(sb, "%c%02x", delim, cp[k]);
 1194                                 else
 1195                                         sbuf_printf(sb, "   ");
 1196                         }
 1197                 }
 1198 
 1199                 if ((flags & HD_OMIT_CHARS) == 0) {
 1200                         sbuf_printf(sb, "  |");
 1201                         for (j = 0; j < cols; j++) {
 1202                                 k = i + j;
 1203                                 if (k >= length)
 1204                                         sbuf_printf(sb, " ");
 1205                                 else if (cp[k] >= ' ' && cp[k] <= '~')
 1206                                         sbuf_printf(sb, "%c", cp[k]);
 1207                                 else
 1208                                         sbuf_printf(sb, ".");
 1209                         }
 1210                         sbuf_printf(sb, "|");
 1211                 }
 1212                 sbuf_printf(sb, "\n");
 1213         }
 1214 }
 1215 
 1216 #ifdef _KERNEL
 1217 void
 1218 counted_warning(unsigned *counter, const char *msg)
 1219 {
 1220         struct thread *td;
 1221         unsigned c;
 1222 
 1223         for (;;) {
 1224                 c = *counter;
 1225                 if (c == 0)
 1226                         break;
 1227                 if (atomic_cmpset_int(counter, c, c - 1)) {
 1228                         td = curthread;
 1229                         log(LOG_INFO, "pid %d (%s) %s%s\n",
 1230                             td->td_proc->p_pid, td->td_name, msg,
 1231                             c > 1 ? "" : " - not logging anymore");
 1232                         break;
 1233                 }
 1234         }
 1235 }
 1236 #endif
 1237 
 1238 #ifdef _KERNEL
 1239 void
 1240 sbuf_putbuf(struct sbuf *sb)
 1241 {
 1242 
 1243         prf_putbuf(sbuf_data(sb), TOLOG | TOCONS, -1);
 1244 }
 1245 #else
 1246 void
 1247 sbuf_putbuf(struct sbuf *sb)
 1248 {
 1249 
 1250         printf("%s", sbuf_data(sb));
 1251 }
 1252 #endif

Cache object: 9f7687f61275719afe2b07b16c99c333


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