Annotation of 3BSD/cmd/ls/ucbls.c, revision 1.1

1.1     ! root        1: /* Copyright (c) 1979 Regents of the University of California */
        !             2: #
        !             3: /*
        !             4:  * ls - list file or directory
        !             5:  *
        !             6:  * Modified by Bill Joy UCB May/August 1977
        !             7:  *
        !             8:  * This version of ls is designed for graphic terminals and to
        !             9:  * list directories with lots of files in them compactly.
        !            10:  * It supports three variants for listings:
        !            11:  *
        !            12:  *     1) Columnar output.
        !            13:  *     2) Stream output.
        !            14:  *     3) Old one per line format.
        !            15:  *
        !            16:  * Columnar output is the default.
        !            17:  * If, however, the standard output is not a teletype, the default
        !            18:  * is one-per-line.
        !            19:  *
        !            20:  * With columnar output, the items are sorted down the columns.
        !            21:  * We use columns only for a directory we are interpreting.
        !            22:  * Thus, in particular, we do not use columns for
        !            23:  *
        !            24:  *     ls /usr/bin/p*
        !            25:  *
        !            26:  * This version of ls also prints non-printing characters as '?' if
        !            27:  * the standard output is a teletype.
        !            28:  *
        !            29:  * Flags relating to these and other new features are:
        !            30:  *
        !            31:  *     -m      force stream output.
        !            32:  *
        !            33:  *     -1      force one entry per line, e.g. to a teletype
        !            34:  *
        !            35:  *     -q      force non-printings to be '?'s, e.g. to a file
        !            36:  *
        !            37:  *     -c      force columnar output, e.g. into a file
        !            38:  *
        !            39:  *     -n      like -l, but user/group id's in decimal rather than
        !            40:  *             looking in /etc/passwd to save time
        !            41:  */
        !            42: 
        !            43: #include <sys/param.h>
        !            44: #include <sys/stat.h>
        !            45: #include <sys/dir.h>
        !            46: #include <stdio.h>
        !            47: #include <ctype.h>
        !            48: 
        !            49: 
        !            50: #define        NFILES  1024
        !            51: FILE   *pwdf, *dirf;
        !            52: 
        !            53: struct lbuf {
        !            54:        union {
        !            55:                char    lname[15];
        !            56:                char    *namep;
        !            57:        } ln;
        !            58:        char    ltype;
        !            59:        short   lnum;
        !            60:        short   lflags;
        !            61:        short   lnl;
        !            62:        short   luid;
        !            63:        short   lgid;
        !            64:        long    lsize;
        !            65:        long    lmtime;
        !            66: };
        !            67: 
        !            68: int    aflg, dflg, lflg, sflg, tflg, uflg, iflg, fflg, gflg, cflg;
        !            69: int    Aflg, nflg, qflg, across;
        !            70: int    nopad;
        !            71: char   buff[32];
        !            72: int    rflg    = 1;
        !            73: long   year;
        !            74: int    flags;
        !            75: int    lastuid = -1;
        !            76: char   tbuf[16];
        !            77: long   tblocks;
        !            78: int    statreq;
        !            79: struct lbuf    *flist[NFILES];
        !            80: struct lbuf    **lastp = flist;
        !            81: struct lbuf    **firstp = flist;
        !            82: char   *dotp   = ".";
        !            83: 
        !            84: char   *makename();
        !            85: struct lbuf *gstat();
        !            86: char   *ctime();
        !            87: long   nblock();
        !            88: 
        !            89: #define        ISARG   0100000
        !            90: int    colwidth = 15;
        !            91: int    outcol;
        !            92: 
        !            93: char   obuf[BUFSIZ];
        !            94: 
        !            95: main(argc, argv)
        !            96: char *argv[];
        !            97: {
        !            98:        int i;
        !            99:        register struct lbuf *ep, **ep1;
        !           100:        register struct lbuf **slastp;
        !           101:        struct lbuf **epp;
        !           102:        struct lbuf lb;
        !           103:        char *t;
        !           104:        char *cp;
        !           105:        int compar();
        !           106: 
        !           107:        Aflg = getuid() == 0;
        !           108:        setbuf(stdout, obuf);
        !           109:        time(&lb.lmtime);
        !           110:        year = lb.lmtime - 6L*30L*24L*60L*60L; /* 6 months ago */
        !           111:        qflg = gtty(1, buff) == 0;
        !           112:        /*
        !           113:         * If the standard output is not a teletype,
        !           114:         * then we default to one-per-line format
        !           115:         * otherwise decide between stream and
        !           116:         * columnar based on our name.
        !           117:         */
        !           118:        if (qflg) {
        !           119:                cflg = 1;
        !           120:                for (cp = argv[0]; cp[0] && cp[1]; cp++)
        !           121:                        continue;
        !           122:                /*
        !           123:                 * Name ends in l => stream
        !           124:                 */
        !           125:                if (cp[0] == 'l')
        !           126:                        nopad = 1, cflg = 0;
        !           127:                /*
        !           128:                 * ... if doesn't end in l or s ==> columns sorted across
        !           129:                 *
        !           130:                else if (cp[0] == 'x')
        !           131:                        across = 1;
        !           132:                 */
        !           133:        }
        !           134:        if (--argc > 0 && *argv[1] == '-') {
        !           135:                argv++;
        !           136:                while (*++*argv) switch (**argv) {
        !           137:                /*
        !           138:                 * c - force columnar output
        !           139:                 */
        !           140:                case 'c':
        !           141:                        cflg = 1;
        !           142:                        nopad = 0;
        !           143:                        continue;
        !           144:                /*
        !           145:                 * m - force stream output
        !           146:                 */
        !           147:                case 'm':
        !           148:                        cflg = 0;
        !           149:                        nopad = 1;
        !           150:                        continue;
        !           151:                /*
        !           152:                 * x - force sort across
        !           153:                 */
        !           154:                case 'x':
        !           155:                        across = 1;
        !           156:                        nopad = 0;
        !           157:                        cflg = 1;
        !           158:                        continue;
        !           159:                /*
        !           160:                 * q - force ?'s in output
        !           161:                 */
        !           162:                case 'q':
        !           163:                        qflg = 1;
        !           164:                        continue;
        !           165:                /*
        !           166:                 * 1 - force 1/line in output
        !           167:                 */
        !           168:                case '1':
        !           169:                        cflg = 0;
        !           170:                        nopad = 0;
        !           171:                        continue;
        !           172:                /* STANDARD FLAGS */
        !           173:                case 'a':
        !           174:                        aflg++;
        !           175:                        continue;
        !           176: 
        !           177:                case 'A':
        !           178:                        Aflg = !Aflg;
        !           179:                        continue;
        !           180: 
        !           181:                case 's':
        !           182:                        colwidth += 5;
        !           183:                        sflg++;
        !           184:                        statreq++;
        !           185:                        continue;
        !           186: 
        !           187:                case 'd':
        !           188:                        dflg++;
        !           189:                        continue;
        !           190: 
        !           191:                /*
        !           192:                 * n - don't look in password file
        !           193:                 */
        !           194:                case 'n':
        !           195:                        nflg++;
        !           196:                case 'l':
        !           197:                        lflg++;
        !           198:                        statreq++;
        !           199:                        continue;
        !           200: 
        !           201:                case 'r':
        !           202:                        rflg = -1;
        !           203:                        continue;
        !           204: 
        !           205:                case 't':
        !           206:                        tflg++;
        !           207:                        statreq++;
        !           208:                        continue;
        !           209: 
        !           210:                case 'u':
        !           211:                        uflg++;
        !           212:                        continue;
        !           213: 
        !           214:                case 'i':
        !           215:                        colwidth += 5;
        !           216:                        iflg++;
        !           217:                        continue;
        !           218: 
        !           219:                case 'f':
        !           220:                        fflg++;
        !           221:                        continue;
        !           222: 
        !           223:                case 'g':
        !           224:                        gflg++;
        !           225:                        continue;
        !           226: 
        !           227:                default:
        !           228:                        continue;
        !           229:                }
        !           230:                argc--;
        !           231:        }
        !           232:        if (fflg) {
        !           233:                aflg++;
        !           234:                lflg = 0;
        !           235:                sflg = 0;
        !           236:                tflg = 0;
        !           237:                statreq = 0;
        !           238:        }
        !           239:        if(lflg) {
        !           240:                cflg = 0;
        !           241:                t = "/etc/passwd";
        !           242:                if (gflg)
        !           243:                        t = "/etc/group";
        !           244:                nopad = 0;
        !           245:                colwidth = 70;
        !           246:                pwdf = fopen(t, "r");
        !           247:        }
        !           248:        if (argc==0) {
        !           249:                argc++;
        !           250:                argv = &dotp - 1;
        !           251:        }
        !           252:        for (i=0; i < argc; i++) {
        !           253:                if ((ep = gstat(*++argv, 1))==NULL)
        !           254:                        continue;
        !           255:                ep->ln.namep = *argv;
        !           256:                ep->lflags |= ISARG;
        !           257:        }
        !           258:        qsort(firstp, lastp - firstp, sizeof *lastp, compar);
        !           259:        slastp = lastp;
        !           260:        for (epp=firstp; epp<slastp; epp++) {
        !           261:                ep = *epp;
        !           262:                if (ep->ltype=='d' && dflg==0 || fflg) {
        !           263:                        if (argc>1)
        !           264:                                printf("\n%s:\n", ep->ln.namep);
        !           265:                        lastp = slastp;
        !           266:                        readdir(ep->ln.namep);
        !           267:                        if (fflg==0)
        !           268:                                qsort(slastp,lastp - slastp,sizeof *lastp,compar);
        !           269:                        if (lflg || sflg)
        !           270:                                printf("total %D", tblocks);
        !           271:                        pem(slastp, lastp);
        !           272:                        newline();
        !           273:                } else 
        !           274:                        pentry(ep);
        !           275:        }
        !           276:        if (outcol)
        !           277:                putc('\n', stdout);
        !           278:        fflush(stdout);
        !           279: }
        !           280: 
        !           281: pem(slp, lp)
        !           282:        register struct lbuf **slp, **lp;
        !           283: {
        !           284:        int ncols, nrows, row, col;
        !           285:        register struct lbuf **ep;
        !           286: 
        !           287:        ncols = 80 / colwidth;
        !           288:        if (ncols == 1 || cflg == 0) {
        !           289:                for (ep = slp; ep < lp; ep++)
        !           290:                        pentry(*ep);
        !           291:                return;
        !           292:        }
        !           293:        if (across) {
        !           294:                for (ep = slp; ep < lp; ep++)
        !           295:                        pentry(*ep);
        !           296:                return;
        !           297:        }
        !           298:        if (statreq)
        !           299:                slp--;
        !           300:        nrows = (lp - slp - 1) / ncols + 1;
        !           301:        for (row = 0; row < nrows; row++) {
        !           302:                col = row == 0 && statreq;
        !           303:                for (; col < ncols; col++) {
        !           304:                        ep = slp + (nrows * col) + row;
        !           305:                        if (ep < lp)
        !           306:                                pentry(*ep);
        !           307:                }
        !           308:                if (outcol)
        !           309:                        printf("\n");
        !           310:        }
        !           311: }
        !           312: 
        !           313: pputchar(c)
        !           314:        char c;
        !           315: {
        !           316: 
        !           317:        switch (c) {
        !           318:                case '\t':
        !           319:                        outcol = (outcol + 8) &~ 7;
        !           320:                        break;
        !           321:                case '\n':
        !           322:                        outcol = 0;
        !           323:                        break;
        !           324:                default:
        !           325:                        if (qflg && (c < ' ' || c >= 0177))
        !           326:                                c = '?';
        !           327:                        outcol++;
        !           328:                        break;
        !           329:        }
        !           330:        putc(c, stdout);
        !           331: }
        !           332: 
        !           333: newline()
        !           334: {
        !           335:        if (outcol)
        !           336:                putc('\n', stdout);
        !           337:        outcol = 0;
        !           338: }
        !           339: 
        !           340: column()
        !           341: {
        !           342: 
        !           343:        if (outcol == 0)
        !           344:                return;
        !           345:        if (nopad) {
        !           346:                putc(',', stdout);
        !           347:                outcol++;
        !           348:                if (outcol + colwidth + 2 > 80) {
        !           349:                        putc('\n', stdout);
        !           350:                        outcol = 0;
        !           351:                        return;
        !           352:                }
        !           353:                putc(' ', stdout);
        !           354:                outcol++;
        !           355:                return;
        !           356:        }
        !           357:        if (cflg == 0) {
        !           358:                putc('\n', stdout);
        !           359:                return;
        !           360:        }
        !           361:        if ((outcol / colwidth + 2) * colwidth > 80) {
        !           362:                putc('\n', stdout);
        !           363:                outcol = 0;
        !           364:                return;
        !           365:        }
        !           366:        do {
        !           367:                outcol++;
        !           368:                putc(' ', stdout);
        !           369:        } while (outcol % colwidth);
        !           370: }
        !           371: 
        !           372: 
        !           373: getname(uid, buf)
        !           374: int uid;
        !           375: char buf[];
        !           376: {
        !           377:        int j, c, n, i;
        !           378: 
        !           379:        if (uid==lastuid)
        !           380:                return(0);
        !           381:        if(pwdf == NULL)
        !           382:                return(-1);
        !           383:        rewind(pwdf);
        !           384:        lastuid = -1;
        !           385:        do {
        !           386:                i = 0;
        !           387:                j = 0;
        !           388:                n = 0;
        !           389:                while((c=fgetc(pwdf)) != '\n') {
        !           390:                        if (c==EOF)
        !           391:                                return(-1);
        !           392:                        if (c==':') {
        !           393:                                j++;
        !           394:                                c = '0';
        !           395:                        }
        !           396:                        if (j==0)
        !           397:                                buf[i++] = c;
        !           398:                        if (j==2)
        !           399:                                n = n*10 + c - '0';
        !           400:                }
        !           401:        } while (n != uid);
        !           402:        buf[i++] = '\0';
        !           403:        lastuid = uid;
        !           404:        return(0);
        !           405: }
        !           406: 
        !           407: long
        !           408: nblock(size)
        !           409: long size;
        !           410: {
        !           411:        return((size+511)>>9);
        !           412: }
        !           413: 
        !           414: int    m1[] = { 1, S_IREAD>>0, 'r', '-' };
        !           415: int    m2[] = { 1, S_IWRITE>>0, 'w', '-' };
        !           416: int    m3[] = { 2, S_ISUID, 's', S_IEXEC>>0, 'x', '-' };
        !           417: int    m4[] = { 1, S_IREAD>>3, 'r', '-' };
        !           418: int    m5[] = { 1, S_IWRITE>>3, 'w', '-' };
        !           419: int    m6[] = { 2, S_ISGID, 's', S_IEXEC>>3, 'x', '-' };
        !           420: int    m7[] = { 1, S_IREAD>>6, 'r', '-' };
        !           421: int    m8[] = { 1, S_IWRITE>>6, 'w', '-' };
        !           422: int    m9[] = { 2, S_ISVTX, 't', S_IEXEC>>6, 'x', '-' };
        !           423: 
        !           424: int    *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9};
        !           425: 
        !           426: pmode(aflag)
        !           427: {
        !           428:        register int **mp;
        !           429: 
        !           430:        flags = aflag;
        !           431:        for (mp = &m[0]; mp < &m[sizeof(m)/sizeof(m[0])];)
        !           432:                select(*mp++);
        !           433: }
        !           434: 
        !           435: select(pairp)
        !           436: register int *pairp;
        !           437: {
        !           438:        register int n;
        !           439: 
        !           440:        n = *pairp++;
        !           441:        while (--n>=0 && (flags&*pairp++)==0)
        !           442:                pairp++;
        !           443:        pputchar(*pairp);
        !           444: }
        !           445: 
        !           446: char *
        !           447: makename(dir, file)
        !           448: char *dir, *file;
        !           449: {
        !           450:        static char dfile[100];
        !           451:        register char *dp, *fp;
        !           452:        register int i;
        !           453: 
        !           454:        dp = dfile;
        !           455:        fp = dir;
        !           456:        while (*fp)
        !           457:                *dp++ = *fp++;
        !           458:        *dp++ = '/';
        !           459:        fp = file;
        !           460:        for (i=0; i<DIRSIZ; i++)
        !           461:                *dp++ = *fp++;
        !           462:        *dp = 0;
        !           463:        return(dfile);
        !           464: }
        !           465: 
        !           466: readdir(dir)
        !           467: char *dir;
        !           468: {
        !           469:        static struct direct dentry;
        !           470:        register int j;
        !           471:        register struct lbuf *ep;
        !           472: 
        !           473:        if ((dirf = fopen(dir, "r")) == NULL) {
        !           474:                printf("%s unreadable\n", dir);
        !           475:                return;
        !           476:        }
        !           477:        tblocks = 0;
        !           478:        for(;;) {
        !           479:                if (fread(&dentry, sizeof(dentry), 1, dirf) != 1)
        !           480:                        break;
        !           481:                if (dentry.d_ino==0 ||
        !           482:                        aflg==0 && dentry.d_name[0]=='.' && (
        !           483:                        !Aflg ||
        !           484:                        dentry.d_name[1]=='\0'
        !           485:                        || dentry.d_name[1]=='.' && dentry.d_name[2]=='\0'))
        !           486:                        continue;
        !           487:                ep = gstat(makename(dir, dentry.d_name), 0);
        !           488:                if (ep==NULL)
        !           489:                        continue;
        !           490:                if (ep->lnum != -1)
        !           491:                        ep->lnum = dentry.d_ino;
        !           492:                for (j=0; j<DIRSIZ; j++)
        !           493:                        ep->ln.lname[j] = dentry.d_name[j];
        !           494:        }
        !           495:        fclose(dirf);
        !           496: }
        !           497: 
        !           498: struct lbuf *
        !           499: gstat(file, argfl)
        !           500: char *file;
        !           501: {
        !           502:        struct stat statb;
        !           503:        register struct lbuf *rep;
        !           504:        static int nomocore;
        !           505: 
        !           506:        if (nomocore)
        !           507:                return(NULL);
        !           508:        rep = (struct lbuf *)malloc(sizeof(struct lbuf));
        !           509:        if (rep==NULL) {
        !           510:                fprintf(stderr, "ls: out of memory\n");
        !           511:                nomocore = 1;
        !           512:                return(NULL);
        !           513:        }
        !           514:        if (lastp >= &flist[NFILES]) {
        !           515:                static int msg;
        !           516:                lastp--;
        !           517:                if (msg==0) {
        !           518:                        fprintf(stderr, "ls: too many files\n");
        !           519:                        msg++;
        !           520:                }
        !           521:        }
        !           522:        *lastp++ = rep;
        !           523:        rep->lflags = 0;
        !           524:        rep->lnum = 0;
        !           525:        rep->ltype = '-';
        !           526:        if (argfl || statreq) {
        !           527:                if (stat(file, &statb)<0) {
        !           528:                        printf("%s not found\n", file);
        !           529:                        statb.st_ino = -1;
        !           530:                        statb.st_size = 0;
        !           531:                        statb.st_mode = 0;
        !           532:                        if (argfl) {
        !           533:                                lastp--;
        !           534:                                return(0);
        !           535:                        }
        !           536:                }
        !           537:                rep->lnum = statb.st_ino;
        !           538:                rep->lsize = statb.st_size;
        !           539:                switch(statb.st_mode&S_IFMT) {
        !           540: 
        !           541:                case S_IFDIR:
        !           542:                        rep->ltype = 'd';
        !           543:                        break;
        !           544: 
        !           545:                case S_IFBLK:
        !           546:                        rep->ltype = 'b';
        !           547:                        rep->lsize = statb.st_rdev;
        !           548:                        break;
        !           549: 
        !           550:                case S_IFCHR:
        !           551:                        rep->ltype = 'c';
        !           552:                        rep->lsize = statb.st_rdev;
        !           553:                        break;
        !           554:                }
        !           555:                rep->lflags = statb.st_mode & ~S_IFMT;
        !           556:                rep->luid = statb.st_uid;
        !           557:                rep->lgid = statb.st_gid;
        !           558:                rep->lnl = statb.st_nlink;
        !           559:                if(uflg)
        !           560:                        rep->lmtime = statb.st_atime;
        !           561:                else if (cflg)
        !           562:                        rep->lmtime = statb.st_ctime;
        !           563:                else
        !           564:                        rep->lmtime = statb.st_mtime;
        !           565:                tblocks += nblock(statb.st_size);
        !           566:        }
        !           567:        return(rep);
        !           568: }
        !           569: 
        !           570: compar(pp1, pp2)
        !           571: struct lbuf **pp1, **pp2;
        !           572: {
        !           573:        register struct lbuf *p1, *p2;
        !           574: 
        !           575:        p1 = *pp1;
        !           576:        p2 = *pp2;
        !           577:        if (dflg==0) {
        !           578:                if (p1->lflags&ISARG && p1->ltype=='d') {
        !           579:                        if (!(p2->lflags&ISARG && p2->ltype=='d'))
        !           580:                                return(1);
        !           581:                } else {
        !           582:                        if (p2->lflags&ISARG && p2->ltype=='d')
        !           583:                                return(-1);
        !           584:                }
        !           585:        }
        !           586:        if (tflg) {
        !           587:                if(p2->lmtime == p1->lmtime)
        !           588:                        return(0);
        !           589:                if(p2->lmtime > p1->lmtime)
        !           590:                        return(rflg);
        !           591:                return(-rflg);
        !           592:        }
        !           593:        return(rflg * strcmp(p1->lflags&ISARG? p1->ln.namep: p1->ln.lname,
        !           594:                                p2->lflags&ISARG? p2->ln.namep: p2->ln.lname));
        !           595: }
        !           596: pentry(ap)
        !           597: struct lbuf *ap;
        !           598: {
        !           599:        struct { char dminor, dmajor;};
        !           600:        register t;
        !           601:        register struct lbuf *p;
        !           602:        register char *cp;
        !           603: 
        !           604:        p = ap;
        !           605:        if (p->lnum == -1)
        !           606:                return;
        !           607:        column();
        !           608:        if (iflg)
        !           609:                if (nopad && !lflg)
        !           610:                        printf("%d ", p->lnum);
        !           611:                else
        !           612:                        printf("%5d ", p->lnum);
        !           613:        if (sflg)
        !           614:                if (nopad && !lflg)
        !           615:                        printf("%D ", nblock(p->lsize));
        !           616:                else
        !           617:                        printf("%4D ", nblock(p->lsize));
        !           618:        if (lflg) {
        !           619:                pputchar(p->ltype);
        !           620:                pmode(p->lflags);
        !           621:                printf("%2d ", p->lnl);
        !           622:                t = p->luid;
        !           623:                if(gflg)
        !           624:                        t = p->lgid;
        !           625:                if (nflg == 0 && getname(t, tbuf)==0)
        !           626:                        printf("%-8.8s", tbuf);
        !           627:                else
        !           628:                        printf("%-8d", t);
        !           629:                if (p->ltype=='b' || p->ltype=='c')
        !           630:                        printf("%3d,%3d", major((int)p->lsize), minor((int)p->lsize));
        !           631:                else
        !           632:                        printf("%7ld", p->lsize);
        !           633:                cp = ctime(&p->lmtime);
        !           634:                if(p->lmtime < year)
        !           635:                        printf(" %-7.7s %-4.4s ", cp+4, cp+20); else
        !           636:                        printf(" %-12.12s ", cp+4);
        !           637:        }
        !           638:        if (p->lflags&ISARG)
        !           639:                printf("%s", p->ln.namep);
        !           640:        else
        !           641:                printf("%.14s", p->ln.lname);
        !           642: }
        !           643: /* char printf_id[] = "@(#) printf.c:2.2 6/5/79";*/
        !           644: #include "varargs.h"
        !           645: /* This version of printf is compatible with the Version 7 C
        !           646:  * printf. The differences are only minor except that this
        !           647:  * printf assumes it is to print through pputchar. Version 7
        !           648:  * printf is more general (and is much larger) and includes
        !           649:  * provisions for floating point.
        !           650:  */
        !           651:  
        !           652: 
        !           653: #define MAXOCT 11      /* Maximum octal digits in a long */
        !           654: #define MAXINT 32767   /* largest normal length positive integer */
        !           655: #define BIG    1000000000  /* largest power of 10 less than an unsigned long */
        !           656: #define MAXDIGS 10     /* number of digits in BIG */
        !           657: 
        !           658: static int width, sign, fill;
        !           659: 
        !           660: char *b_dconv();
        !           661: 
        !           662: printf(va_alist)
        !           663:        va_dcl
        !           664: {
        !           665:        va_list ap;
        !           666:        register char *fmt;
        !           667:        char fcode;
        !           668:        int prec;
        !           669:        int length,mask1,nbits,n;
        !           670:        long int mask2, num;
        !           671:        register char *bptr;
        !           672:        char *ptr;
        !           673:        char buf[134];
        !           674: 
        !           675:        va_start(ap);
        !           676:        fmt = va_arg(ap,char *);
        !           677:        for (;;) {
        !           678:                /* process format string first */
        !           679:                while ((fcode = *fmt++)!='%') {
        !           680:                        /* ordinary (non-%) character */
        !           681:                        if (fcode=='\0')
        !           682:                                return;
        !           683:                        pputchar(fcode);
        !           684:                }
        !           685:                /* length modifier: -1 for h, 1 for l, 0 for none */
        !           686:                length = 0;
        !           687:                /* check for a leading - sign */
        !           688:                sign = 0;
        !           689:                if (*fmt == '-') {
        !           690:                        sign++;
        !           691:                        fmt++;
        !           692:                }
        !           693:                /* a '0' may follow the - sign */
        !           694:                /* this is the requested fill character */
        !           695:                fill = 1;
        !           696:                if (*fmt == '0') {
        !           697:                        fill--;
        !           698:                        fmt++;
        !           699:                }
        !           700:                
        !           701:                /* Now comes a digit string which may be a '*' */
        !           702:                if (*fmt == '*') {
        !           703:                        width = va_arg(ap, int);
        !           704:                        if (width < 0) {
        !           705:                                width = -width;
        !           706:                                sign = !sign;
        !           707:                        }
        !           708:                        fmt++;
        !           709:                }
        !           710:                else {
        !           711:                        width = 0;
        !           712:                        while (*fmt>='0' && *fmt<='9')
        !           713:                                width = width * 10 + (*fmt++ - '0');
        !           714:                }
        !           715:                
        !           716:                /* maybe a decimal point followed by more digits (or '*') */
        !           717:                if (*fmt=='.') {
        !           718:                        if (*++fmt == '*') {
        !           719:                                prec = va_arg(ap, int);
        !           720:                                fmt++;
        !           721:                        }
        !           722:                        else {
        !           723:                                prec = 0;
        !           724:                                while (*fmt>='0' && *fmt<='9')
        !           725:                                        prec = prec * 10 + (*fmt++ - '0');
        !           726:                        }
        !           727:                }
        !           728:                else
        !           729:                        prec = -1;
        !           730:                
        !           731:                /*
        !           732:                 * At this point, "sign" is nonzero if there was
        !           733:                 * a sign, "fill" is 0 if there was a leading
        !           734:                 * zero and 1 otherwise, "width" and "prec"
        !           735:                 * contain numbers corresponding to the digit
        !           736:                 * strings before and after the decimal point,
        !           737:                 * respectively, and "fmt" addresses the next
        !           738:                 * character after the whole mess. If there was
        !           739:                 * no decimal point, "prec" will be -1.
        !           740:                 */
        !           741:                switch (*fmt) {
        !           742:                        case 'L':
        !           743:                        case 'l':
        !           744:                                length = 2;
        !           745:                                /* no break!! */
        !           746:                        case 'h':
        !           747:                        case 'H':
        !           748:                                length--;
        !           749:                                fmt++;
        !           750:                                break;
        !           751:                }
        !           752:                
        !           753:                /*
        !           754:                 * At exit from the following switch, we will
        !           755:                 * emit the characters starting at "bptr" and
        !           756:                 * ending at "ptr"-1, unless fcode is '\0'.
        !           757:                 */
        !           758:                switch (fcode = *fmt++) {
        !           759:                        /* process characters and strings first */
        !           760:                        case 'c':
        !           761:                                buf[0] = va_arg(ap, int);
        !           762:                                ptr = bptr = &buf[0];
        !           763:                                if (buf[0] != '\0')
        !           764:                                        ptr++;
        !           765:                                break;
        !           766:                        case 's':
        !           767:                                bptr = va_arg(ap,char *);
        !           768:                                if (bptr==0)
        !           769:                                        bptr = "(null pointer)";
        !           770:                                if (prec < 0)
        !           771:                                        prec = MAXINT;
        !           772:                                for (n=0; *bptr++ && n < prec; n++) ;
        !           773:                                ptr = --bptr;
        !           774:                                bptr -= n;
        !           775:                                break;
        !           776:                        case 'O':
        !           777:                                length = 1;
        !           778:                                fcode = 'o';
        !           779:                                /* no break */
        !           780:                        case 'o':
        !           781:                        case 'X':
        !           782:                        case 'x':
        !           783:                                if (length > 0)
        !           784:                                        num = va_arg(ap,long);
        !           785:                                else
        !           786:                                        num = (unsigned)va_arg(ap,int);
        !           787:                                if (fcode=='o') {
        !           788:                                        mask1 = 0x7;
        !           789:                                        mask2 = 0x1fffffffL;
        !           790:                                        nbits = 3;
        !           791:                                }
        !           792:                                else {
        !           793:                                        mask1 = 0xf;
        !           794:                                        mask2 = 0x0fffffffL;
        !           795:                                        nbits = 4;
        !           796:                                }
        !           797:                                n = (num!=0);
        !           798:                                bptr = buf + MAXOCT + 3;
        !           799:                                /* shift and mask for speed */
        !           800:                                do
        !           801:                                    if (((int) num & mask1) < 10)
        !           802:                                        *--bptr = ((int) num & mask1) + 060;
        !           803:                                    else
        !           804:                                        *--bptr = ((int) num & mask1) + 0127;
        !           805:                                while (num = (num >> nbits) & mask2);
        !           806:                                
        !           807:                                if (fcode=='o') {
        !           808:                                        if (n)
        !           809:                                                *--bptr = '0';
        !           810:                                }
        !           811:                                else
        !           812:                                        if (!sign && fill <= 0) {
        !           813:                                                pputchar('0');
        !           814:                                                pputchar(fcode);
        !           815:                                                width -= 2;
        !           816:                                        }
        !           817:                                        else {
        !           818:                                                *--bptr = fcode;
        !           819:                                                *--bptr = '0';
        !           820:                                        }
        !           821:                                ptr = buf + MAXOCT + 3;
        !           822:                                break;
        !           823:                        case 'D':
        !           824:                        case 'U':
        !           825:                        case 'I':
        !           826:                                length = 1;
        !           827:                                fcode = fcode + 'a' - 'A';
        !           828:                                /* no break */
        !           829:                        case 'd':
        !           830:                        case 'i':
        !           831:                        case 'u':
        !           832:                                if (length > 0)
        !           833:                                        num = va_arg(ap,long);
        !           834:                                else {
        !           835:                                        n = va_arg(ap,int);
        !           836:                                        if (fcode=='u')
        !           837:                                                num = (unsigned) n;
        !           838:                                        else
        !           839:                                                num = (long) n;
        !           840:                                }
        !           841:                                if (n = (fcode != 'u' && num < 0))
        !           842:                                        num = -num;
        !           843:                                /* now convert to digits */
        !           844:                                bptr = b_dconv(num, buf);
        !           845:                                if (n)
        !           846:                                        *--bptr = '-';
        !           847:                                if (fill == 0)
        !           848:                                        fill = -1;
        !           849:                                ptr = buf + MAXDIGS + 1;
        !           850:                                break;
        !           851:                        default:
        !           852:                                /* not a control character, 
        !           853:                                 * print it.
        !           854:                                 */
        !           855:                                ptr = bptr = &fcode;
        !           856:                                ptr++;
        !           857:                                break;
        !           858:                        }
        !           859:                        if (fcode != '\0')
        !           860:                                b_emit(bptr,ptr);
        !           861:        }
        !           862:        va_end(ap);
        !           863: }
        !           864: 
        !           865: /* b_dconv converts the unsigned long integer "value" to
        !           866:  * printable decimal and places it in "buffer", right-justified.
        !           867:  * The value returned is the address of the first non-zero character,
        !           868:  * or the address of the last character if all are zero.
        !           869:  * The result is NOT null terminated, and is MAXDIGS characters long,
        !           870:  * starting at buffer[1] (to allow for insertion of a sign).
        !           871:  *
        !           872:  * This program assumes it is running on 2's complement machine
        !           873:  * with reasonable overflow treatment.
        !           874:  */
        !           875: char *
        !           876: b_dconv(value, buffer)
        !           877:        long value;
        !           878:        char *buffer;
        !           879: {
        !           880:        register char *bp;
        !           881:        register int svalue;
        !           882:        int n;
        !           883:        long lval;
        !           884:        
        !           885:        bp = buffer;
        !           886:        
        !           887:        /* zero is a special case */
        !           888:        if (value == 0) {
        !           889:                bp += MAXDIGS;
        !           890:                *bp = '0';
        !           891:                return(bp);
        !           892:        }
        !           893:        
        !           894:        /* develop the leading digit of the value in "n" */
        !           895:        n = 0;
        !           896:        while (value < 0) {
        !           897:                value -= BIG;   /* will eventually underflow */
        !           898:                n++;
        !           899:        }
        !           900:        while ((lval = value - BIG) >= 0) {
        !           901:                value = lval;
        !           902:                n++;
        !           903:        }
        !           904:        
        !           905:        /* stash it in buffer[1] to allow for a sign */
        !           906:        bp[1] = n + '0';
        !           907:        /*
        !           908:         * Now develop the rest of the digits. Since speed counts here,
        !           909:         * we do it in two loops. The first gets "value" down until it
        !           910:         * is no larger than MAXINT. The second one uses integer divides
        !           911:         * rather than long divides to speed it up.
        !           912:         */
        !           913:        bp += MAXDIGS + 1;
        !           914:        while (value > MAXINT) {
        !           915:                *--bp = (int)(value % 10) + '0';
        !           916:                value /= 10;
        !           917:        }
        !           918:        
        !           919:        /* cannot lose precision */
        !           920:        svalue = value;
        !           921:        while (svalue > 0) {
        !           922:                *--bp = (svalue % 10) + '0';
        !           923:                svalue /= 10;
        !           924:        }
        !           925:        
        !           926:        /* fill in intermediate zeroes if needed */
        !           927:        if (buffer[1] != '0') {
        !           928:                while (bp > buffer + 2)
        !           929:                        *--bp = '0';
        !           930:                --bp;
        !           931:        }
        !           932:        return(bp);
        !           933: }
        !           934: 
        !           935: /*
        !           936:  * This program sends string "s" to pputchar. The character after
        !           937:  * the end of "s" is given by "send". This allows the size of the
        !           938:  * field to be computed; it is stored in "alen". "width" contains the
        !           939:  * user specified length. If width<alen, the width will be taken to
        !           940:  * be alen. "sign" is zero if the string is to be right-justified
        !           941:  * in the field, nonzero if it is to be left-justified. "fill" is
        !           942:  * 0 if the string is to be padded with '0', positive if it is to be
        !           943:  * padded with ' ', and negative if an initial '-' should appear before
        !           944:  * any padding in right-justification (to avoid printing "-3" as
        !           945:  * "000-3" where "-0003" was intended).
        !           946:  */
        !           947: b_emit(s, send)
        !           948:        register char *s;
        !           949:        char *send;
        !           950: {
        !           951:        char cfill;
        !           952:        register int alen;
        !           953:        int npad;
        !           954:        
        !           955:        alen = send - s;
        !           956:        if (alen > width)
        !           957:                width = alen;
        !           958:        cfill = fill>0? ' ': '0';
        !           959:        
        !           960:        /* we may want to print a leading '-' before anything */
        !           961:        if (*s == '-' && fill < 0) {
        !           962:                pputchar(*s++);
        !           963:                alen--;
        !           964:                width--;
        !           965:        }
        !           966:        npad = width - alen;
        !           967:        
        !           968:        /* emit any leading pad characters */
        !           969:        if (!sign)
        !           970:                while (--npad >= 0)
        !           971:                        pputchar(cfill);
        !           972:                        
        !           973:        /* emit the string itself */
        !           974:        while (--alen >= 0)
        !           975:                pputchar(*s++);
        !           976:                
        !           977:        /* emit trailing pad characters */
        !           978:        if (sign)
        !           979:                while (--npad >= 0)
        !           980:                        pputchar(cfill);
        !           981: }

unix.superglobalmegacorp.com

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