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

*** 50,59 **** --- 50,62 ---- #include <regexpr.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> + #include <ftw.h> + #include <limits.h> + #include <sys/param.h> static const char *errstr[] = { "Range endpoint too large.", "Bad number.", "``\\digit'' out of range.",
*** 71,80 **** --- 74,84 ---- }; #define errmsg(msg, arg) (void) fprintf(stderr, gettext(msg), arg) #define BLKSIZE 512 #define GBUFSIZ 8192 + #define MAX_DEPTH 1000 static int temp; static long long lnum; static char *linebuf; static char *prntbuf = NULL;
*** 81,90 **** --- 85,96 ---- static long fw_lPrntBufLen = 0; static int nflag; static int bflag; static int lflag; static int cflag; + static int rflag; + static int Rflag; static int vflag; static int sflag; static int iflag; static int wflag; static int hflag;
*** 91,107 **** static int qflag; static int errflg; static int nfile; static long long tln; static int nsucc; static int nlflag; static char *ptr, *ptrend; static char *expbuf; ! static void execute(char *); static void regerr(int); ! static int succeed(char *); int main(int argc, char **argv) { int c; --- 97,116 ---- static int qflag; static int errflg; static int nfile; static long long tln; static int nsucc; + static int outfn = 0; static int nlflag; static char *ptr, *ptrend; static char *expbuf; ! static void execute(const char *, int); static void regerr(int); ! static void prepare(const char *); ! static int recursive(const char *, const struct stat *, int, struct FTW *); ! static int succeed(const char *); int main(int argc, char **argv) { int c;
*** 112,122 **** #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ #endif (void) textdomain(TEXT_DOMAIN); ! while ((c = getopt(argc, argv, "hqblcnsviyw")) != -1) switch (c) { case 'h': hflag++; break; case 'q': /* POSIX: quiet: status only */ --- 121,131 ---- #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ #endif (void) textdomain(TEXT_DOMAIN); ! while ((c = getopt(argc, argv, "hqblcnRrsviyw")) != -1) switch (c) { case 'h': hflag++; break; case 'q': /* POSIX: quiet: status only */
*** 129,138 **** --- 138,153 ---- cflag++; break; case 'n': nflag++; break; + case 'R': + Rflag++; + /* FALLTHROUGH */ + case 'r': + rflag++; + break; case 'b': bflag++; break; case 's': sflag++;
*** 150,160 **** case '?': errflg++; } if (errflg || (optind >= argc)) { ! errmsg("Usage: grep [-c|-l|-q] -hbnsviw pattern file . . .\n", (char *)NULL); exit(2); } argv = &argv[optind]; --- 165,176 ---- case '?': errflg++; } if (errflg || (optind >= argc)) { ! errmsg("Usage: grep [-c|-l|-q] [-r|-R] -hbnsviw " ! "pattern file . . .\n", (char *)NULL); exit(2); } argv = &argv[optind];
*** 188,208 **** expbuf = compile(*argv, (char *)0, (char *)0); if (regerrno) regerr(regerrno); if (--argc == 0) ! execute(NULL); else while (argc-- > 0) ! execute(*++argv); return (nsucc == 2 ? 2 : (nsucc == 0 ? 1 : 0)); } static void ! execute(char *file) { char *lbuf, *p; long count; long offset = 0; char *next_ptr = NULL; long next_count = 0; --- 204,288 ---- expbuf = compile(*argv, (char *)0, (char *)0); if (regerrno) regerr(regerrno); if (--argc == 0) ! execute(NULL, 0); else while (argc-- > 0) ! prepare(*++argv); return (nsucc == 2 ? 2 : (nsucc == 0 ? 1 : 0)); } static void ! prepare(const char *path) { + struct stat st; + int walkflags = FTW_CHDIR; + char *buf = NULL; + + if (rflag) { + if (stat(path, &st) != -1 && + (st.st_mode & S_IFMT) == S_IFDIR) { + outfn = 1; + + /* + * Add trailing slash if arg + * is directory, to resolve symlinks. + */ + if (path[strlen(path) - 1] != '/') { + (void) asprintf(&buf, "%s/", path); + if (buf != NULL) + path = buf; + } + + /* + * Search through subdirs if path is directory. + * Don't follow symlinks if Rflag is not set. + */ + if (!Rflag) + walkflags |= FTW_PHYS; + + if (nftw(path, recursive, MAX_DEPTH, walkflags) != 0) { + if (!sflag) + errmsg("grep: can't open %s\n", path); + nsucc = 2; + } + return; + } + } + execute(path, 0); + } + + static int + recursive(const char *name, const struct stat *statp, int info, struct FTW *ftw) + { + /* + * process files and follow symlinks if Rflag set. + */ + if (info != FTW_F) { + if (!sflag && + (info == FTW_SLN || info == FTW_DNR || info == FTW_NS)) { + /* report broken symlinks and unreadable files */ + errmsg("grep: can't open %s\n", name); + } + return (0); + } + + /* skip devices and pipes if Rflag is not set */ + if (!Rflag && !S_ISREG(statp->st_mode)) + return (0); + + /* pass offset to relative name from FTW_CHDIR */ + execute(name, ftw->base); + return (0); + } + + static void + execute(const char *file, int base) + { char *lbuf, *p; long count; long offset = 0; char *next_ptr = NULL; long next_count = 0;
*** 219,229 **** } } if (file == NULL) temp = 0; ! else if ((temp = open(file, O_RDONLY)) == -1) { if (!sflag) errmsg("grep: can't open %s\n", file); nsucc = 2; return; } --- 299,309 ---- } } if (file == NULL) temp = 0; ! else if ((temp = open(file + base, O_RDONLY)) == -1) { if (!sflag) errmsg("grep: can't open %s\n", file); nsucc = 2; return; }
*** 233,242 **** --- 313,323 ---- (void) close(temp); if (cflag && !qflag) { if (nfile > 1 && !hflag && file) (void) fprintf(stdout, "%s:", file); + if (!rflag) (void) fprintf(stdout, "%lld\n", tln); } return; }
*** 327,344 **** offset = 0; } (void) close(temp); if (cflag && !qflag) { ! if (nfile > 1 && !hflag && file) (void) fprintf(stdout, "%s:", file); (void) fprintf(stdout, "%lld\n", tln); } } static int ! succeed(char *f) { int nchars; nsucc = (nsucc == 2) ? 2 : 1; if (f == NULL) --- 408,426 ---- offset = 0; } (void) close(temp); if (cflag && !qflag) { ! if (!hflag && file && (nfile > 1 || ! (rflag && outfn))) (void) fprintf(stdout, "%s:", file); (void) fprintf(stdout, "%lld\n", tln); } } static int ! succeed(const char *f) { int nchars; nsucc = (nsucc == 2) ? 2 : 1; if (f == NULL)
*** 357,369 **** if (lflag) { (void) fprintf(stdout, "%s\n", f); return (1); } ! if (nfile > 1 && !hflag) /* print filename */ (void) fprintf(stdout, "%s:", f); if (bflag) /* print block number */ (void) fprintf(stdout, "%lld:", (offset_t) ((lseek(temp, (off_t)0, SEEK_CUR) - 1) / BLKSIZE)); --- 439,452 ---- if (lflag) { (void) fprintf(stdout, "%s\n", f); return (1); } ! if (!hflag && (nfile > 1 || (rflag && outfn))) { /* print filename */ (void) fprintf(stdout, "%s:", f); + } if (bflag) /* print block number */ (void) fprintf(stdout, "%lld:", (offset_t) ((lseek(temp, (off_t)0, SEEK_CUR) - 1) / BLKSIZE));