Annotation of coherent/d/bin/dos/ls.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * ls.c
        !             3:  * 03/17/92
        !             4:  * List structure
        !             5:  */
        !             6: 
        !             7: #include <stdio.h>
        !             8: #include <canon.h>
        !             9: #include <time.h>
        !            10: #include <sys/stat.h>
        !            11: #include <sys/dir.h>
        !            12: #include <pwd.h>
        !            13: #include <grp.h>
        !            14: #include <string.h>
        !            15: 
        !            16: #define        BSIZE   BUFSIZ          /* Disc blocking factor for '-s' */
        !            17: #define        NBN     128             /* Number of blocks in an indirect block */
        !            18: #define        ND      10              /* Number of direct blocks */
        !            19: #define        NI      1               /* Number of indirect blocks */
        !            20: #define        NII     1               /* Number of double indirect blocks */
        !            21: #define        NIII    1               /* Number of triple indirect blocks */
        !            22: 
        !            23: #define        MTIME   0               /* Use modify time */
        !            24: #define        ATIME   1               /* Use access time */
        !            25: #define        CTIME   2               /* Use create time */
        !            26: 
        !            27: #define        GAP     1               /* Space between Multi-column entries   */
        !            28: #define        MAXLEN  78              /* Maximum line length                  */
        !            29: #define MAXARG 512             /* Maximum # of args stored for -C sort */
        !            30: #define MAXDIR 128             /* Maximum # of subdirectories for -R   */
        !            31: #define MAXWID 12              /* Default max width for columns        */
        !            32: #define        MAXNBUF 80              /* Maximum namebuf length               */
        !            33: 
        !            34: #define        OLD     (60L*60*24*365) /* old form of dates (seconds) */
        !            35: 
        !            36: /*
        !            37:  * The following flags are mutually exclusive.
        !            38:  * The rightmost one on the command line wins.
        !            39:  */
        !            40: #define EXCLUDE_Clmnox Cflag = lflag = mflag = nflag = oflag = xflag = 0
        !            41: 
        !            42: int    aflag;                  /* List all entries (including "." & "..") */
        !            43: int    bflag;                  /* Print non-raphic chars in octal */
        !            44: int    Cflag;                  /* Multicolumn, sorted down the columns */
        !            45: int    dflag;                  /* Treat directories like files */
        !            46: int    fflag;                  /* Force something to look like a directory */
        !            47: int    Fflag;                  /* Print / after dirs, * after executables */
        !            48: int    gflag;                  /* Print gid vs. uid */
        !            49: int    iflag;                  /* Give i-number */
        !            50: int    lflag;                  /* Longer format */
        !            51: int    mflag;                  /* Stream format output */
        !            52: int    nflag;                  /* Same as -l except GID and UID are #s */
        !            53: int    oflag;                  /* Same as -l except group is not printed */
        !            54: int    pflag;                  /* Print a / after directories */
        !            55: int    qflag;                  /* Force non-graphic chars into ? mode */
        !            56: int    Rflag;                  /* List directories recursively */
        !            57: int    rflag;                  /* Reverse order of sort */
        !            58: int    sflag;                  /* Print size in bytes */
        !            59: int    tflag = MTIME;          /* Which time to display and sort on */
        !            60: int    xflag;                  /* Multicolumn, sort across the columns */
        !            61: int    sortflg;                /* On for sort by time, 0 for by name */
        !            62: int    myuid;                  /* User id for selecting .* suppression */
        !            63: 
        !            64: int    linesiz = 0;            /* Keep track of how much printed for -m */
        !            65: int    first   = 1;            /* First in stream format?              */
        !            66: int    maxwidth = MAXWID;      /* Longest string in multi-column format  */
        !            67: int    ncols   = 1;            /* Number of columns */
        !            68: int    nrows   = 1;            /* Number of rows */
        !            69: int    offset  = 0;            /* How far to move pointer to print next entry*/
        !            70: int    nlast   = 0;            /* Number of cols in last row */
        !            71: int    ccol    = 0;            /* Current Column       */
        !            72: time_t curtime;
        !            73: 
        !            74: char   obuf[BUFSIZ];
        !            75: 
        !            76: char   *deflist[] = {
        !            77:        ".",
        !            78:        NULL
        !            79: };
        !            80: 
        !            81: char   *namelist[MAXARG];      /* store file names for column output */
        !            82: 
        !            83: typedef        struct  dlist{                  
        !            84:        char *name;
        !            85:        fsize_t size;
        !            86: } DLIST;
        !            87: 
        !            88: typedef        struct  ls {
        !            89:        char    ls_dname[DIRSIZ+1];
        !            90:        char    *ls_name;
        !            91:        char    *ck_name;
        !            92:        ino_t   ls_ino;
        !            93:        short   ls_mode;
        !            94:        short   ls_uid;
        !            95:        short   ls_gid;
        !            96:        short   ls_nlink;
        !            97:        fsize_t ls_size;
        !            98:        dev_t   ls_rdev;                /* Real device */
        !            99:        time_t  ls_time;                /* One of atime, mtime, ctime */
        !           100: } LS;
        !           101: 
        !           102: int    (*qcomp)();
        !           103: int    qtcomp();
        !           104: int    qncomp();
        !           105: int    qdncomp();
        !           106: 
        !           107: char   *alloc();
        !           108: void   fatal();
        !           109: char   *getuname();
        !           110: char   *getgname();
        !           111: char   *getname();
        !           112: char   *getflag();
        !           113: 
        !           114: main(argc, argv)
        !           115: char *argv[];
        !           116: {
        !           117:        register char *ap;
        !           118:        register int es;
        !           119: 
        !           120:        setbuf(stdout, obuf);
        !           121: 
        !           122:        /*
        !           123:         * recognize variations on the name "ls" as implying which
        !           124:         * flags to set by default.
        !           125:         *   basename  flags
        !           126:         *      l       -l
        !           127:         *      lc      -C      recognized, but conflicts with COHERENT /bin/lc
        !           128:         *      lf      -CF
        !           129:         *      lr      -CR
        !           130:         *      lx      -x
        !           131:         */
        !           132:        if ((ap = strrchr(argv[0], '/')) == NULL)
        !           133:                ap = argv[0];
        !           134:        else
        !           135:                ++ap;
        !           136:        if (streq(ap, "l"))
        !           137:                lflag = 1;
        !           138:        else if (streq(ap, "lc"))
        !           139:                Cflag = 1;
        !           140:        else if (streq(ap, "lf"))
        !           141:                Cflag = Fflag = 1;
        !           142:        else if (streq(ap, "lr"))
        !           143:                Cflag = Rflag = 1;
        !           144:        else if (streq(ap, "lx"))
        !           145:                xflag = 1;
        !           146: 
        !           147:        while (argc>1 && *argv[1]=='-') {
        !           148:                for (ap=&argv[1][1]; *ap; ap++)
        !           149:                        switch (*ap) {
        !           150:                        case 'a':
        !           151:                                aflag = 1;
        !           152:                                break;
        !           153: 
        !           154:                        case 'b':
        !           155:                                bflag = 1;
        !           156:                                break;
        !           157: 
        !           158:                        case 'c':
        !           159:                                tflag = CTIME;
        !           160:                                break;
        !           161: 
        !           162:                        case 'C':
        !           163:                                EXCLUDE_Clmnox;
        !           164:                                Cflag = 1;
        !           165:                                break;
        !           166: 
        !           167:                        case 'd':
        !           168:                                dflag = 1;
        !           169:                                break;
        !           170: 
        !           171:                        case 'F':
        !           172:                                Fflag = 1;
        !           173:                                break;
        !           174: 
        !           175:                        case 'f':
        !           176:                                aflag = fflag = 1;
        !           177:                                break;
        !           178: 
        !           179:                        case 'g':
        !           180:                                gflag = 1;
        !           181:                                break;
        !           182: 
        !           183:                        case 'i':
        !           184:                                iflag = 1;
        !           185:                                break;
        !           186: 
        !           187:                        case 'l':
        !           188:                                EXCLUDE_Clmnox;
        !           189:                                lflag = 1;
        !           190:                                break;
        !           191: 
        !           192:                        case 'm':
        !           193:                                EXCLUDE_Clmnox;
        !           194:                                mflag = 1;
        !           195:                                break;
        !           196: 
        !           197:                        case 'n':
        !           198:                                EXCLUDE_Clmnox;
        !           199:                                nflag = 1;
        !           200:                                break;
        !           201: 
        !           202:                        case 'o':
        !           203:                                EXCLUDE_Clmnox;
        !           204:                                oflag = 1;
        !           205:                                break;
        !           206: 
        !           207:                        case 'p':
        !           208:                                pflag = 1;
        !           209:                                break;
        !           210: 
        !           211:                        case 'q':
        !           212:                                qflag = 1;
        !           213:                                break;
        !           214: 
        !           215:                        case 'r':
        !           216:                                rflag = 1;
        !           217:                                break;
        !           218: 
        !           219:                        case 'R':
        !           220:                                Rflag = 1;
        !           221:                                break;
        !           222: 
        !           223:                        case 's':
        !           224:                                sflag = 1;
        !           225:                                break;
        !           226: 
        !           227:                        case 't':
        !           228:                                sortflg = 1;
        !           229:                                break;
        !           230: 
        !           231:                        case 'u':
        !           232:                                tflag = ATIME;
        !           233:                                break;
        !           234: 
        !           235:                        case 'x':
        !           236:                                EXCLUDE_Clmnox;
        !           237:                                xflag = 1;
        !           238:                                break;
        !           239: 
        !           240:                        default:
        !           241:                                usage();
        !           242:                        }
        !           243:                argc--;
        !           244:                argv++;
        !           245:        }
        !           246:        if (fflag)
        !           247:                lflag = sflag = 0;
        !           248:        time(&curtime);
        !           249:        myuid = getuid();
        !           250:        qcomp = (sortflg) ? qtcomp : qncomp;
        !           251:        es = (argc > 1) ? ls(argv+1, argc-1) : ls(deflist, 1);
        !           252:        exit(es);
        !           253: }
        !           254: 
        !           255: /*
        !           256:  * Do 'ls' on one file or directory.
        !           257:  * 'narg' is the number of names in 'flist'
        !           258:  * to determine special output format.
        !           259:  */
        !           260: ls(flist, narg)
        !           261: register char **flist;
        !           262: int narg;
        !           263: {
        !           264:        register int estat = 0;
        !           265:        register LS *lsp;
        !           266:        register LS *arena;
        !           267:        LS *asavep;
        !           268:        int Cargs = 0;
        !           269:        struct stat sb;
        !           270: 
        !           271:        arena = (LS *)alloc(narg*sizeof(LS),"arena");
        !           272:        asavep = arena;
        !           273:        for ( ; *flist!=NULL; flist++) {
        !           274:                if (stat(*flist, &sb) < 0) {
        !           275:                        perror(*flist);
        !           276:                        estat = 1;
        !           277:                        continue;
        !           278:                }
        !           279:                astore(*flist, &sb, asavep++);
        !           280:        }
        !           281:        qsort(arena, asavep-arena, sizeof(LS), qcomp);
        !           282:        if (qcomp == qncomp)
        !           283:                qcomp = qdncomp;
        !           284:        if (xflag || Cflag)
        !           285:                ncols = MAXLEN/(maxwidth+GAP);
        !           286: 
        !           287:        for (lsp = arena; lsp < asavep; lsp++) {
        !           288:                if (fflag)
        !           289:                        continue;
        !           290:                if ((lsp->ls_mode & S_IFMT) == S_IFDIR && !dflag)
        !           291:                        continue;
        !           292:                if (Cflag)
        !           293:                        svname(lsp->ck_name,Cargs++);
        !           294:                else if (xflag)
        !           295:                        prcolh(lsp->ck_name);
        !           296:                else
        !           297:                        prstuff(lsp->ls_name, lsp);
        !           298:        }
        !           299:        if (Cflag && Cargs)
        !           300:                prnames(Cargs);
        !           301:        maxwidth = MAXWID;
        !           302:        linesiz = 0;
        !           303:        for (lsp = arena; lsp < asavep; lsp++) {
        !           304:                if (dflag || (lsp->ls_mode&S_IFMT)!=S_IFDIR)
        !           305:                        continue;
        !           306:                if (narg > 1)
        !           307:                        printf("\n%s:\n", lsp->ls_name);
        !           308:                lsdir(lsp->ls_name,lsp->ls_size);
        !           309:                freename(lsp);
        !           310:        }
        !           311:        free(arena);
        !           312:        if ((mflag && linesiz) || ((Cflag || xflag) && ccol)){
        !           313:                putchar('\n');
        !           314:                ccol = 0;
        !           315:                linesiz = 0;
        !           316:        }
        !           317:        return estat;
        !           318: }
        !           319: 
        !           320: /*
        !           321:  * Print for all options except -C and -x
        !           322:  */
        !           323: prstuff(file, lsp)
        !           324: char *file;
        !           325: register LS *lsp;
        !           326: {
        !           327:        register char *cp;
        !           328:        register spcl = 0;
        !           329: 
        !           330:        if (iflag)
        !           331:                printf("%5u ", lsp->ls_ino);
        !           332:        if (sflag) {
        !           333:                prsize(lsp);
        !           334:                putchar(' ');
        !           335:        }
        !           336:        if (lflag || oflag || nflag) {
        !           337:                switch (lsp->ls_mode & S_IFMT) {
        !           338:                case S_IFREG:
        !           339:                        putchar('-');
        !           340:                        break;
        !           341: 
        !           342:                case S_IFDIR:
        !           343:                        putchar('d');
        !           344:                        break;
        !           345: 
        !           346:                case S_IFCHR:
        !           347:                        putchar('c');
        !           348:                        spcl++;
        !           349:                        break;
        !           350: 
        !           351:                case S_IFBLK:
        !           352:                        putchar('b');
        !           353:                        spcl++;
        !           354:                        break;
        !           355: 
        !           356:                case S_IFPIP:
        !           357:                        putchar('p');
        !           358:                        break;
        !           359: 
        !           360:                case S_IFMPB:
        !           361:                case S_IFMPC:
        !           362:                        putchar('m');
        !           363:                        spcl++;
        !           364:                        break;
        !           365: 
        !           366:                default:
        !           367:                        putchar('x');
        !           368:                }
        !           369:                prmode((lsp->ls_mode>>6)&07, lsp->ls_mode&S_ISUID);
        !           370:                prmode((lsp->ls_mode>>3)&07, lsp->ls_mode&S_ISGID);
        !           371:                prmode(lsp->ls_mode&07, 0);
        !           372:                if (lsp->ls_mode & S_ISVTX)
        !           373:                        putchar('t');
        !           374:                else
        !           375:                        putchar(' ');
        !           376:                printf("%2d ", lsp->ls_nlink);
        !           377:                if (!gflag){
        !           378:                        if (!nflag){
        !           379:                                cp = getuname(lsp->ls_uid);
        !           380:                                if (cp == NULL)
        !           381:                                        printf("%-10d ", lsp->ls_uid); 
        !           382:                                else
        !           383:                                        printf("%-10s ", cp);
        !           384:                        } else
        !           385:                                printf("%-10d ", lsp->ls_uid); 
        !           386:                }
        !           387:                if (!oflag){
        !           388:                        if (!nflag){
        !           389:                                cp = getgname(lsp->ls_gid);
        !           390:                                if (cp == NULL)
        !           391:                                        printf("%-10d ", lsp->ls_gid); 
        !           392:                                else
        !           393:                                        printf("%-10s ", cp);
        !           394:                        } else
        !           395:                                printf("%-10d ", lsp->ls_gid); 
        !           396:                }
        !           397:                if (!spcl)
        !           398:                        printf("%7ld", lsp->ls_size);
        !           399:                else
        !           400:                        printf("%3d %3d", major(lsp->ls_rdev),
        !           401:                            minor(lsp->ls_rdev));
        !           402:                prtime(&lsp->ls_time);
        !           403:        }
        !           404:        if (!mflag ){
        !           405:                prname(file);
        !           406:                prflag(lsp->ls_mode);
        !           407:                putchar('\n');
        !           408:        }
        !           409:        else
        !           410:                prstream(file,lsp->ls_mode);
        !           411: }
        !           412: 
        !           413: /*
        !           414:  * Print out a filesize from a ls store buffer.
        !           415:  * This size (in BSIZE units or blocks) takes
        !           416:  * into account indirect blocks.
        !           417:  * However this should be done in a more general manner.
        !           418:  */
        !           419: prsize(lsp)
        !           420: register LS *lsp;
        !           421: {
        !           422:        long blocks, size;
        !           423:        register ftype;
        !           424: 
        !           425:        size = 0;
        !           426:        ftype = lsp->ls_mode & S_IFMT;
        !           427:        if (ftype==S_IFREG || ftype==S_IFDIR || ftype==S_IFPIP) {
        !           428:                size = blocks = (lsp->ls_size+BSIZE-1)/BSIZE;
        !           429:                if (blocks > ND) {
        !           430:                        size++;
        !           431:                        blocks -= ND;
        !           432:                        if (blocks > NBN*NI) {
        !           433:                                blocks -= NBN*NI;
        !           434:                                size += 2 + blocks/NBN;
        !           435:                        }
        !           436:                }
        !           437:        }
        !           438:        printf("%4ld", size);
        !           439:        return size;
        !           440: }
        !           441: 
        !           442: /*
        !           443:  * Print a time (if it is older than
        !           444:  * one year) print the year instead
        !           445:  * of the mm:ss part.
        !           446:  */
        !           447: prtime(tp)
        !           448: register time_t *tp;
        !           449: {
        !           450:        register struct tm *tmp;
        !           451:        register struct tm *now;
        !           452:        register int thisyear;
        !           453:        register char *cp;
        !           454: 
        !           455:        now = localtime(&curtime);
        !           456:        thisyear = now->tm_year;
        !           457:        cp = asctime(tmp = localtime(tp));
        !           458:        if (thisyear > tmp->tm_year) {
        !           459:                cp[10] = '\0';
        !           460:                printf(" %s  %d ", cp, tmp->tm_year+1900);
        !           461:        } else {
        !           462:                cp[16] = '\0';
        !           463:                printf(" %s ", cp);
        !           464:        }
        !           465: }
        !           466: 
        !           467: /*
        !           468:  * Print 'rwx' type modes out.
        !           469:  */
        !           470: prmode(m, suid)
        !           471: int m;
        !           472: int suid;
        !           473: {
        !           474:        m <<= 6;
        !           475:        putchar(m&S_IREAD ? 'r' : '-');
        !           476:        putchar(m&S_IWRITE ? 'w' : '-');
        !           477:        if (suid)
        !           478:                putchar('s');
        !           479:        else
        !           480:                putchar(m&S_IEXEC ? 'x' : '-');
        !           481: }
        !           482: 
        !           483: /*
        !           484:  * Get a user name.  Either look
        !           485:  * in password or group file depending
        !           486:  * on 'gflag'.
        !           487:  */
        !           488: char *
        !           489: getuname(uid)
        !           490: short uid;
        !           491: {
        !           492:        register struct passwd  *pwp;
        !           493:        static          id      = -1;
        !           494:        static char     *name;
        !           495: 
        !           496:        if (uid == id)
        !           497:                return name;
        !           498:        id = uid;
        !           499:        name = NULL;
        !           500:        if ((pwp=getpwuid( uid)) != NULL)
        !           501:                name = pwp->pw_name;
        !           502:        return name;
        !           503: }
        !           504: 
        !           505: /*
        !           506:  * Get group name.
        !           507:  * Look in group file .
        !           508:  */
        !           509: char *
        !           510: getgname(uid)
        !           511: short uid;
        !           512: {
        !           513:        register struct group   *grp;
        !           514:        static          id      = -1;
        !           515:        static char     *name;
        !           516: 
        !           517:        if (uid == id)
        !           518:                return name;
        !           519:        id = uid;
        !           520:        name = NULL;
        !           521:        if ((grp=getgrgid( uid)) != NULL)
        !           522:                name = grp->gr_name;
        !           523:        return name;
        !           524: }
        !           525: 
        !           526: /*
        !           527:  * List out the files in a directory
        !           528:  * If 'fflag' is set, it may not be
        !           529:  * but consider it one anyway.
        !           530:  */
        !           531: lsdir(dir,dirsize)
        !           532: char *dir;
        !           533: fsize_t dirsize;
        !           534: {
        !           535:        int fd, Cargs = 0, Rargs = 0;
        !           536:        struct stat sb;
        !           537:        LS *lsp;
        !           538:        register char *np1, *np2;
        !           539:        register int n;
        !           540:        register struct direct *dp;
        !           541:        register int nb;
        !           542:        unsigned size;
        !           543:        char    *curname;
        !           544:        char    *namebuf;               /* Buffer for constructing names */
        !           545:        char    *dirbuf;                /* Buffer for reading directories */
        !           546:        DLIST **dirlist;
        !           547:        LS *dsaved;
        !           548:        LS *dsavep;
        !           549: 
        !           550:        if ((fd = open(dir, 0)) < 0) {
        !           551:                fprintf(stderr, "%s: cannot read\n", dir);
        !           552:                return;
        !           553:        }
        !           554:        if (!fflag) {
        !           555:                size = dirsize/sizeof (struct direct) * sizeof (LS);
        !           556:                dsaved = alloc(size,"dsaved");
        !           557:                dsavep = dsaved;
        !           558:        }
        !           559:        if (Rflag)
        !           560:                dirlist = (char **)alloc(MAXDIR * sizeof(char *), "dirlist");
        !           561:        dirbuf = alloc(BSIZE,"dirbuf");
        !           562:        namebuf = alloc(MAXNBUF,"namebuf");
        !           563:        curname = alloc(DIRSIZ+1,"curname");
        !           564:        lsp = alloc(sizeof(LS),"lsp");
        !           565:        if (mflag)
        !           566:                first = 1;              /* For stream option */
        !           567:        while ((nb = read(fd, dirbuf, BSIZE )) > 0)
        !           568:        for (dp=dirbuf; dp<(dirbuf+nb); dp++) {
        !           569:                if (dp->d_ino == 0)
        !           570:                        continue;
        !           571:                np1 = dp->d_name;
        !           572:                if (aflag == 0 && *np1++ == '.') {
        !           573:                        if (myuid != 0)
        !           574:                                continue;
        !           575:                        if (*np1=='\0' || (*np1++=='.' && *np1=='\0'))
        !           576:                                continue;
        !           577:                }
        !           578:                if (iflag) {
        !           579:                        sb.st_ino = dp->d_ino;
        !           580:                        canino(sb.st_ino);
        !           581:                }
        !           582:                np2 = curname;
        !           583:                np1 = dp->d_name;
        !           584:                n = DIRSIZ;
        !           585:                do {
        !           586:                        *np2++ = *np1++;
        !           587:                } while (--n);
        !           588:                *np2 = '\0';
        !           589:                if (lflag || xflag || Cflag || sflag || tflag || Rflag ||
        !           590:                           sortflg || pflag || Fflag || oflag || nflag) {
        !           591:                        np2 = namebuf;
        !           592:                        np1 = dir;
        !           593:                        while (*np2++ = *np1++)
        !           594:                                ;
        !           595:                        np2-=2;
        !           596:                        if (*np2++ != '/')
        !           597:                                *np2++ = '/';
        !           598:                        np1 = curname;
        !           599:                        while (*np2++ = *np1++)
        !           600:                                ;
        !           601:                        if (stat(namebuf, &sb) < 0) {
        !           602:                                fprintf(stderr, "%s: cannot stat\n", curname);
        !           603:                                continue;
        !           604:                        }
        !           605:                }
        !           606:                convert(&sb, lsp);
        !           607:                if (Rflag
        !           608:                 && ((lsp->ls_mode & S_IFMT) == S_IFDIR)
        !           609:                 && strcmp(curname, ".") != 0
        !           610:                 && strcmp(curname, "..") != 0 ) {
        !           611:                        if (Rargs >= MAXDIR)
        !           612:                                fatal("too many subdirectories");
        !           613:                        dirlist[Rargs] = alloc(sizeof(DLIST),"dirlist");
        !           614:                        dirlist[Rargs]->name = alloc(strlen(namebuf) + 1,"name");
        !           615:                        strcpy(dirlist[Rargs]->name,namebuf);
        !           616:                        dirlist[Rargs++]->size = lsp->ls_size;
        !           617:                } else if (fflag) {
        !           618:                        ncols = MAXLEN/(maxwidth+GAP);
        !           619:                        if (Cflag)
        !           620:                                svname(curname, Cargs++);
        !           621:                        else if (xflag)
        !           622:                                prcolh(curname);
        !           623:                        else
        !           624:                                prstuff(curname, lsp);
        !           625:                } else {
        !           626:                        store(curname, &sb,dsavep++);
        !           627:                }
        !           628:        }
        !           629:        free(lsp);
        !           630:        free(curname);
        !           631:        free(namebuf);
        !           632:        free(dirbuf);
        !           633:        if (!fflag) {
        !           634:                ncols = MAXLEN/(maxwidth+GAP);
        !           635:                output(dsaved,dsavep);
        !           636:        } else if (Cflag && Cargs)
        !           637:                prnames(Cargs);
        !           638:        if (!fflag)
        !           639:                for (lsp = dsaved; lsp < dsavep; lsp++)
        !           640:                        freename(lsp);
        !           641:        if ((mflag && linesiz) || ((Cflag || xflag) && ccol)){
        !           642:                putchar('\n');
        !           643:                ccol = 0;
        !           644:                linesiz = 0;
        !           645:        }
        !           646:        if (!fflag)
        !           647:                free(dsaved);
        !           648:        close(fd);
        !           649:        maxwidth = MAXWID;
        !           650:        if (Rflag && Rargs){
        !           651:                for(n=0;n<Rargs;n++){
        !           652:                        putchar('\n');
        !           653:                        printf("%s:\n",dirlist[n]->name);
        !           654:                        lsdir(dirlist[n]->name,dirlist[n]->size);
        !           655:                        free(dirlist[n]->name);
        !           656:                }
        !           657:                for(n=0;n<Rargs;n++)
        !           658:                        free(dirlist[n]);
        !           659:        }
        !           660:        if (Rflag)
        !           661:                free(dirlist);
        !           662: }
        !           663: 
        !           664: /*
        !           665:  * Store data away for intra-directory
        !           666:  * sorting.
        !           667:  */
        !           668: store(name, sbp,lsp)
        !           669: char *name;
        !           670: register struct stat *sbp;
        !           671: register LS *lsp;
        !           672: {
        !           673:        convert(sbp, lsp);
        !           674:        if (xflag || Cflag)
        !           675:                cstore(lsp,name);
        !           676:        strncpy(lsp->ls_dname, name, DIRSIZ+1);
        !           677: }
        !           678: 
        !           679: /*
        !           680:  * Store each argument away for inter-directory sorting.
        !           681:  * Sets lsp->ls_name to allocated name.
        !           682:  */
        !           683: astore(name, sbp,lsp)
        !           684: char *name;
        !           685: register struct stat *sbp;
        !           686: register LS *lsp;
        !           687: {
        !           688:        convert(sbp, lsp);
        !           689:        if (xflag || Cflag)
        !           690:                cstore(lsp,name);
        !           691:        lsp->ls_name = alloc(strlen(name)+1,"ls->name");
        !           692:        strcpy(lsp->ls_name, name);
        !           693: }
        !           694: 
        !           695: /*
        !           696:  * Free allocated name fields.
        !           697:  */
        !           698: freename(lsp) register LS *lsp;
        !           699: {
        !           700:        if (lsp->ls_name != NULL)
        !           701:                free(lsp->ls_name);
        !           702:        if (lsp->ck_name != NULL)
        !           703:                free(lsp->ck_name);
        !           704: }
        !           705: 
        !           706: /*
        !           707:  * Convert a stat buffer into an ls store
        !           708:  * buffer.
        !           709:  */
        !           710: convert(sbp, lsp)
        !           711: register struct stat *sbp;
        !           712: register LS *lsp;
        !           713: {
        !           714:        lsp->ls_ino = sbp->st_ino;
        !           715:        lsp->ls_mode = sbp->st_mode;
        !           716:        lsp->ls_nlink = sbp->st_nlink;
        !           717:        lsp->ls_uid = sbp->st_uid;
        !           718:        lsp->ls_gid = sbp->st_gid;
        !           719:        lsp->ls_size = sbp->st_size;
        !           720:        lsp->ls_rdev = sbp->st_rdev;
        !           721:        if (tflag == CTIME)
        !           722:                lsp->ls_time = sbp->st_ctime;
        !           723:        else if (tflag == MTIME)
        !           724:                lsp->ls_time = sbp->st_mtime;
        !           725:        else if (tflag == ATIME)
        !           726:                lsp->ls_time = sbp->st_atime;
        !           727: }
        !           728: 
        !           729: /*
        !           730:  * Sort, output and free up space from
        !           731:  * the current directory being considered.
        !           732:  */
        !           733: output(start,stop)
        !           734: LS *start;
        !           735: LS *stop;
        !           736: {
        !           737:        register LS *lsp, *lse;
        !           738:        register unsigned nel;
        !           739:        int Cargs = 0;
        !           740:        nel = stop - start;
        !           741:        qsort(start, nel, sizeof (LS), qcomp);
        !           742:        for (lsp=start, lse=stop; lsp < lse; lsp++){
        !           743:                if (Cflag)
        !           744:                        svname(lsp->ck_name,Cargs++);
        !           745:                else if (xflag)
        !           746:                        prcolh(lsp->ck_name);
        !           747:                else
        !           748:                        prstuff(lsp->ls_dname, lsp);
        !           749:        }
        !           750:        if (Cflag && Cargs)
        !           751:                prnames(Cargs);
        !           752: }
        !           753: 
        !           754: /*
        !           755:  * The following are the three qsort comparison routines:
        !           756:  * sort by time, sort by directory name, sort by full pathname.
        !           757:  * They can be used both in the argument sort and in each directory sort.
        !           758:  */
        !           759: 
        !           760: /*
        !           761:  * Sort by time (either access, modify, or create setup elsewhere)
        !           762:  * (forward or backward).
        !           763:  */
        !           764: qtcomp(lsp1, lsp2)
        !           765: register LS *lsp1, *lsp2;
        !           766: {
        !           767:        register int rval = 0;
        !           768: 
        !           769:        if (lsp1->ls_time < lsp2->ls_time)
        !           770:                rval++;
        !           771:        else if (lsp1->ls_time > lsp2->ls_time)
        !           772:                rval--;
        !           773:        return (rflag) ? -rval : rval;
        !           774: }
        !           775: 
        !           776: /*
        !           777:  * Sort by directory name.
        !           778:  * (forward or reverse).
        !           779:  */
        !           780: qdncomp(lsp1, lsp2)
        !           781: LS *lsp1, *lsp2;
        !           782: {
        !           783:        register int rval;
        !           784: 
        !           785:        rval = strncmp(lsp1->ls_dname, lsp2->ls_dname, DIRSIZ);
        !           786:        return (rflag) ? -rval : rval;
        !           787: }
        !           788: 
        !           789: /*
        !           790:  * Sort by full pathname.
        !           791:  * (forward or reverse).
        !           792:  */
        !           793: qncomp(lsp1, lsp2)
        !           794: LS *lsp1, *lsp2;
        !           795: {
        !           796:        register int rval;
        !           797: 
        !           798:        rval = strcmp(lsp1->ls_name, lsp2->ls_name);
        !           799:        return (rflag) ? -rval : rval;
        !           800: }
        !           801: 
        !           802: usage()
        !           803: {
        !           804:        fprintf(stderr, "Usage: ls [-abcCdfFgilmnopqrRstux] [files ...]\n");
        !           805:        exit(1);
        !           806: }
        !           807: 
        !           808: is_x(m)
        !           809: int m;
        !           810: {
        !           811:        m <<= 6;
        !           812:        return m&S_IEXEC;
        !           813: }
        !           814: 
        !           815: /*
        !           816:  * Print non-graphic chars in octal or '?' format 
        !           817:  * or as they are depending on which flag is set.
        !           818:  */
        !           819: prname(s)
        !           820: char *s;
        !           821: {
        !           822:        if (bflag) {
        !           823:                while ( *s != '\0')
        !           824:                        if ( *s >= ' ' && *s <= '~')
        !           825:                                putchar(*s++);
        !           826:                        else
        !           827:                                printf("\\0%o",*s++);
        !           828:        } else if (qflag) {
        !           829:                while ( *s != '\0')
        !           830:                        if ( *s >= ' ' && *s <= '~')
        !           831:                                putchar(*s++);
        !           832:                        else {
        !           833:                                putchar('?');
        !           834:                                *s++;
        !           835:                        }
        !           836:        } else
        !           837:                printf(s);
        !           838: }
        !           839: 
        !           840: /*
        !           841:  *  Print in stream format for -m option
        !           842:  */
        !           843: prstream(s,m)
        !           844: char *s;
        !           845: short m;
        !           846: {
        !           847:        register int sl;
        !           848: 
        !           849:        sl = strlen(s);
        !           850:        if ( (linesiz + sl) > MAXLEN ){
        !           851:                putchar(',');
        !           852:                putchar('\n');
        !           853:                prname(s);
        !           854:                linesiz = sl + prflag(m) + 1;
        !           855:        }
        !           856:        else if (!first) {
        !           857:                printf(", ");
        !           858:                prname(s);
        !           859:                linesiz += sl + prflag(m) + 2;
        !           860:        } else {
        !           861:                first = 0;
        !           862:                prname(s);
        !           863:                linesiz = sl + prflag(m);
        !           864:        }
        !           865: }
        !           866: 
        !           867: /*
        !           868:  * Prints flag if executable or directory and -F or -p flsg is set.
        !           869:  */
        !           870: prflag(m)
        !           871: short m;
        !           872: {
        !           873:        if (pflag)
        !           874:                if((m & S_IFMT) == S_IFDIR){
        !           875:                        putchar('/');
        !           876:                        return 1;
        !           877:                }
        !           878:        if (Fflag) {
        !           879:                if((m & S_IFMT) == S_IFDIR) {
        !           880:                        putchar('/');
        !           881:                        return 1;
        !           882:                } else if (is_x(m>>6 & 07) ) {
        !           883:                        putchar('*');
        !           884:                        return 1;
        !           885:                } else if( is_x(m>>3 & 07) ) {
        !           886:                        putchar('*');
        !           887:                        return 1;
        !           888:                } else if( is_x(m & 07) ){
        !           889:                        putchar('*');
        !           890:                        return 1;
        !           891:                }
        !           892:        }
        !           893:        return 0;
        !           894: }
        !           895: 
        !           896: /*
        !           897:  * Returns flag if executable or directory and -F or -p flsg is set.
        !           898:  */
        !           899: char *
        !           900: getflag(m)
        !           901: short m;
        !           902: {
        !           903:        if (pflag) {
        !           904:                if((m & S_IFMT) == S_IFDIR)
        !           905:                        return "/";
        !           906:        }
        !           907:        if (Fflag) {
        !           908:                if((m & S_IFMT) == S_IFDIR)
        !           909:                        return "/";
        !           910:                else if( is_x(m>>6 & 07) )
        !           911:                        return "*";
        !           912:                else if( is_x(m>>3 & 07) )
        !           913:                        return "*";
        !           914:                else if( is_x(m & 07) )
        !           915:                        return "*";
        !           916:        }
        !           917:        return "";
        !           918: }
        !           919: 
        !           920: /*
        !           921:  * Returns file name with non-graphic chars in octal or '?' format 
        !           922:  * or as they are depending on which flag is set.
        !           923:  */
        !           924: char *
        !           925: getname(s)
        !           926: char *s;
        !           927: {
        !           928:        char tmp[80];
        !           929:        char *t;
        !           930:        int i = 0;
        !           931:        char buf[5];
        !           932: 
        !           933:        t = tmp;
        !           934:        if (bflag){
        !           935:                while (*s) {
        !           936:                        if (*s >= ' ' && *s <= '~') {
        !           937:                                *t++ = *s++;
        !           938:                        } else {
        !           939:                                sprintf(buf,"\\0%o",*s++);
        !           940:                                while(buf[i] != '\0'){
        !           941:                                        *t++ = buf[i];
        !           942:                                        buf[i++] = '\0';
        !           943:                                }
        !           944:                                i=0;
        !           945:                        }
        !           946:                }
        !           947:                *t = '\0';
        !           948:        } else if (qflag){
        !           949:                while ( *s != '\0')
        !           950:                        if ( *s >= ' ' && *s <= '~')
        !           951:                                *t++ = *s++;
        !           952:                        else{
        !           953:                                *t++ = '?';
        !           954:                                *s++;
        !           955:                        }
        !           956:                *t = '\0';
        !           957:        } else
        !           958:                strcpy(tmp,s);
        !           959:        return tmp;
        !           960: }
        !           961: 
        !           962: /*
        !           963:  * Prints name in multi-column format across the screen (-x option).
        !           964:  */
        !           965: prcolh(name)
        !           966: char *name;
        !           967: {      
        !           968:        if ( ccol < ncols)
        !           969:                printf(name);
        !           970:        if ( ++ccol <  ncols)
        !           971:                printf("%*s",maxwidth - strlen(name) + GAP,"");
        !           972:        else {
        !           973:                ccol = 0;
        !           974:                putchar('\n');
        !           975:        }
        !           976: }
        !           977: 
        !           978: /*
        !           979:  * Sets chars in buffer to NULs.
        !           980:  */
        !           981: clear(s)
        !           982: char *s;
        !           983: {
        !           984:        while (*s != '\0')
        !           985:                *s++ = '\0';
        !           986: }
        !           987: 
        !           988: /*
        !           989:  * Adds whatever information to file name as indicated by flags
        !           990:  * (i.e. iflag, sflag, bflag) and stores it in ck_name so its
        !           991:  * entire length can be recorded.  Used for -x and -C.
        !           992:  * Sets lsp->ls_name to allocated name.
        !           993: */
        !           994: cstore(lsp, name)
        !           995: LS *lsp;
        !           996: char *name;
        !           997: {
        !           998:        register int sl;
        !           999:        char buf[80],tmp[80],tmp2[80];
        !          1000: 
        !          1001:        clear(buf); clear(tmp); clear(tmp2);
        !          1002:        if ( sflag)
        !          1003:                sprintf(buf,"%3d",getsize(lsp));
        !          1004:        if (iflag){
        !          1005:                sprintf(tmp,"%5u ", lsp->ls_ino);
        !          1006:                strcat(buf,tmp);
        !          1007:        }
        !          1008:        strcpy(tmp2,getname(name));
        !          1009:        strcat(buf,tmp2);
        !          1010:        if ( Fflag || pflag)
        !          1011:                strcat(buf,getflag(lsp->ls_mode));
        !          1012:        sl = strlen(buf);
        !          1013:        if (maxwidth < sl)
        !          1014:                maxwidth = sl;
        !          1015:        lsp->ck_name = alloc(sl+1, "ck_name");
        !          1016:        strcpy(lsp->ck_name,buf);
        !          1017: }
        !          1018: 
        !          1019: /*
        !          1020:  * Returns size of file.  see prsize.
        !          1021:  */
        !          1022: getsize(lsp)
        !          1023: register LS *lsp;
        !          1024: {
        !          1025:        long blocks, size;
        !          1026:        register ftype;
        !          1027: 
        !          1028:        size = 0;
        !          1029:        ftype = lsp->ls_mode & S_IFMT;
        !          1030:        if (ftype==S_IFREG || ftype==S_IFDIR || ftype==S_IFPIP) {
        !          1031:                size = blocks = (lsp->ls_size+BSIZE-1)/BSIZE;
        !          1032:                if (blocks > ND) {
        !          1033:                        size++;
        !          1034:                        blocks -= ND;
        !          1035:                        if (blocks > NBN*NI) {
        !          1036:                                blocks -= NBN*NI;
        !          1037:                                size += 2 + blocks/NBN;
        !          1038:                        }
        !          1039:                }
        !          1040:        }
        !          1041:        return size;
        !          1042: }
        !          1043: 
        !          1044: /*
        !          1045:  * Save file name for -C option.
        !          1046:  * This allocates namelist[i], prnames() eventually frees it.
        !          1047:  */
        !          1048: svname(name,i)
        !          1049: char *name;
        !          1050: int i;
        !          1051: {
        !          1052:        if (i >= MAXARG)
        !          1053:                fatal("more than %d files with -C option", MAXARG);
        !          1054:        namelist[i] = alloc(strlen(name)+1,"svname");
        !          1055:        strcpy(namelist[i],name);
        !          1056: }
        !          1057: 
        !          1058: /*
        !          1059:  * Print names in multi-column format going down the screen (-C option).
        !          1060:  * Free the namelist members allocated by svname.
        !          1061:  */
        !          1062: prnames(Cargs)
        !          1063: int Cargs;
        !          1064: {
        !          1065:        register int nc, i, j, nl;
        !          1066: 
        !          1067:        ncols = MAXLEN/(maxwidth+GAP);
        !          1068:        nc = ncols;
        !          1069:        nlast = Cargs % ncols;
        !          1070:        nrows = Cargs/ncols + (nlast ? 1 : 0);
        !          1071:        offset = nrows -1;
        !          1072: 
        !          1073:        if (nlast == 0)
        !          1074:                nlast = ncols;
        !          1075:        nl = nlast;     
        !          1076:        for(i=0; i < offset; i++){
        !          1077:                for(j = i; j < Cargs;j+=offset+ (nl-- >0) )
        !          1078:                        prcolh(namelist[j]);
        !          1079:                nl = nlast;
        !          1080:        }
        !          1081:        while (nlast--){
        !          1082:                prcolh(namelist[i]);
        !          1083:                i += nrows;
        !          1084:        }
        !          1085:        if (ccol){
        !          1086:                putchar('\n');
        !          1087:                ccol = 0;
        !          1088:        }
        !          1089:        for (i = 0; i < Cargs; i++)
        !          1090:                free(namelist[i]);
        !          1091: }
        !          1092: 
        !          1093: /*
        !          1094:  * Put message and die.
        !          1095:  */
        !          1096: /* VARARGS */
        !          1097: void
        !          1098: fatal(s) char *s;
        !          1099: {
        !          1100:        fprintf(stderr, "\nls: fatal: %r\n", &s);
        !          1101:        exit(1);
        !          1102: }
        !          1103: 
        !          1104: /*
        !          1105:  * Get space or die.
        !          1106:  */
        !          1107: char *
        !          1108: alloc(n, msg) register int n; char *msg;
        !          1109: {
        !          1110:        extern char *calloc();
        !          1111:        register char *cp;
        !          1112: 
        !          1113:        if ((cp = calloc(n, 1)) == NULL)
        !          1114:                fatal("out of space: %s", msg);
        !          1115:        return cp;
        !          1116: }
        !          1117: 
        !          1118: /* end of ls.c */

unix.superglobalmegacorp.com

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