Annotation of Net2/kern/subr_prf.c, revision 1.1.1.3

1.1       root        1: /*-
                      2:  * Copyright (c) 1986, 1988, 1991 The Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  * 3. All advertising materials mentioning features or use of this software
                     14:  *    must display the following acknowledgement:
                     15:  *     This product includes software developed by the University of
                     16:  *     California, Berkeley and its contributors.
                     17:  * 4. Neither the name of the University nor the names of its contributors
                     18:  *    may be used to endorse or promote products derived from this software
                     19:  *    without specific prior written permission.
                     20:  *
                     21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     31:  * SUCH DAMAGE.
                     32:  *
1.1.1.3 ! root       33:  *     from: @(#)subr_prf.c    7.30 (Berkeley) 6/29/91
        !            34:  *     subr_prf.c,v 1.7 1993/06/27 06:01:53 andrew Exp
1.1       root       35:  */
                     36: 
                     37: #include "param.h"
                     38: #include "systm.h"
                     39: #include "buf.h"
                     40: #include "conf.h"
                     41: #include "reboot.h"
                     42: #include "msgbuf.h"
                     43: #include "proc.h"
                     44: #include "ioctl.h"
                     45: #include "vnode.h"
                     46: #include "file.h"
                     47: #include "tty.h"
                     48: #include "tprintf.h"
                     49: #include "syslog.h"
                     50: #include "malloc.h"
                     51: 
                     52: /*
                     53:  * Note that stdarg.h and the ANSI style va_start macro is used for both
                     54:  * ANSI and traditional C compilers.
                     55:  */
                     56: #include <machine/stdarg.h>
                     57: 
                     58: #ifdef KADB
                     59: #include "machine/kdbparam.h"
                     60: #endif
                     61: 
                     62: #define TOCONS 0x01
                     63: #define TOTTY  0x02
                     64: #define TOLOG  0x04
                     65: 
                     66: struct tty *constty;                   /* pointer to console "window" tty */
                     67: 
1.1.1.3 ! root       68: #if defined(KADB) || defined(PANICWAIT)
1.1       root       69: extern cngetc();                       /* standard console getc */
1.1.1.3 ! root       70: #endif
        !            71: #ifdef KADB
1.1       root       72: int    (*v_getc)() = cngetc;           /* "" getc from virtual console */
                     73: extern cnpoll();
                     74: int    (*v_poll)() = cnpoll;           /* kdb hook to enable input polling */
                     75: #endif
                     76: extern cnputc();                       /* standard console putc */
                     77: int    (*v_putc)() = cnputc;           /* routine to putc on virtual console */
                     78: 
                     79: static void  logpri __P((int level));
                     80: static void  putchar __P((int ch, int flags, struct tty *tp));
                     81: static char *ksprintn __P((u_long num, int base, int *len));
                     82: void  kprintf __P((const char *fmt, int flags, struct tty *tp, va_list));
1.1.1.3 ! root       83: volatile void boot(int bootopt);
1.1       root       84: 
                     85: /*
                     86:  * Variable panicstr contains argument to first call to panic; used
                     87:  * as flag to indicate that the kernel has already called panic.
                     88:  */
1.1.1.3 ! root       89: const char     *panicstr;
1.1       root       90: 
                     91: /*
                     92:  * Panic is called on unresolvable fatal errors.  It prints "panic: mesg",
                     93:  * and then reboots.  If we are called twice, then we avoid trying to sync
                     94:  * the disks as this often leads to recursive panics.
                     95:  */
1.1.1.3 ! root       96: #ifdef __STDC__
        !            97: volatile void
        !            98: panic(const char *msg)
        !            99: #else
1.1       root      100: void
                    101: panic(msg)
                    102:        char *msg;
