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