|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.