1.1.1.3 ! root      103: #endif
1.1       root      104: {
                    105:        int bootopt = RB_AUTOBOOT | RB_DUMP;
                    106: 
                    107:        if (panicstr)
                    108:                bootopt |= RB_NOSYNC;
                    109:        else
                    110:                panicstr = msg;
                    111:        printf("panic: %s\n", msg);
                    112: #ifdef KGDB
                    113:        kgdb_panic();
                    114: #endif
                    115: #ifdef KADB
                    116:        if (boothowto & RB_KDB) {
                    117:                int s;
                    118: 
                    119:                s = splnet();   /* below kdb pri */
                    120:                setsoftkdb();
                    121:                splx(s);
                    122:        }
                    123: #endif
1.1.1.3 ! root      124: #ifdef DDB
1.1.1.2   root      125:        Debugger ();
                    126: #else
1.1.1.3 ! root      127: #ifdef PANICWAIT
        !           128:        printf("hit any key to boot/dump...\n>");
        !           129:        cngetc();
        !           130: #endif
1.1.1.2   root      131: #endif
1.1       root      132:        boot(bootopt);
                    133: }
                    134: 
                    135: /*
                    136:  * Warn that a system table is full.
                    137:  */
                    138: void
                    139: tablefull(tab)
                    140:        char *tab;
                    141: {
                    142: 
                    143:        log(LOG_ERR, "%s: table is full\n", tab);
                    144: }
                    145: 
                    146: /*
                    147:  * Uprintf prints to the controlling terminal for the current process.
                    148:  * It may block if the tty queue is overfull.  No message is printed if
                    149:  * the queue does not clear in a reasonable time.
                    150:  */
                    151: void
                    152: #ifdef __STDC__
                    153: uprintf(const char *fmt, ...)
                    154: #else
                    155: uprintf(fmt /*, va_alist */)
                    156:        char *fmt;
                    157: #endif
                    158: {
                    159:        register struct proc *p = curproc;
                    160:        va_list ap;
                    161: 
                    162:        if (p->p_flag & SCTTY && p->p_session->s_ttyvp) {
                    163:                va_start(ap, fmt);
                    164:                kprintf(fmt, TOTTY, p->p_session->s_ttyp, ap);
                    165:                va_end(ap);
                    166:        }
                    167: }
                    168: 
                    169: tpr_t
                    170: tprintf_open(p)
                    171:        register struct proc *p;
                    172: {
                    173: 
                    174:        if (p->p_flag & SCTTY && p->p_session->s_ttyvp) {
                    175:                SESSHOLD(p->p_session);
                    176:                return ((tpr_t) p->p_session);
                    177:        }
                    178:        return ((tpr_t) NULL);
                    179: }
                    180: 
                    181: void
                    182: tprintf_close(sess)
                    183:        tpr_t sess;
                    184: {
                    185: 
                    186:        if (sess)
                    187:                SESSRELE((struct session *) sess);
                    188: }
                    189: 
                    190: /*
                    191:  * tprintf prints on the controlling terminal associated
                    192:  * with the given session.
                    193:  */
                    194: void
                    195: #ifdef __STDC__
                    196: tprintf(tpr_t tpr, const char *fmt, ...)
                    197: #else
                    198: tprintf(tpr, fmt /*, va_alist */)
                    199:        tpr_t tpr;
                    200:        char *fmt;
                    201: #endif
                    202: {
                    203:        register struct session *sess = (struct session *)tpr;
                    204:        struct tty *tp = NULL;
                    205:        int flags = TOLOG;
                    206:        va_list ap;
                    207: 
                    208:        logpri(LOG_INFO);
                    209:        if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) {
                    210:                flags |= TOTTY;
                    211:                tp = sess->s_ttyp;
                    212:        }
                    213:        va_start(ap, fmt);
                    214:        kprintf(fmt, flags, tp, ap);
                    215:        va_end(ap);
                    216:        logwakeup();
                    217: }
                    218: 
                    219: /*
                    220:  * Ttyprintf displays a message on a tty; it should be used only by
                    221:  * the tty driver, or anything that knows the underlying tty will not
                    222:  * be revoke(2)'d away.  Other callers should use tprintf.
                    223:  */
                    224: void
                    225: #ifdef __STDC__
                    226: ttyprintf(struct tty *tp, const char *fmt, ...)
                    227: #else
                    228: ttyprintf(tp, fmt /*, va_alist */)
                    229:        struct tty *tp;
                    230:        char *fmt;
                    231: #endif
                    232: {
                    233:        va_list ap;
                    234: 
                    235:        va_start(ap, fmt);
                    236:        kprintf(fmt, TOTTY, tp, ap);
                    237:        va_end(ap);
                    238: }
                    239: 
                    240: extern int log_open;
                    241: 
                    242: /*
                    243:  * Log writes to the log buffer, and guarantees not to sleep (so can be
                    244:  * called by interrupt routines).  If there is no process reading the
                    245:  * log yet, it writes to the console also.
                    246:  */
                    247: void
                    248: #ifdef __STDC__
                    249: log(int level, const char *fmt, ...)
                    250: #else
                    251: log(level, fmt /*, va_alist */)
                    252:        int level;
                    253:        char *fmt;
                    254: #endif
                    255: {
                    256:        register int s;
                    257:        va_list ap;
                    258: 
                    259:        s = splhigh();
                    260:        logpri(level);
                    261:        va_start(ap, fmt);
                    262:        kprintf(fmt, TOLOG, NULL, ap);
                    263:        splx(s);
                    264:        va_end(ap);
                    265:        if (!log_open) {
                    266:                va_start(ap, fmt);
                    267:                kprintf(fmt, TOCONS, NULL, ap);
                    268:                va_end(ap);
                    269:        }
                    270:        logwakeup();
                    271: }
                    272: 
                    273: static void
                    274: logpri(level)
                    275:        int level;
                    276: {
                    277:        register int ch;
                    278:        register char *p;
                    279: 
                    280:        putchar('<', TOLOG, NULL);
                    281:        for (p = ksprintn((u_long)level, 10, NULL); ch = *p--;)
                    282:                putchar(ch, TOLOG, NULL);
                    283:        putchar('>', TOLOG, NULL);
                    284: }
                    285: 
                    286: void
                    287: #ifdef __STDC__
                    288: addlog(const char *fmt, ...)
                    289: #else
                    290: addlog(fmt /*, va_alist */)
                    291:        char *fmt;
                    292: #endif
                    293: {
                    294:        register int s;
                    295:        va_list ap;
                    296: 
                    297:        s = splhigh();
                    298:        va_start(ap, fmt);
                    299:        kprintf(fmt, TOLOG, NULL, ap);
                    300:        splx(s);
                    301:        va_end(ap);
                    302:        if (!log_open) {
                    303:                va_start(ap, fmt);
                    304:                kprintf(fmt, TOCONS, NULL, ap);
                    305:                va_end(ap);
                    306:        }
                    307:        logwakeup();
                    308: }
                    309: 
                    310: int    consintr = 1;                   /* ok to handle console interrupts? */
                    311: 
