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. 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  * $FreeBSD: src/sys/kern/subr_prf.c,v 1.61.2.5 2002/08/31 18:22:08 dwmalone Exp $
   36  */
   37 
   38 #include "opt_ddb.h"
   39 
   40 #include <sys/param.h>
   41 #include <sys/systm.h>
   42 #include <sys/kernel.h>
   43 #include <sys/msgbuf.h>
   44 #include <sys/malloc.h>
   45 #include <sys/proc.h>
   46 #include <sys/priv.h>
   47 #include <sys/tty.h>
   48 #include <sys/tprintf.h>
   49 #include <sys/stdint.h>
   50 #include <sys/syslog.h>
   51 #include <sys/cons.h>
   52 #include <sys/uio.h>
   53 #include <sys/sysctl.h>
   54 #include <sys/lock.h>
   55 #include <sys/ctype.h>
   56 #include <sys/eventhandler.h>
   57 #include <sys/kthread.h>
   58 
   59 #include <sys/thread2.h>
   60 #include <sys/spinlock2.h>
   61 
   62 #ifdef DDB
   63 #include <ddb/ddb.h>
   64 #endif
   65 
   66 /*
   67  * Note that stdarg.h and the ANSI style va_start macro is used for both
   68  * ANSI and traditional C compilers.  We use the __ machine version to stay
   69  * within the kernel header file set.
   70  */
   71 #include <machine/stdarg.h>
   72 
   73 #define TOCONS          0x01
   74 #define TOTTY           0x02
   75 #define TOLOG           0x04
   76 #define TOWAKEUP        0x08
   77 
   78 /* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */
   79 #define MAXNBUF (sizeof(intmax_t) * NBBY + 1)
   80 
   81 struct putchar_arg {
   82         int     flags;
   83         int     pri;
   84         struct  tty *tty;
   85 };
   86 
   87 struct snprintf_arg {
   88         char    *str;
   89         size_t  remain;
   90 };
   91 
   92 extern  int log_open;
   93 
   94 struct  tty *constty;                   /* pointer to console "window" tty */
   95 
   96 static void  msglogchar(int c, int pri);
   97 static void  msgaddchar(int c, void *dummy);
   98 static void  kputchar (int ch, void *arg);
   99 static char *ksprintn (char *nbuf, uintmax_t num, int base, int *lenp,
  100                        int upper);
  101 static void  snprintf_func (int ch, void *arg);
  102 
  103 static int consintr = 1;                /* Ok to handle console interrupts? */
  104 static int msgbufmapped;                /* Set when safe to use msgbuf */
  105 static struct spinlock cons_spin = SPINLOCK_INITIALIZER(cons_spin);
  106 static thread_t constty_td = NULL;
  107 
  108 int msgbuftrigger;
  109 
  110 static int      log_console_output = 1;
  111 TUNABLE_INT("kern.log_console_output", &log_console_output);
  112 SYSCTL_INT(_kern, OID_AUTO, log_console_output, CTLFLAG_RW,
  113     &log_console_output, 0, "");
  114 
  115 static int unprivileged_read_msgbuf = 1;
  116 SYSCTL_INT(_security, OID_AUTO, unprivileged_read_msgbuf, CTLFLAG_RW,
  117     &unprivileged_read_msgbuf, 0,
  118     "Unprivileged processes may read the kernel message buffer");
  119 
  120 /*
  121  * Warn that a system table is full.
  122  */
  123 void
  124 tablefull(const char *tab)
  125 {
  126 
  127         log(LOG_ERR, "%s: table is full\n", tab);
  128 }
  129 
  130 /*
  131  * Uprintf prints to the controlling terminal for the current process.
  132  */
  133 int
  134 uprintf(const char *fmt, ...)
  135 {
  136         struct proc *p = curproc;
  137         __va_list ap;
  138         struct putchar_arg pca;
  139         int retval = 0;
  140 
  141         if (p && (p->p_flags & P_CONTROLT) && p->p_session->s_ttyvp) {
  142                 __va_start(ap, fmt);
  143                 pca.tty = p->p_session->s_ttyp;
  144                 pca.flags = TOTTY;
  145 
  146                 retval = kvcprintf(fmt, kputchar, &pca, 10, ap);
  147                 __va_end(ap);
  148         }
  149         return (retval);
  150 }
  151 
  152 tpr_t
  153 tprintf_open(struct proc *p)
  154 {
  155         if ((p->p_flags & P_CONTROLT) && p->p_session->s_ttyvp) {
  156                 sess_hold(p->p_session);
  157                 return ((tpr_t) p->p_session);
  158         }
  159         return (NULL);
  160 }
  161 
  162 void
  163 tprintf_close(tpr_t sess)
  164 {
  165         if (sess)
  166                 sess_rele((struct session *) sess);
  167 }
  168 
  169 /*
  170  * tprintf prints on the controlling terminal associated
  171  * with the given session.
  172  */
  173 int
  174 tprintf(tpr_t tpr, const char *fmt, ...)
  175 {
  176         struct session *sess = (struct session *)tpr;
  177         struct tty *tp = NULL;
  178         int flags = TOLOG;
  179         __va_list ap;
  180         struct putchar_arg pca;
  181         int retval;
  182 
  183         if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) {
  184                 flags |= TOTTY;
  185                 tp = sess->s_ttyp;
  186         }
  187         __va_start(ap, fmt);
  188         pca.tty = tp;
  189         pca.flags = flags;
  190         pca.pri = LOG_INFO;
  191         retval = kvcprintf(fmt, kputchar, &pca, 10, ap);
  192         __va_end(ap);
  193         msgbuftrigger = 1;
  194         return (retval);
  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 = kvcprintf(fmt, kputchar, &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 int
  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 = kvcprintf(fmt, kputchar, &pca, 10, ap);
  235         __va_end(ap);
  236 
  237         msgbuftrigger = 1;
  238         return (retval);
  239 }
  240 
  241 #define CONSCHUNK 128
  242 
  243 void
  244 log_console(struct uio *uio)
  245 {
  246         int c, i, error, iovlen, nl;
  247         struct uio muio;
  248         struct iovec *miov = NULL;
  249         char *consbuffer;
  250         int pri;
  251 
  252         if (!log_console_output)
  253                 return;
  254 
  255         pri = LOG_INFO | LOG_CONSOLE;
  256         muio = *uio;
  257         iovlen = uio->uio_iovcnt * sizeof (struct iovec);
  258         miov = kmalloc(iovlen, M_TEMP, M_WAITOK);
  259         consbuffer = kmalloc(CONSCHUNK, M_TEMP, M_WAITOK);
  260         bcopy((caddr_t)muio.uio_iov, (caddr_t)miov, iovlen);
  261         muio.uio_iov = miov;
  262         uio = &muio;
  263 
  264         nl = 0;
  265         while (uio->uio_resid > 0) {
  266                 c = (int)szmin(uio->uio_resid, CONSCHUNK);
  267                 error = uiomove(consbuffer, (size_t)c, uio);
  268                 if (error != 0)
  269                         break;
  270                 for (i = 0; i < c; i++) {
  271                         msglogchar(consbuffer[i], pri);
  272                         if (consbuffer[i] == '\n')
  273                                 nl = 1;
  274                         else
  275                                 nl = 0;
  276                 }
  277         }
  278         if (!nl)
  279                 msglogchar('\n', pri);
  280         msgbuftrigger = 1;
  281         kfree(miov, M_TEMP);
  282         kfree(consbuffer, M_TEMP);
  283         return;
  284 }
  285 
  286 /*
  287  * Output to the console.
  288  */
  289 int
  290 kprintf(const char *fmt, ...)
  291 {
  292         __va_list ap;
  293         int savintr;
  294         struct putchar_arg pca;
  295         int retval;
  296 
  297         savintr = consintr;             /* disable interrupts */
  298         consintr = 0;
  299         __va_start(ap, fmt);
  300         pca.tty = NULL;
  301         pca.flags = TOCONS | TOLOG;
  302         pca.pri = -1;
  303         retval = kvcprintf(fmt, kputchar, &pca, 10, ap);
  304         __va_end(ap);
  305         if (!panicstr)
  306                 msgbuftrigger = 1;
  307         consintr = savintr;             /* reenable interrupts */
  308         return (retval);
  309 }
  310 
  311 int
  312 kvprintf(const char *fmt, __va_list ap)
  313 {
  314         int savintr;
  315         struct putchar_arg pca;
  316         int retval;
  317 
  318         savintr = consintr;             /* disable interrupts */
  319         consintr = 0;
  320         pca.tty = NULL;
  321         pca.flags = TOCONS | TOLOG;
  322         pca.pri = -1;
  323         retval = kvcprintf(fmt, kputchar, &pca, 10, ap);
  324         if (!panicstr)
  325                 msgbuftrigger = 1;
  326         consintr = savintr;             /* reenable interrupts */
  327         return (retval);
  328 }
  329 
  330 /*
  331  * Limited rate kprintf.  The passed rate structure must be initialized
  332  * with the desired reporting frequency.  A frequency of 0 will result in
  333  * no output.
  334  *
  335  * count may be initialized to a negative number to allow an initial
  336  * burst.
  337  */
  338 void
  339 krateprintf(struct krate *rate, const char *fmt, ...)
  340 {
  341         __va_list ap;
  342 
  343         if (rate->ticks != (int)time_uptime) {
  344                 rate->ticks = (int)time_uptime;
  345                 if (rate->count > 0)
  346                         rate->count = 0;
  347         }
  348         if (rate->count < rate->freq) {
  349                 ++rate->count;
  350                 __va_start(ap, fmt);
  351                 kvprintf(fmt, ap);
  352                 __va_end(ap);
  353         }
  354 }
  355 
  356 /*
  357  * Print a character to the dmesg log, the console, and/or the user's
  358  * terminal.
  359  *
  360  * NOTE: TOTTY does not require nonblocking operation, but TOCONS
  361  *       and TOLOG do.  When we have a constty we still output to
  362  *       the real console but we have a monitoring thread which
  363  *       we wakeup which tracks the log.
  364  */
  365 static void
  366 kputchar(int c, void *arg)
  367 {
  368         struct putchar_arg *ap = (struct putchar_arg*) arg;
  369         int flags = ap->flags;
  370         struct tty *tp = ap->tty;
  371 
  372         if (panicstr)
  373                 constty = NULL;
  374         if ((flags & TOCONS) && tp == NULL && constty)
  375                 flags |= TOLOG | TOWAKEUP;
  376         if ((flags & TOTTY) && tputchar(c, tp) < 0)
  377                 ap->flags &= ~TOTTY;
  378         if ((flags & TOLOG))
  379                 msglogchar(c, ap->pri);
  380         if ((flags & TOCONS) && c)
  381                 cnputc(c);
  382         if (flags & TOWAKEUP)
  383                 wakeup(constty_td);
  384 }
  385 
  386 /*
  387  * Scaled down version of sprintf(3).
  388  */
  389 int
  390 ksprintf(char *buf, const char *cfmt, ...)
  391 {
  392         int retval;
  393         __va_list ap;
  394 
  395         __va_start(ap, cfmt);
  396         retval = kvcprintf(cfmt, NULL, buf, 10, ap);
  397         buf[retval] = '\0';
  398         __va_end(ap);
  399         return (retval);
  400 }
  401 
  402 /*
  403  * Scaled down version of vsprintf(3).
  404  */
  405 int
  406 kvsprintf(char *buf, const char *cfmt, __va_list ap)
  407 {
  408         int retval;
  409 
  410         retval = kvcprintf(cfmt, NULL, buf, 10, ap);
  411         buf[retval] = '\0';
  412         return (retval);
  413 }
  414 
  415 /*
  416  * Scaled down version of snprintf(3).
  417  */
  418 int
  419 ksnprintf(char *str, size_t size, const char *format, ...)
  420 {
  421         int retval;
  422         __va_list ap;
  423 
  424         __va_start(ap, format);
  425         retval = kvsnprintf(str, size, format, ap);
  426         __va_end(ap);
  427         return(retval);
  428 }
  429 
  430 /*
  431  * Scaled down version of vsnprintf(3).
  432  */
  433 int
  434 kvsnprintf(char *str, size_t size, const char *format, __va_list ap)
  435 {
  436         struct snprintf_arg info;
  437         int retval;
  438 
  439         info.str = str;
  440         info.remain = size;
  441         retval = kvcprintf(format, snprintf_func, &info, 10, ap);
  442         if (info.remain >= 1)
  443                 *info.str++ = '\0';
  444         return (retval);
  445 }
  446 
  447 int
  448 ksnrprintf(char *str, size_t size, int radix, const char *format, ...)
  449 {
  450         int retval;
  451         __va_list ap;
  452 
  453         __va_start(ap, format);
  454         retval = kvsnrprintf(str, size, radix, format, ap);
  455         __va_end(ap);
  456         return(retval);
  457 }
  458 
  459 int
  460 kvsnrprintf(char *str, size_t size, int radix, const char *format, __va_list ap)
  461 {
  462         struct snprintf_arg info;
  463         int retval;
  464 
  465         info.str = str;
  466         info.remain = size;
  467         retval = kvcprintf(format, snprintf_func, &info, radix, ap);
  468         if (info.remain >= 1)
  469                 *info.str++ = '\0';
  470         return (retval);
  471 }
  472 
  473 int
  474 kvasnrprintf(char **strp, size_t size, int radix,
  475              const char *format, __va_list ap)
  476 {
  477         struct snprintf_arg info;
  478         int retval;
  479 
  480         *strp = kmalloc(size, M_TEMP, M_WAITOK);
  481         info.str = *strp;
  482         info.remain = size;
  483         retval = kvcprintf(format, snprintf_func, &info, radix, ap);
  484         if (info.remain >= 1)
  485                 *info.str++ = '\0';
  486         return (retval);
  487 }
  488 
  489 void
  490 kvasfree(char **strp)
  491 {
  492         if (*strp) {
  493                 kfree(*strp, M_TEMP);
  494                 *strp = NULL;
  495         }
  496 }
  497 
  498 static void
  499 snprintf_func(int ch, void *arg)
  500 {
  501         struct snprintf_arg *const info = arg;
  502 
  503         if (info->remain >= 2) {
  504                 *info->str++ = ch;
  505                 info->remain--;
  506         }
  507 }
  508 
  509 /*
  510  * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
  511  * order; return an optional length and a pointer to the last character
  512  * written in the buffer (i.e., the first character of the string).
  513  * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
  514  */
  515 static char *
  516 ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
  517 {
  518         char *p, c;
  519 
  520         p = nbuf;
  521         *p = '\0';
  522         do {
  523                 c = hex2ascii(num % base);
  524                 *++p = upper ? toupper(c) : c;
  525         } while (num /= base);
  526         if (lenp)
  527                 *lenp = p - nbuf;
  528         return (p);
  529 }
  530 
  531 /*
  532  * Scaled down version of printf(3).
  533  *
  534  * Two additional formats:
  535  *
  536  * The format %b is supported to decode error registers.
  537  * Its usage is:
  538  *
  539  *      kprintf("reg=%b\n", regval, "<base><arg>*");
  540  *
  541  * where <base> is the output base expressed as a control character, e.g.
  542  * \10 gives octal; \20 gives hex.  Each arg is a sequence of characters,
  543  * the first of which gives the bit number to be inspected (origin 1), and
  544  * the next characters (up to a control character, i.e. a character <= 32),
  545  * give the name of the register.  Thus:
  546  *
  547  *      kvcprintf("reg=%b\n", 3, "\1\2BITTWO\1BITONE\n");
  548  *
  549  * would produce output:
  550  *
  551  *      reg=3<BITTWO,BITONE>
  552  */
  553 
  554 #define PCHAR(c) {int cc=(c); if(func) (*func)(cc,arg); else *d++=cc; retval++;}
  555 
  556 int
  557 kvcprintf(char const *fmt, void (*func)(int, void*), void *arg,
  558           int radix, __va_list ap)
  559 {
  560         char nbuf[MAXNBUF];
  561         char *d;
  562         const char *p, *percent, *q;
  563         int ch, n;
  564         uintmax_t num;
  565         int base, tmp, width, ladjust, sharpflag, neg, sign, dot;
  566         int cflag, hflag, jflag, lflag, qflag, tflag, zflag;
  567         int dwidth, upper;
  568         char padc;
  569         int retval = 0, stop = 0;
  570         int usespin;
  571 
  572         /*
  573          * Make a supreme effort to avoid reentrant panics or deadlocks.
  574          *
  575          * NOTE!  Do nothing that would access mycpu/gd/fs unless the
  576          *        function is the normal kputchar(), which allows us to
  577          *        use this function for very early debugging with a special
  578          *        function.
  579          */
  580         if (func == kputchar) {
  581                 if (mycpu->gd_flags & GDF_KPRINTF)
  582                         return(0);
  583                 atomic_set_long(&mycpu->gd_flags, GDF_KPRINTF);
  584         }
  585 
  586         num = 0;
  587         if (!func)
  588                 d = (char *) arg;
  589         else
  590                 d = NULL;
  591 
  592         if (fmt == NULL)
  593                 fmt = "(fmt null)\n";
  594 
  595         if (radix < 2 || radix > 36)
  596                 radix = 10;
  597 
  598         usespin = (func == kputchar &&
  599                    panic_cpu_gd != mycpu &&
  600                    (((struct putchar_arg *)arg)->flags & TOTTY) == 0);
  601         if (usespin) {
  602                 crit_enter_hard();
  603                 spin_lock(&cons_spin);
  604         }
  605 
  606         for (;;) {
  607                 padc = ' ';
  608                 width = 0;
  609                 while ((ch = (u_char)*fmt++) != '%' || stop) {
  610                         if (ch == '\0')
  611                                 goto done;
  612                         PCHAR(ch);
  613                 }
  614                 percent = fmt - 1;
  615                 dot = dwidth = ladjust = neg = sharpflag = sign = upper = 0;
  616                 cflag = hflag = jflag = lflag = qflag = tflag = zflag = 0;
  617 
  618 reswitch:
  619                 switch (ch = (u_char)*fmt++) {
  620                 case '.':
  621                         dot = 1;
  622                         goto reswitch;
  623                 case '#':
  624                         sharpflag = 1;
  625                         goto reswitch;
  626                 case '+':
  627                         sign = 1;
  628                         goto reswitch;
  629                 case '-':
  630                         ladjust = 1;
  631                         goto reswitch;
  632                 case '%':
  633                         PCHAR(ch);
  634                         break;
  635                 case '*':
  636                         if (!dot) {
  637                                 width = __va_arg(ap, int);
  638                                 if (width < 0) {
  639                                         ladjust = !ladjust;
  640                                         width = -width;
  641                                 }
  642                         } else {
  643                                 dwidth = __va_arg(ap, int);
  644                         }
  645                         goto reswitch;
  646                 case '':
  647                         if (!dot) {
  648                                 padc = '';
  649                                 goto reswitch;
  650                         }
  651                 case '1': case '2': case '3': case '4':
  652                 case '5': case '6': case '7': case '8': case '9':
  653                                 for (n = 0;; ++fmt) {
  654                                         n = n * 10 + ch - '';
  655                                         ch = *fmt;
  656                                         if (ch < '' || ch > '9')
  657                                                 break;
  658                                 }
  659                         if (dot)
  660                                 dwidth = n;
  661                         else
  662                                 width = n;
  663                         goto reswitch;
  664                 case 'b':
  665                         num = (u_int)__va_arg(ap, int);
  666                         p = __va_arg(ap, char *);
  667                         for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;)
  668                                 PCHAR(*q--);
  669 
  670                         if (num == 0)
  671                                 break;
  672 
  673                         for (tmp = 0; *p;) {
  674                                 n = *p++;
  675                                 if (num & (1 << (n - 1))) {
  676                                         PCHAR(tmp ? ',' : '<');
  677                                         for (; (n = *p) > ' '; ++p)
  678                                                 PCHAR(n);
  679                                         tmp = 1;
  680                                 } else
  681                                         for (; *p > ' '; ++p)
  682                                                 continue;
  683                         }
  684                         if (tmp)
  685                                 PCHAR('>');
  686                         break;
  687                 case 'c':
  688                         PCHAR(__va_arg(ap, int));
  689                         break;
  690                 case 'd':
  691                 case 'i':
  692                         base = 10;
  693                         sign = 1;
  694                         goto handle_sign;
  695                 case 'h':
  696                         if (hflag) {
  697                                 hflag = 0;
  698                                 cflag = 1;
  699                         } else
  700                                 hflag = 1;
  701                         goto reswitch;
  702                 case 'j':
  703                         jflag = 1;
  704                         goto reswitch;
  705                 case 'l':
  706                         if (lflag) {
  707                                 lflag = 0;
  708                                 qflag = 1;
  709                         } else
  710                                 lflag = 1;
  711                         goto reswitch;
  712                 case 'n':
  713                         if (cflag)
  714                                 *(__va_arg(ap, char *)) = retval;
  715                         else if (hflag)
  716                                 *(__va_arg(ap, short *)) = retval;
  717                         else if (jflag)
  718                                 *(__va_arg(ap, intmax_t *)) = retval;
  719                         else if (lflag)
  720                                 *(__va_arg(ap, long *)) = retval;
  721                         else if (qflag)
  722                                 *(__va_arg(ap, quad_t *)) = retval;
  723                         else
  724                                 *(__va_arg(ap, int *)) = retval;
  725                         break;
  726                 case 'o':
  727                         base = 8;
  728                         goto handle_nosign;
  729                 case 'p':
  730                         base = 16;
  731                         sharpflag = (width == 0);
  732                         sign = 0;
  733                         num = (uintptr_t)__va_arg(ap, void *);
  734                         goto number;
  735                 case 'q':
  736                         qflag = 1;
  737                         goto reswitch;
  738                 case 'r':
  739                         base = radix;
  740                         if (sign)
  741                                 goto handle_sign;
  742                         goto handle_nosign;
  743                 case 's':
  744                         p = __va_arg(ap, char *);
  745                         if (p == NULL)
  746                                 p = "(null)";
  747                         if (!dot)
  748                                 n = strlen (p);
  749                         else
  750                                 for (n = 0; n < dwidth && p[n]; n++)
  751                                         continue;
  752 
  753                         width -= n;
  754 
  755                         if (!ladjust && width > 0)
  756                                 while (width--)
  757                                         PCHAR(padc);
  758                         while (n--)
  759                                 PCHAR(*p++);
  760                         if (ladjust && width > 0)
  761                                 while (width--)
  762                                         PCHAR(padc);
  763                         break;
  764                 case 't':
  765                         tflag = 1;
  766                         goto reswitch;
  767                 case 'u':
  768                         base = 10;
  769                         goto handle_nosign;
  770                 case 'X':
  771                         upper = 1;
  772                         /* FALLTHROUGH */
  773                 case 'x':
  774                         base = 16;
  775                         goto handle_nosign;
  776                 case 'z':
  777                         zflag = 1;
  778                         goto reswitch;
  779 handle_nosign:
  780                         sign = 0;
  781                         if (cflag)
  782                                 num = (u_char)__va_arg(ap, int);
  783                         else if (hflag)
  784                                 num = (u_short)__va_arg(ap, int);
  785                         else if (jflag)
  786                                 num = __va_arg(ap, uintmax_t);
  787                         else if (lflag)
  788                                 num = __va_arg(ap, u_long);
  789                         else if (qflag)
  790                                 num = __va_arg(ap, u_quad_t);
  791                         else if (tflag)
  792                                 num = __va_arg(ap, ptrdiff_t);
  793                         else if (zflag)
  794                                 num = __va_arg(ap, size_t);
  795                         else
  796                                 num = __va_arg(ap, u_int);
  797                         goto number;
  798 handle_sign:
  799                         if (cflag)
  800                                 num = (char)__va_arg(ap, int);
  801                         else if (hflag)
  802                                 num = (short)__va_arg(ap, int);
  803                         else if (jflag)
  804                                 num = __va_arg(ap, intmax_t);
  805                         else if (lflag)
  806                                 num = __va_arg(ap, long);
  807                         else if (qflag)
  808                                 num = __va_arg(ap, quad_t);
  809                         else if (tflag)
  810                                 num = __va_arg(ap, ptrdiff_t);
  811                         else if (zflag)
  812                                 num = __va_arg(ap, ssize_t);
  813                         else
  814                                 num = __va_arg(ap, int);
  815 number:
  816                         if (sign && (intmax_t)num < 0) {
  817                                 neg = 1;
  818                                 num = -(intmax_t)num;
  819                         }
  820                         p = ksprintn(nbuf, num, base, &n, upper);
  821                         tmp = 0;
  822                         if (sharpflag && num != 0) {
  823                                 if (base == 8)
  824                                         tmp++;
  825                                 else if (base == 16)
  826                                         tmp += 2;
  827                         }
  828                         if (neg)
  829                                 tmp++;
  830 
  831                         if (!ladjust && padc == '')
  832                                 dwidth = width - tmp;
  833                         width -= tmp + imax(dwidth, n);
  834                         dwidth -= n;
  835                         if (!ladjust)
  836                                 while (width-- > 0)
  837                                         PCHAR(' ');
  838                         if (neg)
  839                                 PCHAR('-');
  840                         if (sharpflag && num != 0) {
  841                                 if (base == 8) {
  842                                         PCHAR('');
  843                                 } else if (base == 16) {
  844                                         PCHAR('');
  845                                         PCHAR('x');
  846                                 }
  847                         }
  848                         while (dwidth-- > 0)
  849                                 PCHAR('');
  850 
  851                         while (*p)
  852                                 PCHAR(*p--);
  853 
  854                         if (ladjust)
  855                                 while (width-- > 0)
  856                                         PCHAR(' ');
  857 
  858                         break;
  859                 default:
  860                         while (percent < fmt)
  861                                 PCHAR(*percent++);
  862                         /*
  863                          * Since we ignore an formatting argument it is no 
  864                          * longer safe to obey the remaining formatting
  865                          * arguments as the arguments will no longer match
  866                          * the format specs.
  867                          */
  868                         stop = 1;
  869                         break;
  870                 }
  871         }
  872 done:
  873         /*
  874          * Cleanup reentrancy issues.
  875          */
  876         if (func == kputchar)
  877                 atomic_clear_long(&mycpu->gd_flags, GDF_KPRINTF);
  878         if (usespin) {
  879                 spin_unlock(&cons_spin);
  880                 crit_exit_hard();
  881         }
  882         return (retval);
  883 }
  884 
  885 #undef PCHAR
  886 
  887 /*
  888  * Called from the panic code to try to get the console working
  889  * again in case we paniced inside a kprintf().
  890  */
  891 void
  892 kvcreinitspin(void)
  893 {
  894         spin_init(&cons_spin);
  895         atomic_clear_long(&mycpu->gd_flags, GDF_KPRINTF);
  896 }
  897 
  898 /*
  899  * Console support thread for constty intercepts.  This is needed because
  900  * console tty intercepts can block.  Instead of having kputchar() attempt
  901  * to directly write to the console intercept we just force it to log
  902  * and wakeup this baby to track and dump the log to constty.
  903  */
  904 static void
  905 constty_daemon(void)
  906 {
  907         int rindex = -1;
  908         int windex = -1;
  909         struct msgbuf *mbp;
  910         struct tty *tp;
  911 
  912         EVENTHANDLER_REGISTER(shutdown_pre_sync, shutdown_kproc,
  913                               constty_td, SHUTDOWN_PRI_FIRST);
  914         constty_td->td_flags |= TDF_SYSTHREAD;
  915 
  916         for (;;) {
  917                 kproc_suspend_loop();
  918 
  919                 crit_enter();
  920                 mbp = msgbufp;
  921                 if (mbp == NULL || msgbufmapped == 0 ||
  922                     windex == mbp->msg_bufx) {
  923                         tsleep(constty_td, 0, "waiting", hz*60);
  924                         crit_exit();
  925                         continue;
  926                 }
  927                 windex = mbp->msg_bufx;
  928                 crit_exit();
  929 
  930                 /*
  931                  * Get message buf FIFO indices.  rindex is tracking.
  932                  */
  933                 if ((tp = constty) == NULL) {
  934                         rindex = mbp->msg_bufx;
  935                         continue;
  936                 }
  937 
  938                 /*
  939                  * Don't blow up if the message buffer is broken
  940                  */
  941                 if (windex < 0 || windex >= mbp->msg_size)
  942                         continue;
  943                 if (rindex < 0 || rindex >= mbp->msg_size)
  944                         rindex = windex;
  945 
  946                 /*
  947                  * And dump it.  If constty gets stuck will give up.
  948                  */
  949                 while (rindex != windex) {
  950                         if (tputchar((uint8_t)mbp->msg_ptr[rindex], tp) < 0) {
  951                                 constty = NULL;
  952                                 rindex = mbp->msg_bufx;
  953                                 break;
  954                         }
  955                         if (++rindex >= mbp->msg_size)
  956                                 rindex = 0;
  957                         if (tp->t_outq.c_cc >= tp->t_ohiwat) {
  958                                 tsleep(constty_daemon, 0, "blocked", hz / 10);
  959                                 if (tp->t_outq.c_cc >= tp->t_ohiwat) {
  960                                         rindex = windex;
  961                                         break;
  962                                 }
  963                         }
  964                 }
  965         }
  966 }
  967 
  968 static struct kproc_desc constty_kp = {
  969         "consttyd",
  970         constty_daemon,
  971         &constty_td
  972 };
  973 SYSINIT(bufdaemon, SI_SUB_KTHREAD_UPDATE, SI_ORDER_ANY,
  974         kproc_start, &constty_kp)
  975 
  976 /*
  977  * Put character in log buffer with a particular priority.
  978  *
  979  * MPSAFE
  980  */
  981 static void
  982 msglogchar(int c, int pri)
  983 {
  984         static int lastpri = -1;
  985         static int dangling;
  986         char nbuf[MAXNBUF];
  987         char *p;
  988 
  989         if (!msgbufmapped)
  990                 return;
  991         if (c == '\0' || c == '\r')
  992                 return;
  993         if (pri != -1 && pri != lastpri) {
  994                 if (dangling) {
  995                         msgaddchar('\n', NULL);
  996                         dangling = 0;
  997                 }
  998                 msgaddchar('<', NULL);
  999                 for (p = ksprintn(nbuf, (uintmax_t)pri, 10, NULL, 0); *p;)
 1000                         msgaddchar(*p--, NULL);
 1001                 msgaddchar('>', NULL);
 1002                 lastpri = pri;
 1003         }
 1004         msgaddchar(c, NULL);
 1005         if (c == '\n') {
 1006                 dangling = 0;
 1007                 lastpri = -1;
 1008         } else {
 1009                 dangling = 1;
 1010         }
 1011 }
 1012 
 1013 /*
 1014  * Put char in log buffer.   Make sure nothing blows up beyond repair if
 1015  * we have an MP race.
 1016  *
 1017  * MPSAFE.
 1018  */
 1019 static void
 1020 msgaddchar(int c, void *dummy)
 1021 {
 1022         struct msgbuf *mbp;
 1023         int rindex;
 1024         int windex;
 1025 
 1026         if (!msgbufmapped)
 1027                 return;
 1028         mbp = msgbufp;
 1029         windex = mbp->msg_bufx;
 1030         mbp->msg_ptr[windex] = c;
 1031         if (++windex >= mbp->msg_size)
 1032                 windex = 0;
 1033         rindex = mbp->msg_bufr;
 1034         if (windex == rindex) {
 1035                 rindex += 32;
 1036                 if (rindex >= mbp->msg_size)
 1037                         rindex -= mbp->msg_size;
 1038                 mbp->msg_bufr = rindex;
 1039         }
 1040         mbp->msg_bufx = windex;
 1041 }
 1042 
 1043 static void
 1044 msgbufcopy(struct msgbuf *oldp)
 1045 {
 1046         int pos;
 1047 
 1048         pos = oldp->msg_bufr;
 1049         while (pos != oldp->msg_bufx) {
 1050                 msglogchar(oldp->msg_ptr[pos], -1);
 1051                 if (++pos >= oldp->msg_size)
 1052                         pos = 0;
 1053         }
 1054 }
 1055 
 1056 void
 1057 msgbufinit(void *ptr, size_t size)
 1058 {
 1059         char *cp;
 1060         static struct msgbuf *oldp = NULL;
 1061 
 1062         size -= sizeof(*msgbufp);
 1063         cp = (char *)ptr;
 1064         msgbufp = (struct msgbuf *) (cp + size);
 1065         if (msgbufp->msg_magic != MSG_MAGIC || msgbufp->msg_size != size ||
 1066             msgbufp->msg_bufx >= size || msgbufp->msg_bufr >= size) {
 1067                 bzero(cp, size);
 1068                 bzero(msgbufp, sizeof(*msgbufp));
 1069                 msgbufp->msg_magic = MSG_MAGIC;
 1070                 msgbufp->msg_size = (char *)msgbufp - cp;
 1071         }
 1072         msgbufp->msg_ptr = cp;
 1073         if (msgbufmapped && oldp != msgbufp)
 1074                 msgbufcopy(oldp);
 1075         msgbufmapped = 1;
 1076         oldp = msgbufp;
 1077 }
 1078 
 1079 /* Sysctls for accessing/clearing the msgbuf */
 1080 
 1081 static int
 1082 sysctl_kern_msgbuf(SYSCTL_HANDLER_ARGS)
 1083 {
 1084         struct ucred *cred;
 1085         int error;
 1086 
 1087         /*
 1088          * Only wheel or root can access the message log.
 1089          */
 1090         if (unprivileged_read_msgbuf == 0) {
 1091                 KKASSERT(req->td->td_proc);
 1092                 cred = req->td->td_proc->p_ucred;
 1093 
 1094                 if ((cred->cr_prison || groupmember(0, cred) == 0) &&
 1095                     priv_check(req->td, PRIV_ROOT) != 0
 1096                 ) {
 1097                         return (EPERM);
 1098                 }
 1099         }
 1100 
 1101         /*
 1102          * Unwind the buffer, so that it's linear (possibly starting with
 1103          * some initial nulls).
 1104          */
 1105         error = sysctl_handle_opaque(oidp, msgbufp->msg_ptr + msgbufp->msg_bufx,
 1106             msgbufp->msg_size - msgbufp->msg_bufx, req);
 1107         if (error)
 1108                 return (error);
 1109         if (msgbufp->msg_bufx > 0) {
 1110                 error = sysctl_handle_opaque(oidp, msgbufp->msg_ptr,
 1111                     msgbufp->msg_bufx, req);
 1112         }
 1113         return (error);
 1114 }
 1115 
 1116 SYSCTL_PROC(_kern, OID_AUTO, msgbuf, CTLTYPE_STRING | CTLFLAG_RD,
 1117     0, 0, sysctl_kern_msgbuf, "A", "Contents of kernel message buffer");
 1118 
 1119 static int msgbuf_clear;
 1120 
 1121 static int
 1122 sysctl_kern_msgbuf_clear(SYSCTL_HANDLER_ARGS)
 1123 {
 1124         int error;
 1125         error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
 1126         if (!error && req->newptr) {
 1127                 /* Clear the buffer and reset write pointer */
 1128                 bzero(msgbufp->msg_ptr, msgbufp->msg_size);
 1129                 msgbufp->msg_bufr = msgbufp->msg_bufx = 0;
 1130                 msgbuf_clear = 0;
 1131         }
 1132         return (error);
 1133 }
 1134 
 1135 SYSCTL_PROC(_kern, OID_AUTO, msgbuf_clear,
 1136     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE, &msgbuf_clear, 0,
 1137     sysctl_kern_msgbuf_clear, "I", "Clear kernel message buffer");
 1138 
 1139 #ifdef DDB
 1140 
 1141 DB_SHOW_COMMAND(msgbuf, db_show_msgbuf)
 1142 {
 1143         int i, j;
 1144 
 1145         if (!msgbufmapped) {
 1146                 db_printf("msgbuf not mapped yet\n");
 1147                 return;
 1148         }
 1149         db_printf("msgbufp = %p\n", msgbufp);
 1150         db_printf("magic = %x, size = %d, r= %d, w = %d, ptr = %p\n",
 1151             msgbufp->msg_magic, msgbufp->msg_size, msgbufp->msg_bufr,
 1152             msgbufp->msg_bufx, msgbufp->msg_ptr);
 1153         for (i = 0; i < msgbufp->msg_size; i++) {
 1154                 j = (i + msgbufp->msg_bufr) % msgbufp->msg_size;
 1155                 db_printf("%c", msgbufp->msg_ptr[j]);
 1156         }
 1157         db_printf("\n");
 1158 }
 1159 
 1160 #endif /* DDB */
 1161 
 1162 
 1163 void
 1164 hexdump(const void *ptr, int length, const char *hdr, 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                         kprintf("%s", hdr);
 1185 
 1186                 if ((flags & HD_OMIT_COUNT) == 0)
 1187                         kprintf("%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                                         kprintf("%c%02x", delim, cp[k]);
 1194                                 else
 1195                                         kprintf("   ");
 1196                         }
 1197                 }
 1198 
 1199                 if ((flags & HD_OMIT_CHARS) == 0) {
 1200                         kprintf("  |");
 1201                         for (j = 0; j < cols; j++) {
 1202                                 k = i + j;
 1203                                 if (k >= length)
 1204                                         kprintf(" ");
 1205                                 else if (cp[k] >= ' ' && cp[k] <= '~')
 1206                                         kprintf("%c", cp[k]);
 1207                                 else
 1208                                         kprintf(".");
 1209                         }
 1210                         kprintf("|");
 1211                 }
 1212                 kprintf("\n");
 1213         }
 1214 }

Cache object: b700b1151d733d0e966d71fb23e47d09


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