Annotation of 40BSD/cmd/ls/ucbls.c, revision 1.1.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.