Annotation of coherent/d/bin/find/find.y, revision 1.1.1.1

1.1       root        1: %{
                      2: /*
                      3:  * Find all files in the given
                      4:  * directory hierarchies that
                      5:  * satisfy the given expression
                      6:  * primaries.
                      7:  */
                      8: 
                      9: #include <stdio.h>
                     10: #include <sys/stat.h>
                     11: #include <sys/dir.h>
                     12: #include <pwd.h>
                     13: #include <grp.h>
                     14: #include "findnode.h"
                     15: 
                     16: #define        NPRIM   (sizeof(primaries)/sizeof(primaries[0]))
                     17: #define        NARG    50
                     18: #define        NRECUR  14              /* Maximum recursion depth before forking */
                     19: #define        NFNAME  600             /* size of filename buffer */
                     20: #define        FILEARG ((char *)EOF)
                     21: #define        DAYSEC  (60L*60L*24L)   /* seconds in a day */
                     22: #define        inode(f,v)      lnode(FUN,f,v,NULL)
                     23: #define        snode(f,s)      lnode(FUN,f,0,s)
                     24: %}
                     25: %start command
                     26: 
                     27: %union {
                     28:        NODE  *nodeptr;
                     29:        }
                     30: 
                     31: %left  OR
                     32: %left  AND
                     33: %left  '!'
                     34: %token <nodeptr> NAME PERM TYPE LINKS USER GROUP SIZE INUM
                     35: %token <nodeptr> ATIME CTIME MTIME EXEC OK PRINT NEWER FUN NOP
                     36: %type  <nodeptr> exp
                     37: 
                     38: %%
                     39: 
                     40: command:
                     41:        exp '\n'                { if (seflag)
                     42:                                        code = $1; else
                     43:                                        code = bnode(AND,$1,snode(xprint,NULL));
                     44:                                  return;
                     45:                                }
                     46:       | '\n'                   { code = snode(xprint, NULL); return; }
                     47:        ;
                     48: 
                     49: exp:
                     50:         '(' exp ')'            { $$ = $2; }
                     51:       | '!' exp                        { $$ = bnode('!', $2, NULL); }
                     52:       | exp OR exp             { $$ = bnode(OR, $1, $3); }
                     53:       | exp AND exp            { $$ = bnode(AND, $1, $3); }
                     54:       | NAME                   { $$ = snode(xname, next()); }
                     55:       | PERM                   { $$ = onode(xperm); }
                     56:       | TYPE                   { $$ = snode(xtype, next()); }
                     57:       | LINKS                  { $$ = nnode(xlinks); }
                     58:       | USER                   { $$ = getuser(); }
                     59:       | GROUP                  { $$ = getgroup(); }
                     60:       | SIZE                   { $$ = nnode(xsize); }
                     61:       | INUM                   { $$ = nnode(xinum); }
                     62:       | ATIME                  { $$ = nnode(xatime); }
                     63:       | CTIME                  { $$ = nnode(xctime); }
                     64:       | MTIME                  { $$ = nnode(xmtime); }
                     65:       | EXEC                   { $$ = enode(0); }
                     66:       | OK                     { $$ = enode(1); }
                     67:       | PRINT                  { $$ = snode(xprint, NULL); seflag++; }
                     68:       | NEWER                  { $$ = getnewer(); }
                     69:       | NOP                    { $$ = snode(xnop, NULL); seflag++; }
                     70:        ;
                     71: 
                     72: %%
                     73: struct primary {
                     74:        char    *p_name;
                     75:        int     p_lval;
                     76: }      primaries[] = {
                     77:        "-name", NAME,
                     78:        "-perm", PERM,
                     79:        "-type", TYPE,
                     80:        "-links", LINKS,
                     81:        "-user", USER,
                     82:        "-group", GROUP,
                     83:        "-size", SIZE,
                     84:        "-inum", INUM,
                     85:        "-atime", ATIME,
                     86:        "-ctime", CTIME,
                     87:        "-mtime", MTIME,
                     88:        "-exec", EXEC,
                     89:        "-ok", OK,
                     90:        "-print", PRINT,
                     91:        "-newer", NEWER,
                     92:        "-nop", NOP,
                     93:        "-o", OR,
                     94:        "-a", AND,
                     95: };
                     96: 
                     97: char   **gav;
                     98: int    gac;
                     99: int    depth;                  /* Recursive depth */
                    100: 
                    101: struct stat    sb;
                    102: char   fname[NFNAME];
                    103: char   *prompt;
                    104: 
                    105: char   toodeep[] = "directory structure too deep to traverse";
                    106: char   nospace[] = "out of memory";
                    107: 
                    108: time_t curtime;
                    109: 
                    110: NODE   *code;
                    111: int    seflag;                 /* Set if a side effect (print, exec) found */
                    112: 
                    113: char   *next();
                    114: NODE   *bnode();
                    115: NODE   *enode();
                    116: NODE   *lnode();
                    117: NODE   *nnode();
                    118: NODE   *onode();
                    119: NODE   *getuser();
                    120: NODE   *getgroup();
                    121: NODE   *getnewer();
                    122: int    xname();
                    123: int    xperm();
                    124: int    xtype();
                    125: int    xlinks();
                    126: int    xuser();
                    127: int    xgroup();
                    128: int    xsize();
                    129: int    xinum();
                    130: int    xatime();
                    131: int    xctime();
                    132: int    xmtime();
                    133: int    xnewer();
                    134: int    xexec();
                    135: int    xprint();
                    136: int    xnop();
                    137: char   *getenv();
                    138: 
                    139: main(argc, argv)
                    140: char *argv[];
                    141: {
                    142:        register int i;
                    143:        register char *ap;
                    144:        register int eargc;
                    145: 
                    146:        for (i=1; i<argc; i++) {
                    147:                ap = argv[i];
                    148:                if (*ap == '-')
                    149:                        break;
                    150:                if (ap[1]=='\0' && (*ap=='!' || *ap=='('))
                    151:                        break;
                    152:        }
                    153:        if ((eargc=i) < 2)
                    154:                usage();
                    155:        gav = argv+i;
                    156:        gac = argc-i;
                    157:        yyparse();
                    158:        time(&curtime);
                    159:        if ((prompt = getenv("PS1")) == NULL)
                    160:                prompt = "> ";
                    161:        for (i=1; i<eargc; i++)
                    162:                find(argv[i]);
                    163: }
                    164: 
                    165: /*
                    166:  * Lexical analyser
                    167:  */
                    168: yylex()
                    169: {
                    170:        static int binop = 0;
                    171:        static int ntoken = 0;
                    172:        register char *ap;
                    173:        struct primary *pp;
                    174:        register int token;
                    175: 
                    176:        if (ntoken) {
                    177:                token = ntoken;
                    178:                ntoken = 0;
                    179:        } else if ((ap = next()) == NULL)
                    180:                token = '\n';
                    181:        else if (ap[1] == '\0')
                    182:                token = ap[0];
                    183:        else if (*ap == '-') {
                    184:                for (pp = primaries; pp < &primaries[NPRIM]; pp++)
                    185:                        if (strcmp(pp->p_name, ap) == 0) {
                    186:                                token = pp->p_lval;
                    187:                                break;
                    188:                        }
                    189:                if (pp >= &primaries[NPRIM])
                    190:                        ferr("`%s' is an illegal primary", ap);
                    191:        } else
                    192:                ferr("Illegal expression %s\n", ap);
                    193:        if (binop && token!=')' && token!='\n' && token!=OR && token!=AND) {
                    194:                binop = 0;
                    195:                ntoken = token;
                    196:                return (AND);
                    197:        }
                    198:        if (token!=OR && token!=AND && token!='!' && token!='\n' && token!='(')
                    199:                binop = 1; else
                    200:                binop = 0;
                    201:        return (token);
                    202: }
                    203: 
                    204: yyerror()
                    205: {
                    206:        fprintf(stderr, "Primary expression syntax error\n");
                    207:        usage();
                    208: }
                    209: 
                    210: /*
                    211:  * Return the next argument from the arg list.
                    212:  */
                    213: char *
                    214: next()
                    215: {
                    216:        if (gac < 1)
                    217:                return (NULL);
                    218:        gac--;
                    219:        return (*gav++);
                    220: }
                    221: 
                    222: /*
                    223:  * Produce a node consisting
                    224:  * of an octal number.
                    225:  */
                    226: NODE *
                    227: onode(fun)
                    228: int (*fun)();
                    229: {
                    230:        register char *ap;
                    231:        register int num;
                    232:        register NODE *np;
                    233:        register int type;
                    234:        char *aap;
                    235: 
                    236:        if ((ap = next()) == NULL)
                    237:                ferr("Missing octal permission");
                    238:        aap = ap;
                    239:        if (*ap == '-') {
                    240:                ap++;
                    241:                type = -1;
                    242:        } else
                    243:                type = 0;
                    244:        num = 0;
                    245:        while (*ap>='0' && *ap<='7')
                    246:                num = num*8 + *ap++-'0';
                    247:        if (*ap != '\0')
                    248:                ferr("%s: bad octal permission", aap);
                    249:        np = inode(fun, num);
                    250:        np->n_un.n_val = num;
                    251:        np->n_type = type;
                    252:        return (np);
                    253: }
                    254: 
                    255: /*
                    256:  * Get a number -- it also may be
                    257:  * prefixed by `+' or `-' to
                    258:  * represent quantities greater or
                    259:  * less.
                    260:  */
                    261: NODE *
                    262: nnode(fun)
                    263: int (*fun);
                    264: {
                    265:        register char *ap;
                    266:        register int num = 0;
                    267:        register int type = 0;
                    268:        register NODE *np;
                    269:        char *aap;
                    270: 
                    271:        if ((ap = next()) == NULL)
                    272:                ferr("Missing number");
                    273:        aap = ap;
                    274:        if (*ap == '+') {
                    275:                type = 1;
                    276:                ap++;
                    277:        } else if (*ap == '-') {
                    278:                type = -1;
                    279:                ap++;
                    280:        }
                    281:        while (*ap>='0' && *ap<='9')
                    282:                num = num*10 + *ap++ - '0';
                    283:        if (*ap != '\0')
                    284:                ferr("%s: invalid number", aap);
                    285:        np = inode(fun, num);
                    286:        np->n_type = type;
                    287:        return (np);
                    288: }
                    289: 
                    290: /*
                    291:  * Get a user name or number.
                    292:  */
                    293: NODE *
                    294: getuser()
                    295: {
                    296:        register struct passwd *pwp;
                    297:        register char *cp;
                    298:        register int uid;
                    299: 
                    300:        if ((cp = next()) == NULL)
                    301:                ferr("Missing username");
                    302:        if (*cp>='0' && *cp<='9')
                    303:                uid = atoi(cp);
                    304:        else {
                    305:                if ((pwp = getpwnam(cp)) == NULL)
                    306:                        ferr("%s: bad user name", cp);
                    307:                uid = pwp->pw_uid;
                    308:        }
                    309:        return (lnode(FUN, xuser, uid, NULL));
                    310: }
                    311: 
                    312: /*
                    313:  * Get group
                    314:  */
                    315: NODE *
                    316: getgroup()
                    317: {
                    318:        register struct group *grp;
                    319:        register char *cp;
                    320:        register int gid;
                    321: 
                    322:        if ((cp = next()) == NULL)
                    323:                ferr("Missing group name");
                    324:        if (*cp>='0' && *cp<='9')
                    325:                gid = atoi(cp);
                    326:        else {
                    327:                if ((grp = getgrnam(cp)) == NULL)
                    328:                        ferr("%s: bad group name", cp);
                    329:                gid = grp->gr_gid;
                    330:        }
                    331:        return (lnode(FUN, xgroup, gid, NULL));
                    332: }
                    333: 
                    334: /*
                    335:  * Get the time for the file used in
                    336:  * the `-newer' primary.
                    337:  */
                    338: NODE *
                    339: getnewer()
                    340: {
                    341:        register NODE *np;
                    342:        register char *fn;
                    343: 
                    344:        if ((fn = next()) == NULL)
                    345:                ferr("Missing filename for `-newer'");
                    346:        if (stat(fn, &sb) < 0)
                    347:                ferr("%s: nonexistent", fn);
                    348:        np = inode(xnewer, 0);
                    349:        np->n_un.n_time = sb.st_mtime;
                    350:        return (np);
                    351: }
                    352: 
                    353: /*
                    354:  * Build an expression tree node (non-leaf).
                    355:  */
                    356: NODE *
                    357: bnode(op, left, right)
                    358: int op;
                    359: NODE *left, *right;
                    360: {
                    361:        register NODE *np;
                    362: 
                    363:        if ((np = malloc(sizeof (NODE))) == NULL)
                    364:                ferr(nospace);
                    365:        np->n_op = op;
                    366:        np->n_left = left;
                    367:        np->n_right = right;
                    368:        np->n_un.n_val = 0;
                    369:        return (np);
                    370: }
                    371: 
                    372: /*
                    373:  * Build a leaf node in expression tree.
                    374:  */
                    375: NODE *
                    376: lnode(op, fn, val, str)
                    377: int (*fn)();
                    378: char *str;
                    379: {
                    380:        register NODE *np;
                    381: 
                    382:        if ((np = malloc(sizeof (NODE))) == NULL)
                    383:                ferr(nospace);
                    384:        np->n_left = np->n_right = NULL;
                    385:        np->n_op = op;
                    386:        np->n_fun = fn;
                    387:        if (str != NULL)
                    388:                np->n_un.n_str = str; else
                    389:                np->n_un.n_val = val;
                    390:        return (np);
                    391: }
                    392: 
                    393: /*
                    394:  * Build an execution node
                    395:  * for -ok or -exec.
                    396:  */
                    397: NODE *
                    398: enode(type)
                    399: {
                    400:        register NODE *np;
                    401:        register char **app;
                    402:        register char *ap;
                    403: 
                    404:        seflag++;
                    405:        np = snode(xexec, NULL);
                    406:        np->n_type = type;
                    407:        if ((np->n_un.n_strp = (char**)malloc(sizeof(char*[NARG])))==NULL)
                    408:                ferr(nospace);
                    409:        app = np->n_un.n_strp;
                    410:        for (;;) {
                    411:                if ((ap = next()) == NULL)
                    412:                        ferr("Non-terminated -exec or -ok command list");
                    413:                if (strcmp(ap, "{}") == 0)
                    414:                        ap = FILEARG;
                    415:                else if (strcmp(ap, ";") == 0)
                    416:                        break;
                    417:                if (app-np->n_un.n_strp >= NARG-1)
                    418:                        ferr("Too many -exec or -ok command arguments");
                    419:                *app++ = ap;
                    420:        }
                    421:        *app = NULL;
                    422:        return (np);
                    423: }
                    424: 
                    425: /*
                    426:  * Execute find on a single
                    427:  * pathname hierarchy.
                    428:  */
                    429: find(dir)
                    430: char *dir;
                    431: {
                    432:        register char *ep, *cp;
                    433: 
                    434:        cp = dir;
                    435:        ep = fname;
                    436:        while (*cp)
                    437:                *ep++ = *cp++;
                    438:        *ep = '\0';
                    439:        if (stat(dir, &sb) < 0)
                    440:                ferr("Cannot find directory `%s'", dir);
                    441:        if ((sb.st_mode&S_IFMT) != S_IFDIR)
                    442:                ferr("%s: not a directory", dir);
                    443:        fentry(ep, &sb);
                    444: }
                    445: 
                    446: /*
                    447:  * The pointer is the end pointer
                    448:  * into the fname buffer.
                    449:  * And the stat buffer is passed to this
                    450:  * which traverses the directory hierarchy.
                    451:  */
                    452: fentry(ep, sbp)
                    453: char *ep;
                    454: struct stat *sbp;
                    455: {
                    456:        char *buildname();
                    457:        register char *np;
                    458:        register struct direct *dp;
                    459:        register int nb;
                    460:        int fd;
                    461:        int dirflag;
                    462:        char *iobuf;
                    463: 
                    464:        if (sbp != NULL) {
                    465:                dirflag = (sbp->st_mode&S_IFMT)==S_IFDIR;
                    466:                execute(code);
                    467:        } else
                    468:                dirflag = 1;
                    469:        if (dirflag) {
                    470:                if (++depth >= NRECUR) {
                    471:                        depth = 0;
                    472:                        ffork(ep, sbp);
                    473:                        return;
                    474:                }
                    475:                if ((fd = open(fname, 0)) < 0) {
                    476:                        fmsg("%s: cannot open directory", fname);
                    477:                        return;
                    478:                }
                    479:                if ((iobuf = malloc(BUFSIZ)) == NULL)
                    480:                        ferr(nospace);
                    481:                while ((nb = read(fd, iobuf, BUFSIZ)) > 0)
                    482:                        for (dp = iobuf; dp < &iobuf[nb]; dp++) {
                    483:                                if (dp->d_ino == 0)
                    484:                                        continue;
                    485:                                np = dp->d_name;
                    486:                                if (*np++=='.'
                    487:                                  && (*np=='\0' || (*np++=='.' && *np=='\0')))
                    488:                                        continue;
                    489:                                np = buildname(dp, ep);
                    490:                                if (stat(fname, &sb) < 0) {
                    491:                                        fmsg("%s: cannot stat", fname);
                    492:                                        continue;
                    493:                                }
                    494:                                fentry(np, &sb);
                    495:                        }
                    496:                if (nb < 0)
                    497:                        fmsg("%s: directory read error", fname);
                    498:                free(iobuf);
                    499:                *ep = '\0';
                    500:                close(fd);
                    501:                depth--;
                    502:        }
                    503: }
                    504: 
                    505: /*
                    506:  * Fork to do a find on recursive directory
                    507:  * structure that is too deep to fit into
                    508:  * user's open files.
                    509:  */
                    510: ffork(ep, sbp)
                    511: char *ep;
                    512: struct stat *sbp;
                    513: {
                    514:        register int i;
                    515:        register int pid;
                    516:        int status;
                    517: 
                    518:        fflush(stdout);
                    519:        if ((pid = fork()) < 0) {
                    520:                fmsg(toodeep);
                    521:                return;
                    522:        }
                    523:        if (pid) {
                    524:                while (wait(&status) >= 0)
                    525:                        ;
                    526:                if (status)
                    527:                        fmsg("panic: child failed: %o", status);
                    528:                return;
                    529:        }
                    530:        for (i=3; i<_NFILE; i++)
                    531:                close(i);
                    532:        fentry(ep, (struct stat *)NULL);
                    533:        fflush(stdout);
                    534:        exit(0);
                    535: }
                    536: 
                    537: /*
                    538:  * Build up the next entry
                    539:  * in the name.
                    540:  */
                    541: char *
                    542: buildname(dp, ep)
                    543: struct direct *dp;
                    544: register char *ep;
                    545: {
                    546:        register char *cp = dp->d_name;
                    547:        register unsigned n = DIRSIZ;
                    548: 
                    549:        if (ep+DIRSIZ+2 >= &fname[NFNAME]) {
                    550:                fmsg(toodeep);
                    551:                return (NULL);
                    552:        }
                    553:        if (ep>fname && ep[-1]!='/')
                    554:                *ep++ = '/';
                    555:        do {
                    556:                if (*cp == '\0')
                    557:                        break;
                    558:                *ep++ = *cp++;
                    559:        } while (--n);
                    560:        *ep = '\0';
                    561:        return (ep);
                    562: }
                    563: 
                    564: /*
                    565:  * Execute compiled code.
                    566:  */
                    567: execute(np)
                    568: register NODE *np;
                    569: {
                    570:        switch (np->n_op) {
                    571:        case AND:
                    572:                if (execute(np->n_left) && execute(np->n_right))
                    573:                        return (1);
                    574:                return (0);
                    575: 
                    576:        case OR:
                    577:                if (execute(np->n_left) || execute(np->n_right))
                    578:                        return (1);
                    579:                return (0);
                    580: 
                    581:        case '!':
                    582:                return (!execute(np->n_left));
                    583: 
                    584:        case FUN:
                    585:                return ((*np->n_fun)(np));
                    586: 
                    587:        default:
                    588:                ferr("Panic: bad expression tree (op %d)", np->n_op);
                    589:        }
                    590:        /* NOTREACHED */
                    591: }
                    592: 
                    593: /*
                    594:  * Check for a match on the filename
                    595:  */
                    596: xname(np)
                    597: NODE *np;
                    598: {
                    599:        register char *ep;
                    600: 
                    601:        ep = fname;
                    602:        while (*ep != '\0')
                    603:                ep++;
                    604:        while (ep>fname && *--ep!='/')
                    605:                ;
                    606:        if (*ep == '/')
                    607:                ep++;
                    608:        return (pnmatch(ep, np->n_un.n_str, 0));
                    609: }
                    610: 
                    611: /*
                    612:  * Compare the mode for a match again
                    613:  * octal number `np->n_un.n_val'.
                    614:  */
                    615: xperm(np)
                    616: NODE *np;
                    617: {
                    618:        register int onum;
                    619:        register int mode;
                    620: 
                    621:        mode = np->n_type<0 ? sb.st_mode&017777 : sb.st_mode&0777;
                    622:        onum = np->n_un.n_val;
                    623:        if (np->n_type < 0)
                    624:                return ((mode&onum) == onum);
                    625:        return (mode == onum);
                    626: }
                    627: 
                    628: /*
                    629:  * Compare again filetypes
                    630:  */
                    631: xtype(np)
                    632: NODE *np;
                    633: {
                    634:        register char *type;
                    635:        register int ftype;
                    636: 
                    637:        type = np->n_un.n_str;
                    638:        ftype = sb.st_mode&S_IFMT;
                    639:        if (type[1] == '\0')
                    640:                switch (type[0]) {
                    641:                case 'b':
                    642:                        return (ftype == S_IFBLK);
                    643:        
                    644:                case 'c':
                    645:                        return (ftype == S_IFCHR);
                    646:        
                    647:                case 'd':
                    648:                        return (ftype == S_IFDIR);
                    649:        
                    650:                case 'f':
                    651:                        return (ftype == S_IFREG);
                    652:        
                    653:                case 'm':
                    654:                        return (ftype==S_IFMPB || ftype==S_IFMPC);
                    655: 
                    656:                case 'p':
                    657:                        return (ftype == S_IFPIP);
                    658:                }
                    659:        ferr("Bad file type  `%s'", type);
                    660: }
                    661: 
                    662: /*
                    663:  * Compare link counts.
                    664:  */
                    665: xlinks(np)
                    666: NODE *np;
                    667: {
                    668:        return (ncomp(np, sb.st_nlink));
                    669: }
                    670: 
                    671: /*
                    672:  * Compare uid.
                    673:  */
                    674: xuser(np)
                    675: NODE *np;
                    676: {
                    677:        return (np->n_un.n_val == sb.st_uid);
                    678: }
                    679: 
                    680: /*
                    681:  * Compare group id of file
                    682:  * with given one.
                    683:  */
                    684: xgroup(np)
                    685: NODE *np;
                    686: {
                    687:        return (np->n_un.n_val == sb.st_gid);
                    688: }
                    689: 
                    690: /*
                    691:  * Compare size of file in blocks
                    692:  * with given.
                    693:  */
                    694: xsize(np)
                    695: NODE *np;
                    696: {
                    697:        register int fsize;
                    698: 
                    699:        fsize = (sb.st_size+BUFSIZ-1)/BUFSIZ;
                    700:        return (ncomp(np, fsize));
                    701: }
                    702: 
                    703: /*
                    704:  * Compare the i-number of the file
                    705:  * with that given.
                    706:  */
                    707: xinum(np)
                    708: NODE *np;
                    709: {
                    710:        return (ncomp(np, sb.st_ino));
                    711: }
                    712: 
                    713: /*
                    714:  * Return true if file has been accessed
                    715:  * in `n' days.
                    716:  */
                    717: xatime(np)
                    718: NODE *np;
                    719: {
                    720:        return (ndays(np, sb.st_atime));
                    721: }
                    722: 
                    723: /*
                    724:  * Return non-zero if file has been created
                    725:  * in `n' days.
                    726:  */
                    727: xctime(np)
                    728: NODE *np;
                    729: {
                    730:        return (ndays(np, sb.st_ctime));
                    731: }
                    732: 
                    733: /*
                    734:  * Return true if file has been modified
                    735:  * in `n' days.
                    736:  */
                    737: xmtime(np)
                    738: NODE *np;
                    739: {
                    740:        return (ndays(np, sb.st_mtime));
                    741: }
                    742: 
                    743: /*
                    744:  * Execute a command based on the filename
                    745:  */
                    746: xexec(np)
                    747: NODE *np;
                    748: {
                    749:        static char command[200];
                    750:        register char *ap, **app;
                    751:        register int c;
                    752:        int ok;
                    753: 
                    754:        command[0] = '\0';
                    755:        app = np->n_un.n_strp;
                    756:        while (*app != NULL) {
                    757:                if ((ap = *app++) == FILEARG)
                    758:                        ap = fname;
                    759:                strcat(command, ap);
                    760:                if (*app != NULL)
                    761:                        strcat(command, " ");
                    762:        }
                    763:        if (np->n_type) {
                    764:                printf("%s%s? ", prompt, command);
                    765:                ok = (c = getchar()) == 'y';
                    766:                while (c!='\n' && c!=EOF)
                    767:                        c = getchar();
                    768:                if (!ok)
                    769:                        return (0);
                    770:        }
                    771:        return (!system(command));
                    772: }
                    773: 
                    774: /*
                    775:  * Print the filename.
                    776:  */
                    777: /* ARGSUSED */
                    778: xprint(np)
                    779: NODE *np;
                    780: {
                    781:        printf("%s\n", fname);
                    782:        return (1);
                    783: }
                    784: 
                    785: xnop(np)
                    786: NODE *np;
                    787: {
                    788:        return (1);
                    789: }
                    790: 
                    791: /*
                    792:  * Return true if the file is newer than
                    793:  * the given one.
                    794:  */
                    795: xnewer(np)
                    796: register NODE *np;
                    797: {
                    798:        return (sb.st_mtime > np->n_un.n_time);
                    799: }
                    800: 
                    801: /*
                    802:  * Do a numerical comparison on dates.
                    803:  */
                    804: ndays(np, t)
                    805: register NODE *np;
                    806: time_t t;
                    807: {
                    808:        register int days;
                    809: 
                    810:        days = (curtime-t+DAYSEC/2)/DAYSEC;
                    811:        return (ncomp(np, days));
                    812: }
                    813: 
                    814: /*
                    815:  * Numerical compare.
                    816:  */
                    817: ncomp(np, val)
                    818: register NODE *np;
                    819: register unsigned val;
                    820: {
                    821:        if (np->n_type == 0)
                    822:                return (np->n_un.n_val == val);
                    823:        if (np->n_type > 0)
                    824:                return (val > np->n_un.n_val);
                    825:        return (val < np->n_un.n_val);
                    826: }
                    827: 
                    828: /*
                    829:  * Errors
                    830:  */
                    831: /* VARARGS */
                    832: ferr(x)
                    833: {
                    834:        fprintf(stderr, "find: %r\n", &x);
                    835:        exit (1);
                    836: }
                    837: 
                    838: /* VARARGS */
                    839: fmsg(x)
                    840: {
                    841:        fprintf(stderr, "find: %r\n", &x);
                    842: }
                    843: 
                    844: usage()
                    845: {
                    846:        fprintf(stderr, "Usage: find directory ... [ expression ]\n");
                    847: }

unix.superglobalmegacorp.com

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