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

*** 22,33 **** /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ - #pragma ident "%Z%%M% %I% %E% SMI" - /* * grep - pattern matching program - combined grep, egrep, and fgrep. * Based on MKS grep command, with XCU & Solaris mods. */ --- 22,31 ----
*** 34,43 **** --- 32,43 ---- /* * Copyright 1985, 1992 by Mortice Kern Systems Inc. All rights reserved. * */ + /* Copyright 2012 Nexenta Systems, Inc. All rights reserved. */ + #include <string.h> #include <stdlib.h> #include <ctype.h> #include <stdarg.h> #include <regex.h>
*** 49,61 **** --- 49,64 ---- #include <locale.h> #include <wchar.h> #include <errno.h> #include <unistd.h> #include <wctype.h> + #include <ftw.h> + #include <sys/param.h> #define BSIZE 512 /* Size of block for -b */ #define BUFSIZE 8192 /* Input buffer size */ + #define MAX_DEPTH 1000 /* how deep to recurse */ #define M_CSETSIZE 256 /* singlebyte chars */ static int bmglen; /* length of BMG pattern */ static char *bmgpat; /* BMG pattern */ static int bmgtab[M_CSETSIZE]; /* BMG delta1 table */
*** 68,120 **** } PATTERN; static PATTERN *patterns; static char errstr[128]; /* regerror string buffer */ static int regflags = 0; /* regcomp options */ static uchar_t fgrep = 0; /* Invoked as fgrep */ static uchar_t egrep = 0; /* Invoked as egrep */ static uchar_t nvflag = 1; /* Print matching lines */ static uchar_t cflag; /* Count of matches */ static uchar_t iflag; /* Case insensitve matching */ static uchar_t hflag; /* Supress printing of filename */ static uchar_t lflag; /* Print file names of matches */ static uchar_t nflag; /* Precede lines by line number */ static uchar_t bflag; /* Preccede matches by block number */ static uchar_t sflag; /* Suppress file error messages */ static uchar_t qflag; /* Suppress standard output */ static uchar_t wflag; /* Search for expression as a word */ static uchar_t xflag; /* Anchoring */ static uchar_t Eflag; /* Egrep or -E flag */ static uchar_t Fflag; /* Fgrep or -F flag */ static uchar_t outfn; /* Put out file name */ static char *cmdname; static int use_wchar, use_bmg, mblocale; static size_t outbuflen, prntbuflen; static char *prntbuf; static wchar_t *outline; ! static void addfile(char *fn); static void addpattern(char *s); static void fixpatterns(void); static void usage(void); ! static int grep(int, char *); static void bmgcomp(char *, int); static char *bmgexec(char *, char *); /* * mainline for grep */ int main(int argc, char **argv) { char *ap; - int matched = 0; int c; int fflag = 0; - int errors = 0; int i, n_pattern = 0, n_file = 0; char **pattern_list = NULL; char **file_list = NULL; (void) setlocale(LC_ALL, ""); --- 71,128 ---- } PATTERN; static PATTERN *patterns; static char errstr[128]; /* regerror string buffer */ static int regflags = 0; /* regcomp options */ + static int matched = 0; /* return of the grep() */ + static int errors = 0; /* count of errors */ static uchar_t fgrep = 0; /* Invoked as fgrep */ static uchar_t egrep = 0; /* Invoked as egrep */ static uchar_t nvflag = 1; /* Print matching lines */ static uchar_t cflag; /* Count of matches */ static uchar_t iflag; /* Case insensitve matching */ static uchar_t hflag; /* Supress printing of filename */ static uchar_t lflag; /* Print file names of matches */ static uchar_t nflag; /* Precede lines by line number */ + static uchar_t rflag; /* Search directories recursively */ static uchar_t bflag; /* Preccede matches by block number */ static uchar_t sflag; /* Suppress file error messages */ static uchar_t qflag; /* Suppress standard output */ static uchar_t wflag; /* Search for expression as a word */ static uchar_t xflag; /* Anchoring */ static uchar_t Eflag; /* Egrep or -E flag */ static uchar_t Fflag; /* Fgrep or -F flag */ + static uchar_t Rflag; /* Like rflag, but follow symlinks */ static uchar_t outfn; /* Put out file name */ static char *cmdname; static int use_wchar, use_bmg, mblocale; static size_t outbuflen, prntbuflen; static char *prntbuf; static wchar_t *outline; ! static void addfile(const char *fn); static void addpattern(char *s); static void fixpatterns(void); static void usage(void); ! static int grep(int, const char *); static void bmgcomp(char *, int); static char *bmgexec(char *, char *); + static int recursive(const char *, const struct stat *, int, struct FTW *); + static void process_path(const char *); + static void process_file(const char *, int); /* * mainline for grep */ int main(int argc, char **argv) { char *ap; int c; int fflag = 0; int i, n_pattern = 0, n_file = 0; char **pattern_list = NULL; char **file_list = NULL; (void) setlocale(LC_ALL, "");
*** 145,155 **** if (*ap == 'f' || *ap == 'F') { fgrep++; } } ! while ((c = getopt(argc, argv, "vwchilnbse:f:qxEFI")) != EOF) { switch (c) { case 'v': /* POSIX: negate matches */ nvflag = 0; break; --- 153,163 ---- if (*ap == 'f' || *ap == 'F') { fgrep++; } } ! while ((c = getopt(argc, argv, "vwchilnrbse:f:qxEFIR")) != EOF) { switch (c) { case 'v': /* POSIX: negate matches */ nvflag = 0; break;
*** 168,177 **** --- 176,189 ---- case 'n': /* POSIX: Write line numbers */ nflag++; break; + case 'r': /* Solaris: search recursively */ + rflag++; + break; + case 'b': /* Solaris: Write file block numbers */ bflag++; break; case 's': /* POSIX: No error msgs for files */
*** 228,237 **** --- 240,254 ---- case 'F': /* POSIX: strings, not RE's */ Fflag++; break; + case 'R': /* Solaris: like rflag, but follow symlinks */ + Rflag++; + rflag++; + break; + default: usage(); } } /*
*** 332,358 **** matched = grep(0, gettext("(standard input)")); } else { if (argc > 2 && hflag == 0) outfn = 1; /* Print filename on match line */ for (argv++; *argv != NULL; argv++) { ! int fd; ! ! if ((fd = open(*argv, O_RDONLY)) == -1) { ! errors = 1; ! if (sflag) ! continue; ! (void) fprintf(stderr, gettext( ! "%s: can't open \"%s\"\n"), ! cmdname, *argv); ! continue; } - matched |= grep(fd, *argv); - (void) close(fd); - if (ferror(stdout)) - break; } - } /* * Return() here is used instead of exit */ (void) fflush(stdout); --- 349,361 ---- matched = grep(0, gettext("(standard input)")); } else { if (argc > 2 && hflag == 0) outfn = 1; /* Print filename on match line */ for (argv++; *argv != NULL; argv++) { ! process_path(*argv); } } /* * Return() here is used instead of exit */ (void) fflush(stdout);
*** 360,374 **** if (errors) return (2); return (matched ? 0 : 1); } /* * Add a file of strings to the pattern list. */ static void ! addfile(char *fn) { FILE *fp; char *inbuf; char *bufp; size_t bufsiz, buflen, bufused; --- 363,476 ---- if (errors) return (2); return (matched ? 0 : 1); } + static void + process_path(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; /* Print filename */ + + /* + * 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) + (void) fprintf(stderr, + gettext("%s: can't open \"%s\"\n"), + cmdname, path); + errors = 1; + } + return; + } + } + process_file(path, 0); + } + /* + * Read and process all files in directory recursively. + */ + 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) { + /* Report broken symlinks and unreadable files */ + if (!sflag && + (info == FTW_SLN || info == FTW_DNR || info == FTW_NS)) { + (void) fprintf(stderr, + gettext("%s: can't open \"%s\"\n"), cmdname, 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 */ + process_file(name, ftw->base); + return (0); + } + + /* + * Opens file and call grep function. + */ + static void + process_file(const char *name, int base) + { + int fd; + + if ((fd = open(name + base, O_RDONLY)) == -1) { + errors = 1; + if (!sflag) /* Silent mode */ + (void) fprintf(stderr, gettext( + "%s: can't open \"%s\"\n"), + cmdname, name); + return; + } + matched |= grep(fd, name); + (void) close(fd); + + if (ferror(stdout)) { + (void) fprintf(stderr, gettext( + "%s: error writing to stdout\n"), + cmdname); + (void) fflush(stdout); + exit(2); + } + + } + + /* * Add a file of strings to the pattern list. */ static void ! addfile(const char *fn) { FILE *fp; char *inbuf; char *bufp; size_t bufsiz, buflen, bufused;
*** 673,683 **** * This is an order of magnitude faster. * Otherwise we split the buffer into lines, * and check for a match on each line. */ static int ! grep(int fd, char *fn) { PATTERN *pp; off_t data_len; /* length of the data chunk */ off_t line_len; /* length of the current line */ off_t line_offset; /* current line's offset from the beginning */ --- 775,785 ---- * This is an order of magnitude faster. * Otherwise we split the buffer into lines, * and check for a match on each line. */ static int ! grep(int fd, const char *fn) { PATTERN *pp; off_t data_len; /* length of the data chunk */ off_t line_len; /* length of the current line */ off_t line_offset; /* current line's offset from the beginning */
*** 738,752 **** */ count = read(fd, ptr + data_len, prntbuflen - data_len); if (count < 0) { /* read error */ if (cflag) { ! if (outfn) { (void) fprintf(stdout, "%s:", fn); } ! if (!qflag) { (void) fprintf(stdout, "%lld\n", matches); } } return (0); --- 840,854 ---- */ count = read(fd, ptr + data_len, prntbuflen - data_len); if (count < 0) { /* read error */ if (cflag) { ! if (outfn && !rflag) { (void) fprintf(stdout, "%s:", fn); } ! if (!qflag && !rflag) { (void) fprintf(stdout, "%lld\n", matches); } } return (0);
*** 1054,1094 **** usage(void) { if (egrep || fgrep) { (void) fprintf(stderr, gettext("Usage:\t%s"), cmdname); (void) fprintf(stderr, ! gettext(" [-c|-l|-q] [-bhinsvx] " "pattern_list [file ...]\n")); (void) fprintf(stderr, "\t%s", cmdname); (void) fprintf(stderr, ! gettext(" [-c|-l|-q] [-bhinsvx] [-e pattern_list]... " "[-f pattern_file]... [file...]\n")); } else { (void) fprintf(stderr, gettext("Usage:\t%s"), cmdname); (void) fprintf(stderr, ! gettext(" [-c|-l|-q] [-bhinsvwx] " "pattern_list [file ...]\n")); (void) fprintf(stderr, "\t%s", cmdname); (void) fprintf(stderr, ! gettext(" [-c|-l|-q] [-bhinsvwx] [-e pattern_list]... " "[-f pattern_file]... [file...]\n")); (void) fprintf(stderr, "\t%s", cmdname); (void) fprintf(stderr, ! gettext(" -E [-c|-l|-q] [-bhinsvx] " "pattern_list [file ...]\n")); (void) fprintf(stderr, "\t%s", cmdname); (void) fprintf(stderr, ! gettext(" -E [-c|-l|-q] [-bhinsvx] [-e pattern_list]... " "[-f pattern_file]... [file...]\n")); (void) fprintf(stderr, "\t%s", cmdname); (void) fprintf(stderr, ! gettext(" -F [-c|-l|-q] [-bhinsvx] " "pattern_list [file ...]\n")); (void) fprintf(stderr, "\t%s", cmdname); (void) fprintf(stderr, gettext(" -F [-c|-l|-q] [-bhinsvx] [-e pattern_list]... " --- 1156,1199 ---- usage(void) { if (egrep || fgrep) { (void) fprintf(stderr, gettext("Usage:\t%s"), cmdname); (void) fprintf(stderr, ! gettext(" [-c|-l|-q] [-r|-R] [-bhinsvx] " "pattern_list [file ...]\n")); (void) fprintf(stderr, "\t%s", cmdname); (void) fprintf(stderr, ! gettext(" [-c|-l|-q] [-r|-R] [-bhinsvx] " ! "[-e pattern_list]... " "[-f pattern_file]... [file...]\n")); } else { (void) fprintf(stderr, gettext("Usage:\t%s"), cmdname); (void) fprintf(stderr, ! gettext(" [-c|-l|-q] [-r|-R] [-bhinsvwx] " "pattern_list [file ...]\n")); (void) fprintf(stderr, "\t%s", cmdname); (void) fprintf(stderr, ! gettext(" [-c|-l|-q] [-r|-R] [-bhinsvwx] " ! "[-e pattern_list]... " "[-f pattern_file]... [file...]\n")); (void) fprintf(stderr, "\t%s", cmdname); (void) fprintf(stderr, ! gettext(" -E [-c|-l|-q] [-r|-R] [-bhinsvx] " "pattern_list [file ...]\n")); (void) fprintf(stderr, "\t%s", cmdname); (void) fprintf(stderr, ! gettext(" -E [-c|-l|-q] [-r|-R] [-bhinsvx] " ! "[-e pattern_list]... " "[-f pattern_file]... [file...]\n")); (void) fprintf(stderr, "\t%s", cmdname); (void) fprintf(stderr, ! gettext(" -F [-c|-l|-q] [-r|-R] [-bhinsvx] " "pattern_list [file ...]\n")); (void) fprintf(stderr, "\t%s", cmdname); (void) fprintf(stderr, gettext(" -F [-c|-l|-q] [-bhinsvx] [-e pattern_list]... "