Print this page
3047 grep support for -r would be useful

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/grep/grep.c
          +++ new/usr/src/cmd/grep/grep.c
↓ open down ↓ 44 lines elided ↑ open up ↑
  45   45  
  46   46  #include <ctype.h>
  47   47  #include <fcntl.h>
  48   48  #include <locale.h>
  49   49  #include <memory.h>
  50   50  #include <regexpr.h>
  51   51  #include <stdio.h>
  52   52  #include <stdlib.h>
  53   53  #include <string.h>
  54   54  #include <unistd.h>
       55 +#include <ftw.h>
       56 +#include <limits.h>
       57 +#include <sys/param.h>
  55   58  
  56   59  static const char *errstr[] = {
  57   60          "Range endpoint too large.",
  58   61          "Bad number.",
  59   62          "``\\digit'' out of range.",
  60   63          "No remembered search string.",
  61   64          "\\( \\) imbalance.",
  62   65          "Too many \\(.",
  63   66          "More than 2 numbers given in \\{ \\}.",
  64   67          "} expected after \\.",
↓ open down ↓ 1 lines elided ↑ open up ↑
  66   69          "[ ] imbalance.",
  67   70          "Regular expression overflow.",
  68   71          "Illegal byte sequence.",
  69   72          "Unknown regexp error code!!",
  70   73          NULL
  71   74  };
  72   75  
  73   76  #define errmsg(msg, arg)        (void) fprintf(stderr, gettext(msg), arg)
  74   77  #define BLKSIZE 512
  75   78  #define GBUFSIZ 8192
       79 +#define MAX_DEPTH       1000
  76   80  
  77   81  static int      temp;
  78   82  static long long        lnum;
  79   83  static char     *linebuf;
  80   84  static char     *prntbuf = NULL;
  81   85  static long     fw_lPrntBufLen = 0;
  82   86  static int      nflag;
  83   87  static int      bflag;
  84   88  static int      lflag;
  85   89  static int      cflag;
       90 +static int      rflag;
       91 +static int      Rflag;
  86   92  static int      vflag;
  87   93  static int      sflag;
  88   94  static int      iflag;
  89   95  static int      wflag;
  90   96  static int      hflag;
  91   97  static int      qflag;
  92   98  static int      errflg;
  93   99  static int      nfile;
  94  100  static long long        tln;
  95  101  static int      nsucc;
      102 +static int      outfn = 0;
  96  103  static int      nlflag;
  97  104  static char     *ptr, *ptrend;
  98  105  static char     *expbuf;
  99  106  
 100      -static void     execute(char *);
      107 +static void     execute(const char *, int);
 101  108  static void     regerr(int);
 102      -static int      succeed(char *);
      109 +static void     prepare(const char *);
      110 +static int      recursive(const char *, const struct stat *, int, struct FTW *);
      111 +static int      succeed(const char *);
 103  112  
 104  113  int
 105  114  main(int argc, char **argv)
 106  115  {
 107  116          int     c;
 108  117          char    *arg;
 109  118          extern int      optind;
 110  119  
 111  120          (void) setlocale(LC_ALL, "");
 112  121  #if !defined(TEXT_DOMAIN)       /* Should be defined by cc -D */
 113  122  #define TEXT_DOMAIN "SYS_TEST"  /* Use this only if it weren't */
 114  123  #endif
 115  124          (void) textdomain(TEXT_DOMAIN);
 116  125  
 117      -        while ((c = getopt(argc, argv, "hqblcnsviyw")) != -1)
      126 +        while ((c = getopt(argc, argv, "hqblcnRrsviyw")) != -1)
 118  127                  switch (c) {
 119  128                  case 'h':
 120  129                          hflag++;
 121  130                          break;
 122  131                  case 'q':       /* POSIX: quiet: status only */
 123  132                          qflag++;
 124  133                          break;
 125  134                  case 'v':
 126  135                          vflag++;
 127  136                          break;
 128  137                  case 'c':
 129  138                          cflag++;
 130  139                          break;
 131  140                  case 'n':
 132  141                          nflag++;
 133  142                          break;
      143 +                case 'R':
      144 +                        Rflag++;
      145 +                        /* FALLTHROUGH */
      146 +                case 'r':
      147 +                        rflag++;
      148 +                        break;
 134  149                  case 'b':
 135  150                          bflag++;
 136  151                          break;
 137  152                  case 's':
 138  153                          sflag++;
 139  154                          break;
 140  155                  case 'l':
 141  156                          lflag++;
 142  157                          break;
 143  158                  case 'y':
↓ open down ↓ 1 lines elided ↑ open up ↑
 145  160                          iflag++;
 146  161                          break;
 147  162                  case 'w':
 148  163                          wflag++;
 149  164                          break;
 150  165                  case '?':
 151  166                          errflg++;
 152  167                  }
 153  168  
 154  169          if (errflg || (optind >= argc)) {
 155      -                errmsg("Usage: grep [-c|-l|-q] -hbnsviw pattern file . . .\n",
      170 +                errmsg("Usage: grep [-c|-l|-q] [-r|-R] -hbnsviw "
      171 +                    "pattern file . . .\n",
 156  172                      (char *)NULL);
 157  173                  exit(2);
 158  174          }
 159  175  
 160  176          argv = &argv[optind];
 161  177          argc -= optind;
 162  178          nfile = argc - 1;
 163  179  
 164  180          if (strrchr(*argv, '\n') != NULL)
 165  181                  regerr(41);
↓ open down ↓ 17 lines elided ↑ open up ↑
 183  199                  (void) strcat(wordbuf, *argv);
 184  200                  (void) strcat(wordbuf, "\\>");
 185  201                  *argv = wordbuf;
 186  202          }
 187  203  
 188  204          expbuf = compile(*argv, (char *)0, (char *)0);
 189  205          if (regerrno)
 190  206                  regerr(regerrno);
 191  207  
 192  208          if (--argc == 0)
 193      -                execute(NULL);
      209 +                execute(NULL, 0);
 194  210          else
 195  211                  while (argc-- > 0)
 196      -                        execute(*++argv);
      212 +                        prepare(*++argv);
 197  213  
 198  214          return (nsucc == 2 ? 2 : (nsucc == 0 ? 1 : 0));
 199  215  }
 200  216  
 201  217  static void
 202      -execute(char *file)
      218 +prepare(const char *path)
 203  219  {
      220 +        struct  stat st;
      221 +        int     walkflags = FTW_CHDIR;
      222 +        char    *buf = NULL;
      223 +
      224 +        if (rflag) {
      225 +                if (stat(path, &st) != -1 &&
      226 +                    (st.st_mode & S_IFMT) == S_IFDIR) {
      227 +                        outfn = 1;
      228 +
      229 +                        /*
      230 +                         * Add trailing slash if arg
      231 +                         * is directory, to resolve symlinks.
      232 +                         */
      233 +                        if (path[strlen(path) - 1] != '/') {
      234 +                                (void) asprintf(&buf, "%s/", path);
      235 +                                if (buf != NULL)
      236 +                                        path = buf;
      237 +                        }
      238 +
      239 +                        /*
      240 +                         * Search through subdirs if path is directory.
      241 +                         * Don't follow symlinks if Rflag is not set.
      242 +                         */
      243 +                        if (!Rflag)
      244 +                                walkflags |= FTW_PHYS;
      245 +
      246 +                        if (nftw(path, recursive, MAX_DEPTH, walkflags) != 0) {
      247 +                                if (!sflag)
      248 +                                        errmsg("grep: can't open %s\n", path);
      249 +                                nsucc = 2;
      250 +                        }
      251 +                        return;
      252 +                }
      253 +        }
      254 +        execute(path, 0);
      255 +}
      256 +
      257 +static int
      258 +recursive(const char *name, const struct stat *statp, int info, struct FTW *ftw)
      259 +{
      260 +        /*
      261 +         * process files and follow symlinks if Rflag set.
      262 +         */
      263 +        if (info != FTW_F) {
      264 +                if (!sflag &&
      265 +                    (info == FTW_SLN || info == FTW_DNR || info == FTW_NS)) {
      266 +                        /* report broken symlinks and unreadable files */
      267 +                        errmsg("grep: can't open %s\n", name);
      268 +                }
      269 +                return (0);
      270 +        }
      271 +
      272 +        /* skip devices and pipes if Rflag is not set */
      273 +        if (!Rflag && !S_ISREG(statp->st_mode))
      274 +                return (0);
      275 +
      276 +        /* pass offset to relative name from FTW_CHDIR */
      277 +        execute(name, ftw->base);
      278 +        return (0);
      279 +}
      280 +
      281 +static void
      282 +execute(const char *file, int base)
      283 +{
 204  284          char    *lbuf, *p;
 205  285          long    count;
 206  286          long    offset = 0;
 207  287          char    *next_ptr = NULL;
 208  288          long    next_count = 0;
 209  289  
 210  290          tln = 0;
 211  291  
 212  292          if (prntbuf == NULL) {
 213  293                  fw_lPrntBufLen = GBUFSIZ + 1;
 214  294                  if ((prntbuf = malloc(fw_lPrntBufLen)) == NULL) {
 215  295                          exit(2); /* out of memory - BAIL */
 216  296                  }
 217  297                  if ((linebuf = malloc(fw_lPrntBufLen)) == NULL) {
 218  298                          exit(2); /* out of memory - BAIL */
 219  299                  }
 220  300          }
 221  301  
 222  302          if (file == NULL)
 223  303                  temp = 0;
 224      -        else if ((temp = open(file, O_RDONLY)) == -1) {
      304 +        else if ((temp = open(file + base, O_RDONLY)) == -1) {
 225  305                  if (!sflag)
 226  306                          errmsg("grep: can't open %s\n", file);
 227  307                  nsucc = 2;
 228  308                  return;
 229  309          }
 230  310  
 231  311          /* read in first block of bytes */
 232  312          if ((count = read(temp, prntbuf, GBUFSIZ)) <= 0) {
 233  313                  (void) close(temp);
 234  314  
 235  315                  if (cflag && !qflag) {
 236  316                          if (nfile > 1 && !hflag && file)
 237  317                                  (void) fprintf(stdout, "%s:", file);
      318 +                        if (!rflag)
 238  319                          (void) fprintf(stdout, "%lld\n", tln);
 239  320                  }
 240  321                  return;
 241  322          }
 242  323  
 243  324          lnum = 0;
 244  325          ptr = prntbuf;
 245  326          for (;;) {
 246  327                  /* look for next newline */
 247  328                  if ((ptrend = memchr(ptr + offset, '\n', count)) == NULL) {
↓ open down ↓ 74 lines elided ↑ open up ↑
 322  403                  if (!nlflag)
 323  404                          break;
 324  405  
 325  406                  ptr = next_ptr;
 326  407                  count = next_count;
 327  408                  offset = 0;
 328  409          }
 329  410          (void) close(temp);
 330  411  
 331  412          if (cflag && !qflag) {
 332      -                if (nfile > 1 && !hflag && file)
      413 +                if (!hflag && file && (nfile > 1 ||
      414 +                    (rflag && outfn)))
 333  415                          (void) fprintf(stdout, "%s:", file);
 334  416                  (void) fprintf(stdout, "%lld\n", tln);
 335  417          }
 336  418  }
 337  419  
 338  420  static int
 339      -succeed(char *f)
      421 +succeed(const char *f)
 340  422  {
 341  423          int nchars;
 342  424          nsucc = (nsucc == 2) ? 2 : 1;
 343  425  
 344  426          if (f == NULL)
 345  427                  f = "<stdin>";
 346  428  
 347  429          if (qflag) {
 348  430                  /* no need to continue */
 349  431                  return (1);
↓ open down ↓ 2 lines elided ↑ open up ↑
 352  434          if (cflag) {
 353  435                  tln++;
 354  436                  return (0);
 355  437          }
 356  438  
 357  439          if (lflag) {
 358  440                  (void) fprintf(stdout, "%s\n", f);
 359  441                  return (1);
 360  442          }
 361  443  
 362      -        if (nfile > 1 && !hflag)
      444 +        if (!hflag && (nfile > 1 || (rflag && outfn))) {
 363  445                  /* print filename */
 364  446                  (void) fprintf(stdout, "%s:", f);
      447 +        }
 365  448  
 366  449          if (bflag)
 367  450                  /* print block number */
 368  451                  (void) fprintf(stdout, "%lld:", (offset_t)
 369  452                      ((lseek(temp, (off_t)0, SEEK_CUR) - 1) / BLKSIZE));
 370  453  
 371  454          if (nflag)
 372  455                  /* print line number */
 373  456                  (void) fprintf(stdout, "%lld:", lnum);
 374  457  
↓ open down ↓ 62 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX