Annotation of 43BSDTahoe/usr.bin/find/find.c, revision 1.1.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.