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

Cache object: c0e2a139d6e772c254cb0f66db915c75


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