Changeset 1770 in MondoRescue for branches/stable/mindi-busybox/findutils/grep.c
- Timestamp:
- Nov 6, 2007, 11:01:53 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/stable/mindi-busybox/findutils/grep.c
r821 r1770 6 6 * Copyright (C) 1999,2000,2001 by Mark Whitley <markw@codepoet.org> 7 7 * 8 * Licensed under the GPL v2 , see the file LICENSE in this tarball.8 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. 9 9 */ 10 10 /* BB_AUDIT SUSv3 defects - unsupported option -x. */ … … 15 15 * correction "-e pattern1 -e pattern2" logic and more optimizations. 16 16 * precompiled regex 17 */ 18 19 #include "busybox.h" 20 #include <stdio.h> 21 #include <stdlib.h> 22 #include <getopt.h> 23 #include <string.h> 24 #include <errno.h> 17 */ 18 /* 19 * (C) 2006 Jac Goudsmit added -o option 20 */ 21 22 #include "libbb.h" 25 23 #include "xregex.h" 26 24 27 28 25 /* options */ 29 static unsigned long opt; 30 #define GREP_OPTS "lnqvscFiHhe:f:L" 31 #define GREP_OPT_l (1<<0) 32 #define PRINT_FILES_WITH_MATCHES (opt & GREP_OPT_l) 33 #define GREP_OPT_n (1<<1) 34 #define PRINT_LINE_NUM (opt & GREP_OPT_n) 35 #define GREP_OPT_q (1<<2) 36 #define BE_QUIET (opt & GREP_OPT_q) 37 #define GREP_OPT_v (1<<3) 38 typedef char invert_search_t; 39 static invert_search_t invert_search; 40 #define GREP_OPT_s (1<<4) 41 #define SUPPRESS_ERR_MSGS (opt & GREP_OPT_s) 42 #define GREP_OPT_c (1<<5) 43 #define PRINT_MATCH_COUNTS (opt & GREP_OPT_c) 44 #define GREP_OPT_F (1<<6) 45 #define FGREP_FLAG (opt & GREP_OPT_F) 46 #define GREP_OPT_i (1<<7) 47 #define GREP_OPT_H (1<<8) 48 #define GREP_OPT_h (1<<9) 49 #define GREP_OPT_e (1<<10) 50 #define GREP_OPT_f (1<<11) 51 #define GREP_OPT_L (1<<12) 52 #define PRINT_FILES_WITHOUT_MATCHES ((opt & GREP_OPT_L) != 0) 53 #if ENABLE_FEATURE_GREP_CONTEXT 54 #define GREP_OPT_CONTEXT "A:B:C" 55 #define GREP_OPT_A (1<<13) 56 #define GREP_OPT_B (1<<14) 57 #define GREP_OPT_C (1<<15) 58 #define GREP_OPT_E (1<<16) 59 #else 60 #define GREP_OPT_CONTEXT "" 61 #define GREP_OPT_A (0) 62 #define GREP_OPT_B (0) 63 #define GREP_OPT_C (0) 64 #define GREP_OPT_E (1<<13) 65 #endif 66 #if ENABLE_FEATURE_GREP_EGREP_ALIAS 67 # define OPT_EGREP "E" 68 #else 69 # define OPT_EGREP "" 70 #endif 71 26 #define OPTSTR_GREP \ 27 "lnqvscFiHhe:f:Lorm:" \ 28 USE_FEATURE_GREP_CONTEXT("A:B:C:") \ 29 USE_FEATURE_GREP_EGREP_ALIAS("E") \ 30 USE_DESKTOP("w") \ 31 "aI" 32 /* ignored: -a "assume all files to be text" */ 33 /* ignored: -I "assume binary files have no matches" */ 34 35 enum { 36 OPTBIT_l, /* list matched file names only */ 37 OPTBIT_n, /* print line# */ 38 OPTBIT_q, /* quiet - exit(0) of first match */ 39 OPTBIT_v, /* invert the match, to select non-matching lines */ 40 OPTBIT_s, /* suppress errors about file open errors */ 41 OPTBIT_c, /* count matches per file (suppresses normal output) */ 42 OPTBIT_F, /* literal match */ 43 OPTBIT_i, /* case-insensitive */ 44 OPTBIT_H, /* force filename display */ 45 OPTBIT_h, /* inhibit filename display */ 46 OPTBIT_e, /* -e PATTERN */ 47 OPTBIT_f, /* -f FILE_WITH_PATTERNS */ 48 OPTBIT_L, /* list unmatched file names only */ 49 OPTBIT_o, /* show only matching parts of lines */ 50 OPTBIT_r, /* recurse dirs */ 51 OPTBIT_m, /* -m MAX_MATCHES */ 52 USE_FEATURE_GREP_CONTEXT( OPTBIT_A ,) /* -A NUM: after-match context */ 53 USE_FEATURE_GREP_CONTEXT( OPTBIT_B ,) /* -B NUM: before-match context */ 54 USE_FEATURE_GREP_CONTEXT( OPTBIT_C ,) /* -C NUM: -A and -B combined */ 55 USE_FEATURE_GREP_EGREP_ALIAS(OPTBIT_E ,) /* extended regexp */ 56 USE_DESKTOP( OPTBIT_w ,) /* whole word match */ 57 OPT_l = 1 << OPTBIT_l, 58 OPT_n = 1 << OPTBIT_n, 59 OPT_q = 1 << OPTBIT_q, 60 OPT_v = 1 << OPTBIT_v, 61 OPT_s = 1 << OPTBIT_s, 62 OPT_c = 1 << OPTBIT_c, 63 OPT_F = 1 << OPTBIT_F, 64 OPT_i = 1 << OPTBIT_i, 65 OPT_H = 1 << OPTBIT_H, 66 OPT_h = 1 << OPTBIT_h, 67 OPT_e = 1 << OPTBIT_e, 68 OPT_f = 1 << OPTBIT_f, 69 OPT_L = 1 << OPTBIT_L, 70 OPT_o = 1 << OPTBIT_o, 71 OPT_r = 1 << OPTBIT_r, 72 OPT_m = 1 << OPTBIT_m, 73 OPT_A = USE_FEATURE_GREP_CONTEXT( (1 << OPTBIT_A)) + 0, 74 OPT_B = USE_FEATURE_GREP_CONTEXT( (1 << OPTBIT_B)) + 0, 75 OPT_C = USE_FEATURE_GREP_CONTEXT( (1 << OPTBIT_C)) + 0, 76 OPT_E = USE_FEATURE_GREP_EGREP_ALIAS((1 << OPTBIT_E)) + 0, 77 OPT_w = USE_DESKTOP( (1 << OPTBIT_w)) + 0, 78 }; 79 80 #define PRINT_FILES_WITH_MATCHES (option_mask32 & OPT_l) 81 #define PRINT_LINE_NUM (option_mask32 & OPT_n) 82 #define BE_QUIET (option_mask32 & OPT_q) 83 #define SUPPRESS_ERR_MSGS (option_mask32 & OPT_s) 84 #define PRINT_MATCH_COUNTS (option_mask32 & OPT_c) 85 #define FGREP_FLAG (option_mask32 & OPT_F) 86 #define PRINT_FILES_WITHOUT_MATCHES (option_mask32 & OPT_L) 87 88 typedef unsigned char byte_t; 89 90 static int max_matches; 72 91 static int reflags; 73 static int print_filename; 74 75 #if ENABLE_FEATURE_GREP_CONTEXT 92 static byte_t invert_search; 93 static byte_t print_filename; 94 static byte_t open_errors; 95 96 #if ENABLE_FEATURE_GREP_CONTEXT 97 static byte_t did_print_line; 76 98 static int lines_before; 77 99 static int lines_after; … … 79 101 static int last_line_printed; 80 102 #endif /* ENABLE_FEATURE_GREP_CONTEXT */ 81 82 103 /* globals used internally */ 83 104 static llist_t *pattern_head; /* growable list of patterns to match */ 84 static c har *cur_file;/* the current file we are reading */85 86 typedef struct GREP_LIST_DATA{105 static const char *cur_file; /* the current file we are reading */ 106 107 typedef struct grep_list_data_t { 87 108 char *pattern; 88 109 regex_t preg; … … 95 116 { 96 117 #if ENABLE_FEATURE_GREP_CONTEXT 118 /* Happens when we go to next file, immediately hit match 119 * and try to print prev context... from prev file! Don't do it */ 120 if (linenum < 1) 121 return; 97 122 /* possibly print the little '--' separator */ 98 if ((lines_before || lines_after) && last_line_printed&&99 last_line_printed <linenum - 1) {123 if ((lines_before || lines_after) && did_print_line && 124 last_line_printed != linenum - 1) { 100 125 puts("--"); 101 126 } 127 /* guard against printing "--" before first line of first file */ 128 did_print_line = 1; 102 129 last_line_printed = linenum; 103 130 #endif 104 if (print_filename > 0)131 if (print_filename) 105 132 printf("%s%c", cur_file, decoration); 106 133 if (PRINT_LINE_NUM) 107 134 printf("%i%c", linenum, decoration); 108 puts(line); 109 } 110 135 /* Emulate weird GNU grep behavior with -ov */ 136 if ((option_mask32 & (OPT_v|OPT_o)) != (OPT_v|OPT_o)) 137 puts(line); 138 } 111 139 112 140 static int grep_file(FILE *file) 113 141 { 114 142 char *line; 115 invert_search_t ret;143 byte_t ret; 116 144 int linenum = 0; 117 145 int nmatches = 0; 146 regmatch_t regmatch; 118 147 #if ENABLE_FEATURE_GREP_CONTEXT 119 148 int print_n_lines_after = 0; 120 149 int curpos = 0; /* track where we are in the circular 'before' buffer */ 121 150 int idx = 0; /* used for iteration through the circular buffer */ 151 #else 152 enum { print_n_lines_after = 0 }; 122 153 #endif /* ENABLE_FEATURE_GREP_CONTEXT */ 123 154 124 while ((line = bb_get_chomped_line_from_file(file)) != NULL) {155 while ((line = xmalloc_getline(file)) != NULL) { 125 156 llist_t *pattern_ptr = pattern_head; 126 157 grep_list_data_t * gl; … … 139 170 * invert search) 140 171 */ 141 if (!(gl->flg_mem_alocated_compiled & COMPILED)) {172 if (!(gl->flg_mem_alocated_compiled & COMPILED)) { 142 173 gl->flg_mem_alocated_compiled |= COMPILED; 143 174 xregcomp(&(gl->preg), gl->pattern, reflags); 144 175 } 145 ret |= regexec(&(gl->preg), line, 0, NULL, 0) == 0; 176 regmatch.rm_so = 0; 177 regmatch.rm_eo = 0; 178 if (regexec(&(gl->preg), line, 1, ®match, 0) == 0) { 179 if (!(option_mask32 & OPT_w)) 180 ret = 1; 181 else { 182 char c = ' '; 183 if (regmatch.rm_so) 184 c = line[regmatch.rm_so - 1]; 185 if (!isalnum(c) && c != '_') { 186 c = line[regmatch.rm_eo]; 187 if (!c || (!isalnum(c) && c != '_')) 188 ret = 1; 189 } 190 } 191 } 146 192 } 147 193 pattern_ptr = pattern_ptr->link; 148 194 } /* while (pattern_ptr) */ 149 195 150 if ((ret ^ invert_search)) { 151 152 if (PRINT_FILES_WITH_MATCHES || BE_QUIET) 153 free(line); 154 155 /* if we found a match but were told to be quiet, stop here */ 156 if (BE_QUIET || PRINT_FILES_WITHOUT_MATCHES) 157 return -1; 158 159 /* keep track of matches */ 160 nmatches++; 161 196 if (ret ^ invert_search) { 197 /* keep track of matches */ 198 nmatches++; 199 200 /* quiet/print (non)matching file names only? */ 201 if (option_mask32 & (OPT_q|OPT_l|OPT_L)) { 202 free(line); /* we don't need line anymore */ 203 if (BE_QUIET) { 204 /* manpage says about -q: 205 * "exit immediately with zero status 206 * if any match is found, 207 * even if errors were detected" */ 208 exit(0); 209 } 162 210 /* if we're just printing filenames, we stop after the first match */ 163 if (PRINT_FILES_WITH_MATCHES) 164 break; 165 166 /* print the matched line */ 167 if (PRINT_MATCH_COUNTS == 0) { 168 #if ENABLE_FEATURE_GREP_CONTEXT 169 int prevpos = (curpos == 0) ? lines_before - 1 : curpos - 1; 170 171 /* if we were told to print 'before' lines and there is at least 172 * one line in the circular buffer, print them */ 173 if (lines_before && before_buf[prevpos] != NULL) { 174 int first_buf_entry_line_num = linenum - lines_before; 175 176 /* advance to the first entry in the circular buffer, and 177 * figure out the line number is of the first line in the 178 * buffer */ 179 idx = curpos; 180 while (before_buf[idx] == NULL) { 181 idx = (idx + 1) % lines_before; 182 first_buf_entry_line_num++; 183 } 184 185 /* now print each line in the buffer, clearing them as we go */ 186 while (before_buf[idx] != NULL) { 187 print_line(before_buf[idx], first_buf_entry_line_num, '-'); 188 free(before_buf[idx]); 189 before_buf[idx] = NULL; 190 idx = (idx + 1) % lines_before; 191 first_buf_entry_line_num++; 192 } 211 if (PRINT_FILES_WITH_MATCHES) { 212 puts(cur_file); 213 /* fall thru to "return 1" */ 214 } 215 /* OPT_L aka PRINT_FILES_WITHOUT_MATCHES: return early */ 216 return 1; /* one match */ 217 } 218 219 #if ENABLE_FEATURE_GREP_CONTEXT 220 /* Were we printing context and saw next (unwanted) match? */ 221 if ((option_mask32 & OPT_m) && nmatches > max_matches) 222 break; 223 #endif 224 225 /* print the matched line */ 226 if (PRINT_MATCH_COUNTS == 0) { 227 #if ENABLE_FEATURE_GREP_CONTEXT 228 int prevpos = (curpos == 0) ? lines_before - 1 : curpos - 1; 229 230 /* if we were told to print 'before' lines and there is at least 231 * one line in the circular buffer, print them */ 232 if (lines_before && before_buf[prevpos] != NULL) { 233 int first_buf_entry_line_num = linenum - lines_before; 234 235 /* advance to the first entry in the circular buffer, and 236 * figure out the line number is of the first line in the 237 * buffer */ 238 idx = curpos; 239 while (before_buf[idx] == NULL) { 240 idx = (idx + 1) % lines_before; 241 first_buf_entry_line_num++; 193 242 } 194 243 195 /* make a note that we need to print 'after' lines */ 196 print_n_lines_after = lines_after; 244 /* now print each line in the buffer, clearing them as we go */ 245 while (before_buf[idx] != NULL) { 246 print_line(before_buf[idx], first_buf_entry_line_num, '-'); 247 free(before_buf[idx]); 248 before_buf[idx] = NULL; 249 idx = (idx + 1) % lines_before; 250 first_buf_entry_line_num++; 251 } 252 } 253 254 /* make a note that we need to print 'after' lines */ 255 print_n_lines_after = lines_after; 197 256 #endif 257 if (option_mask32 & OPT_o) { 258 line[regmatch.rm_eo] = '\0'; 259 print_line(line + regmatch.rm_so, linenum, ':'); 260 } else { 198 261 print_line(line, linenum, ':'); 199 262 } 200 263 } 201 #if ENABLE_FEATURE_GREP_CONTEXT 202 else { /* no match */ 203 /* Add the line to the circular 'before' buffer */ 204 if(lines_before) { 205 free(before_buf[curpos]); 206 before_buf[curpos] = bb_xstrdup(line); 207 curpos = (curpos + 1) % lines_before; 208 } 209 } 210 264 } 265 #if ENABLE_FEATURE_GREP_CONTEXT 266 else { /* no match */ 211 267 /* if we need to print some context lines after the last match, do so */ 212 if (print_n_lines_after && (last_line_printed != linenum)) {268 if (print_n_lines_after) { 213 269 print_line(line, linenum, '-'); 214 270 print_n_lines_after--; 271 } else if (lines_before) { 272 /* Add the line to the circular 'before' buffer */ 273 free(before_buf[curpos]); 274 before_buf[curpos] = line; 275 curpos = (curpos + 1) % lines_before; 276 /* avoid free(line) - we took line */ 277 line = NULL; 215 278 } 279 } 280 216 281 #endif /* ENABLE_FEATURE_GREP_CONTEXT */ 217 282 free(line); 218 } 219 283 284 /* Did we print all context after last requested match? */ 285 if ((option_mask32 & OPT_m) 286 && !print_n_lines_after && nmatches == max_matches) 287 break; 288 } 220 289 221 290 /* special-case file post-processing for options where we don't print line … … 224 293 /* grep -c: print [filename:]count, even if count is zero */ 225 294 if (PRINT_MATCH_COUNTS) { 226 if (print_filename > 0)295 if (print_filename) 227 296 printf("%s:", cur_file); 228 printf("%d\n", nmatches); 229 } 230 231 /* grep -l: print just the filename, but only if we grepped the line in the file */ 232 if (PRINT_FILES_WITH_MATCHES && nmatches > 0) { 233 puts(cur_file); 234 } 235 236 /* grep -L: print just the filename, but only if we didn't grep the line in the file */ 237 if (PRINT_FILES_WITHOUT_MATCHES && nmatches == 0) { 297 printf("%d\n", nmatches); 298 } 299 300 /* grep -L: print just the filename */ 301 if (PRINT_FILES_WITHOUT_MATCHES) { 302 /* nmatches is zero, no need to check it: 303 * we return 1 early if we detected a match 304 * and PRINT_FILES_WITHOUT_MATCHES is set */ 238 305 puts(cur_file); 239 306 } … … 260 327 } 261 328 262 263 329 static void load_regexes_from_file(llist_t *fopt) 264 330 { … … 266 332 FILE *f; 267 333 268 while (fopt) {334 while (fopt) { 269 335 llist_t *cur = fopt; 270 336 char *ffile = cur->data; … … 272 338 fopt = cur->link; 273 339 free(cur); 274 f = bb_xfopen(ffile, "r");275 while ((line = bb_get_chomped_line_from_file(f)) != NULL) {340 f = xfopen(ffile, "r"); 341 while ((line = xmalloc_getline(f)) != NULL) { 276 342 llist_add_to(&pattern_head, 277 343 new_grep_list_data(line, PATTERN_MEM_A)); … … 280 346 } 281 347 282 348 static int file_action_grep(const char *filename, struct stat *statbuf, void* matched, int depth) 349 { 350 FILE *file = fopen(filename, "r"); 351 if (file == NULL) { 352 if (!SUPPRESS_ERR_MSGS) 353 bb_perror_msg("%s", cur_file); 354 open_errors = 1; 355 return 0; 356 } 357 cur_file = filename; 358 *(int*)matched += grep_file(file); 359 fclose(file); 360 return 1; 361 } 362 363 static int grep_dir(const char *dir) 364 { 365 int matched = 0; 366 recursive_action(dir, 367 /* recurse=yes */ ACTION_RECURSE | 368 /* followLinks=no */ 369 /* depthFirst=yes */ ACTION_DEPTHFIRST, 370 /* fileAction= */ file_action_grep, 371 /* dirAction= */ NULL, 372 /* userData= */ &matched, 373 /* depth= */ 0); 374 return matched; 375 } 376 377 int grep_main(int argc, char **argv); 283 378 int grep_main(int argc, char **argv) 284 379 { 285 380 FILE *file; 286 381 int matched; 382 char *mopt; 287 383 llist_t *fopt = NULL; 288 int error_open_count = 0;289 384 290 385 /* do normal option parsing */ 291 386 #if ENABLE_FEATURE_GREP_CONTEXT 292 {293 char *junk;294 387 char *slines_after; 295 388 char *slines_before; 296 389 char *Copt; 297 390 298 bb_opt_complementally = "H-h:e::f::C-AB";299 opt = bb_getopt_ulflags(argc,argv,300 GREP_OPTS GREP_OPT_CONTEXT OPT_EGREP,301 &pattern_head, &fopt, 391 opt_complementary = "H-h:e::f::C-AB"; 392 getopt32(argv, 393 OPTSTR_GREP, 394 &pattern_head, &fopt, &mopt, 302 395 &slines_after, &slines_before, &Copt); 303 396 304 if (opt & GREP_OPT_C) {305 /* C option unseted A and B options, but next-A or -B306 may be ovewrite own option*/307 if (!(opt & GREP_OPT_A)) /* not overwtited*/397 if (option_mask32 & OPT_C) { 398 /* -C unsets prev -A and -B, but following -A or -B 399 may override it */ 400 if (!(option_mask32 & OPT_A)) /* not overridden */ 308 401 slines_after = Copt; 309 if (!(opt & GREP_OPT_B)) /* not overwtited*/402 if (!(option_mask32 & OPT_B)) /* not overridden */ 310 403 slines_before = Copt; 311 opt |= GREP_OPT_A|GREP_OPT_B; /* set for parse now */ 312 } 313 if(opt & GREP_OPT_A) { 314 lines_after = strtoul(slines_after, &junk, 10); 315 if(*junk != '\0') 316 bb_error_msg_and_die(bb_msg_invalid_arg, slines_after, "-A"); 317 } 318 if(opt & GREP_OPT_B) { 319 lines_before = strtoul(slines_before, &junk, 10); 320 if(*junk != '\0') 321 bb_error_msg_and_die(bb_msg_invalid_arg, slines_before, "-B"); 322 } 323 /* sanity checks after parse may be invalid numbers ;-) */ 324 if ((opt & (GREP_OPT_c|GREP_OPT_q|GREP_OPT_l|GREP_OPT_L))) { 325 opt &= ~GREP_OPT_n; 404 option_mask32 |= OPT_A|OPT_B; /* for parser */ 405 } 406 if (option_mask32 & OPT_A) { 407 lines_after = xatoi_u(slines_after); 408 } 409 if (option_mask32 & OPT_B) { 410 lines_before = xatoi_u(slines_before); 411 } 412 /* sanity checks */ 413 if (option_mask32 & (OPT_c|OPT_q|OPT_l|OPT_L)) { 414 option_mask32 &= ~OPT_n; 326 415 lines_before = 0; 327 416 lines_after = 0; 328 } else if(lines_before > 0) 329 before_buf = (char **)xcalloc(lines_before, sizeof(char *)); 330 } 417 } else if (lines_before > 0) 418 before_buf = xzalloc(lines_before * sizeof(char *)); 331 419 #else 332 420 /* with auto sanity checks */ 333 bb_opt_complementally = "H-h:e::f::c-n:q-n:l-n";334 opt = bb_getopt_ulflags(argc, argv, GREP_OPTS OPT_EGREP,335 &pattern_head, &fopt );421 opt_complementary = "H-h:e::f::c-n:q-n:l-n"; 422 getopt32(argv, OPTSTR_GREP, 423 &pattern_head, &fopt, &mopt); 336 424 #endif 337 invert_search = (opt & GREP_OPT_v) != 0; /* 0 | 1 */ 338 339 if(opt & GREP_OPT_H) 340 print_filename++; 341 if(opt & GREP_OPT_h) 342 print_filename--; 425 if (option_mask32 & OPT_m) { 426 max_matches = xatoi_u(mopt); 427 } 428 invert_search = ((option_mask32 & OPT_v) != 0); /* 0 | 1 */ 429 343 430 if (pattern_head != NULL) { 344 /* convert char * argv[]to grep_list_data_t */431 /* convert char **argv to grep_list_data_t */ 345 432 llist_t *cur; 346 433 347 for (cur = pattern_head; cur; cur = cur->link)434 for (cur = pattern_head; cur; cur = cur->link) 348 435 cur->data = new_grep_list_data(cur->data, 0); 349 436 } 350 if (opt & GREP_OPT_f)437 if (option_mask32 & OPT_f) 351 438 load_regexes_from_file(fopt); 352 439 353 if(ENABLE_FEATURE_GREP_FGREP_ALIAS && bb_applet_name[0] == 'f') 354 opt |= GREP_OPT_F; 355 356 if(ENABLE_FEATURE_GREP_EGREP_ALIAS && 357 (bb_applet_name[0] == 'e' || (opt & GREP_OPT_E))) 358 reflags = REG_EXTENDED | REG_NOSUB; 359 else 440 if (ENABLE_FEATURE_GREP_FGREP_ALIAS && applet_name[0] == 'f') 441 option_mask32 |= OPT_F; 442 443 if (!(option_mask32 & (OPT_o | OPT_w))) 360 444 reflags = REG_NOSUB; 361 445 362 if(opt & GREP_OPT_i) 446 if (ENABLE_FEATURE_GREP_EGREP_ALIAS && 447 (applet_name[0] == 'e' || (option_mask32 & OPT_E))) 448 reflags |= REG_EXTENDED; 449 450 if (option_mask32 & OPT_i) 363 451 reflags |= REG_ICASE; 364 452 … … 369 457 * argv[optind] should be the pattern. no pattern, no worky */ 370 458 if (pattern_head == NULL) { 459 char *pattern; 371 460 if (*argv == NULL) 372 461 bb_show_usage(); 373 else { 374 char *pattern = new_grep_list_data(*argv++, 0); 375 376 llist_add_to(&pattern_head, pattern); 377 argc--; 378 } 462 pattern = new_grep_list_data(*argv++, 0); 463 llist_add_to(&pattern_head, pattern); 464 argc--; 379 465 } 380 466 381 467 /* argv[(optind)..(argc-1)] should be names of file to grep through. If 382 * there is more than one file to grep, we will print the filenames */ 383 if (argc > 1) { 384 print_filename++; 468 * there is more than one file to grep, we will print the filenames. */ 469 if (argc > 1) 470 print_filename = 1; 471 /* -H / -h of course override */ 472 if (option_mask32 & OPT_H) 473 print_filename = 1; 474 if (option_mask32 & OPT_h) 475 print_filename = 0; 385 476 386 477 /* If no files were specified, or '-' was specified, take input from 387 478 * stdin. Otherwise, we grep through all the files specified. */ 388 } else if (argc == 0) {479 if (argc == 0) 389 480 argc++; 390 }391 481 matched = 0; 392 482 while (argc--) { 393 483 cur_file = *argv++; 394 if(!cur_file || (*cur_file == '-' && !cur_file[1])) { 484 file = stdin; 485 if (!cur_file || (*cur_file == '-' && !cur_file[1])) { 395 486 cur_file = "(standard input)"; 396 file = stdin;397 487 } else { 488 if (option_mask32 & OPT_r) { 489 struct stat st; 490 if (stat(cur_file, &st) == 0 && S_ISDIR(st.st_mode)) { 491 if (!(option_mask32 & OPT_h)) 492 print_filename = 1; 493 matched += grep_dir(cur_file); 494 goto grep_done; 495 } 496 } 497 /* else: fopen(dir) will succeed, but reading won't */ 398 498 file = fopen(cur_file, "r"); 499 if (file == NULL) { 500 if (!SUPPRESS_ERR_MSGS) 501 bb_perror_msg("%s", cur_file); 502 open_errors = 1; 503 continue; 504 } 399 505 } 400 if (file == NULL) { 401 if (!SUPPRESS_ERR_MSGS) 402 bb_perror_msg("%s", cur_file); 403 error_open_count++; 404 } else { 405 matched += grep_file(file); 406 if(matched < 0) { 407 /* we found a match but were told to be quiet, stop here and 408 * return success */ 409 break; 410 } 411 fclose(file); 412 } 506 matched += grep_file(file); 507 fclose_if_not_stdin(file); 508 grep_done: ; 413 509 } 414 510 … … 421 517 422 518 pattern_head = pattern_head->link; 423 if ((gl->flg_mem_alocated_compiled & PATTERN_MEM_A))519 if ((gl->flg_mem_alocated_compiled & PATTERN_MEM_A)) 424 520 free(gl->pattern); 425 if ((gl->flg_mem_alocated_compiled & COMPILED))521 if ((gl->flg_mem_alocated_compiled & COMPILED)) 426 522 regfree(&(gl->preg)); 523 free(gl); 427 524 free(pattern_head_ptr); 428 525 } 429 526 } 430 527 /* 0 = success, 1 = failed, 2 = error */ 431 /* If the -q option is specified, the exit status shall be zero 432 * if an input line is selected, even if an error was detected. */ 433 if(BE_QUIET && matched) 434 return 0; 435 if(error_open_count) 528 if (open_errors) 436 529 return 2; 437 530 return !matched; /* invert return value 0 = success, 1 = failed */
Note:
See TracChangeset
for help on using the changeset viewer.