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

1.1     ! root        1: /*-
        !             2:  * Copyright (c) 1990 The Regents of the University of California.
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * This code is derived from software contributed to Berkeley by
        !             6:  * Cimarron D. Taylor of the University of California, Berkeley.
        !             7:  *
        !             8:  * Redistribution and use in source and binary forms are permitted provided
        !             9:  * that: (1) source distributions retain this entire copyright notice and
        !            10:  * comment, and (2) distributions including binaries display the following
        !            11:  * acknowledgement:  ``This product includes software developed by the
        !            12:  * University of California, Berkeley and its contributors'' in the
        !            13:  * documentation or other materials provided with the distribution and in
        !            14:  * all advertising materials mentioning features or use of this software.
        !            15:  * Neither the name of the University nor the names of its contributors may
        !            16:  * be used to endorse or promote products derived from this software without
        !            17:  * specific prior written permission.
        !            18:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
        !            19:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
        !            20:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !            21:  */
        !            22: 
        !            23: #ifndef lint
        !            24: static char sccsid[] = "@(#)function.c 5.8 (Berkeley) 6/30/90";
        !            25: #endif /* not lint */
        !            26: 
        !            27: #include <sys/types.h>
        !            28: #include <sys/stat.h>
        !            29: #include <sys/wait.h>
        !            30: #include <sys/mount.h>
        !            31: #include <grp.h>
        !            32: #include <pwd.h>
        !            33: #include <fts.h>
        !            34: #include <unistd.h>
        !            35: #include <tzfile.h>
        !            36: #include <stdio.h>
        !            37: #include <string.h>
        !            38: #include "find.h"
        !            39: 
        !            40: #define        FIND_EQUAL      0
        !            41: #define        FIND_LESSTHAN   1
        !            42: #define        FIND_GREATER    2
        !            43: 
        !            44: #define        COMPARE(a, b) { \
        !            45:        switch(plan->flags) { \
        !            46:        case FIND_EQUAL: \
        !            47:                return(a == b); \
        !            48:        case FIND_LESSTHAN: \
        !            49:                return(a < b); \
        !            50:        case FIND_GREATER: \
        !            51:                return(a > b); \
        !            52:        } \
        !            53:        return(0); \
        !            54: }
        !            55: 
        !            56: #define NEW(t, f) { \
        !            57:        new = (PLAN *)emalloc(sizeof(PLAN)); \
        !            58:        new->type = t; \
        !            59:        new->eval = f; \
        !            60:        new->flags = 0; \
        !            61:        new->next = NULL; \
        !            62: }
        !            63: 
        !            64: /*
        !            65:  * find_parsenum --
        !            66:  *     Parse a string of the form [+-]# and return the value.
        !            67:  */
        !            68: long
        !            69: find_parsenum(plan, option, str, endch)
        !            70:        PLAN *plan;
        !            71:        char *option, *str, *endch;
        !            72: {
        !            73:        long value;
        !            74:        char *endchar;          /* pointer to character ending conversion */
        !            75:     
        !            76:        /* determine comparison from leading + or - */
        !            77:        switch(*str) {
        !            78:        case '+':
        !            79:                ++str;
        !            80:                plan->flags = FIND_GREATER;
        !            81:                break;
        !            82:        case '-':
        !            83:                ++str;
        !            84:                plan->flags = FIND_LESSTHAN;
        !            85:                break;
        !            86:        default:
        !            87:                plan->flags = FIND_EQUAL;
        !            88:                break;
        !            89:        }
        !            90:     
        !            91:        /*
        !            92:         * convert the string with strtol().  Note, if strtol() returns zero
        !            93:         * and endchar points to the beginning of the string we know we have
        !            94:         * a syntax error.
        !            95:         */
        !            96:        value = strtol(str, &endchar, 10);
        !            97:        if (!value && endchar == str ||
        !            98:            endchar[0] && (!endch || endchar[0] != *endch))
        !            99:                bad_arg(option, "illegal numeric value");
        !           100:        if (endch)
        !           101:                *endch = endchar[0];
        !           102:        return(value);
        !           103: }
        !           104: 
        !           105: /*
        !           106:  * -atime n functions --
        !           107:  *
        !           108:  *     True if the difference between the file access time and the
        !           109:  *     current time is n 24 hour periods.
        !           110:  *
        !           111:  */
        !           112: f_atime(plan, entry)
        !           113:        PLAN *plan;
        !           114:        FTSENT *entry;
        !           115: {
        !           116:        extern time_t now;
        !           117: 
        !           118:        COMPARE((now - entry->fts_statb.st_atime +
        !           119:            SECSPERDAY - 1) / SECSPERDAY, plan->t_data);
        !           120: }
        !           121:  
        !           122: PLAN *
        !           123: c_atime(arg)
        !           124:        char *arg;
        !           125: {
        !           126:        PLAN *new;
        !           127: 
        !           128:        ftsoptions &= ~FTS_NOSTAT;
        !           129: 
        !           130:        NEW(T_ATIME, f_atime);
        !           131:        new->t_data = find_parsenum(new, "-atime", arg, (char *)NULL);
        !           132:        return(new);
        !           133: }
        !           134: /*
        !           135:  * -ctime n functions --
        !           136:  *
        !           137:  *     True if the difference between the last change of file
        !           138:  *     status information and the current time is n 24 hour periods.
        !           139:  */
        !           140: f_ctime(plan, entry)
        !           141:        PLAN *plan;
        !           142:        FTSENT *entry;
        !           143: {
        !           144:        extern time_t now;
        !           145: 
        !           146:        COMPARE((now - entry->fts_statb.st_ctime +
        !           147:            SECSPERDAY - 1) / SECSPERDAY, plan->t_data);
        !           148: }
        !           149:  
        !           150: PLAN *
        !           151: c_ctime(arg)
        !           152:        char *arg;
        !           153: {
        !           154:        PLAN *new;
        !           155: 
        !           156:        ftsoptions &= ~FTS_NOSTAT;
        !           157: 
        !           158:        NEW(T_CTIME, f_ctime);
        !           159:        new->t_data = find_parsenum(new, "-ctime", arg, (char *)NULL);
        !           160:        return(new);
        !           161: }
        !           162: 
        !           163: /*
        !           164:  * -depth functions --
        !           165:  *
        !           166:  *     Always true, causes descent of the directory hierarchy to be done
        !           167:  *     so that all entries in a directory are acted on before the directory
        !           168:  *     itself.
        !           169:  */
        !           170: /* ARGSUSED */
        !           171: f_always_true(plan, entry)
        !           172:        PLAN *plan;
        !           173:        FTSENT *entry;
        !           174: {
        !           175:        return(1);
        !           176: }
        !           177:  
        !           178: PLAN *
        !           179: c_depth()
        !           180: {
        !           181:        extern int depth;
        !           182:        PLAN *new;
        !           183:     
        !           184:        depth = 1;
        !           185: 
        !           186:        NEW(T_DEPTH, f_always_true);
        !           187:        return(new);
        !           188: }
        !           189:  
        !           190: /*
        !           191:  * [-exec | -ok] utility [arg ... ] ; functions --
        !           192:  *
        !           193:  *     True if the executed utility returns a zero value as exit status.
        !           194:  *     The end of the primary expression is delimited by a semicolon.  If
        !           195:  *     "{}" occurs anywhere, it gets replaced by the current pathname.
        !           196:  *     The current directory for the execution of utility is the same as
        !           197:  *     the current directory when the find utility was started.
        !           198:  *
        !           199:  *     The primary -ok is different in that it requests affirmation of the
        !           200:  *     user before executing the utility.
        !           201:  */
        !           202: f_exec(plan, entry)
        !           203:        register PLAN *plan;
        !           204:        FTSENT *entry;
        !           205: {
        !           206:        register int cnt;
        !           207:        char *find_subst();
        !           208:        union wait pstat;
        !           209:        pid_t pid, waitpid();
        !           210: 
        !           211:        for (cnt = 0; plan->e_argv[cnt]; ++cnt)
        !           212:                if (plan->e_len[cnt])
        !           213:                        find_subst(plan->e_orig[cnt], &plan->e_argv[cnt],
        !           214:                            entry->fts_path, plan->e_len[cnt]);
        !           215: 
        !           216:        if (plan->flags && !find_queryuser(plan->e_argv))
        !           217:                return(0);
        !           218: 
        !           219:        switch(pid = vfork()) {
        !           220:        case -1:
        !           221:                (void)fprintf(stderr, "find: fork: %s.\n", strerror(errno));
        !           222:                exit(1);
        !           223:                /* NOTREACHED */
        !           224:        case 0:
        !           225:                execvp(plan->e_argv[0], plan->e_argv);
        !           226:                (void)fprintf(stderr,
        !           227:                    "find: %s: %s.\n", plan->e_argv[0], strerror(errno));
        !           228:                exit(1);
        !           229:                /* NOTREACHED */
        !           230:        }
        !           231:        pid = waitpid(pid, &pstat, 0);
        !           232:        return(pid != -1 && !pstat.w_status);
        !           233: }
        !           234:  
        !           235: /*
        !           236:  * c_exec --
        !           237:  *     build three parallel arrays, one with pointers to the strings passed
        !           238:  *     on the command line, one with (possibly duplicated) pointers to the
        !           239:  *     argv array, and one with integer values that are lengths of the
        !           240:  *     strings, but also flags meaning that the string has to be massaged.
        !           241:  */
        !           242: PLAN *
        !           243: c_exec(argvp, isok)
        !           244:        char ***argvp;
        !           245:        int isok;
        !           246: {
        !           247:        PLAN *new;                      /* node returned */
        !           248:        register int cnt;
        !           249:        register char **argv, **ap, *p;
        !           250: 
        !           251:        ftsoptions |= FTS_NOCHDIR;
        !           252:        output_specified = 1;
        !           253:     
        !           254:        NEW(T_EXEC, f_exec);
        !           255:        new->flags = isok;
        !           256: 
        !           257:        for (ap = argv = *argvp;; ++ap) {
        !           258:                if (!*ap)
        !           259:                        bad_arg(isok ? "-ok" : "-exec", "no terminating \";\"");
        !           260:                if (**ap == ';')
        !           261:                        break;
        !           262:        }
        !           263: 
        !           264:        cnt = ap - *argvp + 1;
        !           265:        new->e_argv = (char **)emalloc((u_int)cnt * sizeof(char *));
        !           266:        new->e_orig = (char **)emalloc((u_int)cnt * sizeof(char *));
        !           267:        new->e_len = (int *)emalloc((u_int)cnt * sizeof(u_char));
        !           268: 
        !           269:        for (argv = *argvp, cnt = 0; argv < ap; ++argv, ++cnt) {
        !           270:                new->e_orig[cnt] = *argv;
        !           271:                for (p = *argv; *p; ++p)
        !           272:                        if (p[0] == '{' && p[1] == '}') {
        !           273:                                new->e_argv[cnt] = emalloc((u_int)1024);
        !           274:                                new->e_len[cnt] = 1024;
        !           275:                                break;
        !           276:                        }
        !           277:                if (!*p) {
        !           278:                        new->e_argv[cnt] = *argv;
        !           279:                        new->e_len[cnt] = 0;
        !           280:                }
        !           281:        }
        !           282:        new->e_argv[cnt] = new->e_orig[cnt] = NULL;
        !           283: 
        !           284:        *argvp = argv + 1;
        !           285:        return(new);
        !           286: }
        !           287:  
        !           288: /*
        !           289:  * -follow functions --
        !           290:  *
        !           291:  *     Always true, causes symbolic links to be followed on a global
        !           292:  *     basis.
        !           293:  */
        !           294: PLAN *
        !           295: c_follow()
        !           296: {
        !           297:        PLAN *new;
        !           298:     
        !           299:        ftsoptions &= ~FTS_PHYSICAL;
        !           300:        ftsoptions |= FTS_LOGICAL;
        !           301: 
        !           302:        NEW(T_FOLLOW, f_always_true);
        !           303:        return(new);
        !           304: }
        !           305:  
        !           306: /*
        !           307:  * -fstype functions --
        !           308:  *
        !           309:  *     True if the file is of a certain type.
        !           310:  */
        !           311: f_fstype(plan, entry)
        !           312:        PLAN *plan;
        !           313:        FTSENT *entry;
        !           314: {
        !           315:        static dev_t curdev;    /* need a guaranteed illegal dev value */
        !           316:        static int first = 1;
        !           317:        struct statfs sb;
        !           318:        static short val;
        !           319: 
        !           320:        /* only check when we cross mount point */
        !           321:        if (first || curdev != entry->fts_statb.st_dev) {
        !           322:                curdev = entry->fts_statb.st_dev;
        !           323:                if (statfs(entry->fts_accpath, &sb)) {
        !           324:                        (void)fprintf(stderr, "find: %s: %s.\n",
        !           325:                            entry->fts_accpath, strerror(errno));
        !           326:                        exit(1);
        !           327:                }
        !           328:                first = 0;
        !           329:                val = plan->flags == MOUNT_NONE ? sb.f_flags : sb.f_type;
        !           330:        }
        !           331:        return(plan->flags == MOUNT_NONE ?
        !           332:            val & MNT_LOCAL : val == plan->flags);
        !           333: }
        !           334:  
        !           335: PLAN *
        !           336: c_fstype(arg)
        !           337:        char *arg;
        !           338: {
        !           339:        register PLAN *new;
        !           340:     
        !           341:        ftsoptions &= ~FTS_NOSTAT;
        !           342:     
        !           343:        NEW(T_FSTYPE, f_fstype);
        !           344:        switch(*arg) {
        !           345:        case 'l':
        !           346:                if (!strcmp(arg, "local")) {
        !           347:                        new->flags = MOUNT_NONE;
        !           348:                        return(new);
        !           349:                }
        !           350:                break;
        !           351:        case 'm':
        !           352:                if (!strcmp(arg, "mfs")) {
        !           353:                        new->flags = MOUNT_MFS;
        !           354:                        return(new);
        !           355:                }
        !           356:                break;
        !           357:        case 'n':
        !           358:                if (!strcmp(arg, "nfs")) {
        !           359:                        new->flags = MOUNT_NFS;
        !           360:                        return(new);
        !           361:                }
        !           362:                break;
        !           363:        case 'p':
        !           364:                if (!strcmp(arg, "pc")) {
        !           365:                        new->flags = MOUNT_PC;
        !           366:                        return(new);
        !           367:                }
        !           368:                break;
        !           369:        case 'u':
        !           370:                if (!strcmp(arg, "ufs")) {
        !           371:                        new->flags = MOUNT_UFS;
        !           372:                        return(new);
        !           373:                }
        !           374:                break;
        !           375:        }
        !           376:        (void)fprintf(stderr, "find: unknown file type %s.\n", arg);
        !           377:        exit(1);
        !           378:        /* NOTREACHED */
        !           379: }
        !           380:  
        !           381: /*
        !           382:  * -group gname functions --
        !           383:  *
        !           384:  *     True if the file belongs to the group gname.  If gname is numeric and
        !           385:  *     an equivalent of the getgrnam() function does not return a valid group
        !           386:  *     name, gname is taken as a group ID.
        !           387:  */
        !           388: f_group(plan, entry)
        !           389:        PLAN *plan;
        !           390:        FTSENT *entry;
        !           391: {
        !           392:        return(entry->fts_statb.st_gid == plan->g_data);
        !           393: }
        !           394:  
        !           395: PLAN *
        !           396: c_group(gname)
        !           397:        char *gname;
        !           398: {
        !           399:        PLAN *new;
        !           400:        struct group *g;
        !           401:        gid_t gid;
        !           402:     
        !           403:        ftsoptions &= ~FTS_NOSTAT;
        !           404: 
        !           405:        g = getgrnam(gname);
        !           406:        if (g == NULL) {
        !           407:                gid = atoi(gname);
        !           408:                if (gid == 0 && gname[0] != '0')
        !           409:                        bad_arg("-group", "no such group");
        !           410:        } else
        !           411:                gid = g->gr_gid;
        !           412:     
        !           413:        NEW(T_GROUP, f_group);
        !           414:        new->g_data = gid;
        !           415:        return(new);
        !           416: }
        !           417: 
        !           418: /*
        !           419:  * -inum n functions --
        !           420:  *
        !           421:  *     True if the file has inode # n.
        !           422:  */
        !           423: f_inum(plan, entry)
        !           424:        PLAN *plan;
        !           425:        FTSENT *entry;
        !           426: {
        !           427:        COMPARE(entry->fts_statb.st_ino, plan->i_data);
        !           428: }
        !           429:  
        !           430: PLAN *
        !           431: c_inum(arg)
        !           432:        char *arg;
        !           433: {
        !           434:        PLAN *new;
        !           435:     
        !           436:        ftsoptions &= ~FTS_NOSTAT;
        !           437:     
        !           438:        NEW(T_INUM, f_inum);
        !           439:        new->i_data = find_parsenum(new, "-inum", arg, (char *)NULL);
        !           440:        return(new);
        !           441: }
        !           442:  
        !           443: /*
        !           444:  * -links n functions --
        !           445:  *
        !           446:  *     True if the file has n links.
        !           447:  */
        !           448: f_links(plan, entry)
        !           449:        PLAN *plan;
        !           450:        FTSENT *entry;
        !           451: {
        !           452:        COMPARE(entry->fts_statb.st_nlink, plan->l_data);
        !           453: }
        !           454:  
        !           455: PLAN *
        !           456: c_links(arg)
        !           457:        char *arg;
        !           458: {
        !           459:        PLAN *new;
        !           460:     
        !           461:        ftsoptions &= ~FTS_NOSTAT;
        !           462:     
        !           463:        NEW(T_LINKS, f_links);
        !           464:        new->l_data = find_parsenum(new, "-links", arg, (char *)NULL);
        !           465:        return(new);
        !           466: }
        !           467:  
        !           468: /*
        !           469:  * -ls functions --
        !           470:  *
        !           471:  *     Always true - prints the current entry to stdout in "ls" format.
        !           472:  */
        !           473: /* ARGSUSED */
        !           474: f_ls(plan, entry)
        !           475:        PLAN *plan;
        !           476:        FTSENT *entry;
        !           477: {
        !           478:        printlong(entry->fts_path, entry->fts_accpath, &entry->fts_statb);
        !           479:        return(1);
        !           480: }
        !           481:  
        !           482: PLAN *
        !           483: c_ls()
        !           484: {
        !           485:        PLAN *new;
        !           486:     
        !           487:        ftsoptions &= ~FTS_NOSTAT;
        !           488:        output_specified = 1;
        !           489:     
        !           490:        NEW(T_LS, f_ls);
        !           491:        return(new);
        !           492: }
        !           493: 
        !           494: /*
        !           495:  * -name functions --
        !           496:  *
        !           497:  *     True if the basename of the filename being examined
        !           498:  *     matches pattern using Pattern Matching Notation S3.14
        !           499:  */
        !           500: f_name(plan, entry)
        !           501:        PLAN *plan;
        !           502:        FTSENT *entry;
        !           503: {
        !           504:        return(fnmatch(plan->c_data, entry->fts_name, FNM_QUOTE));
        !           505: }
        !           506:  
        !           507: PLAN *
        !           508: c_name(pattern)
        !           509:        char *pattern;
        !           510: {
        !           511:        PLAN *new;
        !           512: 
        !           513:        NEW(T_NAME, f_name);
        !           514:        new->c_data = pattern;
        !           515:        return(new);
        !           516: }
        !           517:  
        !           518: /*
        !           519:  * -newer file functions --
        !           520:  *
        !           521:  *     True if the current file has been modified more recently
        !           522:  *     then the modification time of the file named by the pathname
        !           523:  *     file.
        !           524:  */
        !           525: f_newer(plan, entry)
        !           526:        PLAN *plan;
        !           527:        FTSENT *entry;
        !           528: {
        !           529:        return(entry->fts_statb.st_mtime > plan->t_data);
        !           530: }
        !           531:  
        !           532: PLAN *
        !           533: c_newer(filename)
        !           534:        char *filename;
        !           535: {
        !           536:        PLAN *new;
        !           537:        struct stat sb;
        !           538:     
        !           539:        ftsoptions &= ~FTS_NOSTAT;
        !           540: 
        !           541:        if (stat(filename, &sb)) {
        !           542:                (void)fprintf(stderr, "find: %s: %s.\n",
        !           543:                    filename, strerror(errno));
        !           544:                exit(1);
        !           545:        }
        !           546:        NEW(T_NEWER, f_newer);
        !           547:        new->t_data = sb.st_mtime;
        !           548:        return(new);
        !           549: }
        !           550:  
        !           551: /*
        !           552:  * -nogroup functions --
        !           553:  *
        !           554:  *     True if file belongs to a user ID for which the equivalent
        !           555:  *     of the getgrnam() 9.2.1 [POSIX.1] function returns NULL.
        !           556:  */
        !           557: /* ARGSUSED */
        !           558: f_nogroup(plan, entry)
        !           559:        PLAN *plan;
        !           560:        FTSENT *entry;
        !           561: {
        !           562:        return(group_from_gid(entry->fts_statb.st_gid, 1));
        !           563: }
        !           564:  
        !           565: PLAN *
        !           566: c_nogroup()
        !           567: {
        !           568:        PLAN *new;
        !           569:     
        !           570:        ftsoptions &= ~FTS_NOSTAT;
        !           571: 
        !           572:        NEW(T_NOGROUP, f_nogroup);
        !           573:        return(new);
        !           574: }
        !           575:  
        !           576: /*
        !           577:  * -nouser functions --
        !           578:  *
        !           579:  *     True if file belongs to a user ID for which the equivalent
        !           580:  *     of the getpwuid() 9.2.2 [POSIX.1] function returns NULL.
        !           581:  */
        !           582: /* ARGSUSED */
        !           583: f_nouser(plan, entry)
        !           584:        PLAN *plan;
        !           585:        FTSENT *entry;
        !           586: {
        !           587:        return(user_from_uid(entry->fts_statb.st_uid, 1));
        !           588: }
        !           589:  
        !           590: PLAN *
        !           591: c_nouser()
        !           592: {
        !           593:        PLAN *new;
        !           594:     
        !           595:        ftsoptions &= ~FTS_NOSTAT;
        !           596: 
        !           597:        NEW(T_NOUSER, f_nouser);
        !           598:        return(new);
        !           599: }
        !           600:  
        !           601: /*
        !           602:  * -perm functions --
        !           603:  *
        !           604:  *     The mode argument is used to represent file mode bits.  If it starts
        !           605:  *     with a leading digit, it's treated as an octal mode, otherwise as a
        !           606:  *     symbolic mode.
        !           607:  */
        !           608: f_perm(plan, entry)
        !           609:        PLAN *plan;
        !           610:        FTSENT *entry;
        !           611: {
        !           612:        mode_t mode;
        !           613: 
        !           614:        mode = entry->fts_statb.st_mode &
        !           615:            (S_ISUID|S_ISGID|S_ISTXT|S_IRWXU|S_IRWXG|S_IRWXO);
        !           616:        if (plan->flags)
        !           617:                return((plan->m_data | mode) == mode);
        !           618:        else
        !           619:                return(mode == plan->m_data);
        !           620:        /* NOTREACHED */
        !           621: }
        !           622:  
        !           623: PLAN *
        !           624: c_perm(perm)
        !           625:        char *perm;
        !           626: {
        !           627:        PLAN *new;
        !           628:        mode_t *set, *setmode();
        !           629: 
        !           630:        ftsoptions &= ~FTS_NOSTAT;
        !           631: 
        !           632:        NEW(T_PERM, f_perm);
        !           633: 
        !           634:        if (*perm == '-') {
        !           635:                new->flags = 1;
        !           636:                ++perm;
        !           637:        }
        !           638: 
        !           639:        if ((set = setmode(perm)) == NULL)
        !           640:                bad_arg("-perm", "illegal mode string");
        !           641: 
        !           642:        new->m_data = getmode(set, 0);
        !           643:        return(new);
        !           644: }
        !           645:  
        !           646: /*
        !           647:  * -print functions --
        !           648:  *
        !           649:  *     Always true, causes the current pathame to be written to
        !           650:  *     standard output.
        !           651:  */
        !           652: /* ARGSUSED */
        !           653: f_print(plan, entry)
        !           654:        PLAN *plan;
        !           655:        FTSENT *entry;
        !           656: {
        !           657:        (void)printf("%s\n", entry->fts_path);
        !           658:        return(1);
        !           659: }
        !           660:  
        !           661: PLAN *
        !           662: c_print()
        !           663: {
        !           664:        PLAN *new;
        !           665:     
        !           666:        output_specified = 1;
        !           667: 
        !           668:        NEW(T_PRINT, f_print);
        !           669:        return(new);
        !           670: }
        !           671:  
        !           672: /*
        !           673:  * -prune functions --
        !           674:  *
        !           675:  *     Prune a portion of the hierarchy.
        !           676:  */
        !           677: /* ARGSUSED */
        !           678: f_prune(plan, entry)
        !           679:        PLAN *plan;
        !           680:        FTSENT *entry;
        !           681: {
        !           682:        extern FTS *tree;
        !           683: 
        !           684:        if (ftsset(tree, entry, FTS_SKIP)) {
        !           685:                (void)fprintf(stderr,
        !           686:                    "find: %s: %s.\n", entry->fts_path, strerror(errno));
        !           687:                exit(1);
        !           688:        }
        !           689:        return(1);
        !           690: }
        !           691:  
        !           692: PLAN *
        !           693: c_prune()
        !           694: {
        !           695:        PLAN *new;
        !           696: 
        !           697:        NEW(T_PRUNE, f_prune);
        !           698:        return(new);
        !           699: }
        !           700:  
        !           701: /*
        !           702:  * -size n[c] functions --
        !           703:  *
        !           704:  *     True if the file size in bytes, divided by an implementation defined
        !           705:  *     value and rounded up to the next integer, is n.  If n is followed by
        !           706:  *     a c, the size is in bytes.
        !           707:  */
        !           708: #define        FIND_SIZE       512
        !           709: static int divsize = 1;
        !           710: 
        !           711: f_size(plan, entry)
        !           712:        PLAN *plan;
        !           713:        FTSENT *entry;
        !           714: {
        !           715:        off_t size;
        !           716: 
        !           717:        size = divsize ? (entry->fts_statb.st_size + FIND_SIZE - 1) /
        !           718:            FIND_SIZE : entry->fts_statb.st_size;
        !           719:        COMPARE(size, plan->o_data);
        !           720: }
        !           721:  
        !           722: PLAN *
        !           723: c_size(arg)
        !           724:        char *arg;
        !           725: {
        !           726:        PLAN *new;
        !           727:        char endch;
        !           728:     
        !           729:        ftsoptions &= ~FTS_NOSTAT;
        !           730: 
        !           731:        NEW(T_SIZE, f_size);
        !           732:        new->o_data = find_parsenum(new, "-size", arg, &endch);
        !           733:        if (endch == 'c')
        !           734:                divsize = 0;
        !           735:        return(new);
        !           736: }
        !           737:  
        !           738: /*
        !           739:  * -type c functions --
        !           740:  *
        !           741:  *     True if the type of the file is c, where c is b, c, d, p, or f for
        !           742:  *     block special file, character special file, directory, FIFO, or
        !           743:  *     regular file, respectively.
        !           744:  */
        !           745: f_type(plan, entry)
        !           746:        PLAN *plan;
        !           747:        FTSENT *entry;
        !           748: {
        !           749:        return((entry->fts_statb.st_mode & S_IFMT) == plan->m_data);
        !           750: }
        !           751:  
        !           752: PLAN *
        !           753: c_type(typestring)
        !           754:        char *typestring;
        !           755: {
        !           756:        PLAN *new;
        !           757:        mode_t  mask;
        !           758:     
        !           759:        ftsoptions &= ~FTS_NOSTAT;
        !           760: 
        !           761:        switch (typestring[0]) {
        !           762:        case 'b':
        !           763:                mask = S_IFBLK;
        !           764:                break;
        !           765:        case 'c':
        !           766:                mask = S_IFCHR;
        !           767:                break;
        !           768:        case 'd':
        !           769:                mask = S_IFDIR;
        !           770:                break;
        !           771:        case 'f':
        !           772:                mask = S_IFREG;
        !           773:                break;
        !           774:        case 'l':
        !           775:                mask = S_IFLNK;
        !           776:                break;
        !           777:        case 'p':
        !           778:                mask = S_IFIFO;
        !           779:                break;
        !           780:        case 's':
        !           781:                mask = S_IFSOCK;
        !           782:                break;
        !           783:        default:
        !           784:                bad_arg("-type", "unknown type");
        !           785:        }
        !           786:     
        !           787:        NEW(T_TYPE, f_type);
        !           788:        new->m_data = mask;
        !           789:        return(new);
        !           790: }
        !           791:  
        !           792: /*
        !           793:  * -user uname functions --
        !           794:  *
        !           795:  *     True if the file belongs to the user uname.  If uname is numeric and
        !           796:  *     an equivalent of the getpwnam() S9.2.2 [POSIX.1] function does not
        !           797:  *     return a valid user name, uname is taken as a user ID.
        !           798:  */
        !           799: f_user(plan, entry)
        !           800:        PLAN *plan;
        !           801:        FTSENT *entry;
        !           802: {
        !           803:        return(entry->fts_statb.st_uid == plan->u_data);
        !           804: }
        !           805:  
        !           806: PLAN *
        !           807: c_user(username)
        !           808:        char *username;
        !           809: {
        !           810:        PLAN *new;
        !           811:        struct passwd *p;
        !           812:        uid_t uid;
        !           813:     
        !           814:        ftsoptions &= ~FTS_NOSTAT;
        !           815: 
        !           816:        p = getpwnam(username);
        !           817:        if (p == NULL) {
        !           818:                uid = atoi(username);
        !           819:                if (uid == 0 && username[0] != '0')
        !           820:                        bad_arg("-user", "no such user");
        !           821:        } else
        !           822:                uid = p->pw_uid;
        !           823: 
        !           824:        NEW(T_USER, f_user);
        !           825:        new->u_data = uid;
        !           826:        return(new);
        !           827: }
        !           828:  
        !           829: /*
        !           830:  * -xdev functions --
        !           831:  *
        !           832:  *     Always true, causes find not to decend past directories that have a
        !           833:  *     different device ID (st_dev, see stat() S5.6.2 [POSIX.1])
        !           834:  */
        !           835: PLAN *
        !           836: c_xdev()
        !           837: {
        !           838:        PLAN *new;
        !           839:     
        !           840:        ftsoptions &= ~FTS_NOSTAT;
        !           841:        ftsoptions |= FTS_XDEV;
        !           842: 
        !           843:        NEW(T_XDEV, f_always_true);
        !           844:        return(new);
        !           845: }
        !           846: 
        !           847: /*
        !           848:  * ( expression ) functions --
        !           849:  *
        !           850:  *     True if expression is true.
        !           851:  */
        !           852: f_expr(plan, entry)
        !           853:        PLAN *plan;
        !           854:        FTSENT *entry;
        !           855: {
        !           856:        register PLAN *p;
        !           857:        register int state;
        !           858: 
        !           859:        for (p = plan->p_data[0];
        !           860:            p && (state = (p->eval)(p, entry)); p = p->next);
        !           861:        return(state);
        !           862: }
        !           863:  
        !           864: /*
        !           865:  * T_OPENPAREN and T_CLOSEPAREN nodes are temporary place markers.  They are
        !           866:  * eliminated during phase 2 of find_formplan() --- the '(' node is converted
        !           867:  * to a T_EXPR node containing the expression and the ')' node is discarded.
        !           868:  */
        !           869: PLAN *
        !           870: c_openparen()
        !           871: {
        !           872:        PLAN *new;
        !           873: 
        !           874:        NEW(T_OPENPAREN, (int (*)())-1);
        !           875:        return(new);
        !           876: }
        !           877:  
        !           878: PLAN *
        !           879: c_closeparen()
        !           880: {
        !           881:        PLAN *new;
        !           882: 
        !           883:        NEW(T_CLOSEPAREN, (int (*)())-1);
        !           884:        return(new);
        !           885: }
        !           886:  
        !           887: /*
        !           888:  * -mtime n functions --
        !           889:  *
        !           890:  *     True if the difference between the file modification time and the
        !           891:  *     current time is n 24 hour periods.
        !           892:  */
        !           893: f_mtime(plan, entry)
        !           894:        PLAN *plan;
        !           895:        FTSENT *entry;
        !           896: {
        !           897:        extern time_t now;
        !           898: 
        !           899:        COMPARE((now - entry->fts_statb.st_mtime + SECSPERDAY - 1) /
        !           900:            SECSPERDAY, plan->t_data);
        !           901: }
        !           902:  
        !           903: PLAN *
        !           904: c_mtime(arg)
        !           905:        char *arg;
        !           906: {
        !           907:        PLAN *new;
        !           908: 
        !           909:        ftsoptions &= ~FTS_NOSTAT;
        !           910: 
        !           911:        NEW(T_MTIME, f_mtime);
        !           912:        new->t_data = find_parsenum(new, "-mtime", arg, (char *)NULL);
        !           913:        return(new);
        !           914: }
        !           915: 
        !           916: /*
        !           917:  * ! expression functions --
        !           918:  *
        !           919:  *     Negation of a primary; the unary NOT operator.
        !           920:  */
        !           921: f_not(plan, entry)
        !           922:        PLAN *plan;
        !           923:        FTSENT *entry;
        !           924: {
        !           925:        register PLAN *p;
        !           926:        register int state;
        !           927: 
        !           928:        for (p = plan->p_data[0];
        !           929:            p && (state = (p->eval)(p, entry)); p = p->next);
        !           930:        return(!state);
        !           931: }
        !           932:  
        !           933: PLAN *
        !           934: c_not()
        !           935: {
        !           936:        PLAN *new;
        !           937: 
        !           938:        NEW(T_NOT, f_not);
        !           939:        return(new);
        !           940: }
        !           941:  
        !           942: /*
        !           943:  * expression -o expression functions --
        !           944:  *
        !           945:  *     Alternation of primaries; the OR operator.  The second expression is
        !           946:  * not evaluated if the first expression is true.
        !           947:  */
        !           948: f_or(plan, entry)
        !           949:        PLAN *plan;
        !           950:        FTSENT *entry;
        !           951: {
        !           952:        register PLAN *p;
        !           953:        register int state;
        !           954: 
        !           955:        for (p = plan->p_data[0];
        !           956:            p && (state = (p->eval)(p, entry)); p = p->next);
        !           957: 
        !           958:        if (state)
        !           959:                return(1);
        !           960: 
        !           961:        for (p = plan->p_data[1];
        !           962:            p && (state = (p->eval)(p, entry)); p = p->next);
        !           963:        return(state);
        !           964: }
        !           965: 
        !           966: PLAN *
        !           967: c_or()
        !           968: {
        !           969:        PLAN *new;
        !           970: 
        !           971:        NEW(T_OR, f_or);
        !           972:        return(new);
        !           973: }

unix.superglobalmegacorp.com

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