Ignore:
Timestamp:
Nov 6, 2007, 11:01:53 AM (16 years ago)
Author:
Bruno Cornec
Message:
  • 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:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/stable/mindi-busybox/findutils/grep.c

    r821 r1770  
    66 * Copyright (C) 1999,2000,2001 by Mark Whitley <markw@codepoet.org>
    77 *
    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.
    99 */
    1010/* BB_AUDIT SUSv3 defects - unsupported option -x.  */
     
    1515 * correction "-e pattern1 -e pattern2" logic and more optimizations.
    1616 * 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"
    2523#include "xregex.h"
    2624
    27 
    2825/* 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
     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;
    7291static int reflags;
    73 static int print_filename;
    74 
    75 #if ENABLE_FEATURE_GREP_CONTEXT
     92static byte_t invert_search;
     93static byte_t print_filename;
     94static byte_t open_errors;
     95
     96#if ENABLE_FEATURE_GREP_CONTEXT
     97static byte_t did_print_line;
    7698static int lines_before;
    7799static int lines_after;
     
    79101static int last_line_printed;
    80102#endif /* ENABLE_FEATURE_GREP_CONTEXT */
    81 
    82103/* globals used internally */
    83104static llist_t *pattern_head;   /* growable list of patterns to match */
    84 static char *cur_file;          /* the current file we are reading */
    85 
    86 typedef struct GREP_LIST_DATA {
     105static const char *cur_file;    /* the current file we are reading */
     106
     107typedef struct grep_list_data_t {
    87108    char *pattern;
    88109    regex_t preg;
     
    95116{
    96117#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;
    97122    /* 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) {
    100125        puts("--");
    101126    }
     127    /* guard against printing "--" before first line of first file */
     128    did_print_line = 1;
    102129    last_line_printed = linenum;
    103130#endif
    104     if (print_filename > 0)
     131    if (print_filename)
    105132        printf("%s%c", cur_file, decoration);
    106133    if (PRINT_LINE_NUM)
    107134        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}
    111139
    112140static int grep_file(FILE *file)
    113141{
    114142    char *line;
    115     invert_search_t ret;
     143    byte_t ret;
    116144    int linenum = 0;
    117145    int nmatches = 0;
     146    regmatch_t regmatch;
    118147#if ENABLE_FEATURE_GREP_CONTEXT
    119148    int print_n_lines_after = 0;
    120149    int curpos = 0; /* track where we are in the circular 'before' buffer */
    121150    int idx = 0; /* used for iteration through the circular buffer */
     151#else
     152    enum { print_n_lines_after = 0 };
    122153#endif /* ENABLE_FEATURE_GREP_CONTEXT */
    123154
    124     while ((line = bb_get_chomped_line_from_file(file)) != NULL) {
     155    while ((line = xmalloc_getline(file)) != NULL) {
    125156        llist_t *pattern_ptr = pattern_head;
    126157        grep_list_data_t * gl;
     
    139170                 * invert search)
    140171                 */
    141                 if(!(gl->flg_mem_alocated_compiled & COMPILED)) {
     172                if (!(gl->flg_mem_alocated_compiled & COMPILED)) {
    142173                    gl->flg_mem_alocated_compiled |= COMPILED;
    143174                    xregcomp(&(gl->preg), gl->pattern, reflags);
    144175                }
    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, &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                }
    146192            }
    147193            pattern_ptr = pattern_ptr->link;
    148194        } /* while (pattern_ptr) */
    149195
    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                }
    162210                /* 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++;
    193242                    }
    194243
    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;
    197256#endif
     257                if (option_mask32 & OPT_o) {
     258                    line[regmatch.rm_eo] = '\0';
     259                    print_line(line + regmatch.rm_so, linenum, ':');
     260                } else {
    198261                    print_line(line, linenum, ':');
    199262                }
    200263            }
    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 */
    211267            /* 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) {
    213269                print_line(line, linenum, '-');
    214270                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;
    215278            }
     279        }
     280
    216281#endif /* ENABLE_FEATURE_GREP_CONTEXT */
    217282        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    }
    220289
    221290    /* special-case file post-processing for options where we don't print line
     
    224293    /* grep -c: print [filename:]count, even if count is zero */
    225294    if (PRINT_MATCH_COUNTS) {
    226         if (print_filename > 0)
     295        if (print_filename)
    227296            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 */
    238305        puts(cur_file);
    239306    }
     
    260327}
    261328
    262 
    263329static void load_regexes_from_file(llist_t *fopt)
    264330{
     
    266332    FILE *f;
    267333
    268     while(fopt) {
     334    while (fopt) {
    269335        llist_t *cur = fopt;
    270336        char *ffile = cur->data;
     
    272338        fopt = cur->link;
    273339        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) {
    276342            llist_add_to(&pattern_head,
    277343                new_grep_list_data(line, PATTERN_MEM_A));
     
    280346}
    281347
    282 
     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}
     362
     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);
    283378int grep_main(int argc, char **argv)
    284379{
    285380    FILE *file;
    286381    int matched;
     382    char *mopt;
    287383    llist_t *fopt = NULL;
    288     int error_open_count = 0;
    289384
    290385    /* do normal option parsing */
    291386#if ENABLE_FEATURE_GREP_CONTEXT
    292   {
    293     char *junk;
    294387    char *slines_after;
    295388    char *slines_before;
    296389    char *Copt;
    297390
    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,
    302395        &slines_after, &slines_before, &Copt);
    303396
    304     if(opt & GREP_OPT_C) {
    305         /* C option unseted A and B options, but next -A or -B
    306            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 */
    308401            slines_after = Copt;
    309         if(!(opt & GREP_OPT_B))         /* not overwtited */
     402        if (!(option_mask32 & OPT_B)) /* not overridden */
    310403            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;
    326415        lines_before = 0;
    327416        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 *));
    331419#else
    332420    /* 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);
    336424#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
    343430    if (pattern_head != NULL) {
    344         /* convert char *argv[] to grep_list_data_t */
     431        /* convert char **argv to grep_list_data_t */
    345432        llist_t *cur;
    346433
    347         for(cur = pattern_head; cur; cur = cur->link)
     434        for (cur = pattern_head; cur; cur = cur->link)
    348435            cur->data = new_grep_list_data(cur->data, 0);
    349436    }
    350     if(opt & GREP_OPT_f)
     437    if (option_mask32 & OPT_f)
    351438        load_regexes_from_file(fopt);
    352439
    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)))
    360444        reflags = REG_NOSUB;
    361445
    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)
    363451        reflags |= REG_ICASE;
    364452
     
    369457     * argv[optind] should be the pattern. no pattern, no worky */
    370458    if (pattern_head == NULL) {
     459        char *pattern;
    371460        if (*argv == NULL)
    372461            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--;
    379465    }
    380466
    381467    /* 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;
    385476
    386477    /* If no files were specified, or '-' was specified, take input from
    387478     * stdin. Otherwise, we grep through all the files specified. */
    388     } else if (argc == 0) {
     479    if (argc == 0)
    389480        argc++;
    390     }
    391481    matched = 0;
    392482    while (argc--) {
    393483        cur_file = *argv++;
    394         if(!cur_file || (*cur_file == '-' && !cur_file[1])) {
     484        file = stdin;
     485        if (!cur_file || (*cur_file == '-' && !cur_file[1])) {
    395486            cur_file = "(standard input)";
    396             file = stdin;
    397487        } 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 */
    398498            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            }
    399505        }
    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: ;
    413509    }
    414510
     
    421517
    422518            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))
    424520                free(gl->pattern);
    425             if((gl->flg_mem_alocated_compiled & COMPILED))
     521            if ((gl->flg_mem_alocated_compiled & COMPILED))
    426522                regfree(&(gl->preg));
     523            free(gl);
    427524            free(pattern_head_ptr);
    428525        }
    429526    }
    430527    /* 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)
    436529        return 2;
    437530    return !matched; /* invert return value 0 = success, 1 = failed */
Note: See TracChangeset for help on using the changeset viewer.