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));