LCOV - code coverage report
Current view: top level - kern - subr_prf.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 375 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 22 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: subr_prf.c,v 1.95 2018/04/10 09:24:56 mpi Exp $       */
       2             : /*      $NetBSD: subr_prf.c,v 1.45 1997/10/24 18:14:25 chuck Exp $      */
       3             : 
       4             : /*-
       5             :  * Copyright (c) 1986, 1988, 1991, 1993
       6             :  *      The Regents of the University of California.  All rights reserved.
       7             :  * (c) UNIX System Laboratories, Inc.
       8             :  * All or some portions of this file are derived from material licensed
       9             :  * to the University of California by American Telephone and Telegraph
      10             :  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
      11             :  * the permission of UNIX System Laboratories, Inc.
      12             :  *
      13             :  * Redistribution and use in source and binary forms, with or without
      14             :  * modification, are permitted provided that the following conditions
      15             :  * are met:
      16             :  * 1. Redistributions of source code must retain the above copyright
      17             :  *    notice, this list of conditions and the following disclaimer.
      18             :  * 2. Redistributions in binary form must reproduce the above copyright
      19             :  *    notice, this list of conditions and the following disclaimer in the
      20             :  *    documentation and/or other materials provided with the distribution.
      21             :  * 3. Neither the name of the University nor the names of its contributors
      22             :  *    may be used to endorse or promote products derived from this software
      23             :  *    without specific prior written permission.
      24             :  *
      25             :  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      26             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      27             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      28             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      29             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      30             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      31             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      32             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      33             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      34             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      35             :  * SUCH DAMAGE.
      36             :  *
      37             :  *      @(#)subr_prf.c  8.3 (Berkeley) 1/21/94
      38             :  */
      39             : 
      40             : #include <sys/param.h>
      41             : #include <sys/systm.h>
      42             : #include <sys/conf.h>
      43             : #include <sys/reboot.h>
      44             : #include <sys/msgbuf.h>
      45             : #include <sys/proc.h>
      46             : #include <sys/ioctl.h>
      47             : #include <sys/vnode.h>
      48             : #include <sys/tty.h>
      49             : #include <sys/tprintf.h>
      50             : #include <sys/syslog.h>
      51             : #include <sys/malloc.h>
      52             : #include <sys/pool.h>
      53             : #include <sys/mutex.h>
      54             : 
      55             : #include <dev/cons.h>
      56             : 
      57             : /*
      58             :  * note that stdarg.h and the ansi style va_start macro is used for both
      59             :  * ansi and traditional c compilers.
      60             :  */
      61             : #include <sys/stdarg.h>
      62             : 
      63             : #ifdef DDB
      64             : #include <ddb/db_output.h>        /* db_printf, db_putchar prototypes */
      65             : #include <ddb/db_var.h>           /* db_log, db_radix */
      66             : #endif
      67             : 
      68             : 
      69             : /*
      70             :  * defines
      71             :  */
      72             : 
      73             : /* flags for kprintf */
      74             : #define TOCONS          0x01    /* to the console */
      75             : #define TOTTY           0x02    /* to the process' tty */
      76             : #define TOLOG           0x04    /* to the kernel message buffer */
      77             : #define TOBUFONLY       0x08    /* to the buffer (only) [for snprintf] */
      78             : #define TODDB           0x10    /* to ddb console */
      79             : #define TOCOUNT         0x20    /* act like [v]snprintf */
      80             : 
      81             : /* max size buffer kprintf needs to print quad_t [size in base 8 + \0] */
      82             : #define KPRINTF_BUFSIZE         (sizeof(quad_t) * NBBY / 3 + 2)
      83             : 
      84             : 
      85             : /*
      86             :  * local prototypes
      87             :  */
      88             : 
      89             : int      kprintf(const char *, int, void *, char *, va_list);
      90             : void     kputchar(int, int, struct tty *);
      91             : 
      92             : struct mutex kprintf_mutex =
      93             :     MUTEX_INITIALIZER_FLAGS(IPL_HIGH, "kprintf", MTX_NOWITNESS);
      94             : 
      95             : /*
      96             :  * globals
      97             :  */
      98             : 
      99             : extern  int log_open;   /* subr_log: is /dev/klog open? */
     100             : const   char *panicstr; /* arg to first call to panic (used as a flag
     101             :                            to indicate that panic has already been called). */
     102             : const   char *faultstr; /* page fault string */
     103             : #ifdef DDB
     104             : /*
     105             :  * Enter ddb on panic.
     106             :  */
     107             : int     db_panic = 1;
     108             : 
     109             : /*
     110             :  * db_console controls if we can be able to enter ddb by a special key
     111             :  * combination (machine dependent).
     112             :  * If DDB_SAFE_CONSOLE is defined in the kernel configuration it allows
     113             :  * to break into console during boot. It's _really_ useful when debugging
     114             :  * some things in the kernel that can cause init(8) to crash.
     115             :  */
     116             : #ifdef DDB_SAFE_CONSOLE
     117             : int     db_console = 1;
     118             : #else
     119             : int     db_console = 0;
     120             : #endif
     121             : 
     122             : /*
     123             :  * flag to indicate if we are currently in ddb (on some processor)
     124             :  */
     125             : int db_is_active;
     126             : #endif
     127             : 
     128             : /*
     129             :  * panic on spl assertion failure?
     130             :  */
     131             : int splassert_ctl = 1;
     132             : 
     133             : /*
     134             :  * v_putc: routine to putc on virtual console
     135             :  *
     136             :  * the v_putc pointer can be used to redirect the console cnputc elsewhere
     137             :  * [e.g. to a "virtual console"].
     138             :  */
     139             : 
     140             : void (*v_putc)(int) = cnputc;   /* start with cnputc (normal cons) */
     141             : 
     142             : 
     143             : /*
     144             :  * functions
     145             :  */
     146             : 
     147             : /*
     148             :  *      Partial support (the failure case) of the assertion facility
     149             :  *      commonly found in userland.
     150             :  */
     151             : void
     152           0 : __assert(const char *t, const char *f, int l, const char *e)
     153             : {
     154             : 
     155           0 :         panic(__KASSERTSTR, t, e, f, l);
     156             : }
     157             : 
     158             : /*
     159             :  * tablefull: warn that a system table is full
     160             :  */
     161             : 
     162             : void
     163           0 : tablefull(const char *tab)
     164             : {
     165           0 :         log(LOG_ERR, "%s: table is full\n", tab);
     166           0 : }
     167             : 
     168             : /*
     169             :  * panic: handle an unresolvable fatal error
     170             :  *
     171             :  * prints "panic: <message>" and reboots.   if called twice (i.e. recursive
     172             :  * call) we avoid trying to sync the disk and just reboot (to avoid
     173             :  * recursive panics).
     174             :  */
     175             : 
     176             : void
     177           0 : panic(const char *fmt, ...)
     178             : {
     179             :         static char panicbuf[512];
     180             :         int bootopt;
     181           0 :         va_list ap;
     182             : 
     183             :         /* do not trigger assertions, we know that we are inconsistent */
     184           0 :         splassert_ctl = 0;
     185             : 
     186             :         bootopt = RB_AUTOBOOT | RB_DUMP;
     187           0 :         va_start(ap, fmt);
     188           0 :         if (panicstr)
     189           0 :                 bootopt |= RB_NOSYNC;
     190             :         else {
     191           0 :                 vsnprintf(panicbuf, sizeof panicbuf, fmt, ap);
     192           0 :                 panicstr = panicbuf;
     193             :         }
     194           0 :         va_end(ap);
     195             : 
     196           0 :         printf("panic: ");
     197           0 :         va_start(ap, fmt);
     198           0 :         vprintf(fmt, ap);
     199           0 :         printf("\n");
     200           0 :         va_end(ap);
     201             : 
     202             : #ifdef DDB
     203           0 :         if (db_panic)
     204           0 :                 db_enter();
     205             :         else
     206           0 :                 db_stack_dump();
     207             : #endif
     208           0 :         reboot(bootopt);
     209             :         /* NOTREACHED */
     210             : }
     211             : 
     212             : /*
     213             :  * We print only the function name. The file name is usually very long and
     214             :  * would eat tons of space in the kernel.
     215             :  */
     216             : void
     217           0 : splassert_fail(int wantipl, int haveipl, const char *func)
     218             : {
     219           0 :         if (panicstr || db_active)
     220             :                 return;
     221             : 
     222           0 :         printf("splassert: %s: want %d have %d\n", func, wantipl, haveipl);
     223           0 :         switch (splassert_ctl) {
     224             :         case 1:
     225             :                 break;
     226             :         case 2:
     227             : #ifdef DDB
     228           0 :                 db_stack_dump();
     229             : #endif
     230           0 :                 break;
     231             :         case 3:
     232             : #ifdef DDB
     233           0 :                 db_stack_dump();
     234           0 :                 db_enter();
     235             : #endif
     236           0 :                 break;
     237             :         default:
     238           0 :                 panic("spl assertion failure in %s", func);
     239             :         }
     240           0 : }
     241             : 
     242             : /*
     243             :  * kernel logging functions: log, logpri, addlog
     244             :  */
     245             : 
     246             : /*
     247             :  * log: write to the log buffer
     248             :  *
     249             :  * => will not sleep [so safe to call from interrupt]
     250             :  * => will log to console if /dev/klog isn't open
     251             :  */
     252             : 
     253             : void
     254           0 : log(int level, const char *fmt, ...)
     255             : {
     256             :         int s;
     257           0 :         va_list ap;
     258             : 
     259           0 :         s = splhigh();
     260           0 :         logpri(level);          /* log the level first */
     261           0 :         va_start(ap, fmt);
     262           0 :         kprintf(fmt, TOLOG, NULL, NULL, ap);
     263           0 :         va_end(ap);
     264           0 :         splx(s);
     265           0 :         if (!log_open) {
     266           0 :                 va_start(ap, fmt);
     267           0 :                 mtx_enter(&kprintf_mutex);
     268           0 :                 kprintf(fmt, TOCONS, NULL, NULL, ap);
     269           0 :                 mtx_leave(&kprintf_mutex);
     270           0 :                 va_end(ap);
     271           0 :         }
     272           0 :         logwakeup();            /* wake up anyone waiting for log msgs */
     273           0 : }
     274             : 
     275             : /*
     276             :  * logpri: log the priority level to the klog
     277             :  */
     278             : 
     279             : void
     280           0 : logpri(int level)
     281             : {
     282             :         char *p;
     283           0 :         char snbuf[KPRINTF_BUFSIZE];
     284             : 
     285           0 :         kputchar('<', TOLOG, NULL);
     286           0 :         snprintf(snbuf, sizeof snbuf, "%d", level);
     287           0 :         for (p = snbuf ; *p ; p++)
     288           0 :                 kputchar(*p, TOLOG, NULL);
     289           0 :         kputchar('>', TOLOG, NULL);
     290           0 : }
     291             : 
     292             : /*
     293             :  * addlog: add info to previous log message
     294             :  */
     295             : 
     296             : int
     297           0 : addlog(const char *fmt, ...)
     298             : {
     299             :         int s;
     300           0 :         va_list ap;
     301             : 
     302           0 :         s = splhigh();
     303           0 :         va_start(ap, fmt);
     304           0 :         kprintf(fmt, TOLOG, NULL, NULL, ap);
     305           0 :         va_end(ap);
     306           0 :         splx(s);
     307           0 :         if (!log_open) {
     308           0 :                 va_start(ap, fmt);
     309           0 :                 mtx_enter(&kprintf_mutex);
     310           0 :                 kprintf(fmt, TOCONS, NULL, NULL, ap);
     311           0 :                 mtx_leave(&kprintf_mutex);
     312           0 :                 va_end(ap);
     313           0 :         }
     314           0 :         logwakeup();
     315           0 :         return(0);
     316           0 : }
     317             : 
     318             : 
     319             : /*
     320             :  * kputchar: print a single character on console or user terminal.
     321             :  *
     322             :  * => if console, then the last MSGBUFS chars are saved in msgbuf
     323             :  *      for inspection later (e.g. dmesg/syslog)
     324             :  */
     325             : void
     326           0 : kputchar(int c, int flags, struct tty *tp)
     327             : {
     328             :         extern int msgbufmapped;
     329             :         int ddb_active = 0;
     330             : 
     331             : #ifdef DDB
     332           0 :         ddb_active = db_is_active;
     333             : #endif
     334             : 
     335           0 :         if (panicstr)
     336           0 :                 constty = NULL;
     337             : 
     338           0 :         if ((flags & TOCONS) && tp == NULL && constty && !ddb_active) {
     339             :                 tp = constty;
     340           0 :                 flags |= TOTTY;
     341           0 :         }
     342           0 :         if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 &&
     343           0 :             (flags & TOCONS) && tp == constty)
     344           0 :                 constty = NULL;
     345           0 :         if ((flags & TOLOG) &&
     346           0 :             c != '\0' && c != '\r' && c != 0177 && msgbufmapped)
     347           0 :                 msgbuf_putchar(msgbufp, c);
     348           0 :         if ((flags & TOCONS) && (constty == NULL || ddb_active) && c != '\0')
     349           0 :                 (*v_putc)(c);
     350             : #ifdef DDB
     351           0 :         if (flags & TODDB)
     352           0 :                 db_putchar(c);
     353             : #endif
     354           0 : }
     355             : 
     356             : 
     357             : /*
     358             :  * uprintf: print to the controlling tty of the current process
     359             :  *
     360             :  * => we may block if the tty queue is full
     361             :  * => no message is printed if the queue doesn't clear in a reasonable
     362             :  *      time
     363             :  */
     364             : 
     365             : void
     366           0 : uprintf(const char *fmt, ...)
     367             : {
     368           0 :         struct process *pr = curproc->p_p;
     369           0 :         va_list ap;
     370             : 
     371           0 :         if (pr->ps_flags & PS_CONTROLT && pr->ps_session->s_ttyvp) {
     372           0 :                 va_start(ap, fmt);
     373           0 :                 kprintf(fmt, TOTTY, pr->ps_session->s_ttyp, NULL, ap);
     374           0 :                 va_end(ap);
     375           0 :         }
     376           0 : }
     377             : 
     378             : #if defined(NFSSERVER) || defined(NFSCLIENT)
     379             : 
     380             : /*
     381             :  * tprintf functions: used to send messages to a specific process
     382             :  *
     383             :  * usage:
     384             :  *   get a tpr_t handle on a process "p" by using "tprintf_open(p)"
     385             :  *   use the handle when calling "tprintf"
     386             :  *   when done, do a "tprintf_close" to drop the handle
     387             :  */
     388             : 
     389             : /*
     390             :  * tprintf_open: get a tprintf handle on a process "p"
     391             :  * XXX change s/proc/process
     392             :  *
     393             :  * => returns NULL if process can't be printed to
     394             :  */
     395             : 
     396             : tpr_t
     397           0 : tprintf_open(struct proc *p)
     398             : {
     399           0 :         struct process *pr = p->p_p;
     400             : 
     401           0 :         if (pr->ps_flags & PS_CONTROLT && pr->ps_session->s_ttyvp) {
     402           0 :                 SESSHOLD(pr->ps_session);
     403           0 :                 return ((tpr_t)pr->ps_session);
     404             :         }
     405           0 :         return ((tpr_t) NULL);
     406           0 : }
     407             : 
     408             : /*
     409             :  * tprintf_close: dispose of a tprintf handle obtained with tprintf_open
     410             :  */
     411             : 
     412             : void
     413           0 : tprintf_close(tpr_t sess)
     414             : {
     415             : 
     416           0 :         if (sess)
     417           0 :                 SESSRELE((struct session *) sess);
     418           0 : }
     419             : 
     420             : /*
     421             :  * tprintf: given tprintf handle to a process [obtained with tprintf_open],
     422             :  * send a message to the controlling tty for that process.
     423             :  *
     424             :  * => also sends message to /dev/klog
     425             :  */
     426             : void
     427           0 : tprintf(tpr_t tpr, const char *fmt, ...)
     428             : {
     429             :         struct session *sess = (struct session *)tpr;
     430             :         struct tty *tp = NULL;
     431             :         int flags = TOLOG;
     432           0 :         va_list ap;
     433             : 
     434           0 :         logpri(LOG_INFO);
     435           0 :         if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) {
     436             :                 flags |= TOTTY;
     437           0 :                 tp = sess->s_ttyp;
     438           0 :         }
     439           0 :         va_start(ap, fmt);
     440           0 :         kprintf(fmt, flags, tp, NULL, ap);
     441           0 :         va_end(ap);
     442           0 :         logwakeup();
     443           0 : }
     444             : 
     445             : #endif  /* NFSSERVER || NFSCLIENT */
     446             : 
     447             : 
     448             : /*
     449             :  * ttyprintf: send a message to a specific tty
     450             :  *
     451             :  * => should be used only by tty driver or anything that knows the
     452             :  *      underlying tty will not be revoked(2)'d away.  [otherwise,
     453             :  *      use tprintf]
     454             :  */
     455             : void
     456           0 : ttyprintf(struct tty *tp, const char *fmt, ...)
     457             : {
     458           0 :         va_list ap;
     459             : 
     460           0 :         va_start(ap, fmt);
     461           0 :         kprintf(fmt, TOTTY, tp, NULL, ap);
     462           0 :         va_end(ap);
     463           0 : }
     464             : 
     465             : #ifdef DDB
     466             : 
     467             : /*
     468             :  * db_printf: printf for DDB (via db_putchar)
     469             :  */
     470             : 
     471             : int
     472           0 : db_printf(const char *fmt, ...)
     473             : {
     474           0 :         va_list ap;
     475             :         int retval;
     476             : 
     477           0 :         va_start(ap, fmt);
     478           0 :         retval = db_vprintf(fmt, ap);
     479           0 :         va_end(ap);
     480           0 :         return(retval);
     481           0 : }
     482             : 
     483             : int
     484           0 : db_vprintf(const char *fmt, va_list ap)
     485             : {
     486             :         int flags;
     487             : 
     488             :         flags = TODDB;
     489           0 :         if (db_log)
     490           0 :                 flags |= TOLOG;
     491           0 :         return (kprintf(fmt, flags, NULL, NULL, ap));
     492             : }
     493             : #endif /* DDB */
     494             : 
     495             : 
     496             : /*
     497             :  * normal kernel printf functions: printf, vprintf, snprintf
     498             :  */
     499             : 
     500             : /*
     501             :  * printf: print a message to the console and the log
     502             :  */
     503             : int
     504           0 : printf(const char *fmt, ...)
     505             : {
     506           0 :         va_list ap;
     507             :         int retval;
     508             : 
     509             : 
     510           0 :         va_start(ap, fmt);
     511           0 :         mtx_enter(&kprintf_mutex);
     512           0 :         retval = kprintf(fmt, TOCONS | TOLOG, NULL, NULL, ap);
     513           0 :         mtx_leave(&kprintf_mutex);
     514           0 :         va_end(ap);
     515           0 :         if (!panicstr)
     516           0 :                 logwakeup();
     517             : 
     518             : 
     519           0 :         return(retval);
     520           0 : }
     521             : 
     522             : /*
     523             :  * vprintf: print a message to the console and the log [already have a
     524             :  *      va_list]
     525             :  */
     526             : 
     527             : int
     528           0 : vprintf(const char *fmt, va_list ap)
     529             : {
     530             :         int retval;
     531             : 
     532           0 :         mtx_enter(&kprintf_mutex);
     533           0 :         retval = kprintf(fmt, TOCONS | TOLOG, NULL, NULL, ap);
     534           0 :         mtx_leave(&kprintf_mutex);
     535           0 :         if (!panicstr)
     536           0 :                 logwakeup();
     537             : 
     538             : 
     539           0 :         return (retval);
     540             : }
     541             : 
     542             : /*
     543             :  * snprintf: print a message to a buffer
     544             :  */
     545             : int
     546           0 : snprintf(char *buf, size_t size, const char *fmt, ...)
     547             : {
     548             :         int retval;
     549           0 :         va_list ap;
     550           0 :         char *p;
     551             : 
     552           0 :         p = buf + size - 1;
     553           0 :         if (size < 1)
     554           0 :                 p = buf;
     555           0 :         va_start(ap, fmt);
     556           0 :         retval = kprintf(fmt, TOBUFONLY | TOCOUNT, &p, buf, ap);
     557           0 :         va_end(ap);
     558           0 :         if (size > 0)
     559           0 :                 *(p) = 0;       /* null terminate */
     560           0 :         return(retval);
     561           0 : }
     562             : 
     563             : /*
     564             :  * vsnprintf: print a message to a buffer [already have va_alist]
     565             :  */
     566             : int
     567           0 : vsnprintf(char *buf, size_t size, const char *fmt, va_list ap)
     568             : {
     569             :         int retval;
     570           0 :         char *p;
     571             : 
     572           0 :         p = buf + size - 1;
     573           0 :         if (size < 1)
     574           0 :                 p = buf;
     575           0 :         retval = kprintf(fmt, TOBUFONLY | TOCOUNT, &p, buf, ap);
     576           0 :         if (size > 0)
     577           0 :                 *(p) = 0;       /* null terminate */
     578           0 :         return(retval);
     579           0 : }
     580             : 
     581             : /*
     582             :  * kprintf: scaled down version of printf(3).
     583             :  *
     584             :  * this version based on vfprintf() from libc which was derived from
     585             :  * software contributed to Berkeley by Chris Torek.
     586             :  *
     587             :  * The additional format %b is supported to decode error registers.
     588             :  * Its usage is:
     589             :  *
     590             :  *      printf("reg=%b\n", regval, "<base><arg>*");
     591             :  *
     592             :  * where <base> is the output base expressed as a control character, e.g.
     593             :  * \10 gives octal; \20 gives hex.  Each arg is a sequence of characters,
     594             :  * the first of which gives the bit number to be inspected (origin 1), and
     595             :  * the next characters (up to a control character, i.e. a character <= 32),
     596             :  * give the name of the register.  Thus:
     597             :  *
     598             :  *      kprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
     599             :  *
     600             :  * would produce output:
     601             :  *
     602             :  *      reg=3<BITTWO,BITONE>
     603             :  *
     604             :  * To support larger integers (> 32 bits), %b formatting will also accept
     605             :  * control characters in the region 0x80 - 0xff.  0x80 refers to bit 0,
     606             :  * 0x81 refers to bit 1, and so on.  The equivalent string to the above is:
     607             :  *
     608             :  *      kprintf("reg=%b\n", 3, "\10\201BITTWO\200BITONE\n");
     609             :  *
     610             :  * and would produce the same output.
     611             :  *
     612             :  * Like the rest of printf, %b can be prefixed to handle various size
     613             :  * modifiers, eg. %b is for "int", %lb is for "long", and %llb supports
     614             :  * "long long".
     615             :  *
     616             :  * This code is large and complicated...
     617             :  */
     618             : 
     619             : /*
     620             :  * macros for converting digits to letters and vice versa
     621             :  */
     622             : #define to_digit(c)     ((c) - '0')
     623             : #define is_digit(c)     ((unsigned)to_digit(c) <= 9)
     624             : #define to_char(n)      ((n) + '0')
     625             : 
     626             : /*
     627             :  * flags used during conversion.
     628             :  */
     629             : #define ALT             0x001           /* alternate form */
     630             : #define HEXPREFIX       0x002           /* add 0x or 0X prefix */
     631             : #define LADJUST         0x004           /* left adjustment */
     632             : #define LONGDBL         0x008           /* long double; unimplemented */
     633             : #define LONGINT         0x010           /* long integer */
     634             : #define QUADINT         0x020           /* quad integer */
     635             : #define SHORTINT        0x040           /* short integer */
     636             : #define ZEROPAD         0x080           /* zero (as opposed to blank) pad */
     637             : #define FPT             0x100           /* Floating point number */
     638             : #define SIZEINT         0x200           /* (signed) size_t */
     639             : 
     640             :         /*
     641             :          * To extend shorts properly, we need both signed and unsigned
     642             :          * argument extraction methods.
     643             :          */
     644             : #define SARG() \
     645             :         (flags&QUADINT ? va_arg(ap, quad_t) : \
     646             :             flags&LONGINT ? va_arg(ap, long) : \
     647             :             flags&SIZEINT ? va_arg(ap, ssize_t) : \
     648             :             flags&SHORTINT ? (long)(short)va_arg(ap, int) : \
     649             :             (long)va_arg(ap, int))
     650             : #define UARG() \
     651             :         (flags&QUADINT ? va_arg(ap, u_quad_t) : \
     652             :             flags&LONGINT ? va_arg(ap, u_long) : \
     653             :             flags&SIZEINT ? va_arg(ap, size_t) : \
     654             :             flags&SHORTINT ? (u_long)(u_short)va_arg(ap, int) : \
     655             :             (u_long)va_arg(ap, u_int))
     656             : 
     657             : #define KPRINTF_PUTCHAR(C) do {                                 \
     658             :         int chr = (C);                                                  \
     659             :         ret += 1;                                                       \
     660             :         if (oflags & TOBUFONLY) {                                   \
     661             :                 if ((vp != NULL) && (sbuf == tailp)) {                  \
     662             :                         if (!(oflags & TOCOUNT))                            \
     663             :                                 goto overflow;                          \
     664             :                 } else                                                  \
     665             :                         *sbuf++ = chr;                                  \
     666             :         } else {                                                        \
     667             :                 kputchar(chr, oflags, (struct tty *)vp);                        \
     668             :         }                                                               \
     669             : } while(0)
     670             : 
     671             : int
     672           0 : kprintf(const char *fmt0, int oflags, void *vp, char *sbuf, va_list ap)
     673             : {
     674             :         char *fmt;              /* format string */
     675             :         int ch;                 /* character from fmt */
     676             :         int n;                  /* handy integer (short term usage) */
     677             :         char *cp = NULL;        /* handy char pointer (short term usage) */
     678             :         int flags;              /* flags as above */
     679             :         int ret;                /* return value accumulator */
     680             :         int width;              /* width from format (%8d), or 0 */
     681             :         int prec;               /* precision from format (%.3d), or -1 */
     682             :         char sign;              /* sign prefix (' ', '+', '-', or \0) */
     683             : 
     684             :         u_quad_t _uquad;        /* integer arguments %[diouxX] */
     685             :         enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */
     686             :         int dprec;              /* a copy of prec if [diouxX], 0 otherwise */
     687             :         int realsz;             /* field size expanded by dprec */
     688             :         int size = 0;           /* size of converted field or string */
     689             :         char *xdigs = NULL;     /* digits for [xX] conversion */
     690           0 :         char buf[KPRINTF_BUFSIZE]; /* space for %c, %[diouxX] */
     691             :         char *tailp = NULL;     /* tail pointer for snprintf */
     692             : 
     693           0 :         if (oflags & TOCONS)
     694           0 :                 MUTEX_ASSERT_LOCKED(&kprintf_mutex);
     695             : 
     696           0 :         if ((oflags & TOBUFONLY) && (vp != NULL))
     697           0 :                 tailp = *(char **)vp;
     698             : 
     699             :         fmt = (char *)fmt0;
     700             :         ret = 0;
     701             : 
     702             :         /*
     703             :          * Scan the format for conversions (`%' character).
     704             :          */
     705           0 :         for (;;) {
     706           0 :                 while (*fmt != '%' && *fmt) {
     707           0 :                         KPRINTF_PUTCHAR(*fmt++);
     708             :                 }
     709           0 :                 if (*fmt == 0)
     710             :                         goto done;
     711             : 
     712           0 :                 fmt++;          /* skip over '%' */
     713             : 
     714             :                 flags = 0;
     715             :                 dprec = 0;
     716             :                 width = 0;
     717             :                 prec = -1;
     718           0 :                 sign = '\0';
     719             : 
     720           0 : rflag:          ch = *fmt++;
     721           0 : reswitch:       switch (ch) {
     722             :                 /* XXX: non-standard '%b' format */
     723             :                 case 'b': {
     724             :                         char *b, *z;
     725             :                         int tmp;
     726           0 :                         _uquad = UARG();
     727           0 :                         b = va_arg(ap, char *);
     728           0 :                         if (*b == 8)
     729           0 :                                 snprintf(buf, sizeof buf, "%llo", _uquad);
     730           0 :                         else if (*b == 10)
     731           0 :                                 snprintf(buf, sizeof buf, "%lld", _uquad);
     732           0 :                         else if (*b == 16)
     733           0 :                                 snprintf(buf, sizeof buf, "%llx", _uquad);
     734             :                         else
     735           0 :                                 break;
     736           0 :                         b++;
     737             : 
     738           0 :                         z = buf;
     739           0 :                         while (*z) {
     740           0 :                                 KPRINTF_PUTCHAR(*z++);
     741             :                         }
     742             : 
     743           0 :                         if (_uquad) {
     744             :                                 tmp = 0;
     745           0 :                                 while ((n = *b++) != 0) {
     746           0 :                                         if (n & 0x80)
     747           0 :                                                 n &= 0x7f;
     748           0 :                                         else if (n <= ' ')
     749           0 :                                                 n = n - 1;
     750           0 :                                         if (_uquad & (1LL << n)) {
     751           0 :                                                 KPRINTF_PUTCHAR(tmp ? ',':'<');
     752           0 :                                                 while (*b > ' ' &&
     753           0 :                                                     (*b & 0x80) == 0) {
     754           0 :                                                         KPRINTF_PUTCHAR(*b);
     755           0 :                                                         b++;
     756             :                                                 }
     757             :                                                 tmp = 1;
     758           0 :                                         } else {
     759           0 :                                                 while (*b > ' ' &&
     760           0 :                                                     (*b & 0x80) == 0)
     761           0 :                                                         b++;
     762             :                                         }
     763             :                                 }
     764           0 :                                 if (tmp) {
     765           0 :                                         KPRINTF_PUTCHAR('>');
     766             :                                 }
     767             :                         }
     768           0 :                         continue;       /* no output */
     769             :                 }
     770             : 
     771             :                 case ' ':
     772             :                         /*
     773             :                          * ``If the space and + flags both appear, the space
     774             :                          * flag will be ignored.''
     775             :                          *      -- ANSI X3J11
     776             :                          */
     777           0 :                         if (!sign)
     778           0 :                                 sign = ' ';
     779           0 :                         goto rflag;
     780             :                 case '#':
     781           0 :                         flags |= ALT;
     782           0 :                         goto rflag;
     783             :                 case '*':
     784             :                         /*
     785             :                          * ``A negative field width argument is taken as a
     786             :                          * - flag followed by a positive field width.''
     787             :                          *      -- ANSI X3J11
     788             :                          * They don't exclude field widths read from args.
     789             :                          */
     790           0 :                         if ((width = va_arg(ap, int)) >= 0)
     791           0 :                                 goto rflag;
     792           0 :                         width = -width;
     793             :                         /* FALLTHROUGH */
     794             :                 case '-':
     795           0 :                         flags |= LADJUST;
     796           0 :                         goto rflag;
     797             :                 case '+':
     798             :                         sign = '+';
     799           0 :                         goto rflag;
     800             :                 case '.':
     801           0 :                         if ((ch = *fmt++) == '*') {
     802           0 :                                 n = va_arg(ap, int);
     803           0 :                                 prec = n < 0 ? -1 : n;
     804           0 :                                 goto rflag;
     805             :                         }
     806             :                         n = 0;
     807           0 :                         while (is_digit(ch)) {
     808           0 :                                 n = 10 * n + to_digit(ch);
     809           0 :                                 ch = *fmt++;
     810             :                         }
     811           0 :                         prec = n < 0 ? -1 : n;
     812           0 :                         goto reswitch;
     813             :                 case '0':
     814             :                         /*
     815             :                          * ``Note that 0 is taken as a flag, not as the
     816             :                          * beginning of a field width.''
     817             :                          *      -- ANSI X3J11
     818             :                          */
     819           0 :                         flags |= ZEROPAD;
     820           0 :                         goto rflag;
     821             :                 case '1': case '2': case '3': case '4':
     822             :                 case '5': case '6': case '7': case '8': case '9':
     823             :                         n = 0;
     824           0 :                         do {
     825           0 :                                 n = 10 * n + to_digit(ch);
     826           0 :                                 ch = *fmt++;
     827           0 :                         } while (is_digit(ch));
     828             :                         width = n;
     829           0 :                         goto reswitch;
     830             :                 case 'h':
     831           0 :                         flags |= SHORTINT;
     832           0 :                         goto rflag;
     833             :                 case 'l':
     834           0 :                         if (*fmt == 'l') {
     835           0 :                                 fmt++;
     836           0 :                                 flags |= QUADINT;
     837           0 :                         } else {
     838           0 :                                 flags |= LONGINT;
     839             :                         }
     840           0 :                         goto rflag;
     841             :                 case 'q':
     842           0 :                         flags |= QUADINT;
     843           0 :                         goto rflag;
     844             :                 case 'z':
     845           0 :                         flags |= SIZEINT;
     846           0 :                         goto rflag;
     847             :                 case 'c':
     848           0 :                         *(cp = buf) = va_arg(ap, int);
     849             :                         size = 1;
     850             :                         sign = '\0';
     851           0 :                         break;
     852             :                 case 't':
     853             :                         /* ptrdiff_t */
     854             :                         /* FALLTHROUGH */
     855             :                 case 'D':
     856           0 :                         flags |= LONGINT;
     857             :                         /*FALLTHROUGH*/
     858             :                 case 'd':
     859             :                 case 'i':
     860           0 :                         _uquad = SARG();
     861           0 :                         if ((quad_t)_uquad < 0) {
     862           0 :                                 _uquad = -_uquad;
     863             :                                 sign = '-';
     864           0 :                         }
     865             :                         base = DEC;
     866           0 :                         goto number;
     867             :                 case 'n':
     868             :                         /* %n is unsupported in the kernel; just skip it */
     869           0 :                         if (flags & QUADINT)
     870           0 :                                 (void)va_arg(ap, quad_t *);
     871           0 :                         else if (flags & LONGINT)
     872           0 :                                 (void)va_arg(ap, long *);
     873           0 :                         else if (flags & SHORTINT)
     874           0 :                                 (void)va_arg(ap, short *);
     875           0 :                         else if (flags & SIZEINT)
     876           0 :                                 (void)va_arg(ap, ssize_t *);
     877             :                         else
     878           0 :                                 (void)va_arg(ap, int *);
     879           0 :                         continue;       /* no output */
     880             :                 case 'O':
     881           0 :                         flags |= LONGINT;
     882             :                         /*FALLTHROUGH*/
     883             :                 case 'o':
     884           0 :                         _uquad = UARG();
     885             :                         base = OCT;
     886           0 :                         goto nosign;
     887             :                 case 'p':
     888             :                         /*
     889             :                          * ``The argument shall be a pointer to void.  The
     890             :                          * value of the pointer is converted to a sequence
     891             :                          * of printable characters, in an implementation-
     892             :                          * defined manner.''
     893             :                          *      -- ANSI X3J11
     894             :                          */
     895           0 :                         _uquad = (u_long)va_arg(ap, void *);
     896             :                         base = HEX;
     897             :                         xdigs = "0123456789abcdef";
     898           0 :                         flags |= HEXPREFIX;
     899             :                         ch = 'x';
     900           0 :                         goto nosign;
     901             :                 case 's':
     902           0 :                         if ((cp = va_arg(ap, char *)) == NULL)
     903             :                                 cp = "(null)";
     904           0 :                         if (prec >= 0) {
     905             :                                 /*
     906             :                                  * can't use strlen; can only look for the
     907             :                                  * NUL in the first `prec' characters, and
     908             :                                  * strlen() will go further.
     909             :                                  */
     910           0 :                                 char *p = memchr(cp, 0, prec);
     911             : 
     912           0 :                                 if (p != NULL) {
     913           0 :                                         size = p - cp;
     914           0 :                                         if (size > prec)
     915           0 :                                                 size = prec;
     916             :                                 } else
     917             :                                         size = prec;
     918           0 :                         } else
     919           0 :                                 size = strlen(cp);
     920             :                         sign = '\0';
     921           0 :                         break;
     922             :                 case 'U':
     923           0 :                         flags |= LONGINT;
     924             :                         /*FALLTHROUGH*/
     925             :                 case 'u':
     926           0 :                         _uquad = UARG();
     927             :                         base = DEC;
     928           0 :                         goto nosign;
     929             :                 case 'X':
     930             :                         xdigs = "0123456789ABCDEF";
     931           0 :                         goto hex;
     932             :                 case 'x':
     933           0 :                         xdigs = "0123456789abcdef";
     934           0 : hex:                    _uquad = UARG();
     935             :                         base = HEX;
     936             :                         /* leading 0x/X only if non-zero */
     937           0 :                         if (flags & ALT && _uquad != 0)
     938           0 :                                 flags |= HEXPREFIX;
     939             : 
     940             :                         /* unsigned conversions */
     941           0 : nosign:                 sign = '\0';
     942             :                         /*
     943             :                          * ``... diouXx conversions ... if a precision is
     944             :                          * specified, the 0 flag will be ignored.''
     945             :                          *      -- ANSI X3J11
     946             :                          */
     947           0 : number:                 if ((dprec = prec) >= 0)
     948           0 :                                 flags &= ~ZEROPAD;
     949             : 
     950             :                         /*
     951             :                          * ``The result of converting a zero value with an
     952             :                          * explicit precision of zero is no characters.''
     953             :                          *      -- ANSI X3J11
     954             :                          */
     955           0 :                         cp = buf + KPRINTF_BUFSIZE;
     956           0 :                         if (_uquad != 0 || prec != 0) {
     957             :                                 /*
     958             :                                  * Unsigned mod is hard, and unsigned mod
     959             :                                  * by a constant is easier than that by
     960             :                                  * a variable; hence this switch.
     961             :                                  */
     962           0 :                                 switch (base) {
     963             :                                 case OCT:
     964           0 :                                         do {
     965           0 :                                                 *--cp = to_char(_uquad & 7);
     966           0 :                                                 _uquad >>= 3;
     967           0 :                                         } while (_uquad);
     968             :                                         /* handle octal leading 0 */
     969           0 :                                         if (flags & ALT && *cp != '0')
     970           0 :                                                 *--cp = '0';
     971             :                                         break;
     972             : 
     973             :                                 case DEC:
     974             :                                         /* many numbers are 1 digit */
     975           0 :                                         while (_uquad >= 10) {
     976           0 :                                                 *--cp = to_char(_uquad % 10);
     977           0 :                                                 _uquad /= 10;
     978             :                                         }
     979           0 :                                         *--cp = to_char(_uquad);
     980           0 :                                         break;
     981             : 
     982             :                                 case HEX:
     983           0 :                                         do {
     984           0 :                                                 *--cp = xdigs[_uquad & 15];
     985           0 :                                                 _uquad >>= 4;
     986           0 :                                         } while (_uquad);
     987             :                                         break;
     988             : 
     989             :                                 default:
     990             :                                         cp = "bug in kprintf: bad base";
     991           0 :                                         size = strlen(cp);
     992           0 :                                         goto skipsize;
     993             :                                 }
     994             :                         }
     995           0 :                         size = buf + KPRINTF_BUFSIZE - cp;
     996             :                 skipsize:
     997             :                         break;
     998             :                 default:        /* "%?" prints ?, unless ? is NUL */
     999           0 :                         if (ch == '\0')
    1000             :                                 goto done;
    1001             :                         /* pretend it was %c with argument ch */
    1002           0 :                         cp = buf;
    1003           0 :                         *cp = ch;
    1004             :                         size = 1;
    1005             :                         sign = '\0';
    1006           0 :                         break;
    1007             :                 }
    1008             : 
    1009             :                 /*
    1010             :                  * All reasonable formats wind up here.  At this point, `cp'
    1011             :                  * points to a string which (if not flags&LADJUST) should be
    1012             :                  * padded out to `width' places.  If flags&ZEROPAD, it should
    1013             :                  * first be prefixed by any sign or other prefix; otherwise,
    1014             :                  * it should be blank padded before the prefix is emitted.
    1015             :                  * After any left-hand padding and prefixing, emit zeroes
    1016             :                  * required by a decimal [diouxX] precision, then print the
    1017             :                  * string proper, then emit zeroes required by any leftover
    1018             :                  * floating precision; finally, if LADJUST, pad with blanks.
    1019             :                  *
    1020             :                  * Compute actual size, so we know how much to pad.
    1021             :                  * size excludes decimal prec; realsz includes it.
    1022             :                  */
    1023           0 :                 realsz = dprec > size ? dprec : size;
    1024           0 :                 if (sign)
    1025           0 :                         realsz++;
    1026           0 :                 else if (flags & HEXPREFIX)
    1027           0 :                         realsz+= 2;
    1028             : 
    1029             :                 /* right-adjusting blank padding */
    1030           0 :                 if ((flags & (LADJUST|ZEROPAD)) == 0) {
    1031           0 :                         n = width - realsz;
    1032           0 :                         while (n-- > 0)
    1033           0 :                                 KPRINTF_PUTCHAR(' ');
    1034             :                 }
    1035             : 
    1036             :                 /* prefix */
    1037           0 :                 if (sign) {
    1038           0 :                         KPRINTF_PUTCHAR(sign);
    1039           0 :                 } else if (flags & HEXPREFIX) {
    1040           0 :                         KPRINTF_PUTCHAR('0');
    1041           0 :                         KPRINTF_PUTCHAR(ch);
    1042             :                 }
    1043             : 
    1044             :                 /* right-adjusting zero padding */
    1045           0 :                 if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) {
    1046           0 :                         n = width - realsz;
    1047           0 :                         while (n-- > 0)
    1048           0 :                                 KPRINTF_PUTCHAR('0');
    1049             :                 }
    1050             : 
    1051             :                 /* leading zeroes from decimal precision */
    1052           0 :                 n = dprec - size;
    1053           0 :                 while (n-- > 0)
    1054           0 :                         KPRINTF_PUTCHAR('0');
    1055             : 
    1056             :                 /* the string or number proper */
    1057           0 :                 while (size--)
    1058           0 :                         KPRINTF_PUTCHAR(*cp++);
    1059             :                 /* left-adjusting padding (always blank) */
    1060           0 :                 if (flags & LADJUST) {
    1061           0 :                         n = width - realsz;
    1062           0 :                         while (n-- > 0)
    1063           0 :                                 KPRINTF_PUTCHAR(' ');
    1064             :                 }
    1065             :         }
    1066             : 
    1067             : done:
    1068           0 :         if ((oflags & TOBUFONLY) && (vp != NULL))
    1069           0 :                 *(char **)vp = sbuf;
    1070             : overflow:
    1071           0 :         return (ret);
    1072             :         /* NOTREACHED */
    1073           0 : }
    1074             : 
    1075             : #if __GNUC_PREREQ__(2,96)
    1076             : /*
    1077             :  * XXX - these functions shouldn't be in the kernel, but gcc 3.X feels like
    1078             :  *       translating some printf calls to puts and since it doesn't seem
    1079             :  *       possible to just turn off parts of those optimizations (some of
    1080             :  *       them are really useful), we have to provide a dummy puts and putchar
    1081             :  *       that are wrappers around printf.
    1082             :  */
    1083             : int     puts(const char *);
    1084             : int     putchar(int c);
    1085             : 
    1086             : int
    1087           0 : puts(const char *str)
    1088             : {
    1089           0 :         printf("%s\n", str);
    1090             : 
    1091           0 :         return (0);
    1092             : }
    1093             : 
    1094             : int
    1095           0 : putchar(int c)
    1096             : {
    1097           0 :         printf("%c", c);
    1098             : 
    1099           0 :         return (c);
    1100             : }
    1101             : 
    1102             : 
    1103             : #endif

Generated by: LCOV version 1.13