Mercurial > hg > toybox
annotate toys/pending/find.c @ 978:6d3c39cb8a9d
Cleanup renice and implement '|' (required option) in argument parsing.
author | Rob Landley <rob@landley.net> |
---|---|
date | Wed, 31 Jul 2013 03:24:58 -0500 |
parents | b042cd34e564 |
children | c99c215b4604 |
rev | line source |
---|---|
814 | 1 /* vi: set sw=4 ts=4: |
2 * | |
3 * find.c - find files matching a criteria | |
4 * | |
5 * Copyright 2012 Tim Bird <tbird20d@gmail.com> | |
6 * | |
7 * See http://opengroup.org/onlinepubs/9699919799/utilities/find.html | |
8 | |
815
0c5b15cf4911
A couple quick fixes to find so I can try it out.
Rob Landley <rob@landley.net>
parents:
814
diff
changeset
|
9 USE_FIND(NEWTOY(find, "?", TOYFLAG_USR|TOYFLAG_BIN)) |
814 | 10 |
11 config FIND | |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
12 bool "find" |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
13 default n |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
14 help |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
15 usage: find [<dir>] [<options] |
814 | 16 |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
17 -name <pattern> match pattern |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
18 -type [fcdl] match file type |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
19 !, -a, -o not, and , or |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
20 (, ) group expressions |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
21 -mtime [-+]n match file modification time (to within 24 hours) |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
22 \t\t +=greater (older) than, -=less (younger) than |
814 | 23 */ |
24 | |
25 /* To Do: | |
26 * -exec action | |
27 */ | |
28 | |
849 | 29 #define FOR_find |
814 | 30 #include "toys.h" |
31 | |
32 struct filter_node { | |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
33 struct filter_node *next; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
34 int op; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
35 union { |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
36 char *name_regex; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
37 struct { |
887 | 38 int sign; |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
39 time_t time; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
40 } t; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
41 mode_t type; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
42 struct { |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
43 int arg_path_index; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
44 char **exec_args; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
45 } e; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
46 } data; |
814 | 47 }; |
48 | |
874 | 49 GLOBALS( |
50 char *dir; | |
51 struct filter_node *filter_root; | |
887 | 52 time_t itime; |
874 | 53 ) |
54 | |
814 | 55 /* filter operation types */ |
56 #define OP_UNKNOWN 0 | |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
57 #define OP_OR 2 |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
58 #define OP_AND 3 |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
59 #define OP_NOT 4 |
814 | 60 |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
61 #define LPAREN 1 |
814 | 62 #define RPAREN 5 |
63 | |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
64 #define MAX_OP 5 |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
65 |
814 | 66 #define CHECK_NAME 7 |
67 #define CHECK_MTIME 8 | |
68 #define CHECK_TYPE 9 | |
69 | |
70 #define ACTION_PRINT 20 | |
71 #define ACTION_PRINT0 21 | |
72 #define ACTION_EXEC 22 | |
73 | |
874 | 74 #define IS_ACTION(x) (x >= 20) |
75 | |
814 | 76 /* executes the command for a filter node |
875 | 77 returns 0 for failure or 1 for success |
814 | 78 */ |
847
2506cbdccd20
Partial cleanup of find
Felix Janda <felix.janda@posteo.de>
parents:
816
diff
changeset
|
79 static int do_exec(struct filter_node *filter, struct dirtree *node) |
814 | 80 { |
849 | 81 char *path = NULL; |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
82 char **arg_array; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
83 pid_t pid; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
84 int status; |
814 | 85 |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
86 arg_array = filter->data.e.exec_args; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
87 if (filter->data.e.arg_path_index) { |
875 | 88 int plen; |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
89 path = dirtree_path(node, &plen); |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
90 arg_array[filter->data.e.arg_path_index] = path; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
91 } |
816
3a7defbc671e
Remove more debug code from find.
Rob Landley <rob@landley.net>
parents:
815
diff
changeset
|
92 |
849 | 93 if (!(pid = fork())) xexec(arg_array); |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
94 free(path); |
849 | 95 waitpid(pid, &status, 0); |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
96 |
875 | 97 return !WEXITSTATUS(status); |
814 | 98 } |
99 | |
100 /* prefix evaluator */ | |
847
2506cbdccd20
Partial cleanup of find
Felix Janda <felix.janda@posteo.de>
parents:
816
diff
changeset
|
101 /* returns 0 for failure or 1 for success */ |
2506cbdccd20
Partial cleanup of find
Felix Janda <felix.janda@posteo.de>
parents:
816
diff
changeset
|
102 static int evaluate(struct filter_node *filter, struct dirtree *node, |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
103 struct filter_node **fnext) |
814 | 104 { |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
105 int result; |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
106 int op; |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
107 static int skip = 0; |
814 | 108 |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
109 /* if no filters, success */ |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
110 if (!filter) { |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
111 *fnext = NULL; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
112 return 1; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
113 } |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
114 op = filter->op; |
814 | 115 |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
116 if (op==OP_NOT) return !evaluate(filter->next, node, fnext); |
849 | 117 |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
118 if (op==OP_OR || op==OP_AND) { |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
119 result = evaluate(filter->next, node, fnext); |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
120 if(!skip) { |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
121 if (op==OP_OR) { |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
122 skip = result; |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
123 result = evaluate(*fnext, node, fnext) || result; |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
124 } else { |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
125 skip = !result; |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
126 result = evaluate(*fnext, node, fnext) && result; |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
127 } |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
128 skip = 0; |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
129 } |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
130 else result = evaluate(*fnext, node, fnext); |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
131 return result; |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
132 } |
849 | 133 |
134 // we're down to single operations, mark our position | |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
135 *fnext = filter->next; |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
136 if(skip) return 0; |
849 | 137 |
138 // TODO: Do a regex comparison | |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
139 if (op==CHECK_NAME) |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
140 return !strcmp(filter->data.name_regex, node->name); |
849 | 141 |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
142 if (op==CHECK_MTIME) { |
887 | 143 long delta = (long)(((double)TT.itime - node->st.st_mtime) / 86400) |
144 -filter->data.t.time; | |
145 return filter->data.t.sign == (delta > 0) - (delta < 0); | |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
146 } |
875 | 147 if (op==CHECK_TYPE) return (node->st.st_mode & S_IFMT) == filter->data.type; |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
148 |
814 | 149 |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
150 if (op==ACTION_PRINT || op==ACTION_PRINT0) { |
875 | 151 char *path; |
152 int plen = 0; | |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
153 char terminator = (op==ACTION_PRINT)*'\n'; |
849 | 154 |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
155 path = dirtree_path(node, &plen); |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
156 printf("%s%c", path, terminator); |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
157 free(path); |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
158 return 1; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
159 } |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
160 |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
161 if (op==ACTION_EXEC) return !do_exec(filter, node); |
849 | 162 |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
163 error_msg("Ran out of operations in filter list!"); |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
164 return 1; |
814 | 165 } |
166 | |
847
2506cbdccd20
Partial cleanup of find
Felix Janda <felix.janda@posteo.de>
parents:
816
diff
changeset
|
167 static int check_node_callback(struct dirtree *node) |
814 | 168 { |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
169 struct filter_node *junk; |
814 | 170 |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
171 /* only recurse on "." at the root */ |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
172 /* so, don't recurse on 1) non-root "." and 2) any ".." */ |
816
3a7defbc671e
Remove more debug code from find.
Rob Landley <rob@landley.net>
parents:
815
diff
changeset
|
173 |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
174 if (node->name[0] == '.' && |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
175 ((!node->name[1] && node->parent) || |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
176 (node->name[1]=='.' && !node->name[2]))) |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
177 return 0; |
814 | 178 |
875 | 179 evaluate(TT.filter_root, node, &junk); |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
180 return DIRTREE_RECURSE; |
814 | 181 } |
182 | |
183 | |
847
2506cbdccd20
Partial cleanup of find
Felix Janda <felix.janda@posteo.de>
parents:
816
diff
changeset
|
184 static void build_filter_list(void) |
814 | 185 { |
849 | 186 struct filter_node *node_list, *op_stack, *node, *op_node, *next; |
874 | 187 char **arg; |
188 int j; | |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
189 int prevop = 0; |
875 | 190 int have_action = 0; |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
191 |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
192 /* part optargs here and build a filter list in prefix format */ |
814 | 193 |
849 | 194 TT.dir = "."; |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
195 node_list = NULL; |
874 | 196 for (arg = toys.optargs; *arg; arg++) { |
197 struct { | |
198 char *arg; | |
199 int op; | |
200 int extrarg; | |
201 } arg_map[] = {{"-o", OP_OR, 0}, | |
202 {"-a", OP_AND, 0}, | |
203 {"!", OP_NOT, 0}, | |
204 {"(", LPAREN, 0}, | |
205 {")", RPAREN, 0}, | |
206 {"-name", CHECK_NAME, 1}, | |
207 {"-mtime", CHECK_MTIME, 1}, | |
208 {"-type", CHECK_TYPE, 1}, | |
209 {"-print", ACTION_PRINT, 0}, | |
210 {"-print0", ACTION_PRINT0, 0}, | |
211 {"-exec", ACTION_EXEC, 1} | |
212 }; | |
213 mode_t types[]={S_IFREG,S_IFDIR,S_IFCHR,S_IFBLK,S_IFLNK,S_IFSOCK,S_IFIFO}; | |
214 char **arg_array; | |
215 node = (struct filter_node *) xmalloc(sizeof(struct filter_node)); | |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
216 node->op = OP_UNKNOWN; |
874 | 217 for (j=0; j < sizeof(arg_map)/sizeof(*arg_map); j++) { |
218 if (!strcmp(*arg, arg_map[j].arg)) { | |
219 node->op = arg_map[j].op; | |
220 if (arg_map[j].extrarg && !*(++arg)) | |
221 error_exit("Missing argument to %s", arg_map[j].arg); | |
222 break; | |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
223 } |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
224 } |
814 | 225 |
874 | 226 switch(node->op) { |
227 case CHECK_NAME: | |
228 node->data.name_regex = *arg; | |
229 break; | |
230 case CHECK_MTIME: | |
231 switch(**arg) { | |
232 case '+': | |
887 | 233 node->data.t.sign=+1; |
234 (*arg)++; | |
874 | 235 break; |
236 case '-': | |
887 | 237 node->data.t.sign=-1; |
238 (*arg)++; | |
874 | 239 break; |
240 default: | |
887 | 241 node->data.t.sign=0; |
874 | 242 break; |
243 } | |
887 | 244 node->data.t.time = atoi(*arg); |
874 | 245 break; |
246 case CHECK_TYPE: | |
247 if (-1 == (j = stridx("fdcblsp", **arg))) | |
248 error_exit("bad type '%s'", *arg); | |
249 else node->data.type = types[j]; | |
250 break; | |
251 case ACTION_EXEC: | |
252 arg_array = xmalloc(sizeof(char *)); | |
253 for (j = 0; *arg && strcmp(*arg, ";"); j++) { | |
254 /* new method */ | |
255 arg_array = xrealloc(arg_array, sizeof(char *) * (j+2)); | |
256 arg_array[j] = *arg; | |
257 if (!strcmp(*arg, "{}")) node->data.e.arg_path_index = j; | |
849 | 258 |
874 | 259 arg++; |
260 } | |
261 if (!*arg) error_exit("need ';' in exec"); | |
262 arg_array[j] = 0; | |
263 node->data.e.exec_args = arg_array; | |
264 break; | |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
265 } |
874 | 266 |
875 | 267 have_action |= IS_ACTION(node->op); |
814 | 268 |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
269 if (node->op == OP_UNKNOWN) { |
874 | 270 if (**arg == '-') error_exit("bad option '%s'", *arg); |
271 else TT.dir = *arg; | |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
272 } else { |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
273 // add OP_AND where necessary |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
274 if (node_list) { |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
275 int o1 = node_list->op, o2 = node->op; |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
276 if ((o1>MAX_OP && o2>MAX_OP) || |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
277 (o1==RPAREN && o2>=OP_NOT && o2!=RPAREN) || |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
278 (o1>=OP_NOT && o1!=LPAREN && o2==LPAREN)) { |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
279 struct filter_node *n = (struct filter_node *) |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
280 xmalloc(sizeof(struct filter_node)); |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
281 n->op = OP_AND; |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
282 n->next = node_list; |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
283 node_list = n; |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
284 } |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
285 } |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
286 /* push node */ |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
287 node->next = node_list;; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
288 node_list = node; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
289 } |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
290 |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
291 } |
814 | 292 |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
293 /* now convert from infix to prefix */ |
875 | 294 if(have_action) TT.filter_root = NULL; |
295 else TT.filter_root = &(struct filter_node){0, ACTION_PRINT}; | |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
296 op_stack = NULL; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
297 node = node_list; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
298 while( node ) { |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
299 int op = node->op; |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
300 next = node->next; |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
301 if (op==LPAREN || op==RPAREN) { |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
302 free(node); |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
303 node = 0; |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
304 } |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
305 if (op<=MAX_OP) { |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
306 if (prevop > op) { |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
307 /* pop opstack to output */ |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
308 op_node = op_stack; |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
309 while (op_node) { |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
310 /* remove from op_stack */ |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
311 op_stack = op_node->next; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
312 /* push to output */ |
874 | 313 op_node->next = TT.filter_root; |
314 TT.filter_root = op_node; | |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
315 /* get next node */ |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
316 op_node = op_stack; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
317 } |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
318 } |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
319 if (node) { |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
320 /* push to opstack */ |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
321 node->next = op_stack; |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
322 op_stack = node; |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
323 } |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
324 prevop = op*(op!=RPAREN); |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
325 } |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
326 else { |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
327 /* push to output */ |
874 | 328 node->next = TT.filter_root; |
329 TT.filter_root = node; | |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
330 } |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
331 node = next; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
332 } |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
333 /* end of input - push opstack to output */ |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
334 /* pop opstack to output till empty */ |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
335 op_node = op_stack; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
336 while (op_node) { |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
337 op_stack = op_node->next; |
874 | 338 op_node->next = TT.filter_root; |
339 TT.filter_root = op_node; | |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
340 op_node = op_stack; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
341 } |
875 | 342 if(!have_action) { |
343 node = TT.filter_root; | |
344 TT.filter_root = (struct filter_node*) xmalloc(sizeof(struct filter_node)); | |
345 TT.filter_root->next = node; | |
346 TT.filter_root->op = OP_AND; | |
347 } | |
814 | 348 } |
349 | |
350 void find_main(void) | |
351 { | |
887 | 352 TT.itime = time(NULL); |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
353 /* parse filters, if present */ |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
354 build_filter_list(); |
814 | 355 |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
356 /* FIXTHIS - parse actions, if present */ |
814 | 357 |
849 | 358 dirtree_read(TT.dir, check_node_callback); |
814 | 359 } |