Ignore:
Timestamp:
Nov 4, 2007, 3:16:40 AM (16 years ago)
Author:
Bruno Cornec
Message:

Update to busybox 1.7.2

File:
1 edited

Legend:

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

    r821 r1765  
    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.