Annotation of 43BSDReno/usr.bin/find/find.c, revision 1.1.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: char copyright[] =
                     25: "@(#) Copyright (c) 1990 The Regents of the University of California.\n\
                     26:  All rights reserved.\n";
                     27: #endif /* not lint */
                     28: 
                     29: #ifndef lint
                     30: static char sccsid[] = "@(#)find.c     4.32 (Berkeley) 7/1/90";
                     31: #endif /* not lint */
                     32: 
                     33: #include <sys/types.h>
                     34: #include <sys/stat.h>
                     35: #include <fts.h>
                     36: #include <stdio.h>
                     37: #include <string.h>
                     38: #include <errno.h>
                     39: #include "find.h"
                     40: 
                     41: FTS *tree;                     /* pointer to top of FTS hierarchy */
                     42: time_t now;                    /* time find was run */
                     43: int ftsoptions;                        /* options passed to ftsopen() */
                     44: int deprecated;                        /* old or new syntax */
                     45: int depth;                     /* set by -depth option */
                     46: int output_specified;          /* one of -print, -ok or -exec was specified */
                     47: 
                     48: main(argc, argv)
                     49:        int argc;
                     50:        char **argv;
                     51: {
                     52:        PLAN *plan;
                     53:        char **p, **paths;
                     54:        PLAN *find_formplan();
                     55:        time_t time();
                     56:     
                     57:        (void)time(&now);                       /* initialize the time-of-day */
                     58: 
                     59:        if (argc < 2)
                     60:                usage();
                     61: 
                     62:        paths = argv;
                     63:        ftsoptions = FTS_NOSTAT|FTS_PHYSICAL;
                     64: 
                     65:        /*
                     66:         * if arguments start with an option, treat it like new syntax;
                     67:         * otherwise, if has a "-option" anywhere (which isn't an argument
                     68:         * to another command) treat it as old syntax.
                     69:         */
                     70:        if (argv[1][0] != '-')
                     71:                for (p = argv + 1; *p; ++p) {
                     72:                        if (!strcmp(*p, "exec") || !strcmp(*p, "ok")) {
                     73:                                while (p[1] && strcmp(*++p, ";"));
                     74:                                continue;
                     75:                        }
                     76:                        if (**p == '-') {
                     77:                                deprecated = 1;
                     78:                                oldsyntax(&argv);
                     79:                                break;
                     80:                        }
                     81:                }
                     82:        if (!deprecated)
                     83:                newsyntax(argc, &argv);
                     84:     
                     85:        plan = find_formplan(argv);             /* execution plan */
                     86:        find_execute(plan, paths);
                     87: }
                     88: 
                     89: /*
                     90:  * find_formplan --
                     91:  *     process the command line and create a "plan" corresponding to the
                     92:  *     command arguments.
                     93:  */
                     94: PLAN *
                     95: find_formplan(argv)
                     96:        char **argv;
                     97: {
                     98:        PLAN *plan, *tail, *new;
                     99:        PLAN *c_print(), *find_create(), *find_squish_not(), *find_squish_or();
                    100:        PLAN *find_squish_paren();
                    101: 
                    102:        /*
                    103:         * for each argument in the command line, determine what kind of node
                    104:         * it is, create the appropriate node type and add the new plan node
                    105:         * to the end of the existing plan.  The resulting plan is a linked
                    106:         * list of plan nodes.  For example, the string:
                    107:         *
                    108:         *      % find . -name foo -newer bar -print
                    109:         *
                    110:         * results in the plan:
                    111:         *
                    112:         *      [-name foo]--> [-newer bar]--> [-print]
                    113:         *
                    114:         * in this diagram, `[-name foo]' represents the plan node generated
                    115:         * by c_name() with an argument of foo and `-->' represents the
                    116:         * plan->next pointer.
                    117:         */
                    118:        for (plan = NULL; *argv;) {
                    119:                if (!(new = find_create(&argv)))
                    120:                        continue;
                    121:                if (plan == NULL)
                    122:                        tail = plan = new;
                    123:                else {
                    124:                        tail->next = new;
                    125:                        tail = new;
                    126:                }
                    127:        }
                    128:     
                    129:        /*
                    130:         * if the user didn't specify one of -print, -ok or -exec, then -print
                    131:         * is assumed so we add a -print node on the end.  It is possible that
                    132:         * the user might want the -print someplace else on the command line,
                    133:         * but there's no way to know that.
                    134:         */
                    135:        if (!output_specified) {
                    136:                new = c_print();
                    137:                if (plan == NULL)
                    138:                        tail = plan = new;
                    139:                else {
                    140:                        tail->next = new;
                    141:                        tail = new;
                    142:                }
                    143:        }
                    144:     
                    145:        /*
                    146:         * the command line has been completely processed into a search plan
                    147:         * except for the (, ), !, and -o operators.  Rearrange the plan so
                    148:         * that the portions of the plan which are affected by the operators
                    149:         * are moved into operator nodes themselves.  For example:
                    150:         *
                    151:         *      [!]--> [-name foo]--> [-print]
                    152:         *
                    153:         * becomes
                    154:         *
                    155:         *      [! [-name foo] ]--> [-print]
                    156:         *
                    157:         * and
                    158:         *
                    159:         *      [(]--> [-depth]--> [-name foo]--> [)]--> [-print]
                    160:         *
                    161:         * becomes
                    162:         *
                    163:         *      [expr [-depth]-->[-name foo] ]--> [-print]
                    164:         *
                    165:         * operators are handled in order of precedence.
                    166:         */
                    167: 
                    168:        plan = find_squish_paren(plan);         /* ()'s */
                    169:        plan = find_squish_not(plan);           /* !'s */
                    170:        plan = find_squish_or(plan);            /* -o's */
                    171:        return(plan);
                    172: }
                    173:  
                    174: /*
                    175:  * find_execute --
                    176:  *     take a search plan and an array of search paths and executes the plan
                    177:  *     over all FTSENT's returned for the given search paths.
                    178:  */
                    179: find_execute(plan, paths)
                    180:        PLAN *plan;             /* search plan */
                    181:        char **paths;           /* array of pathnames to traverse */
                    182: {
                    183:        FTSENT *entry;          /* current fts entry */
                    184:        PLAN *p;
                    185:     
                    186:        if (!(tree = ftsopen(paths, ftsoptions, NULL))) {
                    187:                (void)fprintf(stderr, "find: ftsopen: %s.\n", strerror(errno));
                    188:                exit(1);
                    189:        }
                    190:        while (entry = ftsread(tree)) {
                    191:                switch(entry->fts_info) {
                    192:                case FTS_DNR:
                    193:                        (void)fprintf(stderr,
                    194:                            "find: %s: unable to read.\n", entry->fts_path);
                    195:                        continue;
                    196:                case FTS_DNX:
                    197:                        (void)fprintf(stderr,
                    198:                            "find: %s: unable to search.\n", entry->fts_path);
                    199:                        continue;
                    200:                case FTS_ERR:
                    201:                        (void)fprintf(stderr,
                    202:                            "find: %s: %s.\n", entry->fts_path,
                    203:                            strerror(errno));
                    204:                        continue;
                    205:                case FTS_D:
                    206:                        if (depth)
                    207:                                continue;
                    208:                        break;
                    209:                case FTS_DC:
                    210:                        (void)fprintf(stderr,
                    211:                            "find: directory cycle: %s.\n", entry->fts_path);
                    212:                        continue;
                    213:                case FTS_DP:
                    214:                        if (!depth)
                    215:                                continue;
                    216:                case FTS_NS:
                    217:                        if (!(ftsoptions & FTS_NOSTAT)) {
                    218:                                (void)fprintf(stderr,
                    219:                                    "find: can't stat: %s.\n", entry->fts_path);
                    220:                                continue;
                    221:                        }
                    222:                        break;
                    223:                }
                    224: 
                    225:                /*
                    226:                 * call all the functions in the execution plan until one is
                    227:                 * false or all have been executed.  This is where we do all
                    228:                 * the work specified by the user on the command line.
                    229:                 */
                    230:                for (p = plan; p && (p->eval)(p, entry); p = p->next);
                    231:        }
                    232:        (void)ftsclose(tree);
                    233: }

unix.superglobalmegacorp.com

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