diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2006-10-14 14:24:30 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2006-10-14 14:24:30 +0000 |
commit | 3a6755f56f811f246934f02182531fb1e8ccc72d (patch) | |
tree | 3bcbe0186fd69f665ed3634dc2f990f994ec399f | |
parent | c345d8e94589e3c74a9fac40f440affbc359c8d1 (diff) | |
download | busybox-w32-3a6755f56f811f246934f02182531fb1e8ccc72d.tar.gz busybox-w32-3a6755f56f811f246934f02182531fb1e8ccc72d.tar.bz2 busybox-w32-3a6755f56f811f246934f02182531fb1e8ccc72d.zip |
grep: add support for -r
-rw-r--r-- | findutils/find.c | 52 | ||||
-rw-r--r-- | findutils/grep.c | 179 | ||||
-rw-r--r-- | include/libbb.h | 4 | ||||
-rw-r--r-- | include/usage.h | 3 | ||||
-rw-r--r-- | libbb/recursive_action.c | 14 |
5 files changed, 144 insertions, 108 deletions
diff --git a/findutils/find.c b/findutils/find.c index 913a778eb..62cb5d7eb 100644 --- a/findutils/find.c +++ b/findutils/find.c | |||
@@ -74,7 +74,7 @@ static int fileAction(const char *fileName, struct stat *statbuf, void* junk) | |||
74 | tmp = fileName; | 74 | tmp = fileName; |
75 | else | 75 | else |
76 | tmp++; | 76 | tmp++; |
77 | if (!(fnmatch(pattern, tmp, FNM_PERIOD) == 0)) | 77 | if (fnmatch(pattern, tmp, FNM_PERIOD) != 0) |
78 | goto no_match; | 78 | goto no_match; |
79 | } | 79 | } |
80 | #ifdef CONFIG_FEATURE_FIND_TYPE | 80 | #ifdef CONFIG_FEATURE_FIND_TYPE |
@@ -143,8 +143,8 @@ static int fileAction(const char *fileName, struct stat *statbuf, void* junk) | |||
143 | #else | 143 | #else |
144 | puts(fileName); | 144 | puts(fileName); |
145 | #endif | 145 | #endif |
146 | no_match: | 146 | no_match: |
147 | return (TRUE); | 147 | return TRUE; |
148 | } | 148 | } |
149 | 149 | ||
150 | #ifdef CONFIG_FEATURE_FIND_TYPE | 150 | #ifdef CONFIG_FEATURE_FIND_TYPE |
@@ -153,27 +153,27 @@ static int find_type(char *type) | |||
153 | int mask = 0; | 153 | int mask = 0; |
154 | 154 | ||
155 | switch (type[0]) { | 155 | switch (type[0]) { |
156 | case 'b': | 156 | case 'b': |
157 | mask = S_IFBLK; | 157 | mask = S_IFBLK; |
158 | break; | 158 | break; |
159 | case 'c': | 159 | case 'c': |
160 | mask = S_IFCHR; | 160 | mask = S_IFCHR; |
161 | break; | 161 | break; |
162 | case 'd': | 162 | case 'd': |
163 | mask = S_IFDIR; | 163 | mask = S_IFDIR; |
164 | break; | 164 | break; |
165 | case 'p': | 165 | case 'p': |
166 | mask = S_IFIFO; | 166 | mask = S_IFIFO; |
167 | break; | 167 | break; |
168 | case 'f': | 168 | case 'f': |
169 | mask = S_IFREG; | 169 | mask = S_IFREG; |
170 | break; | 170 | break; |
171 | case 'l': | 171 | case 'l': |
172 | mask = S_IFLNK; | 172 | mask = S_IFLNK; |
173 | break; | 173 | break; |
174 | case 's': | 174 | case 's': |
175 | mask = S_IFSOCK; | 175 | mask = S_IFSOCK; |
176 | break; | 176 | break; |
177 | } | 177 | } |
178 | 178 | ||
179 | if (mask == 0 || type[1] != '\0') | 179 | if (mask == 0 || type[1] != '\0') |
@@ -306,12 +306,12 @@ int find_main(int argc, char **argv) | |||
306 | } | 306 | } |
307 | 307 | ||
308 | if (firstopt == 1) { | 308 | if (firstopt == 1) { |
309 | if (! recursive_action(".", TRUE, dereference, FALSE, fileAction, | 309 | if (!recursive_action(".", TRUE, dereference, FALSE, fileAction, |
310 | fileAction, NULL)) | 310 | fileAction, NULL)) |
311 | status = EXIT_FAILURE; | 311 | status = EXIT_FAILURE; |
312 | } else { | 312 | } else { |
313 | for (i = 1; i < firstopt; i++) { | 313 | for (i = 1; i < firstopt; i++) { |
314 | if (! recursive_action(argv[i], TRUE, dereference, FALSE, fileAction, | 314 | if (!recursive_action(argv[i], TRUE, dereference, FALSE, fileAction, |
315 | fileAction, NULL)) | 315 | fileAction, NULL)) |
316 | status = EXIT_FAILURE; | 316 | status = EXIT_FAILURE; |
317 | } | 317 | } |
diff --git a/findutils/grep.c b/findutils/grep.c index c0c495bd1..1285d21f8 100644 --- a/findutils/grep.c +++ b/findutils/grep.c | |||
@@ -24,43 +24,41 @@ | |||
24 | 24 | ||
25 | 25 | ||
26 | /* options */ | 26 | /* options */ |
27 | static unsigned opt; | 27 | #define GREP_OPTS "lnqvscFiHhe:f:Lor" |
28 | #define GREP_OPTS "lnqvscFiHhe:f:Lo" | ||
29 | #define GREP_OPT_l (1<<0) | 28 | #define GREP_OPT_l (1<<0) |
30 | #define PRINT_FILES_WITH_MATCHES (opt & GREP_OPT_l) | 29 | #define PRINT_FILES_WITH_MATCHES (option_mask32 & GREP_OPT_l) |
31 | #define GREP_OPT_n (1<<1) | 30 | #define GREP_OPT_n (1<<1) |
32 | #define PRINT_LINE_NUM (opt & GREP_OPT_n) | 31 | #define PRINT_LINE_NUM (option_mask32 & GREP_OPT_n) |
33 | #define GREP_OPT_q (1<<2) | 32 | #define GREP_OPT_q (1<<2) |
34 | #define BE_QUIET (opt & GREP_OPT_q) | 33 | #define BE_QUIET (option_mask32 & GREP_OPT_q) |
35 | #define GREP_OPT_v (1<<3) | 34 | #define GREP_OPT_v (1<<3) |
36 | typedef char invert_search_t; | ||
37 | static invert_search_t invert_search; | ||
38 | #define GREP_OPT_s (1<<4) | 35 | #define GREP_OPT_s (1<<4) |
39 | #define SUPPRESS_ERR_MSGS (opt & GREP_OPT_s) | 36 | #define SUPPRESS_ERR_MSGS (option_mask32 & GREP_OPT_s) |
40 | #define GREP_OPT_c (1<<5) | 37 | #define GREP_OPT_c (1<<5) |
41 | #define PRINT_MATCH_COUNTS (opt & GREP_OPT_c) | 38 | #define PRINT_MATCH_COUNTS (option_mask32 & GREP_OPT_c) |
42 | #define GREP_OPT_F (1<<6) | 39 | #define GREP_OPT_F (1<<6) |
43 | #define FGREP_FLAG (opt & GREP_OPT_F) | 40 | #define FGREP_FLAG (option_mask32 & GREP_OPT_F) |
44 | #define GREP_OPT_i (1<<7) | 41 | #define GREP_OPT_i (1<<7) |
45 | #define GREP_OPT_H (1<<8) | 42 | #define GREP_OPT_H (1<<8) |
46 | #define GREP_OPT_h (1<<9) | 43 | #define GREP_OPT_h (1<<9) |
47 | #define GREP_OPT_e (1<<10) | 44 | #define GREP_OPT_e (1<<10) |
48 | #define GREP_OPT_f (1<<11) | 45 | #define GREP_OPT_f (1<<11) |
49 | #define GREP_OPT_L (1<<12) | 46 | #define GREP_OPT_L (1<<12) |
50 | #define PRINT_FILES_WITHOUT_MATCHES (opt & GREP_OPT_L) | 47 | #define PRINT_FILES_WITHOUT_MATCHES (option_mask32 & GREP_OPT_L) |
51 | #define GREP_OPT_o (1<<13) | 48 | #define GREP_OPT_o (1<<13) |
49 | #define GREP_OPT_r (1<<14) | ||
52 | #if ENABLE_FEATURE_GREP_CONTEXT | 50 | #if ENABLE_FEATURE_GREP_CONTEXT |
53 | #define GREP_OPT_CONTEXT "A:B:C:" | 51 | # define GREP_OPT_CONTEXT "A:B:C:" |
54 | #define GREP_OPT_A (1<<14) | 52 | # define GREP_OPT_A (1<<15) |
55 | #define GREP_OPT_B (1<<15) | 53 | # define GREP_OPT_B (1<<16) |
56 | #define GREP_OPT_C (1<<16) | 54 | # define GREP_OPT_C (1<<17) |
57 | #define GREP_OPT_E (1<<17) | 55 | # define GREP_OPT_E (1<<18) |
58 | #else | 56 | #else |
59 | #define GREP_OPT_CONTEXT "" | 57 | # define GREP_OPT_CONTEXT "" |
60 | #define GREP_OPT_A 0 | 58 | # define GREP_OPT_A 0 |
61 | #define GREP_OPT_B 0 | 59 | # define GREP_OPT_B 0 |
62 | #define GREP_OPT_C 0 | 60 | # define GREP_OPT_C 0 |
63 | #define GREP_OPT_E (1<<14) | 61 | # define GREP_OPT_E (1<<15) |
64 | #endif | 62 | #endif |
65 | #if ENABLE_FEATURE_GREP_EGREP_ALIAS | 63 | #if ENABLE_FEATURE_GREP_EGREP_ALIAS |
66 | # define OPT_EGREP "E" | 64 | # define OPT_EGREP "E" |
@@ -68,8 +66,12 @@ static invert_search_t invert_search; | |||
68 | # define OPT_EGREP "" | 66 | # define OPT_EGREP "" |
69 | #endif | 67 | #endif |
70 | 68 | ||
69 | typedef unsigned char byte_t; | ||
70 | |||
71 | static int reflags; | 71 | static int reflags; |
72 | static int print_filename; | 72 | static byte_t invert_search; |
73 | static byte_t print_filename; | ||
74 | static byte_t open_errors; | ||
73 | 75 | ||
74 | #if ENABLE_FEATURE_GREP_CONTEXT | 76 | #if ENABLE_FEATURE_GREP_CONTEXT |
75 | static int lines_before; | 77 | static int lines_before; |
@@ -80,7 +82,7 @@ static int last_line_printed; | |||
80 | 82 | ||
81 | /* globals used internally */ | 83 | /* globals used internally */ |
82 | static llist_t *pattern_head; /* growable list of patterns to match */ | 84 | static llist_t *pattern_head; /* growable list of patterns to match */ |
83 | static char *cur_file; /* the current file we are reading */ | 85 | static const char *cur_file; /* the current file we are reading */ |
84 | 86 | ||
85 | typedef struct GREP_LIST_DATA { | 87 | typedef struct GREP_LIST_DATA { |
86 | char *pattern; | 88 | char *pattern; |
@@ -100,12 +102,12 @@ static void print_line(const char *line, int linenum, char decoration) | |||
100 | } | 102 | } |
101 | last_line_printed = linenum; | 103 | last_line_printed = linenum; |
102 | #endif | 104 | #endif |
103 | if (print_filename > 0) | 105 | if (print_filename) |
104 | printf("%s%c", cur_file, decoration); | 106 | printf("%s%c", cur_file, decoration); |
105 | if (PRINT_LINE_NUM) | 107 | if (PRINT_LINE_NUM) |
106 | printf("%i%c", linenum, decoration); | 108 | printf("%i%c", linenum, decoration); |
107 | /* Emulate weird GNU grep behavior with -ov */ | 109 | /* Emulate weird GNU grep behavior with -ov */ |
108 | if ((opt & (GREP_OPT_v+GREP_OPT_o)) != (GREP_OPT_v+GREP_OPT_o)) | 110 | if ((option_mask32 & (GREP_OPT_v+GREP_OPT_o)) != (GREP_OPT_v+GREP_OPT_o)) |
109 | puts(line); | 111 | puts(line); |
110 | } | 112 | } |
111 | 113 | ||
@@ -113,7 +115,7 @@ static void print_line(const char *line, int linenum, char decoration) | |||
113 | static int grep_file(FILE *file) | 115 | static int grep_file(FILE *file) |
114 | { | 116 | { |
115 | char *line; | 117 | char *line; |
116 | invert_search_t ret; | 118 | byte_t ret; |
117 | int linenum = 0; | 119 | int linenum = 0; |
118 | int nmatches = 0; | 120 | int nmatches = 0; |
119 | regmatch_t regmatch; | 121 | regmatch_t regmatch; |
@@ -199,7 +201,7 @@ static int grep_file(FILE *file) | |||
199 | /* make a note that we need to print 'after' lines */ | 201 | /* make a note that we need to print 'after' lines */ |
200 | print_n_lines_after = lines_after; | 202 | print_n_lines_after = lines_after; |
201 | #endif | 203 | #endif |
202 | if (opt & GREP_OPT_o) { | 204 | if (option_mask32 & GREP_OPT_o) { |
203 | line[regmatch.rm_eo] = '\0'; | 205 | line[regmatch.rm_eo] = '\0'; |
204 | print_line(line + regmatch.rm_so, linenum, ':'); | 206 | print_line(line + regmatch.rm_so, linenum, ':'); |
205 | } else { | 207 | } else { |
@@ -231,7 +233,7 @@ static int grep_file(FILE *file) | |||
231 | 233 | ||
232 | /* grep -c: print [filename:]count, even if count is zero */ | 234 | /* grep -c: print [filename:]count, even if count is zero */ |
233 | if (PRINT_MATCH_COUNTS) { | 235 | if (PRINT_MATCH_COUNTS) { |
234 | if (print_filename > 0) | 236 | if (print_filename) |
235 | printf("%s:", cur_file); | 237 | printf("%s:", cur_file); |
236 | printf("%d\n", nmatches); | 238 | printf("%d\n", nmatches); |
237 | } | 239 | } |
@@ -288,48 +290,71 @@ static void load_regexes_from_file(llist_t *fopt) | |||
288 | } | 290 | } |
289 | 291 | ||
290 | 292 | ||
293 | static int file_action_grep(const char *filename, struct stat *statbuf, void* matched) | ||
294 | { | ||
295 | FILE *file = fopen(filename, "r"); | ||
296 | if (file == NULL) { | ||
297 | if (!SUPPRESS_ERR_MSGS) | ||
298 | bb_perror_msg("%s", cur_file); | ||
299 | open_errors = 1; | ||
300 | return 0; | ||
301 | } | ||
302 | cur_file = filename; | ||
303 | *(int*)matched += grep_file(file); | ||
304 | return 1; | ||
305 | } | ||
306 | |||
307 | |||
308 | static int grep_dir(const char *dir) | ||
309 | { | ||
310 | int matched = 0; | ||
311 | recursive_action(dir, | ||
312 | /* recurse= */ 1, | ||
313 | /* followLinks= */ 0, | ||
314 | /* depthFirst= */ 1, | ||
315 | /* fileAction= */ file_action_grep, | ||
316 | /* dirAction= */ NULL, | ||
317 | /* userData= */ &matched); | ||
318 | return matched; | ||
319 | } | ||
320 | |||
321 | |||
291 | int grep_main(int argc, char **argv) | 322 | int grep_main(int argc, char **argv) |
292 | { | 323 | { |
293 | FILE *file; | 324 | FILE *file; |
294 | int matched; | 325 | int matched; |
295 | llist_t *fopt = NULL; | 326 | llist_t *fopt = NULL; |
296 | int error_open_count = 0; | ||
297 | 327 | ||
298 | /* do normal option parsing */ | 328 | /* do normal option parsing */ |
299 | #if ENABLE_FEATURE_GREP_CONTEXT | 329 | #if ENABLE_FEATURE_GREP_CONTEXT |
300 | char *junk; | ||
301 | char *slines_after; | 330 | char *slines_after; |
302 | char *slines_before; | 331 | char *slines_before; |
303 | char *Copt; | 332 | char *Copt; |
304 | 333 | ||
305 | opt_complementary = "H-h:e::f::C-AB"; | 334 | opt_complementary = "H-h:e::f::C-AB"; |
306 | opt = getopt32(argc, argv, | 335 | getopt32(argc, argv, |
307 | GREP_OPTS GREP_OPT_CONTEXT OPT_EGREP, | 336 | GREP_OPTS GREP_OPT_CONTEXT OPT_EGREP, |
308 | &pattern_head, &fopt, | 337 | &pattern_head, &fopt, |
309 | &slines_after, &slines_before, &Copt); | 338 | &slines_after, &slines_before, &Copt); |
310 | 339 | ||
311 | if (opt & GREP_OPT_C) { | 340 | if (option_mask32 & GREP_OPT_C) { |
312 | /* C option unseted A and B options, but next -A or -B | 341 | /* C option unseted A and B options, but next -A or -B |
313 | may be ovewrite own option */ | 342 | may be ovewrite own option */ |
314 | if (!(opt & GREP_OPT_A)) /* not overwtited */ | 343 | if (!(option_mask32 & GREP_OPT_A)) /* not overwtited */ |
315 | slines_after = Copt; | 344 | slines_after = Copt; |
316 | if (!(opt & GREP_OPT_B)) /* not overwtited */ | 345 | if (!(option_mask32 & GREP_OPT_B)) /* not overwtited */ |
317 | slines_before = Copt; | 346 | slines_before = Copt; |
318 | opt |= GREP_OPT_A|GREP_OPT_B; /* set for parse now */ | 347 | option_mask32 |= GREP_OPT_A|GREP_OPT_B; /* set for parse now */ |
319 | } | 348 | } |
320 | if (opt & GREP_OPT_A) { | 349 | if (option_mask32 & GREP_OPT_A) { |
321 | lines_after = strtoul(slines_after, &junk, 10); | 350 | lines_after = xatoi_u(slines_after); |
322 | if (*junk != '\0') | ||
323 | bb_error_msg_and_die(bb_msg_invalid_arg, slines_after, "-A"); | ||
324 | } | 351 | } |
325 | if (opt & GREP_OPT_B) { | 352 | if (option_mask32 & GREP_OPT_B) { |
326 | lines_before = strtoul(slines_before, &junk, 10); | 353 | lines_before = xatoi_u(slines_before); |
327 | if (*junk != '\0') | ||
328 | bb_error_msg_and_die(bb_msg_invalid_arg, slines_before, "-B"); | ||
329 | } | 354 | } |
330 | /* sanity checks after parse may be invalid numbers ;-) */ | 355 | /* sanity checks after parse may be invalid numbers ;-) */ |
331 | if (opt & (GREP_OPT_c|GREP_OPT_q|GREP_OPT_l|GREP_OPT_L)) { | 356 | if (option_mask32 & (GREP_OPT_c|GREP_OPT_q|GREP_OPT_l|GREP_OPT_L)) { |
332 | opt &= ~GREP_OPT_n; | 357 | option_mask32 &= ~GREP_OPT_n; |
333 | lines_before = 0; | 358 | lines_before = 0; |
334 | lines_after = 0; | 359 | lines_after = 0; |
335 | } else if (lines_before > 0) | 360 | } else if (lines_before > 0) |
@@ -337,15 +362,15 @@ int grep_main(int argc, char **argv) | |||
337 | #else | 362 | #else |
338 | /* with auto sanity checks */ | 363 | /* with auto sanity checks */ |
339 | opt_complementary = "H-h:e::f::c-n:q-n:l-n"; | 364 | opt_complementary = "H-h:e::f::c-n:q-n:l-n"; |
340 | opt = getopt32(argc, argv, GREP_OPTS OPT_EGREP, | 365 | getopt32(argc, argv, GREP_OPTS OPT_EGREP, |
341 | &pattern_head, &fopt); | 366 | &pattern_head, &fopt); |
342 | #endif | 367 | #endif |
343 | invert_search = (opt & GREP_OPT_v) != 0; /* 0 | 1 */ | 368 | invert_search = (option_mask32 & GREP_OPT_v) != 0; /* 0 | 1 */ |
344 | 369 | ||
345 | if (opt & GREP_OPT_H) | 370 | if (option_mask32 & GREP_OPT_H) |
346 | print_filename++; | 371 | print_filename = 1; |
347 | if (opt & GREP_OPT_h) | 372 | if (option_mask32 & GREP_OPT_h) |
348 | print_filename--; | 373 | print_filename = 0; |
349 | if (pattern_head != NULL) { | 374 | if (pattern_head != NULL) { |
350 | /* convert char *argv[] to grep_list_data_t */ | 375 | /* convert char *argv[] to grep_list_data_t */ |
351 | llist_t *cur; | 376 | llist_t *cur; |
@@ -353,20 +378,20 @@ int grep_main(int argc, char **argv) | |||
353 | for (cur = pattern_head; cur; cur = cur->link) | 378 | for (cur = pattern_head; cur; cur = cur->link) |
354 | cur->data = new_grep_list_data(cur->data, 0); | 379 | cur->data = new_grep_list_data(cur->data, 0); |
355 | } | 380 | } |
356 | if (opt & GREP_OPT_f) | 381 | if (option_mask32 & GREP_OPT_f) |
357 | load_regexes_from_file(fopt); | 382 | load_regexes_from_file(fopt); |
358 | 383 | ||
359 | if (ENABLE_FEATURE_GREP_FGREP_ALIAS && applet_name[0] == 'f') | 384 | if (ENABLE_FEATURE_GREP_FGREP_ALIAS && applet_name[0] == 'f') |
360 | opt |= GREP_OPT_F; | 385 | option_mask32 |= GREP_OPT_F; |
361 | 386 | ||
362 | if (!(opt & GREP_OPT_o)) | 387 | if (!(option_mask32 & GREP_OPT_o)) |
363 | reflags = REG_NOSUB; | 388 | reflags = REG_NOSUB; |
364 | 389 | ||
365 | if (ENABLE_FEATURE_GREP_EGREP_ALIAS && | 390 | if (ENABLE_FEATURE_GREP_EGREP_ALIAS && |
366 | (applet_name[0] == 'e' || (opt & GREP_OPT_E))) | 391 | (applet_name[0] == 'e' || (option_mask32 & GREP_OPT_E))) |
367 | reflags |= REG_EXTENDED; | 392 | reflags |= REG_EXTENDED; |
368 | 393 | ||
369 | if (opt & GREP_OPT_i) | 394 | if (option_mask32 & GREP_OPT_i) |
370 | reflags |= REG_ICASE; | 395 | reflags |= REG_ICASE; |
371 | 396 | ||
372 | argv += optind; | 397 | argv += optind; |
@@ -386,9 +411,9 @@ int grep_main(int argc, char **argv) | |||
386 | } | 411 | } |
387 | 412 | ||
388 | /* argv[(optind)..(argc-1)] should be names of file to grep through. If | 413 | /* argv[(optind)..(argc-1)] should be names of file to grep through. If |
389 | * there is more than one file to grep, we will print the filenames */ | 414 | * there is more than one file to grep, we will print the filenames. */ |
390 | if (argc > 1) { | 415 | if (argc > 1) { |
391 | print_filename++; | 416 | print_filename = 1; |
392 | 417 | ||
393 | /* If no files were specified, or '-' was specified, take input from | 418 | /* If no files were specified, or '-' was specified, take input from |
394 | * stdin. Otherwise, we grep through all the files specified. */ | 419 | * stdin. Otherwise, we grep through all the files specified. */ |
@@ -398,25 +423,35 @@ int grep_main(int argc, char **argv) | |||
398 | matched = 0; | 423 | matched = 0; |
399 | while (argc--) { | 424 | while (argc--) { |
400 | cur_file = *argv++; | 425 | cur_file = *argv++; |
426 | file = stdin; | ||
401 | if (!cur_file || (*cur_file == '-' && !cur_file[1])) { | 427 | if (!cur_file || (*cur_file == '-' && !cur_file[1])) { |
402 | cur_file = "(standard input)"; | 428 | cur_file = "(standard input)"; |
403 | file = stdin; | ||
404 | } else { | 429 | } else { |
430 | if (option_mask32 & GREP_OPT_r) { | ||
431 | struct stat st; | ||
432 | if (stat(cur_file, &st) == 0 && S_ISDIR(st.st_mode)) { | ||
433 | print_filename = 1; | ||
434 | matched += grep_dir(cur_file); | ||
435 | goto grep_done; | ||
436 | } | ||
437 | } | ||
438 | /* else: fopen(dir) will succeed, but reading won't */ | ||
405 | file = fopen(cur_file, "r"); | 439 | file = fopen(cur_file, "r"); |
406 | } | 440 | if (file == NULL) { |
407 | if (file == NULL) { | 441 | if (!SUPPRESS_ERR_MSGS) |
408 | if (!SUPPRESS_ERR_MSGS) | 442 | bb_perror_msg("%s", cur_file); |
409 | bb_perror_msg("%s", cur_file); | 443 | open_errors = 1; |
410 | error_open_count++; | 444 | continue; |
411 | } else { | ||
412 | matched += grep_file(file); | ||
413 | if (matched < 0) { | ||
414 | /* we found a match but were told to be quiet, stop here and | ||
415 | * return success */ | ||
416 | break; | ||
417 | } | 445 | } |
418 | fclose(file); | ||
419 | } | 446 | } |
447 | matched += grep_file(file); | ||
448 | grep_done: | ||
449 | if (matched < 0) { | ||
450 | /* we found a match but were told to be quiet, stop here and | ||
451 | * return success */ | ||
452 | break; | ||
453 | } | ||
454 | bb_fclose_nonstdin(file); | ||
420 | } | 455 | } |
421 | 456 | ||
422 | /* destroy all the elments in the pattern list */ | 457 | /* destroy all the elments in the pattern list */ |
@@ -439,7 +474,7 @@ int grep_main(int argc, char **argv) | |||
439 | * if an input line is selected, even if an error was detected. */ | 474 | * if an input line is selected, even if an error was detected. */ |
440 | if (BE_QUIET && matched) | 475 | if (BE_QUIET && matched) |
441 | return 0; | 476 | return 0; |
442 | if (error_open_count) | 477 | if (open_errors) |
443 | return 2; | 478 | return 2; |
444 | return !matched; /* invert return value 0 = success, 1 = failed */ | 479 | return !matched; /* invert return value 0 = success, 1 = failed */ |
445 | } | 480 | } |
diff --git a/include/libbb.h b/include/libbb.h index 0bcabf17b..901c7e669 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -252,8 +252,8 @@ extern FILE *bb_wfopen(const char *path, const char *mode); | |||
252 | extern FILE *bb_wfopen_input(const char *filename); | 252 | extern FILE *bb_wfopen_input(const char *filename); |
253 | extern FILE *xfopen(const char *path, const char *mode); | 253 | extern FILE *xfopen(const char *path, const char *mode); |
254 | 254 | ||
255 | extern int bb_fclose_nonstdin(FILE *f); | 255 | extern int bb_fclose_nonstdin(FILE *f); |
256 | extern void bb_fflush_stdout_and_exit(int retval) ATTRIBUTE_NORETURN; | 256 | extern void bb_fflush_stdout_and_exit(int retval) ATTRIBUTE_NORETURN; |
257 | 257 | ||
258 | extern void xstat(char *filename, struct stat *buf); | 258 | extern void xstat(char *filename, struct stat *buf); |
259 | extern int xsocket(int domain, int type, int protocol); | 259 | extern int xsocket(int domain, int type, int protocol); |
diff --git a/include/usage.h b/include/usage.h index b119c55c1..320294c8a 100644 --- a/include/usage.h +++ b/include/usage.h | |||
@@ -992,7 +992,7 @@ USE_FEATURE_DATE_ISOFMT( \ | |||
992 | "\t-H login_host\tLog login_host into the utmp file as the hostname" | 992 | "\t-H login_host\tLog login_host into the utmp file as the hostname" |
993 | 993 | ||
994 | #define grep_trivial_usage \ | 994 | #define grep_trivial_usage \ |
995 | "[-ihHnqvso" \ | 995 | "[-rihHnqvso" \ |
996 | USE_FEATURE_GREP_EGREP_ALIAS("E") \ | 996 | USE_FEATURE_GREP_EGREP_ALIAS("E") \ |
997 | USE_FEATURE_GREP_CONTEXT("ABC") \ | 997 | USE_FEATURE_GREP_CONTEXT("ABC") \ |
998 | "] PATTERN [FILEs...]" | 998 | "] PATTERN [FILEs...]" |
@@ -1001,6 +1001,7 @@ USE_FEATURE_DATE_ISOFMT( \ | |||
1001 | "Options:\n" \ | 1001 | "Options:\n" \ |
1002 | "\t-H\tprefix output lines with filename where match was found\n" \ | 1002 | "\t-H\tprefix output lines with filename where match was found\n" \ |
1003 | "\t-h\tsuppress the prefixing filename on output\n" \ | 1003 | "\t-h\tsuppress the prefixing filename on output\n" \ |
1004 | "\t-r\trecurse subdirectories\n" \ | ||
1004 | "\t-i\tignore case distinctions\n" \ | 1005 | "\t-i\tignore case distinctions\n" \ |
1005 | "\t-l\tlist names of files that match\n" \ | 1006 | "\t-l\tlist names of files that match\n" \ |
1006 | "\t-L\tlist names of files that do not match\n" \ | 1007 | "\t-L\tlist names of files that do not match\n" \ |
diff --git a/libbb/recursive_action.c b/libbb/recursive_action.c index 28a493403..6949e34f3 100644 --- a/libbb/recursive_action.c +++ b/libbb/recursive_action.c | |||
@@ -46,14 +46,14 @@ int recursive_action(const char *fileName, | |||
46 | return FALSE; | 46 | return FALSE; |
47 | } | 47 | } |
48 | 48 | ||
49 | if (! followLinks && (S_ISLNK(statbuf.st_mode))) { | 49 | if (!followLinks && (S_ISLNK(statbuf.st_mode))) { |
50 | if (fileAction == NULL) | 50 | if (fileAction == NULL) |
51 | return TRUE; | 51 | return TRUE; |
52 | else | 52 | else |
53 | return fileAction(fileName, &statbuf, userData); | 53 | return fileAction(fileName, &statbuf, userData); |
54 | } | 54 | } |
55 | 55 | ||
56 | if (! recurse) { | 56 | if (!recurse) { |
57 | if (S_ISDIR(statbuf.st_mode)) { | 57 | if (S_ISDIR(statbuf.st_mode)) { |
58 | if (dirAction != NULL) | 58 | if (dirAction != NULL) |
59 | return (dirAction(fileName, &statbuf, userData)); | 59 | return (dirAction(fileName, &statbuf, userData)); |
@@ -65,9 +65,9 @@ int recursive_action(const char *fileName, | |||
65 | if (S_ISDIR(statbuf.st_mode)) { | 65 | if (S_ISDIR(statbuf.st_mode)) { |
66 | DIR *dir; | 66 | DIR *dir; |
67 | 67 | ||
68 | if (dirAction != NULL && ! depthFirst) { | 68 | if (dirAction != NULL && !depthFirst) { |
69 | status = dirAction(fileName, &statbuf, userData); | 69 | status = dirAction(fileName, &statbuf, userData); |
70 | if (! status) { | 70 | if (!status) { |
71 | bb_perror_msg("%s", fileName); | 71 | bb_perror_msg("%s", fileName); |
72 | return FALSE; | 72 | return FALSE; |
73 | } else if (status == SKIP) | 73 | } else if (status == SKIP) |
@@ -84,7 +84,7 @@ int recursive_action(const char *fileName, | |||
84 | nextFile = concat_subpath_file(fileName, next->d_name); | 84 | nextFile = concat_subpath_file(fileName, next->d_name); |
85 | if(nextFile == NULL) | 85 | if(nextFile == NULL) |
86 | continue; | 86 | continue; |
87 | if (! recursive_action(nextFile, TRUE, followLinks, depthFirst, | 87 | if (!recursive_action(nextFile, TRUE, followLinks, depthFirst, |
88 | fileAction, dirAction, userData)) { | 88 | fileAction, dirAction, userData)) { |
89 | status = FALSE; | 89 | status = FALSE; |
90 | } | 90 | } |
@@ -92,12 +92,12 @@ int recursive_action(const char *fileName, | |||
92 | } | 92 | } |
93 | closedir(dir); | 93 | closedir(dir); |
94 | if (dirAction != NULL && depthFirst) { | 94 | if (dirAction != NULL && depthFirst) { |
95 | if (! dirAction(fileName, &statbuf, userData)) { | 95 | if (!dirAction(fileName, &statbuf, userData)) { |
96 | bb_perror_msg("%s", fileName); | 96 | bb_perror_msg("%s", fileName); |
97 | return FALSE; | 97 | return FALSE; |
98 | } | 98 | } |
99 | } | 99 | } |
100 | if (! status) | 100 | if (!status) |
101 | return FALSE; | 101 | return FALSE; |
102 | } else { | 102 | } else { |
103 | if (fileAction == NULL) | 103 | if (fileAction == NULL) |