Annotation of 43BSDTahoe/usr.bin/find/find.c, revision 1.1

1.1     ! root        1: #ifndef        lint
        !             2: static char *sccsid = "@(#)find.c      4.20 (Berkeley) 9/28/87";
        !             3: #endif
        !             4: 
        !             5: #include <stdio.h>
        !             6: #include <sys/param.h>
        !             7: #include <sys/dir.h>
        !             8: #include <sys/stat.h>
        !             9: 
        !            10: #define A_DAY  86400L /* a day full of seconds */
        !            11: #define EQ(x, y)       (strcmp(x, y)==0)
        !            12: 
        !            13: int    Randlast;
        !            14: char   Pathname[MAXPATHLEN+1];
        !            15: 
        !            16: #define MAXNODES       100
        !            17: 
        !            18: struct anode {
        !            19:        int (*F)();
        !            20:        struct anode *L, *R;
        !            21: } Node[MAXNODES];
        !            22: int Nn;  /* number of nodes */
        !            23: char   *Fname;
        !            24: long   Now;
        !            25: int    Argc,
        !            26:        Ai,
        !            27:        Pi;
        !            28: char   **Argv;
        !            29: /* cpio stuff */
        !            30: int    Cpio;
        !            31: short  *Buf, *Dbuf, *Wp;
        !            32: int    Bufsize = 5120;
        !            33: int    Wct = 2560;
        !            34: 
        !            35: long   Newer;
        !            36: 
        !            37: int    Xdev = 1;       /* true if SHOULD cross devices (file systems) */
        !            38: int    follow;         /* true if SHOULD descend symlinked directories */
        !            39: struct stat Devstat;   /* stats of each argument path's file system */
        !            40: 
        !            41: struct stat Statb;
        !            42: 
        !            43: struct anode   *exp(),
        !            44:                *e1(),
        !            45:                *e2(),
        !            46:                *e3(),
        !            47:                *mk();
        !            48: char   *nxtarg();
        !            49: char   Home[MAXPATHLEN + 1];
        !            50: long   Blocks;
        !            51: char *rindex();
        !            52: char *sbrk();
        !            53: 
        !            54: /*
        !            55:  * SEE ALSO:   updatedb, bigram.c, code.c
        !            56:  *             Usenix ;login:, February/March, 1983, p. 8.
        !            57:  *
        !            58:  * REVISIONS:  James A. Woods, Informatics General Corporation,
        !            59:  *             NASA Ames Research Center, 6/81.
        !            60:  *
        !            61:  *             The second form searches a pre-computed filelist
        !            62:  *             (constructed nightly by /usr/lib/crontab) which is
        !            63:  *             compressed by updatedb (v.i.z.)  The effect of
        !            64:  *                     find <name>
        !            65:  *             is similar to
        !            66:  *                     find / +0 -name "*<name>*" -print
        !            67:  *             but much faster.
        !            68:  *
        !            69:  *             8/82 faster yet + incorporation of bigram coding -- jaw
        !            70:  *
        !            71:  *             1/83 incorporate glob-style matching -- jaw
        !            72:  */
        !            73: #define        AMES    1
        !            74: 
        !            75: main(argc, argv)
        !            76:        int argc;
        !            77:        char *argv[];
        !            78: {
        !            79:        struct anode *exlist;
        !            80:        int paths;
        !            81:        register char *cp, *sp = 0;
        !            82: #ifdef SUID_PWD
        !            83:        FILE *pwd, *popen();
        !            84: #endif
        !            85: 
        !            86: #ifdef  AMES
        !            87:        if (argc < 2) {
        !            88:                fprintf(stderr,
        !            89:                        "Usage: find name, or find path-list predicate-list\n");
        !            90:                exit(1);
        !            91:        }
        !            92:        if (argc == 2) {
        !            93:                fastfind(argv[1]);
        !            94:                exit(0);
        !            95:        }
        !            96: #endif
        !            97:        time(&Now);
        !            98: #ifdef SUID_PWD
        !            99:        pwd = popen("pwd", "r");
        !           100:        fgets(Home, sizeof Home, pwd);
        !           101:        pclose(pwd);
        !           102:        Home[strlen(Home) - 1] = '\0';
        !           103: #else
        !           104:        if (getwd(Home) == NULL) {
        !           105:                fprintf(stderr, "find: Can't get current working directory\n");
        !           106:                exit(1);
        !           107:        }
        !           108: #endif
        !           109:        Argc = argc; Argv = argv;
        !           110:        if(argc<3) {
        !           111: usage:         fprintf(stderr, "Usage: find path-list predicate-list\n");
        !           112:                exit(1);
        !           113:        }
        !           114:        for(Ai = paths = 1; Ai < (argc-1); ++Ai, ++paths)
        !           115:                if(*Argv[Ai] == '-' || EQ(Argv[Ai], "(") || EQ(Argv[Ai], "!"))
        !           116:                        break;
        !           117:        if(paths == 1) /* no path-list */
        !           118:                goto usage;
        !           119:        if(!(exlist = exp())) { /* parse and compile the arguments */
        !           120:                fprintf(stderr, "find: parsing error\n");
        !           121:                exit(1);
        !           122:        }
        !           123:        if(Ai<argc) {
        !           124:                fprintf(stderr, "find: missing conjunction\n");
        !           125:                exit(1);
        !           126:        }
        !           127:        for(Pi = 1; Pi < paths; ++Pi) {
        !           128:                sp = 0;
        !           129:                chdir(Home);
        !           130:                strcpy(Pathname, Argv[Pi]);
        !           131:                if(cp = rindex(Pathname, '/')) {
        !           132:                        sp = cp + 1;
        !           133:                        *cp = '\0';
        !           134:                        if(chdir(*Pathname? Pathname: "/") == -1) {
        !           135:                                fprintf(stderr, "find: bad starting directory\n");
        !           136:                                exit(2);
        !           137:                        }
        !           138:                        *cp = '/';
        !           139:                }
        !           140:                Fname = sp? sp: Pathname;
        !           141:                if (!Xdev)
        !           142:                        stat(Pathname, &Devstat);
        !           143:                descend(Pathname, Fname, exlist); /* to find files that match  */
        !           144:        }
        !           145:        if(Cpio) {
        !           146:                strcpy(Pathname, "TRAILER!!!");
        !           147:                Statb.st_size = 0;
        !           148:                cpio();
        !           149:                printf("%D blocks\n", Blocks*10);
        !           150:        }
        !           151:        exit(0);
        !           152: }
        !           153: 
        !           154: /* compile time functions:  priority is  exp()<e1()<e2()<e3()  */
        !           155: 
        !           156: struct anode *exp() { /* parse ALTERNATION (-o)  */
        !           157:        int or();
        !           158:        register struct anode * p1;
        !           159: 
        !           160:        p1 = e1() /* get left operand */ ;
        !           161:        if(EQ(nxtarg(), "-o")) {
        !           162:                Randlast--;
        !           163:                return(mk(or, p1, exp()));
        !           164:        }
        !           165:        else if(Ai <= Argc) --Ai;
        !           166:        return(p1);
        !           167: }
        !           168: struct anode *e1() { /* parse CONCATENATION (formerly -a) */
        !           169:        int and();
        !           170:        register struct anode * p1;
        !           171:        register char *a;
        !           172: 
        !           173:        p1 = e2();
        !           174:        a = nxtarg();
        !           175:        if(EQ(a, "-a")) {
        !           176: And:
        !           177:                Randlast--;
        !           178:                return(mk(and, p1, e1()));
        !           179:        } else if(EQ(a, "(") || EQ(a, "!") || (*a=='-' && !EQ(a, "-o"))) {
        !           180:                --Ai;
        !           181:                goto And;
        !           182:        } else if(Ai <= Argc) --Ai;
        !           183:        return(p1);
        !           184: }
        !           185: struct anode *e2() { /* parse NOT (!) */
        !           186:        int not();
        !           187: 
        !           188:        if(Randlast) {
        !           189:                fprintf(stderr, "find: operand follows operand\n");
        !           190:                exit(1);
        !           191:        }
        !           192:        Randlast++;
        !           193:        if(EQ(nxtarg(), "!"))
        !           194:                return(mk(not, e3(), (struct anode *)0));
        !           195:        else if(Ai <= Argc) --Ai;
        !           196:        return(e3());
        !           197: }
        !           198: struct anode *e3() { /* parse parens and predicates */
        !           199:        int exeq(), ok(), glob(),  mtime(), atime(), user(),
        !           200:                group(), size(), perm(), links(), print(),
        !           201:                type(), ino(), cpio(), newer(), 
        !           202:                nouser(), nogroup(), ls(), dummy();
        !           203:        struct anode *p1;
        !           204:        int i;
        !           205:        register char *a, *b;
        !           206:        register int s;
        !           207: 
        !           208:        a = nxtarg();
        !           209:        if(EQ(a, "(")) {
        !           210:                Randlast--;
        !           211:                p1 = exp();
        !           212:                a = nxtarg();
        !           213:                if(!EQ(a, ")")) goto err;
        !           214:                return(p1);
        !           215:        }
        !           216:        else if(EQ(a, "-print")) {
        !           217:                return(mk(print, (struct anode *)0, (struct anode *)0));
        !           218:        }
        !           219:        else if (EQ(a, "-nouser")) {
        !           220:                return (mk(nouser, (struct anode *)0, (struct anode *)0));
        !           221:        }
        !           222:        else if (EQ(a, "-nogroup")) {
        !           223:                return (mk(nogroup, (struct anode *)0, (struct anode *)0));
        !           224:        }
        !           225:        else if (EQ(a, "-ls")) {
        !           226:                return (mk(ls, (struct anode *)0, (struct anode *)0));
        !           227:        }
        !           228:        else if (EQ(a, "-xdev")) {
        !           229:                Xdev = 0;
        !           230:                return (mk(dummy, (struct anode *)0, (struct anode *)0));
        !           231:        }
        !           232:        else if (EQ(a, "-follow")) {
        !           233:                follow=1;
        !           234:                return mk(dummy, (struct anode *)0, (struct anode *)0);
        !           235:        }
        !           236:        b = nxtarg();
        !           237:        s = *b;
        !           238:        if(s=='+') b++;
        !           239:        if(EQ(a, "-name"))
        !           240:                return(mk(glob, (struct anode *)b, (struct anode *)0));
        !           241:        else if(EQ(a, "-mtime"))
        !           242:                return(mk(mtime, (struct anode *)atoi(b), (struct anode *)s));
        !           243:        else if(EQ(a, "-atime"))
        !           244:                return(mk(atime, (struct anode *)atoi(b), (struct anode *)s));
        !           245:        else if(EQ(a, "-user")) {
        !           246:                if((i=getuid(b)) == -1) {
        !           247:                        if(gmatch(b, "[0-9]*"))
        !           248:                                return mk(user, (struct anode *)atoi(b), (struct anode *)s);
        !           249:                        fprintf(stderr, "find: cannot find -user name\n");
        !           250:                        exit(1);
        !           251:                }
        !           252:                return(mk(user, (struct anode *)i, (struct anode *)s));
        !           253:        }
        !           254:        else if(EQ(a, "-inum"))
        !           255:                return(mk(ino, (struct anode *)atoi(b), (struct anode *)s));
        !           256:        else if(EQ(a, "-group")) {
        !           257:                if((i=getgid(b)) == -1) {
        !           258:                        if(gmatch(b, "[0-9]*"))
        !           259:                                return mk(group, (struct anode *)atoi(b), (struct anode *)s);
        !           260:                        fprintf(stderr, "find: cannot find -group name\n");
        !           261:                        exit(1);
        !           262:                }
        !           263:                return(mk(group, (struct anode *)i, (struct anode *)s));
        !           264:        } else if(EQ(a, "-size"))
        !           265:                return(mk(size, (struct anode *)atoi(b), (struct anode *)s));
        !           266:        else if(EQ(a, "-links"))
        !           267:                return(mk(links, (struct anode *)atoi(b), (struct anode *)s));
        !           268:        else if(EQ(a, "-perm")) {
        !           269:                for(i=0; *b ; ++b) {
        !           270:                        if(*b=='-') continue;
        !           271:                        i <<= 3;
        !           272:                        i = i + (*b - '0');
        !           273:                }
        !           274:                return(mk(perm, (struct anode *)i, (struct anode *)s));
        !           275:        }
        !           276:        else if(EQ(a, "-type")) {
        !           277:                i = s=='d' ? S_IFDIR :
        !           278:                    s=='b' ? S_IFBLK :
        !           279:                    s=='c' ? S_IFCHR :
        !           280:                    s=='f' ? S_IFREG :
        !           281:                    s=='l' ? S_IFLNK :
        !           282:                    s=='s' ? S_IFSOCK :
        !           283:                    0;
        !           284:                return(mk(type, (struct anode *)i, (struct anode *)0));
        !           285:        }
        !           286:        else if (EQ(a, "-exec")) {
        !           287:                i = Ai - 1;
        !           288:                while(!EQ(nxtarg(), ";"));
        !           289:                return(mk(exeq, (struct anode *)i, (struct anode *)0));
        !           290:        }
        !           291:        else if (EQ(a, "-ok")) {
        !           292:                i = Ai - 1;
        !           293:                while(!EQ(nxtarg(), ";"));
        !           294:                return(mk(ok, (struct anode *)i, (struct anode *)0));
        !           295:        }
        !           296:        else if(EQ(a, "-cpio")) {
        !           297:                if((Cpio = creat(b, 0666)) < 0) {
        !           298:                        fprintf(stderr, "find: cannot create < %s >\n", s);
        !           299:                        exit(1);
        !           300:                }
        !           301:                Buf = (short *)sbrk(512);
        !           302:                Wp = Dbuf = (short *)sbrk(5120);
        !           303:                return(mk(cpio, (struct anode *)0, (struct anode *)0));
        !           304:        }
        !           305:        else if(EQ(a, "-newer")) {
        !           306:                if(stat(b, &Statb) < 0) {
        !           307:                        fprintf(stderr, "find: cannot access < %s >\n", b);
        !           308:                        exit(1);
        !           309:                }
        !           310:                Newer = Statb.st_mtime;
        !           311:                return mk(newer, (struct anode *)0, (struct anode *)0);
        !           312:        }
        !           313: err:   fprintf(stderr, "find: bad option < %s >\n", a);
        !           314:        exit(1);
        !           315: }
        !           316: struct anode *mk(f, l, r)
        !           317: int (*f)();
        !           318: struct anode *l, *r;
        !           319: {
        !           320:        if (Nn >= MAXNODES) {
        !           321:                fprintf(stderr, "find: Too many options\n");
        !           322:                exit(1);
        !           323:        }
        !           324: 
        !           325:        Node[Nn].F = f;
        !           326:        Node[Nn].L = l;
        !           327:        Node[Nn].R = r;
        !           328:        return(&(Node[Nn++]));
        !           329: }
        !           330: 
        !           331: char *nxtarg() { /* get next arg from command line */
        !           332:        static strikes = 0;
        !           333: 
        !           334:        if(strikes==3) {
        !           335:                fprintf(stderr, "find: incomplete statement\n");
        !           336:                exit(1);
        !           337:        }
        !           338:        if(Ai>=Argc) {
        !           339:                strikes++;
        !           340:                Ai = Argc + 1;
        !           341:                return("");
        !           342:        }
        !           343:        return(Argv[Ai++]);
        !           344: }
        !           345: 
        !           346: /* execution time functions */
        !           347: and(p)
        !           348: register struct anode *p;
        !           349: {
        !           350:        return(((*p->L->F)(p->L)) && ((*p->R->F)(p->R))?1:0);
        !           351: }
        !           352: or(p)
        !           353: register struct anode *p;
        !           354: {
        !           355:         return(((*p->L->F)(p->L)) || ((*p->R->F)(p->R))?1:0);
        !           356: }
        !           357: not(p)
        !           358: register struct anode *p;
        !           359: {
        !           360:        return( !((*p->L->F)(p->L)));
        !           361: }
        !           362: glob(p)
        !           363: register struct { int f; char *pat; } *p; 
        !           364: {
        !           365:        return(gmatch(Fname, p->pat));
        !           366: }
        !           367: print(p)
        !           368: struct anode *p;
        !           369: {
        !           370:        puts(Pathname);
        !           371:        return(1);
        !           372: }
        !           373: mtime(p)
        !           374: register struct { int f, t, s; } *p; 
        !           375: {
        !           376:        return(scomp((int)((Now - Statb.st_mtime) / A_DAY), p->t, p->s));
        !           377: }
        !           378: atime(p)
        !           379: register struct { int f, t, s; } *p; 
        !           380: {
        !           381:        return(scomp((int)((Now - Statb.st_atime) / A_DAY), p->t, p->s));
        !           382: }
        !           383: user(p)
        !           384: register struct { int f, u, s; } *p; 
        !           385: {
        !           386:        return(scomp(Statb.st_uid, p->u, p->s));
        !           387: }
        !           388: nouser(p)
        !           389: struct anode *p;
        !           390: {
        !           391:        char *getname();
        !           392: 
        !           393:        return (getname(Statb.st_uid) == NULL);
        !           394: }
        !           395: ino(p)
        !           396: register struct { int f, u, s; } *p;
        !           397: {
        !           398:        return(scomp((int)Statb.st_ino, p->u, p->s));
        !           399: }
        !           400: group(p)
        !           401: register struct { int f, u; } *p; 
        !           402: {
        !           403:        return(p->u == Statb.st_gid);
        !           404: }
        !           405: nogroup(p)
        !           406: struct anode *p;
        !           407: {
        !           408:        char *getgroup();
        !           409: 
        !           410:        return (getgroup(Statb.st_gid) == NULL);
        !           411: }
        !           412: links(p)
        !           413: register struct { int f, link, s; } *p; 
        !           414: {
        !           415:        return(scomp(Statb.st_nlink, p->link, p->s));
        !           416: }
        !           417: size(p)
        !           418: register struct { int f, sz, s; } *p; 
        !           419: {
        !           420:        return(scomp((int)((Statb.st_size+511)>>9), p->sz, p->s));
        !           421: }
        !           422: perm(p)
        !           423: register struct { int f, per, s; } *p; 
        !           424: {
        !           425:        register i;
        !           426:        i = (p->s=='-') ? p->per : 07777; /* '-' means only arg bits */
        !           427:        return((Statb.st_mode & i & 07777) == p->per);
        !           428: }
        !           429: type(p)
        !           430: register struct { int f, per, s; } *p;
        !           431: {
        !           432:        return((Statb.st_mode&S_IFMT)==p->per);
        !           433: }
        !           434: exeq(p)
        !           435: register struct { int f, com; } *p;
        !           436: {
        !           437:        fflush(stdout); /* to flush possible `-print' */
        !           438:        return(doex(p->com));
        !           439: }
        !           440: ok(p)
        !           441: struct { int f, com; } *p;
        !           442: {
        !           443:        char c;  int yes;
        !           444:        yes = 0;
        !           445:        fflush(stdout); /* to flush possible `-print' */
        !           446:        fprintf(stderr, "< %s ... %s > ?   ", Argv[p->com], Pathname);
        !           447:        fflush(stderr);
        !           448:        if((c=getchar())=='y') yes = 1;
        !           449:        while(c!='\n') c = getchar();
        !           450:        if(yes) return(doex(p->com));
        !           451:        return(0);
        !           452: }
        !           453: 
        !           454: #define MKSHORT(v, lv) {U.l=1L;if(U.c[0]) U.l=lv, v[0]=U.s[1], v[1]=U.s[0]; else U.l=lv, v[0]=U.s[0], v[1]=U.s[1];}
        !           455: union { long l; short s[2]; char c[4]; } U;
        !           456: long mklong(v)
        !           457: short v[];
        !           458: {
        !           459:        U.l = 1;
        !           460:        if(U.c[0] /* VAX */)
        !           461:                U.s[0] = v[1], U.s[1] = v[0];
        !           462:        else
        !           463:                U.s[0] = v[0], U.s[1] = v[1];
        !           464:        return U.l;
        !           465: }
        !           466: cpio(p)
        !           467: struct anode *p;
        !           468: {
        !           469: #define MAGIC 070707
        !           470:        struct header {
        !           471:                short   h_magic,
        !           472:                        h_dev,
        !           473:                        h_ino,
        !           474:                        h_mode,
        !           475:                        h_uid,
        !           476:                        h_gid,
        !           477:                        h_nlink,
        !           478:                        h_rdev;
        !           479:                short   h_mtime[2];
        !           480:                short   h_namesize;
        !           481:                short   h_filesize[2];
        !           482:                char    h_name[256];
        !           483:        } hdr;
        !           484:        register ifile, ct;
        !           485:        static long fsz;
        !           486:        register i;
        !           487: 
        !           488:        hdr.h_magic = MAGIC;
        !           489:        strcpy(hdr.h_name, !strncmp(Pathname, "./", 2)? Pathname+2: Pathname);
        !           490:        hdr.h_namesize = strlen(hdr.h_name) + 1;
        !           491:        hdr.h_uid = Statb.st_uid;
        !           492:        hdr.h_gid = Statb.st_gid;
        !           493:        hdr.h_dev = Statb.st_dev;
        !           494:        hdr.h_ino = Statb.st_ino;
        !           495:        hdr.h_mode = Statb.st_mode;
        !           496:        MKSHORT(hdr.h_mtime, Statb.st_mtime);
        !           497:        hdr.h_nlink = Statb.st_nlink;
        !           498:        fsz = hdr.h_mode & S_IFREG? Statb.st_size: 0L;
        !           499:        MKSHORT(hdr.h_filesize, fsz);
        !           500:        hdr.h_rdev = Statb.st_rdev;
        !           501:        if(EQ(hdr.h_name, "TRAILER!!!")) {
        !           502:                bwrite((short *)&hdr, (sizeof hdr-256)+hdr.h_namesize);
        !           503:                for(i = 0; i < 10; ++i)
        !           504:                        bwrite(Buf, 512);
        !           505:                return;
        !           506:        }
        !           507:        if(!mklong(hdr.h_filesize))
        !           508:                return;
        !           509:        if((ifile = open(Fname, 0)) < 0) {
        !           510: cerror:
        !           511:                fprintf(stderr, "find: cannot copy < %s >\n", hdr.h_name);
        !           512:                return;
        !           513:        }
        !           514:        bwrite((short *)&hdr, (sizeof hdr-256)+hdr.h_namesize);
        !           515:        for(fsz = mklong(hdr.h_filesize); fsz > 0; fsz -= 512) {
        !           516:                ct = fsz>512? 512: fsz;
        !           517:                if(read(ifile, (char *)Buf, ct) < 0)
        !           518:                        goto cerror;
        !           519:                bwrite(Buf, ct);
        !           520:        }
        !           521:        close(ifile);
        !           522:        return;
        !           523: }
        !           524: newer(p)
        !           525: struct anode *p;
        !           526: {
        !           527:        return Statb.st_mtime > Newer;
        !           528: }
        !           529: ls(p)
        !           530: struct anode *p;
        !           531: {
        !           532:        list(Pathname, &Statb);
        !           533:        return (1);
        !           534: }
        !           535: dummy(p)
        !           536: struct anode *p;
        !           537: {
        !           538:        /* dummy */
        !           539:        return (1);
        !           540: }
        !           541: 
        !           542: /* support functions */
        !           543: scomp(a, b, s) /* funny signed compare */
        !           544: register a, b;
        !           545: register char s;
        !           546: {
        !           547:        if(s == '+')
        !           548:                return(a > b);
        !           549:        if(s == '-')
        !           550:                return(a < (b * -1));
        !           551:        return(a == b);
        !           552: }
        !           553: 
        !           554: doex(com)
        !           555: {
        !           556:        register np;
        !           557:        register char *na;
        !           558:        static char *nargv[50];
        !           559:        static ccode;
        !           560:        register int w, pid, omask;
        !           561: 
        !           562:        ccode = np = 0;
        !           563:        while (na=Argv[com++]) {
        !           564:                if(np >= sizeof nargv / sizeof *nargv - 1) break;
        !           565:                if(strcmp(na, ";")==0) break;
        !           566:                if(strcmp(na, "{}")==0) nargv[np++] = Pathname;
        !           567:                else nargv[np++] = na;
        !           568:        }
        !           569:        nargv[np] = 0;
        !           570:        if (np==0) return(9);
        !           571:        switch (pid = vfork()) {
        !           572:        case -1:
        !           573:                perror("find: Can't fork");
        !           574:                exit(1);
        !           575:                break;
        !           576: 
        !           577:        case 0:
        !           578:                chdir(Home);
        !           579:                execvp(nargv[0], nargv, np);
        !           580:                write(2, "find: Can't execute ", 20);
        !           581:                perror(nargv[0]);
        !           582:                /*
        !           583:                 * Kill ourselves; our exit status will be a suicide
        !           584:                 * note indicating we couldn't do the "exec".
        !           585:                 */
        !           586:                kill(getpid(), SIGUSR1);
        !           587:                break;
        !           588: 
        !           589:        default:
        !           590:                omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT));
        !           591:                while ((w = wait(&ccode)) != pid && w != -1)
        !           592:                        ;
        !           593:                (void) sigsetmask(omask);
        !           594:                if ((ccode & 0177) == SIGUSR1)
        !           595:                        exit(1);
        !           596:                return (ccode != 0 ? 0 : 1);
        !           597:        }
        !           598: }
        !           599: 
        !           600: getunum(f, s) char *f, *s; { /* find user/group name and return number */
        !           601:        register i;
        !           602:        register char *sp;
        !           603:        register c;
        !           604:        char str[20];
        !           605:        FILE *pin;
        !           606: 
        !           607:        i = -1;
        !           608:        pin = fopen(f, "r");
        !           609:        c = '\n'; /* prime with a CR */
        !           610:        do {
        !           611:                if(c=='\n') {
        !           612:                        sp = str;
        !           613:                        while((c = *sp++ = getc(pin)) != ':')
        !           614:                                if(c == EOF) goto RET;
        !           615:                        *--sp = '\0';
        !           616:                        if(EQ(str, s)) {
        !           617:                                while((c=getc(pin)) != ':')
        !           618:                                        if(c == EOF) goto RET;
        !           619:                                sp = str;
        !           620:                                while((*sp = getc(pin)) != ':') sp++;
        !           621:                                *sp = '\0';
        !           622:                                i = atoi(str);
        !           623:                                goto RET;
        !           624:                        }
        !           625:                }
        !           626:        } while((c = getc(pin)) != EOF);
        !           627:  RET:
        !           628:        fclose(pin);
        !           629:        return(i);
        !           630: }
        !           631: 
        !           632: descend(name, fname, exlist)
        !           633:        struct anode *exlist;
        !           634:        char *name, *fname;
        !           635: {
        !           636:        DIR     *dir = NULL;
        !           637:        register struct direct  *dp;
        !           638:        register char *c1;
        !           639:        int rv = 0;
        !           640:        char *endofname;
        !           641: 
        !           642:        if ((follow?stat(fname, &Statb):lstat(fname, &Statb))<0) {
        !           643:                fprintf(stderr, "find: bad status < %s >\n", name);
        !           644:                return(0);
        !           645:        }
        !           646:        (*exlist->F)(exlist);
        !           647:        if((Statb.st_mode&S_IFMT)!=S_IFDIR ||
        !           648:           !Xdev && Devstat.st_dev != Statb.st_dev)
        !           649:                return(1);
        !           650: 
        !           651:        if (Statb.st_nlink == 2 && exlist->F == and &&
        !           652:                exlist->L->F == type && ((int) (exlist->L->L)) == S_IFDIR)
        !           653:                        return(1);
        !           654: 
        !           655:        for (c1 = name; *c1; ++c1);
        !           656:        if (*(c1-1) == '/')
        !           657:                --c1;
        !           658:        endofname = c1;
        !           659: 
        !           660:        if (chdir(fname) == -1)
        !           661:                return(0);
        !           662:        if ((dir = opendir(".")) == NULL) {
        !           663:                fprintf(stderr, "find: cannot open < %s >\n", name);
        !           664:                rv = 0;
        !           665:                goto ret;
        !           666:        }
        !           667:        for (dp = readdir(dir); dp != NULL; dp = readdir(dir)) {
        !           668:                if ((dp->d_name[0]=='.' && dp->d_name[1]=='\0') ||
        !           669:                    (dp->d_name[0]=='.' && dp->d_name[1]=='.' && dp->d_name[2]=='\0'))
        !           670:                        continue;
        !           671:                c1 = endofname;
        !           672:                *c1++ = '/';
        !           673:                strcpy(c1, dp->d_name);
        !           674:                Fname = endofname+1;
        !           675:                if(!descend(name, Fname, exlist)) {
        !           676:                        *endofname = '\0';
        !           677:                        chdir(Home);
        !           678:                        if(chdir(Pathname) == -1) {
        !           679:                                fprintf(stderr, "find: bad directory tree\n");
        !           680:                                exit(1);
        !           681:                        }
        !           682:                }
        !           683:        }
        !           684:        rv = 1;
        !           685: ret:
        !           686:        if(dir)
        !           687:                closedir(dir);
        !           688:        if(chdir("..") == -1) {
        !           689:                *endofname = '\0';
        !           690:                fprintf(stderr, "find: bad directory <%s>\n", name);
        !           691:                rv = 1;
        !           692:        }
        !           693:        return(rv);
        !           694: }
        !           695: 
        !           696: gmatch(s, p) /* string match as in glob */
        !           697: register char *s, *p;
        !           698: {
        !           699:        if (*s=='.' && *p!='.') return(0);
        !           700:        return amatch(s, p);
        !           701: }
        !           702: 
        !           703: amatch(s, p)
        !           704: register char *s, *p;
        !           705: {
        !           706:        register cc;
        !           707:        int scc, k;
        !           708:        int c, lc;
        !           709: 
        !           710:        scc = *s;
        !           711:        lc = 077777;
        !           712:        switch (c = *p) {
        !           713: 
        !           714:        case '[':
        !           715:                k = 0;
        !           716:                while (cc = *++p) {
        !           717:                        switch (cc) {
        !           718: 
        !           719:                        case ']':
        !           720:                                if (k)
        !           721:                                        return(amatch(++s, ++p));
        !           722:                                else
        !           723:                                        return(0);
        !           724: 
        !           725:                        case '-':
        !           726:                                cc = p[1];
        !           727:                                k |= lc <= scc && scc <= cc;
        !           728:                        }
        !           729:                        if (scc==(lc=cc)) k++;
        !           730:                }
        !           731:                return(0);
        !           732: 
        !           733:        case '?':
        !           734:        caseq:
        !           735:                if(scc) return(amatch(++s, ++p));
        !           736:                return(0);
        !           737:        case '*':
        !           738:                return(umatch(s, ++p));
        !           739:        case 0:
        !           740:                return(!scc);
        !           741:        }
        !           742:        if (c==scc) goto caseq;
        !           743:        return(0);
        !           744: }
        !           745: 
        !           746: umatch(s, p)
        !           747: register char *s, *p;
        !           748: {
        !           749:        if(*p==0) return(1);
        !           750:        while(*s)
        !           751:                if (amatch(s++, p)) return(1);
        !           752:        return(0);
        !           753: }
        !           754: 
        !           755: bwrite(rp, c)
        !           756: register short *rp;
        !           757: register c;
        !           758: {
        !           759:        register short *wp = Wp;
        !           760: 
        !           761:        c = (c+1) >> 1;
        !           762:        while(c--) {
        !           763:                if(!Wct) {
        !           764: again:
        !           765:                        if(write(Cpio, (char *)Dbuf, Bufsize)<0) {
        !           766:                                Cpio = chgreel(1, Cpio);
        !           767:                                goto again;
        !           768:                        }
        !           769:                        Wct = Bufsize >> 1;
        !           770:                        wp = Dbuf;
        !           771:                        ++Blocks;
        !           772:                }
        !           773:                *wp++ = *rp++;
        !           774:                --Wct;
        !           775:        }
        !           776:        Wp = wp;
        !           777: }
        !           778: chgreel(x, fl)
        !           779: {
        !           780:        register f;
        !           781:        char str[22];
        !           782:        FILE *devtty;
        !           783:        struct stat statb;
        !           784:        extern errno;
        !           785: 
        !           786:        fprintf(stderr, "find: errno: %d, ", errno);
        !           787:        fprintf(stderr, "find: can't %s\n", x? "write output": "read input");
        !           788:        fstat(fl, &statb);
        !           789:        if((statb.st_mode&S_IFMT) != S_IFCHR)
        !           790:                exit(1);
        !           791: again:
        !           792:        fprintf(stderr, "If you want to go on, type device/file name %s\n",
        !           793:                "when ready");
        !           794:        devtty = fopen("/dev/tty", "r");
        !           795:        fgets(str, 20, devtty);
        !           796:        str[strlen(str) - 1] = '\0';
        !           797:        if(!*str)
        !           798:                exit(1);
        !           799:        close(fl);
        !           800:        if((f = open(str, x? 1: 0)) < 0) {
        !           801:                fprintf(stderr, "That didn't work");
        !           802:                fclose(devtty);
        !           803:                goto again;
        !           804:        }
        !           805:        return f;
        !           806: }
        !           807: 
        !           808: #ifdef AMES
        !           809: /*
        !           810:  * 'fastfind' scans a file list for the full pathname of a file
        !           811:  * given only a piece of the name.  The list has been processed with
        !           812:  * with "front-compression" and bigram coding.  Front compression reduces
        !           813:  * space by a factor of 4-5, bigram coding by a further 20-25%.
        !           814:  * The codes are:
        !           815:  *
        !           816:  *     0-28    likeliest differential counts + offset to make nonnegative 
        !           817:  *     30      escape code for out-of-range count to follow in next word
        !           818:  *     128-255 bigram codes, (128 most common, as determined by 'updatedb')
        !           819:  *     32-127  single character (printable) ascii residue
        !           820:  *
        !           821:  * A novel two-tiered string search technique is employed: 
        !           822:  *
        !           823:  * First, a metacharacter-free subpattern and partial pathname is
        !           824:  * matched BACKWARDS to avoid full expansion of the pathname list.
        !           825:  * The time savings is 40-50% over forward matching, which cannot efficiently
        !           826:  * handle overlapped search patterns and compressed path residue.
        !           827:  *
        !           828:  * Then, the actual shell glob-style regular expression (if in this form)
        !           829:  * is matched against the candidate pathnames using the slower routines
        !           830:  * provided in the standard 'find'.
        !           831:  */
        !           832: 
        !           833: #define        FCODES  "/usr/lib/find/find.codes"
        !           834: #define        YES     1
        !           835: #define        NO      0
        !           836: #define        OFFSET  14
        !           837: #define        ESCCODE 30
        !           838: 
        !           839: fastfind ( pathpart )  
        !           840:        char pathpart[];
        !           841: {
        !           842:        register char *p, *s;
        !           843:        register int c; 
        !           844:        char *q, *index(), *patprep();
        !           845:        int i, count = 0, globflag;
        !           846:        FILE *fp, *fopen();
        !           847:        char *patend, *cutoff;
        !           848:        char path[1024];
        !           849:        char bigram1[128], bigram2[128];
        !           850:        int found = NO;
        !           851: 
        !           852:        if ( (fp = fopen ( FCODES, "r" )) == NULL ) {
        !           853:                fprintf ( stderr, "find: can't open %s\n", FCODES );
        !           854:                exit ( 1 );
        !           855:        }
        !           856:        for ( i = 0; i < 128; i++ ) 
        !           857:                bigram1[i] = getc ( fp ),  bigram2[i] = getc ( fp );
        !           858: 
        !           859:        globflag = index ( pathpart, '*' ) || index ( pathpart, '?' ) ||
        !           860:                index ( pathpart, '[' );
        !           861:        patend = patprep ( pathpart );
        !           862: 
        !           863:        c = getc ( fp );
        !           864:        for ( ; ; ) {
        !           865: 
        !           866:                count += ( (c == ESCCODE) ? getw ( fp ) : c ) - OFFSET;
        !           867: 
        !           868:                for ( p = path + count; (c = getc ( fp )) > ESCCODE; )  /* overlay old path */
        !           869:                        if ( c < 0200 ) 
        !           870:                                *p++ = c;
        !           871:                        else            /* bigrams are parity-marked */
        !           872:                                *p++ = bigram1[c & 0177],  *p++ = bigram2[c & 0177];
        !           873:                if ( c == EOF )
        !           874:                        break;
        !           875:                *p-- = NULL;
        !           876:                cutoff = ( found ? path : path + count);
        !           877: 
        !           878:                for ( found = NO, s = p; s >= cutoff; s-- ) 
        !           879:                        if ( *s == *patend ) {          /* fast first char check */
        !           880:                                for ( p = patend - 1, q = s - 1; *p != NULL; p--, q-- )
        !           881:                                        if ( *q != *p )
        !           882:                                                break;
        !           883:                                if ( *p == NULL ) {     /* success on fast match */
        !           884:                                        found = YES;
        !           885:                                        if ( globflag == NO || amatch ( path, pathpart ) )
        !           886:                                                puts ( path );
        !           887:                                        break;
        !           888:                                }
        !           889:                        }
        !           890:        }
        !           891: }
        !           892: 
        !           893: /*
        !           894:     extract last glob-free subpattern in name for fast pre-match;
        !           895:     prepend '\0' for backwards match; return end of new pattern
        !           896: */
        !           897: static char globfree[100];
        !           898: 
        !           899: char *
        !           900: patprep ( name )
        !           901:        char *name;
        !           902: {
        !           903:        register char *p, *endmark;
        !           904:        register char *subp = globfree;
        !           905: 
        !           906:        *subp++ = '\0';
        !           907:        p = name + strlen ( name ) - 1;
        !           908:        /*
        !           909:           skip trailing metacharacters (and [] ranges)
        !           910:        */
        !           911:        for ( ; p >= name; p-- )
        !           912:                if ( index ( "*?", *p ) == 0 )
        !           913:                        break;
        !           914:        if ( p < name )
        !           915:                p = name;
        !           916:        if ( *p == ']' )
        !           917:                for ( p--; p >= name; p-- )
        !           918:                        if ( *p == '[' ) {
        !           919:                                p--;
        !           920:                                break;
        !           921:                        }
        !           922:        if ( p < name )
        !           923:                p = name;
        !           924:        /*
        !           925:           if pattern has only metacharacters,
        !           926:           check every path (force '/' search)
        !           927:        */
        !           928:        if ( (p == name) && index ( "?*[]", *p ) != 0 )
        !           929:                *subp++ = '/';                                  
        !           930:        else {                          
        !           931:                for ( endmark = p; p >= name; p-- )
        !           932:                        if ( index ( "]*?", *p ) != 0 )
        !           933:                                break;
        !           934:                for ( ++p; (p <= endmark) && subp < (globfree + sizeof ( globfree )); )
        !           935:                        *subp++ = *p++;
        !           936:        }
        !           937:        *subp = '\0';
        !           938:        return ( --subp );
        !           939: }
        !           940: #endif
        !           941: 
        !           942: /* rest should be done with nameserver or database */
        !           943: 
        !           944: #include <pwd.h>
        !           945: #include <grp.h>
        !           946: #include <utmp.h>
        !           947: 
        !           948: struct utmp utmp;
        !           949: #define        NMAX    (sizeof (utmp.ut_name))
        !           950: #define SCPYN(a, b)    strncpy(a, b, NMAX)
        !           951: 
        !           952: #define NUID   64
        !           953: #define NGID   300
        !           954: 
        !           955: struct ncache {
        !           956:        int     uid;
        !           957:        char    name[NMAX+1];
        !           958: } nc[NUID];
        !           959: char   outrangename[NMAX+1];
        !           960: int    outrangeuid = -1;
        !           961: char   groups[NGID][NMAX+1];
        !           962: char   outrangegroup[NMAX+1];
        !           963: int    outrangegid = -1;
        !           964: 
        !           965: /*
        !           966:  * This function assumes that the password file is hashed
        !           967:  * (or some such) to allow fast access based on a name key.
        !           968:  * If this isn't true, duplicate the code for getgroup().
        !           969:  */
        !           970: char *
        !           971: getname(uid)
        !           972: {
        !           973:        register struct passwd *pw;
        !           974:        struct passwd *getpwent();
        !           975:        register int cp;
        !           976:        extern int _pw_stayopen;
        !           977: 
        !           978:        _pw_stayopen = 1;
        !           979: 
        !           980: #if    (((NUID) & ((NUID) - 1)) != 0)
        !           981:        cp = uid % (NUID);
        !           982: #else
        !           983:        cp = uid & ((NUID) - 1);
        !           984: #endif
        !           985:        if (uid >= 0 && nc[cp].uid == uid && nc[cp].name[0])
        !           986:                return (nc[cp].name);
        !           987:        pw = getpwuid(uid);
        !           988:        if (!pw)
        !           989:                return (0);
        !           990:        nc[cp].uid = uid;
        !           991:        SCPYN(nc[cp].name, pw->pw_name);
        !           992:        return (nc[cp].name);
        !           993: }
        !           994: 
        !           995: char *
        !           996: getgroup(gid)
        !           997: {
        !           998:        register struct group *gr;
        !           999:        static init;
        !          1000:        struct group *getgrent();
        !          1001: 
        !          1002:        if (gid >= 0 && gid < NGID && groups[gid][0])
        !          1003:                return (&groups[gid][0]);
        !          1004:        if (gid >= 0 && gid == outrangegid)
        !          1005:                return (outrangegroup);
        !          1006: rescan:
        !          1007:        if (init == 2) {
        !          1008:                if (gid < NGID)
        !          1009:                        return (0);
        !          1010:                setgrent();
        !          1011:                while (gr = getgrent()) {
        !          1012:                        if (gr->gr_gid != gid)
        !          1013:                                continue;
        !          1014:                        outrangegid = gr->gr_gid;
        !          1015:                        SCPYN(outrangegroup, gr->gr_name);
        !          1016:                        endgrent();
        !          1017:                        return (outrangegroup);
        !          1018:                }
        !          1019:                endgrent();
        !          1020:                return (0);
        !          1021:        }
        !          1022:        if (init == 0)
        !          1023:                setgrent(), init = 1;
        !          1024:        while (gr = getgrent()) {
        !          1025:                if (gr->gr_gid < 0 || gr->gr_gid >= NGID) {
        !          1026:                        if (gr->gr_gid == gid) {
        !          1027:                                outrangegid = gr->gr_gid;
        !          1028:                                SCPYN(outrangegroup, gr->gr_name);
        !          1029:                                return (outrangegroup);
        !          1030:                        }
        !          1031:                        continue;
        !          1032:                }
        !          1033:                if (groups[gr->gr_gid][0])
        !          1034:                        continue;
        !          1035:                SCPYN(groups[gr->gr_gid], gr->gr_name);
        !          1036:                if (gr->gr_gid == gid)
        !          1037:                        return (&groups[gid][0]);
        !          1038:        }
        !          1039:        init = 2;
        !          1040:        goto rescan;
        !          1041: }
        !          1042: 
        !          1043: int
        !          1044: getuid(username)
        !          1045:        char *username;
        !          1046: {
        !          1047:        register struct passwd *pw;
        !          1048:        struct passwd *getpwnam();
        !          1049: #ifndef        NO_PW_STAYOPEN
        !          1050:        extern int _pw_stayopen;
        !          1051: 
        !          1052:        _pw_stayopen = 1;
        !          1053: #endif
        !          1054: 
        !          1055:        pw = getpwnam(username);
        !          1056:        if (pw != NULL)
        !          1057:                return (pw->pw_uid);
        !          1058:        else
        !          1059:                return (-1);
        !          1060: }
        !          1061: 
        !          1062: int
        !          1063: getgid(groupname)
        !          1064:        char *groupname;
        !          1065: {
        !          1066:        register struct group *gr;
        !          1067:        struct group *getgrnam();
        !          1068: 
        !          1069:        gr = getgrnam(groupname);
        !          1070:        if (gr != NULL)
        !          1071:                return (gr->gr_gid);
        !          1072:        else
        !          1073:                return (-1);
        !          1074: }
        !          1075: 
        !          1076: #define permoffset(who)                ((who) * 3)
        !          1077: #define permission(who, type)  ((type) >> permoffset(who))
        !          1078: #define kbytes(bytes)          (((bytes) + 1023) / 1024)
        !          1079: 
        !          1080: list(file, stp)
        !          1081:        char *file;
        !          1082:        register struct stat *stp;
        !          1083: {
        !          1084:        char pmode[32], uname[32], gname[32], fsize[32], ftime[32];
        !          1085:        char *getname(), *getgroup(), *ctime();
        !          1086:        static long special[] = { S_ISUID, 's', S_ISGID, 's', S_ISVTX, 't' };
        !          1087:        static time_t sixmonthsago = -1;
        !          1088: #ifdef S_IFLNK
        !          1089:        char flink[MAXPATHLEN + 1];
        !          1090: #endif
        !          1091:        register int who;
        !          1092:        register char *cp;
        !          1093:        time_t now;
        !          1094: 
        !          1095:        if (file == NULL || stp == NULL)
        !          1096:                return (-1);
        !          1097: 
        !          1098:        time(&now);
        !          1099:        if (sixmonthsago == -1)
        !          1100:                sixmonthsago = now - 6L*30L*24L*60L*60L;
        !          1101: 
        !          1102:        switch (stp->st_mode & S_IFMT) {
        !          1103: #ifdef S_IFDIR
        !          1104:        case S_IFDIR:   /* directory */
        !          1105:                pmode[0] = 'd';
        !          1106:                break;
        !          1107: #endif
        !          1108: #ifdef S_IFCHR
        !          1109:        case S_IFCHR:   /* character special */
        !          1110:                pmode[0] = 'c';
        !          1111:                break;
        !          1112: #endif
        !          1113: #ifdef S_IFBLK
        !          1114:        case S_IFBLK:   /* block special */
        !          1115:                pmode[0] = 'b';
        !          1116:                break;
        !          1117: #endif
        !          1118: #ifdef S_IFLNK
        !          1119:        case S_IFLNK:   /* symbolic link */
        !          1120:                pmode[0] = 'l';
        !          1121:                break;
        !          1122: #endif
        !          1123: #ifdef S_IFSOCK
        !          1124:        case S_IFSOCK:  /* socket */
        !          1125:                pmode[0] = 's';
        !          1126:                break;
        !          1127: #endif
        !          1128: #ifdef S_IFREG
        !          1129:        case S_IFREG:   /* regular */
        !          1130: #endif
        !          1131:        default:
        !          1132:                pmode[0] = '-';
        !          1133:                break;
        !          1134:        }
        !          1135: 
        !          1136:        for (who = 0; who < 3; who++) {
        !          1137:                if (stp->st_mode & permission(who, S_IREAD))
        !          1138:                        pmode[permoffset(who) + 1] = 'r';
        !          1139:                else
        !          1140:                        pmode[permoffset(who) + 1] = '-';
        !          1141: 
        !          1142:                if (stp->st_mode & permission(who, S_IWRITE))
        !          1143:                        pmode[permoffset(who) + 2] = 'w';
        !          1144:                else
        !          1145:                        pmode[permoffset(who) + 2] = '-';
        !          1146: 
        !          1147:                if (stp->st_mode & special[who * 2])
        !          1148:                        pmode[permoffset(who) + 3] = special[who * 2 + 1];
        !          1149:                else if (stp->st_mode & permission(who, S_IEXEC))
        !          1150:                        pmode[permoffset(who) + 3] = 'x';
        !          1151:                else
        !          1152:                        pmode[permoffset(who) + 3] = '-';
        !          1153:        }
        !          1154:        pmode[permoffset(who) + 1] = '\0';
        !          1155: 
        !          1156:        cp = getname(stp->st_uid);
        !          1157:        if (cp != NULL)
        !          1158:                sprintf(uname, "%-9.9s", cp);
        !          1159:        else
        !          1160:                sprintf(uname, "%-9d", stp->st_uid);
        !          1161: 
        !          1162:        cp = getgroup(stp->st_gid);
        !          1163:        if (cp != NULL)
        !          1164:                sprintf(gname, "%-9.9s", cp);
        !          1165:        else
        !          1166:                sprintf(gname, "%-9d", stp->st_gid);
        !          1167: 
        !          1168:        if (pmode[0] == 'b' || pmode[0] == 'c')
        !          1169:                sprintf(fsize, "%3d,%4d",
        !          1170:                        major(stp->st_rdev), minor(stp->st_rdev));
        !          1171:        else {
        !          1172:                sprintf(fsize, "%8ld", stp->st_size);
        !          1173: #ifdef S_IFLNK
        !          1174:                if (pmode[0] == 'l') {
        !          1175:                        /*
        !          1176:                         * Need to get the tail of the file name, since we have
        !          1177:                         * already chdir()ed into the directory of the file
        !          1178:                         */
        !          1179:                        cp = rindex(file, '/');
        !          1180:                        if (cp == NULL)
        !          1181:                                cp = file;
        !          1182:                        else
        !          1183:                                cp++;
        !          1184:                        who = readlink(cp, flink, sizeof flink - 1);
        !          1185:                        if (who >= 0)
        !          1186:                                flink[who] = '\0';
        !          1187:                        else
        !          1188:                                flink[0] = '\0';
        !          1189:                }
        !          1190: #endif
        !          1191:        }
        !          1192: 
        !          1193:        cp = ctime(&stp->st_mtime);
        !          1194:        if (stp->st_mtime < sixmonthsago || stp->st_mtime > now)
        !          1195:                sprintf(ftime, "%-7.7s %-4.4s", cp + 4, cp + 20);
        !          1196:        else
        !          1197:                sprintf(ftime, "%-12.12s", cp + 4);
        !          1198: 
        !          1199:        printf("%5lu %4ld %s %2d %s%s%s %s %s%s%s\n",
        !          1200:                stp->st_ino,                            /* inode #      */
        !          1201: #ifdef S_IFSOCK
        !          1202:                (long) kbytes(dbtob(stp->st_blocks)),   /* kbytes       */
        !          1203: #else
        !          1204:                (long) kbytes(stp->st_size),            /* kbytes       */
        !          1205: #endif
        !          1206:                pmode,                                  /* protection   */
        !          1207:                stp->st_nlink,                          /* # of links   */
        !          1208:                uname,                                  /* owner        */
        !          1209:                gname,                                  /* group        */
        !          1210:                fsize,                                  /* # of bytes   */
        !          1211:                ftime,                                  /* modify time  */
        !          1212:                file,                                   /* name         */
        !          1213: #ifdef S_IFLNK
        !          1214:                (pmode[0] == 'l') ? " -> " : "",
        !          1215:                (pmode[0] == 'l') ? flink  : ""         /* symlink      */
        !          1216: #else
        !          1217:                "",
        !          1218:                ""
        !          1219: #endif
        !          1220:        );
        !          1221: 
        !          1222:        return (0);
        !          1223: }

unix.superglobalmegacorp.com

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