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

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

unix.superglobalmegacorp.com

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