source: MondoRescue/branches/stable/mindi-busybox/findutils/grep.c@ 1770

Last change on this file since 1770 was 1770, checked in by Bruno Cornec, 16 years ago
  • Better output for mindi-busybox revision
  • Remove dummy file created on NFS - report from Arnaud Tiger <arnaud.tiger_at_hp.com>
  • strace useful for debug
  • fix new versions for pb (2.0.0 for mindi and 1.7.2 for mindi-busybox)
  • fix build process for mindi-busybox + options used in that version (dd for label-partitions-as-necessary)
  • fix typo in label-partitions-as-necessary which doesn't seem to work
  • Update to busybox 1.7.2
  • perl is now required at restore time to support uuid swap partitions (and will be used for many other thigs

in the future for sure)

  • next mindi version will be 2.0.0 due to all the changes made in it (udev may break working distros)
  • small optimization in mindi on keyboard handling (one single find instead of multiple)
  • better interaction for USB device when launching mindi manually
  • attempt to automatically guess block disk size for ramdisk
  • fix typos in bkphw
  • Fix the remaining problem with UUID support for swap partitions
  • Updates mondoarchive man page for USB support
  • Adds preliminary Hardware support to mindi (Proliant SSSTK)
  • Tries to add udev support also for rhel4
  • Fix UUID support which was still broken.
  • Be conservative in test for the start-nfs script
  • Update config file for mindi-busybox for 1.7.2 migration
  • Try to run around a busybox bug (1.2.2 pb on inexistant links)
  • Add build content for mindi-busybox in pb
  • Remove distributions content for mindi-busybox
  • Fix a warning on inexistant raidtab
  • Solve problem on tmpfs in restore init (Problem of inexistant symlink and busybox)
  • Create MONDO_CACHE and use it everywhere + creation at start
  • Really never try to eject a USB device
  • Fix a issue with &> usage (replaced with 1> and 2>)
  • Adds magic file to depllist in order to have file working + ldd which helps for debugging issues
  • tty modes correct to avoid sh error messages
  • Use ext3 normally and not ext2 instead
  • USB device should be corrected after reading (take 1st part)
  • Adds a mount_USB_here function derived from mount_CDROM_here
  • usb detection place before /dev detection in device name at restore time
  • Fix when restoring from USB: media is asked in interactive mode
  • Adds USB support for mondorestore
  • mount_cdrom => mount_media
  • elilo.efi is now searched throughout /boot/efi and not in a fixed place as there is no standard
  • untar-and-softlink => untar (+ interface change)
  • suppress useless softlinks creation/removal in boot process
  • avoids udevd messages on groups
  • Increase # of disks to 99 as in mindi at restore time (should be a conf file parameter)
  • skip existing big file creation
  • seems to work correctly for USB mindi boot
  • Adds group and tty link to udev conf
  • Always load usb-torage (even 2.6) to initiate USB bus discovery
  • Better printing of messages
  • Attempt to fix a bug in supporting OpenSusE 10.3 kernel for initramfs (mindi may now use multiple regex for kernel initrd detection)
  • Links were not correctly done as non relative for modules in mindi
  • exclusion of modules denied now works
  • Also create modules in their ordinary place, so that classical modprobe works + copy modules.dep
  • Fix bugs for DENY_MODS handling
  • Add device /dev/console for udev
  • ide-generic should now really be excluded
  • Fix a bug in major number for tty
  • If udev then adds modprobe/insmod to rootfs
  • tty0 is also cretaed with udev
  • ide-generic put rather in DENY_MODS
  • udevd remove from deplist s handled in mindi directly
  • better default for mindi when using --usb
  • Handles dynamically linked busybox (in case we want to use it soon ;-)
  • Adds fixed devices to create for udev
  • ide-generic should not be part of the initrd when using libata v2
  • support a dynamically linked udev (case on Ubuntu 7.10 and Mandriva 2008.0 so should be quite generic) This will give incitation to move to dyn. linked binaries in the initrd which will help for other tasks (ia6 4)
  • Improvement in udev support (do not use cl options not available in busybox)
  • Udev in mindi
    • auto creation of the right links at boot time with udev-links.conf(from Mandriva 2008.0)
    • rework startup of udev as current makes kernel crash (from Mandriva 2008.0)
    • add support for 64 bits udev
  • Try to render MyInsmod silent at boot time
  • Adds udev support (mandatory for newest distributions to avoid remapping of devices in a different way as on the original system)
  • We also need vaft format support for USB boot
  • Adds libusual support (Ubuntu 7.10 needs it for USB)
  • Improve Ubuntu/Debian keyboard detection and support
  • pbinit adapted to new pb (0.8.10). Filtering of docs done in it
  • Suppress some mondo warnings and errors on USB again
  • Tries to fix lack of files in deb mindi package
  • Verify should now work for USB devices
  • More log/mesages improvement for USB support
  • - Supress g_erase_tmpdir_and_scratchdir
  • Improve some log messages for USB support
  • Try to improve install in mindi to avoid issues with isolinux.cfg not installed vene if in the pkg :-(
  • Improve mindi-busybox build
  • In conformity with pb 0.8.9
  • Add support for Ubuntu 7.10 in build process
  • Add USB Key button to Menu UI (CD streamer removed)
  • Attempt to fix error messages on tmp/scratch files at the end by removing those dir at the latest possible.
  • Fix a bug linked to the size of the -E param which could be used (Arnaud Tiger/René Ribaud).
  • Integrate ~/.pbrc content into mondorescue.pb (required project-builder >= 0.8.7)
  • Put mondorescue in conformity with new pb filtering rules
  • Add USB support at restore time (no test done yet). New start-usb script PB varibale added where useful
  • Unmounting USB device before removal of temporary scratchdir
  • Stil refining USB copy back to mondo (one command was not executed)
  • No need to have the image subdor in the csratchdir when USB.
  • umount the USB partition before attempting to use it
  • Remove useless copy from mindi to mondo at end of USB handling

(risky merge, we are raising the limits of 2 diverging branches. The status of stable is not completely sure as such. Will need lots of tests, but it's not yet done :-()
(merge -r1692:1769 $SVN_M/branches/2.2.5)

File size: 14.9 KB
RevLine 
[821]1/* vi: set sw=4 ts=4: */
2/*
3 * Mini grep implementation for busybox using libc regex.
4 *
5 * Copyright (C) 1999,2000,2001 by Lineo, inc. and Mark Whitley
6 * Copyright (C) 1999,2000,2001 by Mark Whitley <markw@codepoet.org>
7 *
[1770]8 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
[821]9 */
10/* BB_AUDIT SUSv3 defects - unsupported option -x. */
11/* BB_AUDIT GNU defects - always acts as -a. */
12/* http://www.opengroup.org/onlinepubs/007904975/utilities/grep.html */
13/*
14 * 2004,2006 (C) Vladimir Oleynik <dzo@simtreas.ru> -
15 * correction "-e pattern1 -e pattern2" logic and more optimizations.
16 * precompiled regex
[1770]17 */
18/*
19 * (C) 2006 Jac Goudsmit added -o option
20 */
[821]21
[1770]22#include "libbb.h"
[821]23#include "xregex.h"
24
25/* options */
[1770]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" */
[821]34
[1770]35enum {
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
88typedef unsigned char byte_t;
89
90static int max_matches;
[821]91static int reflags;
[1770]92static byte_t invert_search;
93static byte_t print_filename;
94static byte_t open_errors;
[821]95
96#if ENABLE_FEATURE_GREP_CONTEXT
[1770]97static byte_t did_print_line;
[821]98static int lines_before;
99static int lines_after;
100static char **before_buf;
101static int last_line_printed;
102#endif /* ENABLE_FEATURE_GREP_CONTEXT */
103/* globals used internally */
104static llist_t *pattern_head; /* growable list of patterns to match */
[1770]105static const char *cur_file; /* the current file we are reading */
[821]106
[1770]107typedef struct grep_list_data_t {
[821]108 char *pattern;
109 regex_t preg;
110#define PATTERN_MEM_A 1
111#define COMPILED 2
112 int flg_mem_alocated_compiled;
113} grep_list_data_t;
114
115static void print_line(const char *line, int linenum, char decoration)
116{
117#if ENABLE_FEATURE_GREP_CONTEXT
[1770]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;
[821]122 /* possibly print the little '--' separator */
[1770]123 if ((lines_before || lines_after) && did_print_line &&
124 last_line_printed != linenum - 1) {
[821]125 puts("--");
126 }
[1770]127 /* guard against printing "--" before first line of first file */
128 did_print_line = 1;
[821]129 last_line_printed = linenum;
130#endif
[1770]131 if (print_filename)
[821]132 printf("%s%c", cur_file, decoration);
133 if (PRINT_LINE_NUM)
134 printf("%i%c", linenum, decoration);
[1770]135 /* Emulate weird GNU grep behavior with -ov */
136 if ((option_mask32 & (OPT_v|OPT_o)) != (OPT_v|OPT_o))
137 puts(line);
[821]138}
139
140static int grep_file(FILE *file)
141{
142 char *line;
[1770]143 byte_t ret;
[821]144 int linenum = 0;
145 int nmatches = 0;
[1770]146 regmatch_t regmatch;
[821]147#if ENABLE_FEATURE_GREP_CONTEXT
148 int print_n_lines_after = 0;
149 int curpos = 0; /* track where we are in the circular 'before' buffer */
150 int idx = 0; /* used for iteration through the circular buffer */
[1770]151#else
152 enum { print_n_lines_after = 0 };
[821]153#endif /* ENABLE_FEATURE_GREP_CONTEXT */
154
[1770]155 while ((line = xmalloc_getline(file)) != NULL) {
[821]156 llist_t *pattern_ptr = pattern_head;
157 grep_list_data_t * gl;
158
159 linenum++;
160 ret = 0;
161 while (pattern_ptr) {
162 gl = (grep_list_data_t *)pattern_ptr->data;
163 if (FGREP_FLAG) {
164 ret = strstr(line, gl->pattern) != NULL;
165 } else {
166 /*
167 * test for a postitive-assertion match (regexec returns success (0)
168 * and the user did not specify invert search), or a negative-assertion
169 * match (regexec returns failure (REG_NOMATCH) and the user specified
170 * invert search)
171 */
[1770]172 if (!(gl->flg_mem_alocated_compiled & COMPILED)) {
[821]173 gl->flg_mem_alocated_compiled |= COMPILED;
174 xregcomp(&(gl->preg), gl->pattern, reflags);
175 }
[1770]176 regmatch.rm_so = 0;
177 regmatch.rm_eo = 0;
178 if (regexec(&(gl->preg), line, 1, &regmatch, 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 }
[821]192 }
193 pattern_ptr = pattern_ptr->link;
194 } /* while (pattern_ptr) */
195
[1770]196 if (ret ^ invert_search) {
197 /* keep track of matches */
198 nmatches++;
[821]199
[1770]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 }
[821]210 /* if we're just printing filenames, we stop after the first match */
[1770]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 }
[821]218
219#if ENABLE_FEATURE_GREP_CONTEXT
[1770]220 /* Were we printing context and saw next (unwanted) match? */
221 if ((option_mask32 & OPT_m) && nmatches > max_matches)
222 break;
223#endif
[821]224
[1770]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;
[821]229
[1770]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;
[821]234
[1770]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++;
[821]242 }
243
[1770]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;
[821]256#endif
[1770]257 if (option_mask32 & OPT_o) {
258 line[regmatch.rm_eo] = '\0';
259 print_line(line + regmatch.rm_so, linenum, ':');
260 } else {
[821]261 print_line(line, linenum, ':');
262 }
263 }
[1770]264 }
[821]265#if ENABLE_FEATURE_GREP_CONTEXT
[1770]266 else { /* no match */
[821]267 /* if we need to print some context lines after the last match, do so */
[1770]268 if (print_n_lines_after) {
[821]269 print_line(line, linenum, '-');
270 print_n_lines_after--;
[1770]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;
[821]278 }
[1770]279 }
280
[821]281#endif /* ENABLE_FEATURE_GREP_CONTEXT */
282 free(line);
[1770]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;
[821]288 }
289
290 /* special-case file post-processing for options where we don't print line
291 * matches, just filenames and possibly match counts */
292
293 /* grep -c: print [filename:]count, even if count is zero */
294 if (PRINT_MATCH_COUNTS) {
[1770]295 if (print_filename)
[821]296 printf("%s:", cur_file);
[1770]297 printf("%d\n", nmatches);
[821]298 }
299
[1770]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 */
[821]305 puts(cur_file);
306 }
307
308 return nmatches;
309}
310
311#if ENABLE_FEATURE_CLEAN_UP
312#define new_grep_list_data(p, m) add_grep_list_data(p, m)
313static char * add_grep_list_data(char *pattern, int flg_used_mem)
314#else
315#define new_grep_list_data(p, m) add_grep_list_data(p)
316static char * add_grep_list_data(char *pattern)
317#endif
318{
319 grep_list_data_t *gl = xmalloc(sizeof(grep_list_data_t));
320 gl->pattern = pattern;
321#if ENABLE_FEATURE_CLEAN_UP
322 gl->flg_mem_alocated_compiled = flg_used_mem;
323#else
324 gl->flg_mem_alocated_compiled = 0;
325#endif
326 return (char *)gl;
327}
328
329static void load_regexes_from_file(llist_t *fopt)
330{
331 char *line;
332 FILE *f;
333
[1770]334 while (fopt) {
[821]335 llist_t *cur = fopt;
336 char *ffile = cur->data;
337
338 fopt = cur->link;
339 free(cur);
[1770]340 f = xfopen(ffile, "r");
341 while ((line = xmalloc_getline(f)) != NULL) {
[821]342 llist_add_to(&pattern_head,
343 new_grep_list_data(line, PATTERN_MEM_A));
344 }
345 }
346}
347
[1770]348static 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}
[821]362
[1770]363static 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
377int grep_main(int argc, char **argv);
[821]378int grep_main(int argc, char **argv)
379{
380 FILE *file;
381 int matched;
[1770]382 char *mopt;
[821]383 llist_t *fopt = NULL;
384
385 /* do normal option parsing */
386#if ENABLE_FEATURE_GREP_CONTEXT
387 char *slines_after;
388 char *slines_before;
389 char *Copt;
390
[1770]391 opt_complementary = "H-h:e::f::C-AB";
392 getopt32(argv,
393 OPTSTR_GREP,
394 &pattern_head, &fopt, &mopt,
[821]395 &slines_after, &slines_before, &Copt);
396
[1770]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 */
[821]401 slines_after = Copt;
[1770]402 if (!(option_mask32 & OPT_B)) /* not overridden */
[821]403 slines_before = Copt;
[1770]404 option_mask32 |= OPT_A|OPT_B; /* for parser */
[821]405 }
[1770]406 if (option_mask32 & OPT_A) {
407 lines_after = xatoi_u(slines_after);
[821]408 }
[1770]409 if (option_mask32 & OPT_B) {
410 lines_before = xatoi_u(slines_before);
[821]411 }
[1770]412 /* sanity checks */
413 if (option_mask32 & (OPT_c|OPT_q|OPT_l|OPT_L)) {
414 option_mask32 &= ~OPT_n;
[821]415 lines_before = 0;
416 lines_after = 0;
[1770]417 } else if (lines_before > 0)
418 before_buf = xzalloc(lines_before * sizeof(char *));
[821]419#else
420 /* with auto sanity checks */
[1770]421 opt_complementary = "H-h:e::f::c-n:q-n:l-n";
422 getopt32(argv, OPTSTR_GREP,
423 &pattern_head, &fopt, &mopt);
[821]424#endif
[1770]425 if (option_mask32 & OPT_m) {
426 max_matches = xatoi_u(mopt);
427 }
428 invert_search = ((option_mask32 & OPT_v) != 0); /* 0 | 1 */
[821]429
430 if (pattern_head != NULL) {
[1770]431 /* convert char **argv to grep_list_data_t */
[821]432 llist_t *cur;
433
[1770]434 for (cur = pattern_head; cur; cur = cur->link)
[821]435 cur->data = new_grep_list_data(cur->data, 0);
436 }
[1770]437 if (option_mask32 & OPT_f)
[821]438 load_regexes_from_file(fopt);
439
[1770]440 if (ENABLE_FEATURE_GREP_FGREP_ALIAS && applet_name[0] == 'f')
441 option_mask32 |= OPT_F;
[821]442
[1770]443 if (!(option_mask32 & (OPT_o | OPT_w)))
[821]444 reflags = REG_NOSUB;
445
[1770]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)
[821]451 reflags |= REG_ICASE;
452
453 argv += optind;
454 argc -= optind;
455
456 /* if we didn't get a pattern from a -e and no command file was specified,
457 * argv[optind] should be the pattern. no pattern, no worky */
458 if (pattern_head == NULL) {
[1770]459 char *pattern;
[821]460 if (*argv == NULL)
461 bb_show_usage();
[1770]462 pattern = new_grep_list_data(*argv++, 0);
463 llist_add_to(&pattern_head, pattern);
464 argc--;
[821]465 }
466
467 /* argv[(optind)..(argc-1)] should be names of file to grep through. If
[1770]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;
[821]476
477 /* If no files were specified, or '-' was specified, take input from
478 * stdin. Otherwise, we grep through all the files specified. */
[1770]479 if (argc == 0)
[821]480 argc++;
481 matched = 0;
482 while (argc--) {
483 cur_file = *argv++;
[1770]484 file = stdin;
485 if (!cur_file || (*cur_file == '-' && !cur_file[1])) {
[821]486 cur_file = "(standard input)";
487 } else {
[1770]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 */
[821]498 file = fopen(cur_file, "r");
[1770]499 if (file == NULL) {
500 if (!SUPPRESS_ERR_MSGS)
501 bb_perror_msg("%s", cur_file);
502 open_errors = 1;
503 continue;
[821]504 }
505 }
[1770]506 matched += grep_file(file);
507 fclose_if_not_stdin(file);
508 grep_done: ;
[821]509 }
510
511 /* destroy all the elments in the pattern list */
512 if (ENABLE_FEATURE_CLEAN_UP) {
513 while (pattern_head) {
514 llist_t *pattern_head_ptr = pattern_head;
515 grep_list_data_t *gl =
516 (grep_list_data_t *)pattern_head_ptr->data;
517
518 pattern_head = pattern_head->link;
[1770]519 if ((gl->flg_mem_alocated_compiled & PATTERN_MEM_A))
[821]520 free(gl->pattern);
[1770]521 if ((gl->flg_mem_alocated_compiled & COMPILED))
[821]522 regfree(&(gl->preg));
[1770]523 free(gl);
[821]524 free(pattern_head_ptr);
525 }
526 }
527 /* 0 = success, 1 = failed, 2 = error */
[1770]528 if (open_errors)
[821]529 return 2;
530 return !matched; /* invert return value 0 = success, 1 = failed */
531}
Note: See TracBrowser for help on using the repository browser.