1.1.1.3 ! root      312: int
1.1       root      313: #ifdef __STDC__
                    314: printf(const char *fmt, ...)
                    315: #else
                    316: printf(fmt /*, va_alist */)
                    317:        char *fmt;
                    318: #endif
                    319: {
                    320:        va_list ap;
                    321:        register int savintr;
                    322: 
                    323:        savintr = consintr;             /* disable interrupts */
                    324:        consintr = 0;
                    325:        va_start(ap, fmt);
                    326:        kprintf(fmt, TOCONS | TOLOG, NULL, ap);
                    327:        va_end(ap);
                    328:        if (!panicstr)
                    329:                logwakeup();
                    330:        consintr = savintr;             /* reenable interrupts */
1.1.1.3 ! root      331: 
        !           332:        return 0;       /* for compatibility with libc's printf() */
1.1       root      333: }
                    334: 
                    335: /*
                    336:  * Scaled down version of printf(3).
                    337:  *
                    338:  * Two additional formats:
                    339:  *
                    340:  * The format %b is supported to decode error registers.
                    341:  * Its usage is:
                    342:  *
                    343:  *     printf("reg=%b\n", regval, "<base><arg>*");
                    344:  *
                    345:  * where <base> is the output base expressed as a control character, e.g.
                    346:  * \10 gives octal; \20 gives hex.  Each arg is a sequence of characters,
                    347:  * the first of which gives the bit number to be inspected (origin 1), and
                    348:  * the next characters (up to a control character, i.e. a character <= 32),
                    349:  * give the name of the register.  Thus:
                    350:  *
                    351:  *     printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
                    352:  *
                    353:  * would produce output:
                    354:  *
                    355:  *     reg=3<BITTWO,BITONE>
                    356:  *
                    357:  * The format %r is supposed to pass an additional format string and argument
                    358:  * list recursively.
                    359:  * Its usage is:
                    360:  *
                    361:  * fn(otherstuff, char *fmt, ...)
                    362:  * {
                    363:  *     va_list ap;
                    364:  *     va_start(ap, fmt);
                    365:  *     printf("prefix: %r, other stuff\n", fmt, ap);
                    366:  *     va_end(ap);
                    367:  *
                    368:  * Space or zero padding and a field width are supported for the numeric
                    369:  * formats only.
                    370:  */
                    371: void
                    372: kprintf(fmt, flags, tp, ap)
                    373:        register const char *fmt;
                    374:        int flags;
                    375:        struct tty *tp;
                    376:        va_list ap;
                    377: {
1.1.1.3 ! root      378:        register char *p, *p2;
1.1       root      379:        register int ch, n;
                    380:        u_long ul;
                    381:        int base, lflag, tmp, width;
                    382:        char padc;
                    383: 
                    384:        for (;;) {
                    385:                padc = ' ';
                    386:                width = 0;
                    387:                while ((ch = *(u_char *)fmt++) != '%') {
                    388:                        if (ch == '\0')
                    389:                                return;
                    390:                        putchar(ch, flags, tp);
                    391:                }
                    392:                lflag = 0;
                    393: reswitch:      switch (ch = *(u_char *)fmt++) {
                    394:                case '0':
                    395:                        padc = '0';
                    396:                        goto reswitch;
                    397:                case '1': case '2': case '3': case '4':
                    398:                case '5': case '6': case '7': case '8': case '9':
                    399:                        for (width = 0;; ++fmt) {
                    400:                                width = width * 10 + ch - '0';
                    401:                                ch = *fmt;
                    402:                                if (ch < '0' || ch > '9')
                    403:                                        break;
                    404:                        }
                    405:                        goto reswitch;
                    406:                case 'l':
                    407:                        lflag = 1;
                    408:                        goto reswitch;
                    409:                case 'b':
                    410:                        ul = va_arg(ap, int);
                    411:                        p = va_arg(ap, char *);
1.1.1.3 ! root      412:                        for (p2 = ksprintn(ul, *p++, NULL); ch = *p2--;)
1.1       root      413:                                putchar(ch, flags, tp);
                    414: 
                    415:                        if (!ul)
                    416:                                break;
                    417: 
                    418:                        for (tmp = 0; n = *p++;) {
                    419:                                if (ul & (1 << (n - 1))) {
                    420:                                        putchar(tmp ? ',' : '<', flags, tp);
                    421:                                        for (; (n = *p) > ' '; ++p)
                    422:                                                putchar(n, flags, tp);
                    423:                                        tmp = 1;
                    424:                                } else
                    425:                                        for (; *p > ' '; ++p);
                    426:                        }
                    427:                        if (tmp)
                    428:                                putchar('>', flags, tp);
                    429:                        break;
                    430:                case 'c':
                    431:                        putchar(va_arg(ap, int), flags, tp);
                    432:                        break;
                    433:                case 'r':
                    434:                        p = va_arg(ap, char *);
                    435:                        kprintf(p, flags, tp, va_arg(ap, va_list));
                    436:                        break;
                    437:                case 's':
                    438:                        p = va_arg(ap, char *);
                    439:                        while (ch = *p++)
                    440:                                putchar(ch, flags, tp);
                    441:                        break;
                    442:                case 'd':
                    443:                        ul = lflag ? va_arg(ap, long) : va_arg(ap, int);
                    444:                        if ((long)ul < 0) {
                    445:                                putchar('-', flags, tp);
                    446:                                ul = -(long)ul;
                    447:                        }
                    448:                        base = 10;
                    449:                        goto number;
                    450:                case 'o':
                    451:                        ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
                    452:                        base = 8;
                    453:                        goto number;
                    454:                case 'u':
                    455:                        ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
                    456:                        base = 10;
                    457:                        goto number;
                    458:                case 'x':
                    459:                        ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
                    460:                        base = 16;
                    461: number:                        p = ksprintn(ul, base, &tmp);
                    462:                        if (width && (width -= tmp) > 0)
                    463:                                while (width--)
                    464:                                        putchar(padc, flags, tp);
                    465:                        while (ch = *p--)
                    466:                                putchar(ch, flags, tp);
                    467:                        break;
                    468:                default:
                    469:                        putchar('%', flags, tp);
                    470:                        if (lflag)
                    471:                                putchar('l', flags, tp);
                    472:                        /* FALLTHROUGH */
                    473:                case '%':
                    474:                        putchar(ch, flags, tp);
                    475:                }
                    476:        }
                    477: }
                    478: 
                    479: /*
                    480:  * Print a character on console or users terminal.  If destination is
                    481:  * the console then the last MSGBUFS characters are saved in msgbuf for
                    482:  * inspection later.
                    483:  */
                    484: static void
                    485: putchar(c, flags, tp)
                    486:        register int c;
                    487:        int flags;
                    488:        struct tty *tp;
                    489: {
                    490:        extern int msgbufmapped;
                    491:        register struct msgbuf *mbp;
                    492: 
                    493:        if (panicstr)
                    494:                constty = NULL;
                    495:        if ((flags & TOCONS) && tp == NULL && constty) {
                    496:                tp = constty;
                    497:                flags |= TOTTY;
                    498:        }
                    499:        if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 &&
                    500:            (flags & TOCONS) && tp == constty)
                    501:                constty = NULL;
                    502:        if ((flags & TOLOG) &&
                    503:            c != '\0' && c != '\r' && c != 0177 && msgbufmapped) {
                    504:                mbp = msgbufp;
                    505:                if (mbp->msg_magic != MSG_MAGIC) {
                    506:                        bzero((caddr_t)mbp, sizeof(*mbp));
                    507:                        mbp->msg_magic = MSG_MAGIC;
                    508:                }
                    509:                mbp->msg_bufc[mbp->msg_bufx++] = c;
                    510:                if (mbp->msg_bufx < 0 || mbp->msg_bufx >= MSG_BSIZE)
                    511:                        mbp->msg_bufx = 0;
                    512:        }
                    513:        if ((flags & TOCONS) && constty == NULL && c != '\0')
                    514:                (*v_putc)(c);
                    515: }
                    516: 
                    517: /*
                    518:  * Scaled down version of sprintf(3).
                    519:  */
                    520: #ifdef __STDC__
1.1.1.3 ! root      521: int
1.1       root      522: sprintf(char *buf, const char *cfmt, ...)
                    523: #else
1.1.1.3 ! root      524: int
1.1       root      525: sprintf(buf, cfmt /*, va_alist */)
                    526:        char *buf, *cfmt;
                    527: #endif
                    528: {
                    529:        register const char *fmt = cfmt;
                    530:        register char *p, *bp;
                    531:        register int ch, base;
                    532:        u_long ul;
                    533:        int lflag;
                    534:        va_list ap;
                    535: 
                    536:        va_start(ap, cfmt);
                    537:        for (bp = buf; ; ) {
                    538:                while ((ch = *(u_char *)fmt++) != '%')
                    539:                        if ((*bp++ = ch) == '\0')
                    540:                                return ((bp - buf) - 1);
                    541: 
                    542:                lflag = 0;
                    543: reswitch:      switch (ch = *(u_char *)fmt++) {
                    544:                case 'l':
                    545:                        lflag = 1;
                    546:                        goto reswitch;
                    547:                case 'c':
                    548:                        *bp++ = va_arg(ap, int);
                    549:                        break;
                    550:                case 's':
                    551:                        p = va_arg(ap, char *);
                    552:                        while (*bp++ = *p++)
                    553:                                ;
                    554:                        --bp;
                    555:                        break;
                    556:                case 'd':
                    557:                        ul = lflag ? va_arg(ap, long) : va_arg(ap, int);
                    558:                        if ((long)ul < 0) {
                    559:                                *bp++ = '-';
                    560:                                ul = -(long)ul;
                    561:                        }
                    562:                        base = 10;
                    563:                        goto number;
                    564:                        break;
                    565:                case 'o':
                    566:                        ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
                    567:                        base = 8;
                    568:                        goto number;
                    569:                        break;
                    570:                case 'u':
                    571:                        ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
                    572:                        base = 10;
                    573:                        goto number;
                    574:                        break;
                    575:                case 'x':
                    576:                        ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
                    577:                        base = 16;
                    578: number:                        for (p = ksprintn(ul, base, NULL); ch = *p--;)
                    579:                                *bp++ = ch;
                    580:                        break;
                    581:                default:
                    582:                        *bp++ = '%';
                    583:                        if (lflag)
                    584:                                *bp++ = 'l';
                    585:                        /* FALLTHROUGH */
                    586:                case '%':
                    587:                        *bp++ = ch;
                    588:                }
                    589:        }
                    590:        va_end(ap);
                    591: }
                    592: 
                    593: /*
                    594:  * Put a number (base <= 16) in a buffer in reverse order; return an
                    595:  * optional length and a pointer to the NULL terminated (preceded?)
                    596:  * buffer.
                    597:  */
                    598: static char *
                    599: ksprintn(ul, base, lenp)
                    600:        register u_long ul;
                    601:        register int base, *lenp;
                    602: {                                      /* A long in base 8, plus NULL. */
                    603:        static char buf[sizeof(long) * NBBY / 3 + 2];
                    604:        register char *p;
                    605: 
                    606:        p = buf;
                    607:        do {
                    608:                *++p = "0123456789abcdef"[ul % base];
                    609:        } while (ul /= base);
                    610:        if (lenp)
                    611:                *lenp = p - buf;
                    612:        return (p);
                    613: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.