diff options
| author | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2006-10-14 14:24:30 +0000 |
|---|---|---|
| committer | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2006-10-14 14:24:30 +0000 |
| commit | af736e5da84d59b9fab20ffeaf696bbb30b80c7e (patch) | |
| tree | 3bcbe0186fd69f665ed3634dc2f990f994ec399f | |
| parent | ae43b2061a191ef6e7458a5a4d5b00657b49ebf1 (diff) | |
| download | busybox-w32-af736e5da84d59b9fab20ffeaf696bbb30b80c7e.tar.gz busybox-w32-af736e5da84d59b9fab20ffeaf696bbb30b80c7e.tar.bz2 busybox-w32-af736e5da84d59b9fab20ffeaf696bbb30b80c7e.zip | |
grep: add support for -r
git-svn-id: svn://busybox.net/trunk/busybox@16381 69ca8d6d-28ef-0310-b511-8ec308f3f277
| -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) |
