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

1.1     ! root        1: #define UCB                    /* Controls output format for -F */
        !             2: /* #define     UCB_PWHASH      /* If have hashed password file */
        !             3: 
        !             4: /*
        !             5:  * ls - list file or directory
        !             6:  *
        !             7:  * Modified by Bill Joy UCB May/August 1977
        !             8:  * Modified by Dave Presotto BTL Feb/80
        !             9:  * Modified by Bill Joy and Mark Horton Summer 1980
        !            10:  *
        !            11:  * this version of ls is designed for graphic terminals and to
        !            12:  * list directories with lots of files in them compactly.
        !            13:  * It supports three variants for listings:
        !            14:  *
        !            15:  *     1) Columnar output.
        !            16:  *     2) Stream output.
        !            17:  *     3) Old one per line format.
        !            18:  *
        !            19:  * Columnar output is the default.
        !            20:  * If, however, the standard output is not a teletype, the default
        !            21:  * is one-per-line.
        !            22:  *
        !            23:  * With columnar output, the items are sorted down the columns.
        !            24:  * We use columns only for a directory we are interpreting.
        !            25:  * Thus, in particular, we do not use columns for
        !            26:  *
        !            27:  *     ls /usr/bin/p*
        !            28:  *
        !            29:  * This version of ls also prints non-printing characters as '?' if
        !            30:  * the standard output is a teletype.
        !            31:  *
        !            32:  * Flags relating to these and other new features are:
        !            33:  *
        !            34:  *     -m      force stream output.
        !            35:  *
        !            36:  *     -1      force one entry per line, e.g. to a teletype
        !            37:  *
        !            38:  *     -q      force non-printings to be '?'s, e.g. to a file
        !            39:  *
        !            40:  *     -C      force columnar output, e.g. into a file
        !            41:  *
        !            42:  *     -n      like -l, but user/group id's in decimal rather than
        !            43:  *             looking in /etc/passwd to save time
        !            44:  *
        !            45:  *     -F      turns on the "flagging" of executables and directories
        !            46:  *
        !            47:  *     -R      causes ls to recurse through the branches of the subtree
        !            48:  *             ala find
        !            49:  */
        !            50: 
        !            51: #include <sys/param.h>
        !            52: #include <sys/stat.h>
        !            53: #include <sys/dir.h>
        !            54: #include <stdio.h>
        !            55: #include <ctype.h>
        !            56: #include <pwd.h>
        !            57: #include <grp.h>
        !            58: #include <utmp.h>
        !            59: 
        !            60: struct utmp    utmp;
        !            61: #define NMAX   (sizeof utmp.ut_name)
        !            62: 
        !            63: #define MAXFILEWIDTH 14
        !            64: #define NFILES 1024
        !            65: FILE   *pwdf, *dirf;
        !            66: 
        !            67: struct lbuf {
        !            68:        union {
        !            69:                char    lname[15];
        !            70:                char    *namep;
        !            71:        } ln;
        !            72:        char    ltype;
        !            73:        ino_t   lnum;
        !            74:        short   lflags;
        !            75:        short   lnl;
        !            76:        short   luid;
        !            77:        short   lgid;
        !            78:        long    lsize;
        !            79:        long    lmtime;
        !            80: };
        !            81: 
        !            82: struct dchain {
        !            83:        char *dc_name;          /* the path name */
        !            84:        struct dchain *dc_next; /* the next directory on the chain */
        !            85: };
        !            86: 
        !            87: struct dchain *dfirst;         /* the start of the directory chain */
        !            88: struct dchain *cdfirst;                /* the start of the current directory chain */
        !            89: struct dchain *dtemp;          /* temporary used when linking */
        !            90: char *curdir;                  /* the current directory */
        !            91: 
        !            92: int    aflg, bflg, dflg, lflg, sflg, tflg, uflg, iflg, fflg, gflg, cflg;
        !            93: int    Aflg, nflg, qflg, Fflg, Rflg, across, Cflg;
        !            94: int    nopad;
        !            95: int    tabflg;
        !            96: int    rflg    = 1;
        !            97: long   year;
        !            98: int    flags;
        !            99: long   tblocks;
        !           100: int    statreq;
        !           101: int    xtraent;                /* for those switches which print out a total */
        !           102: struct lbuf    *flist[NFILES];
        !           103: struct lbuf    **lastp = flist;
        !           104: struct lbuf    **firstp = flist;
        !           105: char   *dotp   = ".";
        !           106: 
        !           107: char   *makename();
        !           108: struct lbuf *gstat();
        !           109: char   *ctime();
        !           110: long   nblock();
        !           111: char   *getname();
        !           112: 
        !           113: #define ISARG  0100000
        !           114: int    colwidth;
        !           115: int    filewidth;
        !           116: int    fixedwidth;
        !           117: int    outcol;
        !           118: 
        !           119: char   obuf[BUFSIZ];
        !           120: 
        !           121: main(argc, argv)
        !           122: int argc;
        !           123: char *argv[];
        !           124: {
        !           125: #include <sgtty.h>
        !           126: 
        !           127:        int i, width;
        !           128:        register struct lbuf *ep;
        !           129:        register struct lbuf **slastp;
        !           130:        struct lbuf **epp;
        !           131:        struct lbuf lb;
        !           132:        char *t;
        !           133:        char *cp;
        !           134:        int compar();
        !           135:        struct sgttyb sgbuf;
        !           136: 
        !           137:        Fflg = 0;
        !           138:        tabflg = 0;
        !           139:        Aflg = getuid() == 0;
        !           140:        setbuf(stdout, obuf);
        !           141:        lb.lmtime = time((long *) 0);
        !           142:        year = lb.lmtime - 6L*30L*24L*60L*60L; /* 6 months ago */
        !           143:        qflg = gtty(1, &sgbuf) == 0;
        !           144: 
        !           145:        /* guarantee at least on column width */
        !           146:        fixedwidth = 2;
        !           147: 
        !           148:        /*
        !           149:         * If the standard output is not a teletype,
        !           150:         * then we default to one-per-line format
        !           151:         * otherwise decide between stream and
        !           152:         * columnar based on our name.
        !           153:         */
        !           154:        if (qflg) {
        !           155:                Cflg = 1;
        !           156:                if ((sgbuf.sg_flags & XTABS) == 0)
        !           157:                        tabflg++;
        !           158:                for (cp = argv[0]; cp[0] && cp[1]; cp++)
        !           159:                        continue;
        !           160:                /*
        !           161:                 * Certain kinds of links (l, ll, lr, lf, lx) cause some
        !           162:                 * various options to be turned on.
        !           163:                 */
        !           164:                switch (cp[0]) {
        !           165:                case 'l':
        !           166:                        if (cp[-1] == 'l') {
        !           167:                                /* ll => -l */
        !           168:                                lflg = 1;
        !           169:                                statreq++;
        !           170:                                xtraent++;
        !           171:                        } else {
        !           172:                                /* l => -m */
        !           173:                                nopad = 1;
        !           174:                                Cflg = 0;
        !           175:                        }
        !           176:                        break;
        !           177:                case 'x':       /* lx => -x */
        !           178:                        across = 1;
        !           179:                        break;
        !           180:                case 'f':       /* lf => -F */
        !           181:                        Fflg = 1;
        !           182:                        break;
        !           183:                case 'r':       /* lr => -R */
        !           184:                        Rflg = 1;
        !           185:                        break;
        !           186:                }
        !           187:        } else {
        !           188:                tabflg++;
        !           189:        }
        !           190: 
        !           191:        while (--argc > 0 && *argv[1] == '-') {
        !           192:                argv++;
        !           193:                while (*++*argv) switch (**argv) {
        !           194:                /*
        !           195:                 * C - force columnar output
        !           196:                 */
        !           197:                case 'C':
        !           198:                        Cflg = 1;
        !           199:                        nopad = 0;
        !           200:                        continue;
        !           201:                /*
        !           202:                 * m - force stream output
        !           203:                 */
        !           204:                case 'm':
        !           205:                        Cflg = 0;
        !           206:                        nopad = 1;
        !           207:                        continue;
        !           208:                /*
        !           209:                 * x - force sort across
        !           210:                 */
        !           211:                case 'x':
        !           212:                        across = 1;
        !           213:                        nopad = 0;
        !           214:                        Cflg = 1;
        !           215:                        continue;
        !           216:                /*
        !           217:                 * q - force ?'s in output
        !           218:                 */
        !           219:                case 'q':
        !           220:                        qflg = 1;
        !           221:                        bflg = 0;
        !           222:                        continue;
        !           223:                /*
        !           224:                 * b - force octal value in output
        !           225:                 */
        !           226:                case 'b':
        !           227:                        bflg = 1;
        !           228:                        qflg = 0;
        !           229:                        continue;
        !           230:                /*
        !           231:                 * 1 - force 1/line in output
        !           232:                 */
        !           233:                case '1':
        !           234:                        Cflg = 0;
        !           235:                        nopad = 0;
        !           236:                        continue;
        !           237:                /* STANDARD FLAGS */
        !           238:                case 'a':
        !           239:                        aflg++;
        !           240:                        continue;
        !           241: 
        !           242:                case 'A':
        !           243:                        Aflg = !Aflg;
        !           244:                        continue;
        !           245: 
        !           246:                case 'c':
        !           247:                        cflg++;
        !           248:                        continue;
        !           249: 
        !           250:                case 's':
        !           251:                        fixedwidth += 5;
        !           252:                        sflg++;
        !           253:                        statreq++;
        !           254:                        xtraent++;
        !           255:                        continue;
        !           256: 
        !           257:                case 'd':
        !           258:                        dflg++;
        !           259:                        continue;
        !           260: 
        !           261:                /*
        !           262:                 * n - don't look in password file
        !           263:                 */
        !           264:                case 'n':
        !           265:                        nflg++;
        !           266:                case 'l':
        !           267:                        lflg++;
        !           268:                        statreq++;
        !           269:                        xtraent++;
        !           270:                        continue;
        !           271: 
        !           272:                case 'r':
        !           273:                        rflg = -1;
        !           274:                        continue;
        !           275: 
        !           276:                case 't':
        !           277:                        tflg++;
        !           278:                        statreq++;
        !           279:                        continue;
        !           280: 
        !           281:                case 'u':
        !           282:                        uflg++;
        !           283:                        continue;
        !           284: 
        !           285:                case 'i':
        !           286:                        fixedwidth += 6;
        !           287:                        iflg++;
        !           288:                        continue;
        !           289: 
        !           290:                case 'f':
        !           291:                        fflg++;
        !           292:                        continue;
        !           293: 
        !           294:                case 'g':
        !           295:                        gflg++;
        !           296:                        continue;
        !           297: 
        !           298:                case 'F':
        !           299:                        Fflg++;
        !           300:                        continue;
        !           301: 
        !           302:                case 'R':
        !           303:                        Rflg++;
        !           304:                        continue;
        !           305: 
        !           306:                default:
        !           307:                        fprintf (stderr, "usage: ls [-1ACFRabcdfgilmnqrstux] [files]\n");
        !           308:                        exit(1);
        !           309:                }
        !           310:        }
        !           311:        if (Fflg)
        !           312: #ifdef UCB
        !           313:                fixedwidth++;
        !           314: #else
        !           315:                fixedwidth += 2;
        !           316: #endif
        !           317:        if (fflg) {
        !           318:                aflg++;
        !           319:                lflg = 0;
        !           320:                sflg = 0;
        !           321:                tflg = 0;
        !           322:                statreq = 0;
        !           323:                xtraent = 0;
        !           324:        }
        !           325:        if(lflg) {
        !           326:                Cflg = 0;
        !           327:                t = "/etc/passwd";
        !           328:                if (gflg)
        !           329:                        t = "/etc/group";
        !           330:                nopad = 0;
        !           331:                fixedwidth = 70;
        !           332:                pwdf = fopen(t, "r");
        !           333:        }
        !           334:        if (argc==0) {
        !           335:                argc++;
        !           336:                argv = &dotp - 1;
        !           337:        }
        !           338:        for (i=0; i < argc; i++) {
        !           339:                argv++;
        !           340:                if (Cflg) {
        !           341:                        width = strlen (*argv);
        !           342:                        if (width > filewidth)
        !           343:                                filewidth = width;
        !           344:                }
        !           345:                if ((ep = gstat(*argv, 1))==NULL)
        !           346:                        continue;
        !           347:                ep->ln.namep = *argv;
        !           348:                ep->lflags |= ISARG;
        !           349:        }
        !           350:        if (!Cflg)
        !           351:                filewidth = MAXFILEWIDTH;
        !           352:        else
        !           353:        colwidth = fixedwidth + filewidth;
        !           354:        qsort(firstp, lastp - firstp, sizeof *lastp, compar);
        !           355:        slastp = lastp;
        !           356:        /* For each argument user typed */
        !           357:        for (epp=firstp; epp<slastp; epp++) {
        !           358:                ep = *epp;
        !           359:                if (ep->ltype=='d' && dflg==0 || fflg)
        !           360:                        pdirectory(ep->ln.namep, (argc>1), slastp);
        !           361:                else 
        !           362:                        pentry(ep);
        !           363: 
        !           364:                /* -R: print subdirectories found */
        !           365:                while (dfirst || cdfirst) {
        !           366:                        /* Place direct subdirs on front in right order */
        !           367:                        while (cdfirst) {
        !           368:                                /* reverse cdfirst onto front of dfirst */
        !           369:                                dtemp = cdfirst;
        !           370:                                cdfirst = cdfirst -> dc_next;
        !           371:                                dtemp -> dc_next = dfirst;
        !           372:                                dfirst = dtemp;
        !           373:                        }
        !           374:                        /* take off first dir on dfirst & print it */
        !           375:                        dtemp = dfirst;
        !           376:                        dfirst = dfirst->dc_next;
        !           377:                        pdirectory (dtemp->dc_name, 1, firstp);
        !           378:                        cfree (dtemp->dc_name);
        !           379:                        cfree (dtemp);
        !           380:                }
        !           381:        }
        !           382:        if (outcol)
        !           383:                putc('\n', stdout);
        !           384:        fflush(stdout);
        !           385: }
        !           386: 
        !           387: /*
        !           388:  * pdirectory: print the directory name, labelling it if title is
        !           389:  * nonzero, using lp as the place to start reading in the dir.
        !           390:  */
        !           391: pdirectory (name, title, lp)
        !           392: char *name;
        !           393: int title;
        !           394: struct lbuf **lp;
        !           395: {
        !           396:        register struct dchain *dp;
        !           397:        register struct lbuf *ap;
        !           398:        register char *pname;
        !           399:        struct lbuf **app;
        !           400: 
        !           401:        filewidth = 0;
        !           402:        curdir = name;
        !           403:        if (title)
        !           404:                printf("\n%s:\n", name);
        !           405:        lastp = lp;
        !           406:        readdir(name);
        !           407:        if (!Cflg)
        !           408:                filewidth = MAXFILEWIDTH;
        !           409:        colwidth = fixedwidth + filewidth;
        !           410: #ifdef notdef
        !           411:        /* Taken out because it appears this is done below in pem. */
        !           412:        if (tabflg) {
        !           413:                if (colwidth <= 8)
        !           414:                        colwidth = 8;
        !           415:                else
        !           416:                        if (colwidth <= 16)
        !           417:                                colwidth = 16;
        !           418:        }
        !           419: #endif
        !           420:        if (fflg==0)
        !           421:                qsort(lp,lastp - lp,sizeof *lastp,compar);
        !           422:        if (Rflg) for (app=lastp-1; app>=lp; app--) {
        !           423:                ap = *app;
        !           424:                if (ap->ltype == 'd' && strcmp(ap->ln.lname, ".") &&
        !           425:                                strcmp(ap->ln.lname, "..")) {
        !           426:                        dp = (struct dchain *) calloc(1, sizeof(struct dchain));
        !           427:                        pname = makename (curdir, ap->ln.lname);
        !           428:                        dp->dc_name = (char *) calloc(1, strlen(pname)+1);
        !           429:                        strcpy(dp->dc_name, pname);
        !           430:                        dp -> dc_next = dfirst;
        !           431:                        dfirst = dp;
        !           432:                }
        !           433:        }
        !           434:        if (lflg || sflg)
        !           435:                printf("total %D", tblocks);
        !           436:        pem(lp, lastp);
        !           437:        newline();
        !           438: }
        !           439: 
        !           440: /*
        !           441:  * pem: print 'em.  Print a list of files (e.g. a directory) bounded
        !           442:  * by slp and lp.
        !           443:  */
        !           444: pem(slp, lp)
        !           445:        register struct lbuf **slp, **lp;
        !           446: {
        !           447:        int ncols, nrows, row, col;
        !           448:        register struct lbuf **ep;
        !           449: 
        !           450:        if (tabflg) {
        !           451:                if (colwidth <= 9)
        !           452:                        colwidth = 8;
        !           453:                else
        !           454:                        if (colwidth <= 17)
        !           455:                                colwidth = 16;
        !           456:        }
        !           457:        ncols = 80 / colwidth;
        !           458:        if (ncols == 1 || Cflg == 0) {
        !           459:                for (ep = slp; ep < lp; ep++)
        !           460:                        pentry(*ep);
        !           461:                return;
        !           462:        }
        !           463:        if (across) {
        !           464:                for (ep = slp; ep < lp; ep++)
        !           465:                        pentry(*ep);
        !           466:                return;
        !           467:        }
        !           468:        if (xtraent)
        !           469:                slp--;
        !           470:        nrows = (lp - slp - 1) / ncols + 1;
        !           471:        for (row = 0; row < nrows; row++) {
        !           472:                col = row == 0 && xtraent;
        !           473:                for (; col < ncols; col++) {
        !           474:                        ep = slp + (nrows * col) + row;
        !           475:                        if (ep < lp)
        !           476:                                pentry(*ep);
        !           477:                }
        !           478:                if (outcol)
        !           479:                        printf("\n");
        !           480:        }
        !           481: }
        !           482: 
        !           483: /*
        !           484:  * pputchar: like putchar but knows how to handle control chars.
        !           485:  * CAUTION: if you make ctrl chars print in ^x notation, or any
        !           486:  * other notation which is wider than one character, the column
        !           487:  * nature of things (such as files with 14 letter names) will be
        !           488:  * messed up.  Weigh this carefully!
        !           489:  */
        !           490: pputchar(c)
        !           491:        char c;
        !           492: {
        !           493:        char cc;
        !           494: 
        !           495:        switch (c) {
        !           496:                case '\t':
        !           497:                        outcol = (outcol + 8) &~ 7;
        !           498:                        break;
        !           499:                case '\n':
        !           500:                        outcol = 0;
        !           501:                        break;
        !           502:                default:
        !           503:                        if (c < ' ' || c >= 0177) {
        !           504:                                if (qflg)
        !           505:                                        c = '?';
        !           506:                                else if (bflg) {
        !           507:                                        outcol += 3;
        !           508:                                        putc ('\\', stdout);
        !           509:                                        cc = '0' + (c>>6 & 07);
        !           510:                                        putc (cc, stdout);
        !           511:                                        cc = '0' + (c>>3 & 07);
        !           512:                                        putc (cc, stdout);
        !           513:                                        c = '0' + (c & 07);
        !           514:                                }
        !           515:                        }
        !           516:                        outcol++;
        !           517:                        break;
        !           518:        }
        !           519:        putc(c, stdout);
        !           520: }
        !           521: 
        !           522: newline()
        !           523: {
        !           524:        if (outcol)
        !           525:                putc('\n', stdout);
        !           526:        outcol = 0;
        !           527: }
        !           528: 
        !           529: /*
        !           530:  * column: get to the beginning of the next column.
        !           531:  */
        !           532: column()
        !           533: {
        !           534: 
        !           535:        if (outcol == 0)
        !           536:                return;
        !           537:        if (nopad) {
        !           538:                putc(',', stdout);
        !           539:                outcol++;
        !           540:                if (outcol + colwidth + 2 > 80) {
        !           541:                        putc('\n', stdout);
        !           542:                        outcol = 0;
        !           543:                        return;
        !           544:                }
        !           545:                putc(' ', stdout);
        !           546:                outcol++;
        !           547:                return;
        !           548:        }
        !           549:        if (Cflg == 0) {
        !           550:                putc('\n', stdout);
        !           551:                return;
        !           552:        }
        !           553:        if ((outcol / colwidth + 2) * colwidth > 80) {
        !           554:                putc('\n', stdout);
        !           555:                outcol = 0;
        !           556:                return;
        !           557:        }
        !           558:        if (tabflg && (colwidth <= 16)) {
        !           559:                if (colwidth > 8)
        !           560:                        if ((outcol % 16) < 8) {
        !           561:                                outcol += 8 - (outcol % 8);
        !           562:                                putc ('\t', stdout);
        !           563:                        }
        !           564:                outcol += 8 - (outcol % 8);
        !           565:                putc ('\t', stdout);
        !           566:                return;
        !           567:        }
        !           568:        do {
        !           569:                outcol++;
        !           570:                putc(' ', stdout);
        !           571:        } while (outcol % colwidth);
        !           572: }
        !           573: 
        !           574: 
        !           575: /*
        !           576:  * nblock: the number of 512 byte blocks a size byte file takes up.
        !           577:  * (Note: the number stays 512 no matter what BUFSIZ or the filesystem uses.)
        !           578:  */
        !           579: long
        !           580: nblock(size)
        !           581: long size;
        !           582: {
        !           583:        return((size+511)>>9);
        !           584: }
        !           585: 
        !           586: /*
        !           587:  * This code handles the rwx- business.
        !           588:  * You figure it out.
        !           589:  */
        !           590: int    m1[] = { 1, S_IREAD>>0, 'r', '-' };
        !           591: int    m2[] = { 1, S_IWRITE>>0, 'w', '-' };
        !           592: int    m3[] = { 2, S_ISUID, 's', S_IEXEC>>0, 'x', '-' };
        !           593: int    m4[] = { 1, S_IREAD>>3, 'r', '-' };
        !           594: int    m5[] = { 1, S_IWRITE>>3, 'w', '-' };
        !           595: int    m6[] = { 2, S_ISGID, 's', S_IEXEC>>3, 'x', '-' };
        !           596: int    m7[] = { 1, S_IREAD>>6, 'r', '-' };
        !           597: int    m8[] = { 1, S_IWRITE>>6, 'w', '-' };
        !           598: int    m9[] = { 2, S_ISVTX, 't', S_IEXEC>>6, 'x', '-' };
        !           599: 
        !           600: int    *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9};
        !           601: 
        !           602: pmode(aflag)
        !           603: {
        !           604:        register int **mp;
        !           605: 
        !           606:        flags = aflag;
        !           607:        for (mp = &m[0]; mp < &m[sizeof(m)/sizeof(m[0])];)
        !           608:                select(*mp++);
        !           609: }
        !           610: 
        !           611: select(pairp)
        !           612: register int *pairp;
        !           613: {
        !           614:        register int n;
        !           615: 
        !           616:        n = *pairp++;
        !           617:        while (--n>=0 && (flags&*pairp++)==0)
        !           618:                pairp++;
        !           619:        pputchar(*pairp);
        !           620: }
        !           621: 
        !           622: /*
        !           623:  * returns cat(dir, "/", file), unless dir ends in /, when it doesn't //
        !           624:  */
        !           625: char *
        !           626: makename(dir, file)
        !           627: char *dir, *file;
        !           628: {
        !           629:        static char dfile[100];
        !           630:        register char *dp, *fp;
        !           631:        register int i;
        !           632: 
        !           633:        dp = dfile;
        !           634:        fp = dir;
        !           635:        while (*fp)
        !           636:                *dp++ = *fp++;
        !           637:        if (*(dp-1) != '/')
        !           638:        *dp++ = '/';
        !           639:        fp = file;
        !           640:        for (i=0; i<DIRSIZ; i++)
        !           641:                *dp++ = *fp++;
        !           642:        *dp = 0;
        !           643:        return(dfile);
        !           644: }
        !           645: 
        !           646: /*
        !           647:  * readdir: read in the directory whose name is dir,
        !           648:  * starting at lastp.
        !           649:  */
        !           650: readdir(dir)
        !           651: char *dir;
        !           652: {
        !           653:        static struct direct dentry;
        !           654:        register int j, width;
        !           655:        register struct lbuf *ep;
        !           656: 
        !           657:        if ((dirf = fopen(dir, "r")) == NULL) {
        !           658:                printf("%s unreadable\n", dir);
        !           659:                return;
        !           660:        }
        !           661:        tblocks = 0;
        !           662:        for(;;) {
        !           663:                if (fread(&dentry, sizeof(dentry), 1, dirf) != 1)
        !           664:                        break;
        !           665:                if (dentry.d_ino==0 ||
        !           666:                        aflg==0 && dentry.d_name[0]=='.' && (
        !           667:                        !Aflg ||
        !           668:                        dentry.d_name[1]=='\0'
        !           669:                        || dentry.d_name[1]=='.' && dentry.d_name[2]=='\0'))
        !           670:                        continue;
        !           671:                if (Cflg) {
        !           672:                        width = strlen (dentry.d_name);
        !           673:                        if (width > filewidth)
        !           674:                                filewidth = width;
        !           675:                }
        !           676:                ep = gstat(makename(dir, dentry.d_name), Fflg || Rflg);
        !           677:                if (ep==NULL)
        !           678:                        continue;
        !           679:                if (ep->lnum != -1)
        !           680:                        ep->lnum = dentry.d_ino;
        !           681:                for (j=0; j<DIRSIZ; j++)
        !           682:                        ep->ln.lname[j] = dentry.d_name[j];
        !           683:        }
        !           684:        fclose(dirf);
        !           685: }
        !           686: 
        !           687: /*
        !           688:  * stat the given file and return an lbuf containing it.
        !           689:  * argfl is nonzero if a stat is required because the file is
        !           690:  * an argument, rather than having been found in a directory.
        !           691:  */
        !           692: struct lbuf *
        !           693: gstat(file, argfl)
        !           694: char *file;
        !           695: {
        !           696:        struct stat statb;
        !           697:        register struct lbuf *rep;
        !           698:        static int nomocore;
        !           699: 
        !           700:        if (nomocore)
        !           701:                return(NULL);
        !           702:        rep = (struct lbuf *)malloc(sizeof(struct lbuf));
        !           703:        if (rep==NULL) {
        !           704:                fprintf(stderr, "ls: out of memory\n");
        !           705:                nomocore = 1;
        !           706:                return(NULL);
        !           707:        }
        !           708:        if (lastp >= &flist[NFILES]) {
        !           709:                static int msg;
        !           710:                lastp--;
        !           711:                if (msg==0) {
        !           712:                        fprintf(stderr, "ls: too many files\n");
        !           713:                        msg++;
        !           714:                }
        !           715:        }
        !           716:        *lastp++ = rep;
        !           717:        rep->lflags = 0;
        !           718:        rep->lnum = 0;
        !           719:        rep->ltype = '-';
        !           720:        if (argfl || statreq) {
        !           721:                if (stat(file, &statb)<0) {
        !           722:                        printf("%s not found\n", file);
        !           723:                        statb.st_ino = -1;
        !           724:                        statb.st_size = 0;
        !           725:                        statb.st_mode = 0;
        !           726:                        if (argfl) {
        !           727:                                lastp--;
        !           728:                                return(0);
        !           729:                        }
        !           730:                }
        !           731:                rep->lnum = statb.st_ino;
        !           732:                rep->lsize = statb.st_size;
        !           733:                switch(statb.st_mode&S_IFMT) {
        !           734: 
        !           735:                case S_IFDIR:
        !           736:                        rep->ltype = 'd';
        !           737:                        break;
        !           738: 
        !           739:                case S_IFBLK:
        !           740:                        rep->ltype = 'b';
        !           741:                        rep->lsize = statb.st_rdev;
        !           742:                        break;
        !           743: 
        !           744:                case S_IFCHR:
        !           745:                        rep->ltype = 'c';
        !           746:                        rep->lsize = statb.st_rdev;
        !           747:                        break;
        !           748: 
        !           749:                case S_IFMPB:
        !           750:                        rep->ltype = 'M';
        !           751:                        rep->lsize = statb.st_rdev;
        !           752:                        break;
        !           753: 
        !           754:                case S_IFMPC:
        !           755:                        rep->ltype = 'm';
        !           756:                        rep->lsize = statb.st_rdev;
        !           757:                        break;
        !           758:                }
        !           759:                rep->lflags = statb.st_mode & ~S_IFMT;
        !           760:                rep->luid = statb.st_uid;
        !           761:                rep->lgid = statb.st_gid;
        !           762:                rep->lnl = statb.st_nlink;
        !           763:                if(uflg)
        !           764:                        rep->lmtime = statb.st_atime;
        !           765:                else if (cflg)
        !           766:                        rep->lmtime = statb.st_ctime;
        !           767:                else
        !           768:                        rep->lmtime = statb.st_mtime;
        !           769:                tblocks += nblock(statb.st_size);
        !           770:        }
        !           771:        return(rep);
        !           772: }
        !           773: 
        !           774: /*
        !           775:  * decide whether to print pp1 before or after pp2, based on their
        !           776:  * names, various times, and the r flag.
        !           777:  */
        !           778: compar(pp1, pp2)
        !           779: struct lbuf **pp1, **pp2;
        !           780: {
        !           781:        register struct lbuf *p1, *p2;
        !           782: 
        !           783:        p1 = *pp1;
        !           784:        p2 = *pp2;
        !           785:        if (dflg==0) {
        !           786:                if (p1->lflags&ISARG && p1->ltype=='d') {
        !           787:                        if (!(p2->lflags&ISARG && p2->ltype=='d'))
        !           788:                                return(1);
        !           789:                } else {
        !           790:                        if (p2->lflags&ISARG && p2->ltype=='d')
        !           791:                                return(-1);
        !           792:                }
        !           793:        }
        !           794:        if (tflg) {
        !           795:                if(p2->lmtime == p1->lmtime)
        !           796:                        return(0);
        !           797:                if(p2->lmtime > p1->lmtime)
        !           798:                        return(rflg);
        !           799:                return(-rflg);
        !           800:        }
        !           801:        return(rflg * strcmp(p1->lflags&ISARG? p1->ln.namep: p1->ln.lname,
        !           802:                                p2->lflags&ISARG? p2->ln.namep: p2->ln.lname));
        !           803: }
        !           804: 
        !           805: /*
        !           806:  * print the entry pointed at by ap
        !           807:  */
        !           808: pentry(ap)
        !           809: struct lbuf *ap;
        !           810: {
        !           811:        struct { char dminor, dmajor;};
        !           812:        register struct lbuf *p;
        !           813:        register char *cp;
        !           814:        char fname[100];
        !           815:        char *pname;
        !           816:        struct passwd *getpwuid();
        !           817:        struct passwd *pwptr;
        !           818:        struct group *getgrgid();
        !           819:        struct group *grptr;
        !           820: 
        !           821:        fname[0] = 0;
        !           822:        p = ap;
        !           823:        if (p->lnum == -1)
        !           824:                return;
        !           825:        column();
        !           826:        if (iflg)
        !           827:                if (nopad && !lflg)
        !           828:                        printf("%d ", p->lnum);
        !           829:                else
        !           830:                        printf("%5d ", p->lnum);
        !           831:        if (sflg)
        !           832:                if (nopad && !lflg)
        !           833:                        printf("%D ", nblock(p->lsize));
        !           834:                else
        !           835:                        printf("%4D ", nblock(p->lsize));
        !           836:        if (lflg) {
        !           837:                pputchar(p->ltype);
        !           838:                pmode(p->lflags);
        !           839:                printf("%2d ", p->lnl);
        !           840:                if(gflg) {
        !           841:                        grptr = getgrgid(p->lgid);
        !           842:                        if (nflg == 0 && grptr != 0)
        !           843:                                printf("%-8.8s", grptr->gr_name);
        !           844:                        else
        !           845:                                printf("%-8d", p->lgid);
        !           846:                } else {
        !           847: #ifndef UCB_PWHASH
        !           848:                        char *name;
        !           849:                        if (nflg == 0 && (name = getname(p->luid))) {
        !           850:                                printf("%-8.8s", name);
        !           851:                        }
        !           852: #else
        !           853:                        pwptr = getpwuid(p->luid);
        !           854:                        if (nflg == 0 && pwptr != 0)
        !           855:                                printf("%-8.8s", pwptr->pw_name);
        !           856: #endif
        !           857:                        else
        !           858:                                printf("%-8d", p->luid);
        !           859:                }
        !           860:                switch (p->ltype) {
        !           861: 
        !           862:                case 'b':
        !           863:                case 'c':
        !           864:                case 'm':
        !           865:                case 'M':
        !           866:                        printf("%3d,%3d",
        !           867:                            major((int)p->lsize), minor((int)p->lsize));
        !           868:                        break;
        !           869:                default:
        !           870:                        printf("%7ld", p->lsize);
        !           871:                }
        !           872:                cp = ctime(&p->lmtime);
        !           873:                if(p->lmtime < year)
        !           874:                        printf(" %-7.7s %-4.4s ", cp+4, cp+20); else
        !           875:                        printf(" %-12.12s ", cp+4);
        !           876:        }
        !           877: #ifndef UCB
        !           878:        if (Fflg) {
        !           879:            if (p->ltype == 'd')
        !           880:                strcat (fname, "[");
        !           881:            else if (p->lflags & 0111)
        !           882:                strcat (fname, "*");
        !           883:            else if (!nopad)
        !           884:                strcat (fname, " ");
        !           885:        }
        !           886: #endif
        !           887:        if (p->lflags & ISARG)
        !           888:            strncat (fname, p->ln.namep, 98);
        !           889:        else
        !           890:            strncat (fname, p->ln.lname, 14);
        !           891: #ifndef UCB
        !           892:        if (Fflg) {
        !           893:            if (p->ltype == 'd')
        !           894:                strcat (fname, "]");
        !           895:            else if (!nopad)
        !           896:                strcat (fname, " ");
        !           897:        }
        !           898: #else
        !           899:        if (Fflg) {
        !           900:            if (p->ltype == 'd')
        !           901:                strcat (fname, "/");
        !           902:            else if (p->lflags & 0111)
        !           903:                strcat (fname, "*");
        !           904:            else if (!nopad)
        !           905:                strcat (fname, " ");
        !           906:        }
        !           907: #endif
        !           908:        printf ("%s", fname);
        !           909:        free(ap);
        !           910: }
        !           911: 
        !           912: /* char printf_id[] = "@(#) printf.c:2.2 6/5/79";*/
        !           913: 
        !           914: #include "varargs.h"
        !           915: 
        !           916: /*
        !           917:  * This version of printf is compatible with the Version 7 C
        !           918:  * printf. The differences are only minor except that this
        !           919:  * printf assumes it is to print through pputchar. Version 7
        !           920:  * printf is more general (and is much larger) and includes
        !           921:  * provisions for floating point.
        !           922:  */
        !           923: 
        !           924: #define MAXOCT 11          /* Maximum octal digits in a long */
        !           925: #define MAXINT 32767       /* largest normal length positive integer */
        !           926: #define BIG    1000000000  /* largest power of 10 less than an unsigned long */
        !           927: #define MAXDIGS 10         /* number of digits in BIG */
        !           928: 
        !           929: static int width, sign, fill;
        !           930: 
        !           931: char *b_dconv();
        !           932: 
        !           933: printf(va_alist)
        !           934:        va_dcl
        !           935: {
        !           936:        va_list ap;
        !           937:        register char *fmt;
        !           938:        char fcode;
        !           939:        int prec;
        !           940:        int length,mask1,nbits,n;
        !           941:        long int mask2, num;
        !           942:        register char *bptr;
        !           943:        char *ptr;
        !           944:        char buf[134];
        !           945: 
        !           946:        va_start(ap);
        !           947:        fmt = va_arg(ap,char *);
        !           948:        for (;;) {
        !           949:                /* process format string first */
        !           950:                while ((fcode = *fmt++)!='%') {
        !           951:                        /* ordinary (non-%) character */
        !           952:                        if (fcode=='\0')
        !           953:                                return;
        !           954:                        pputchar(fcode);
        !           955:                }
        !           956:                /* length modifier: -1 for h, 1 for l, 0 for none */
        !           957:                length = 0;
        !           958:                /* check for a leading - sign */
        !           959:                sign = 0;
        !           960:                if (*fmt == '-') {
        !           961:                        sign++;
        !           962:                        fmt++;
        !           963:                }
        !           964:                /* a '0' may follow the - sign */
        !           965:                /* this is the requested fill character */
        !           966:                fill = 1;
        !           967:                if (*fmt == '0') {
        !           968:                        fill--;
        !           969:                        fmt++;
        !           970:                }
        !           971:                
        !           972:                /* Now comes a digit string which may be a '*' */
        !           973:                if (*fmt == '*') {
        !           974:                        width = va_arg(ap, int);
        !           975:                        if (width < 0) {
        !           976:                                width = -width;
        !           977:                                sign = !sign;
        !           978:                        }
        !           979:                        fmt++;
        !           980:                }
        !           981:                else {
        !           982:                        width = 0;
        !           983:                        while (*fmt>='0' && *fmt<='9')
        !           984:                                width = width * 10 + (*fmt++ - '0');
        !           985:                }
        !           986:                
        !           987:                /* maybe a decimal point followed by more digits (or '*') */
        !           988:                if (*fmt=='.') {
        !           989:                        if (*++fmt == '*') {
        !           990:                                prec = va_arg(ap, int);
        !           991:                                fmt++;
        !           992:                        }
        !           993:                        else {
        !           994:                                prec = 0;
        !           995:                                while (*fmt>='0' && *fmt<='9')
        !           996:                                        prec = prec * 10 + (*fmt++ - '0');
        !           997:                        }
        !           998:                }
        !           999:                else
        !          1000:                        prec = -1;
        !          1001:                
        !          1002:                /*
        !          1003:                 * At this point, "sign" is nonzero if there was
        !          1004:                 * a sign, "fill" is 0 if there was a leading
        !          1005:                 * zero and 1 otherwise, "width" and "prec"
        !          1006:                 * contain numbers corresponding to the digit
        !          1007:                 * strings before and after the decimal point,
        !          1008:                 * respectively, and "fmt" addresses the next
        !          1009:                 * character after the whole mess. If there was
        !          1010:                 * no decimal point, "prec" will be -1.
        !          1011:                 */
        !          1012:                switch (*fmt) {
        !          1013:                        case 'L':
        !          1014:                        case 'l':
        !          1015:                                length = 2;
        !          1016:                                /* no break!! */
        !          1017:                        case 'h':
        !          1018:                        case 'H':
        !          1019:                                length--;
        !          1020:                                fmt++;
        !          1021:                                break;
        !          1022:                }
        !          1023:                
        !          1024:                /*
        !          1025:                 * At exit from the following switch, we will
        !          1026:                 * emit the characters starting at "bptr" and
        !          1027:                 * ending at "ptr"-1, unless fcode is '\0'.
        !          1028:                 */
        !          1029:                switch (fcode = *fmt++) {
        !          1030:                        /* process characters and strings first */
        !          1031:                        case 'c':
        !          1032:                                buf[0] = va_arg(ap, int);
        !          1033:                                ptr = bptr = &buf[0];
        !          1034:                                if (buf[0] != '\0')
        !          1035:                                        ptr++;
        !          1036:                                break;
        !          1037:                        case 's':
        !          1038:                                bptr = va_arg(ap,char *);
        !          1039:                                if (bptr==0)
        !          1040:                                        bptr = "(null pointer)";
        !          1041:                                if (prec < 0)
        !          1042:                                        prec = MAXINT;
        !          1043:                                for (n=0; *bptr++ && n < prec; n++) ;
        !          1044:                                ptr = --bptr;
        !          1045:                                bptr -= n;
        !          1046:                                break;
        !          1047:                        case 'O':
        !          1048:                                length = 1;
        !          1049:                                fcode = 'o';
        !          1050:                                /* no break */
        !          1051:                        case 'o':
        !          1052:                        case 'X':
        !          1053:                        case 'x':
        !          1054:                                if (length > 0)
        !          1055:                                        num = va_arg(ap,long);
        !          1056:                                else
        !          1057:                                        num = (unsigned)va_arg(ap,int);
        !          1058:                                if (fcode=='o') {
        !          1059:                                        mask1 = 0x7;
        !          1060:                                        mask2 = 0x1fffffffL;
        !          1061:                                        nbits = 3;
        !          1062:                                }
        !          1063:                                else {
        !          1064:                                        mask1 = 0xf;
        !          1065:                                        mask2 = 0x0fffffffL;
        !          1066:                                        nbits = 4;
        !          1067:                                }
        !          1068:                                n = (num!=0);
        !          1069:                                bptr = buf + MAXOCT + 3;
        !          1070:                                /* shift and mask for speed */
        !          1071:                                do
        !          1072:                                    if (((int) num & mask1) < 10)
        !          1073:                                        *--bptr = ((int) num & mask1) + 060;
        !          1074:                                    else
        !          1075:                                        *--bptr = ((int) num & mask1) + 0127;
        !          1076:                                while (num = (num >> nbits) & mask2);
        !          1077:                                
        !          1078:                                if (fcode=='o') {
        !          1079:                                        if (n)
        !          1080:                                                *--bptr = '0';
        !          1081:                                }
        !          1082:                                else
        !          1083:                                        if (!sign && fill <= 0) {
        !          1084:                                                pputchar('0');
        !          1085:                                                pputchar(fcode);
        !          1086:                                                width -= 2;
        !          1087:                                        }
        !          1088:                                        else {
        !          1089:                                                *--bptr = fcode;
        !          1090:                                                *--bptr = '0';
        !          1091:                                        }
        !          1092:                                ptr = buf + MAXOCT + 3;
        !          1093:                                break;
        !          1094:                        case 'D':
        !          1095:                        case 'U':
        !          1096:                        case 'I':
        !          1097:                                length = 1;
        !          1098:          
        !          1099:                      fcode = fcode + 'a' - 'A';
        !          1100:                                /* no break */
        !          1101:                        case 'd':
        !          1102:                        case 'i':
        !          1103:                        case 'u':
        !          1104:                                if (length > 0)
        !          1105:                                        num = va_arg(ap,long);
        !          1106:                                else {
        !          1107:                                        n = va_arg(ap,int);
        !          1108:                                        if (fcode=='u')
        !          1109:                                                num = (unsigned) n;
        !          1110:                                        else
        !          1111:                                                num = (long) n;
        !          1112:                                }
        !          1113:                                if (n = (fcode != 'u' && num < 0))
        !          1114:                                        num = -num;
        !          1115:                                /* now convert to digits */
        !          1116:                                bptr = b_dconv(num, buf);
        !          1117:                                if (n)
        !          1118:                                        *--bptr = '-';
        !          1119:                                if (fill == 0)
        !          1120:                                        fill = -1;
        !          1121:                                ptr = buf + MAXDIGS + 1;
        !          1122:                                break;
        !          1123:                        default:
        !          1124:                                /* not a control character, 
        !          1125:                                 * print it.
        !          1126:                                 */
        !          1127:                                ptr = bptr = &fcode;
        !          1128:                                ptr++;
        !          1129:                                break;
        !          1130:                        }
        !          1131:                        if (fcode != '\0')
        !          1132:                                b_emit(bptr,ptr);
        !          1133:        }
        !          1134:        va_end(ap);
        !          1135: }
        !          1136: 
        !          1137: /* b_dconv converts the unsigned long integer "value" to
        !          1138:  * printable decimal and places it in "buffer", right-justified.
        !          1139:  * The value returned is the address of the first non-zero character,
        !          1140:  * or the address of the last character if all are zero.
        !          1141:  * The result is NOT null terminated, and is MAXDIGS characters long,
        !          1142:  * starting at buffer[1] (to allow for insertion of a sign).
        !          1143:  *
        !          1144:  * This program assumes it is running on 2's complement machine
        !          1145:  * with reasonable overflow treatment.
        !          1146:  */
        !          1147: char *
        !          1148: b_dconv(value, buffer)
        !          1149:        long value;
        !          1150:        char *buffer;
        !          1151: {
        !          1152:        register char *bp;
        !          1153:        register int svalue;
        !          1154:        int n;
        !          1155:        long lval;
        !          1156:        
        !          1157:        bp = buffer;
        !          1158:        
        !          1159:        /* zero is a special case */
        !          1160:        if (value == 0) {
        !          1161:                bp += MAXDIGS;
        !          1162:                *bp = '0';
        !          1163:                return(bp);
        !          1164:        }
        !          1165:        
        !          1166:        /* develop the leading digit of the value in "n" */
        !          1167:        n = 0;
        !          1168:        while (value < 0) {
        !          1169:                value -= BIG;   /* will eventually underflow */
        !          1170:                n++;
        !          1171:        }
        !          1172:        while ((lval = value - BIG) >= 0) {
        !          1173:                value = lval;
        !          1174:                n++;
        !          1175:        }
        !          1176:        
        !          1177:        /* stash it in buffer[1] to allow for a sign */
        !          1178:        bp[1] = n + '0';
        !          1179:        /*
        !          1180:         * Now develop the rest of the digits. Since speed counts here,
        !          1181:         * we do it in two loops. The first gets "value" down until it
        !          1182:         * is no larger than MAXINT. The second one uses integer divides
        !          1183:         * rather than long divides to speed it up.
        !          1184:         */
        !          1185:        bp += MAXDIGS + 1;
        !          1186:        while (value > MAXINT) {
        !          1187:                *--bp = (int)(value % 10) + '0';
        !          1188:                value /= 10;
        !          1189:        }
        !          1190:        
        !          1191:        /* cannot lose precision */
        !          1192:        svalue = value;
        !          1193:        while (svalue > 0) {
        !          1194:                *--bp = (svalue % 10) + '0';
        !          1195:                svalue /= 10;
        !          1196:        }
        !          1197:        
        !          1198:        /* fill in intermediate zeroes if needed */
        !          1199:        if (buffer[1] != '0') {
        !          1200:                while (bp > buffer + 2)
        !          1201:                        *--bp = '0';
        !          1202:                --bp;
        !          1203:        }
        !          1204:        return(bp);
        !          1205: }
        !          1206: 
        !          1207: /*
        !          1208:  * This program sends string "s" to pputchar. The character after
        !          1209:  * the end of "s" is given by "send". This allows the size of the
        !          1210:  * field to be computed; it is stored in "alen". "width" contains the
        !          1211:  * user specified length. If width<alen, the width will be taken to
        !          1212:  * be alen. "sign" is zero if the string is to be right-justified
        !          1213:  * in the field, nonzero if it is to be left-justified. "fill" is
        !          1214:  * 0 if the string is to be padded with '0', positive if it is to be
        !          1215:  * padded with ' ', and negative if an initial '-' should appear before
        !          1216:  * any padding in right-justification (to avoid printing "-3" as
        !          1217:  * "000-3" where "-0003" was intended).
        !          1218:  */
        !          1219: b_emit(s, send)
        !          1220:        register char *s;
        !          1221:        char *send;
        !          1222: {
        !          1223:        char cfill;
        !          1224:        register int alen;
        !          1225:        int npad;
        !          1226:        
        !          1227:        alen = send - s;
        !          1228:        if (alen > width)
        !          1229:                width = alen;
        !          1230:        cfill = fill>0? ' ': '0';
        !          1231:        
        !          1232:        /* we may want to print a leading '-' before anything */
        !          1233:        if (*s == '-' && fill < 0) {
        !          1234:                pputchar(*s++);
        !          1235:                alen--;
        !          1236:                width--;
        !          1237:        }
        !          1238:        npad = width - alen;
        !          1239:        
        !          1240:        /* emit any leading pad characters */
        !          1241:        if (!sign)
        !          1242:                while (--npad >= 0)
        !          1243:                        pputchar(cfill);
        !          1244:                        
        !          1245:        /* emit the string itself */
        !          1246:        while (--alen >= 0)
        !          1247:                pputchar(*s++);
        !          1248:                
        !          1249:        /* emit trailing pad characters */
        !          1250:        if (sign)
        !          1251:                while (--npad >= 0)
        !          1252:                        pputchar(cfill);
        !          1253: }
        !          1254: 
        !          1255: #ifndef UCB_PWHASH
        !          1256: #define NUID   2048
        !          1257: 
        !          1258: char   names[NUID][NMAX+1];
        !          1259: 
        !          1260: char *
        !          1261: getname(uid)
        !          1262: {
        !          1263:        register struct passwd *pw;
        !          1264:        static init;
        !          1265:        struct passwd *getpwent();
        !          1266: 
        !          1267:        if (uid >= 0 && uid < NUID && names[uid][0])
        !          1268:                return (&names[uid][0]);
        !          1269:        if (init == 2)
        !          1270:                return (0);
        !          1271:        if (init == 0)
        !          1272:                setpwent(), init = 1;
        !          1273:        while (pw = getpwent()) {
        !          1274:                if (pw->pw_uid < 0 || pw->pw_uid >= NUID)
        !          1275:                        continue;
        !          1276:                if (names[pw->pw_uid][0])
        !          1277:                        continue;
        !          1278:                strncpy(names[pw->pw_uid], pw->pw_name, NMAX);
        !          1279:                if (pw->pw_uid == uid)
        !          1280:                        return (&names[uid][0]);
        !          1281:        }
        !          1282:        init = 2;
        !          1283:        endpwent();
        !          1284:        return (0);
        !          1285: }
        !          1286: #endif

unix.superglobalmegacorp.com

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