find.c revision 1.2 1 /*-
2 * Copyright (c) 1991 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, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37 #ifndef lint
38 /*static char sccsid[] = "from: @(#)find.c 5.3 (Berkeley) 5/25/91";*/
39 static char rcsid[] = "$Id: find.c,v 1.2 1993/08/01 18:16:16 mycroft Exp $";
40 #endif /* not lint */
41
42 #include <sys/types.h>
43 #include <sys/stat.h>
44 #include <sys/errno.h>
45 #include <fts.h>
46 #include <stdio.h>
47 #include <string.h>
48 #include <stdlib.h>
49 #include "find.h"
50
51 /*
52 * find_formplan --
53 * process the command line and create a "plan" corresponding to the
54 * command arguments.
55 */
56 PLAN *
57 find_formplan(argv)
58 char **argv;
59 {
60 PLAN *plan, *tail, *new;
61 PLAN *c_print(), *find_create(), *not_squish(), *or_squish();
62 PLAN *paren_squish();
63
64 /*
65 * for each argument in the command line, determine what kind of node
66 * it is, create the appropriate node type and add the new plan node
67 * to the end of the existing plan. The resulting plan is a linked
68 * list of plan nodes. For example, the string:
69 *
70 * % find . -name foo -newer bar -print
71 *
72 * results in the plan:
73 *
74 * [-name foo]--> [-newer bar]--> [-print]
75 *
76 * in this diagram, `[-name foo]' represents the plan node generated
77 * by c_name() with an argument of foo and `-->' represents the
78 * plan->next pointer.
79 */
80 for (plan = NULL; *argv;) {
81 if (!(new = find_create(&argv)))
82 continue;
83 if (plan == NULL)
84 tail = plan = new;
85 else {
86 tail->next = new;
87 tail = new;
88 }
89 }
90
91 /*
92 * if the user didn't specify one of -print, -ok or -exec, then -print
93 * is assumed so we add a -print node on the end. It is possible that
94 * the user might want the -print someplace else on the command line,
95 * but there's no way to know that.
96 */
97 if (!isoutput) {
98 new = c_print();
99 if (plan == NULL)
100 tail = plan = new;
101 else {
102 tail->next = new;
103 tail = new;
104 }
105 }
106
107 /*
108 * the command line has been completely processed into a search plan
109 * except for the (, ), !, and -o operators. Rearrange the plan so
110 * that the portions of the plan which are affected by the operators
111 * are moved into operator nodes themselves. For example:
112 *
113 * [!]--> [-name foo]--> [-print]
114 *
115 * becomes
116 *
117 * [! [-name foo] ]--> [-print]
118 *
119 * and
120 *
121 * [(]--> [-depth]--> [-name foo]--> [)]--> [-print]
122 *
123 * becomes
124 *
125 * [expr [-depth]-->[-name foo] ]--> [-print]
126 *
127 * operators are handled in order of precedence.
128 */
129
130 plan = paren_squish(plan); /* ()'s */
131 plan = not_squish(plan); /* !'s */
132 plan = or_squish(plan); /* -o's */
133 return(plan);
134 }
135
136 FTS *tree; /* pointer to top of FTS hierarchy */
137
138 /*
139 * find_execute --
140 * take a search plan and an array of search paths and executes the plan
141 * over all FTSENT's returned for the given search paths.
142 */
143 void
144 find_execute(plan, paths)
145 PLAN *plan; /* search plan */
146 char **paths; /* array of pathnames to traverse */
147 {
148 register FTSENT *entry;
149 PLAN *p;
150
151 if (!(tree = fts_open(paths, ftsoptions, (int (*)())NULL)))
152 err("ftsopen: %s", strerror(errno));
153
154 while (entry = fts_read(tree)) {
155 switch(entry->fts_info) {
156 case FTS_D:
157 if (isdepth)
158 continue;
159 break;
160 case FTS_DP:
161 if (!isdepth)
162 continue;
163 break;
164 case FTS_DNR:
165 case FTS_ERR:
166 case FTS_NS:
167 (void)fprintf(stderr, "find: %s: %s\n",
168 entry->fts_path, strerror(errno));
169 continue;
170 case FTS_SL:
171 if (entry->fts_level == FTS_ROOTLEVEL) {
172 (void)fts_set(tree, entry, FTS_FOLLOW);
173 continue;
174 }
175 break;
176 }
177
178 #define BADCH " \t\n\\'\""
179 if (isxargs && strpbrk(entry->fts_path, BADCH)) {
180 (void)fprintf(stderr,
181 "find: illegal path: %s\n", entry->fts_path);
182 continue;
183 }
184
185 /*
186 * call all the functions in the execution plan until one is
187 * false or all have been executed. This is where we do all
188 * the work specified by the user on the command line.
189 */
190 for (p = plan; p && (p->eval)(p, entry); p = p->next);
191 }
192 (void)fts_close(tree);
193 }
194