From 114c8c73e7cd7d1622a679aa729dc421f6de3c58 Mon Sep 17 00:00:00 2001 From: wosch Date: Fri, 2 Feb 1996 06:45:26 +0000 Subject: recursive grep, enabled with -DHAVE_FTS=1 enable mmap (-DHAVE_MMAP=1) --- gnu/usr.bin/grep/Makefile | 2 +- gnu/usr.bin/grep/grep.1 | 56 ++++++++---- gnu/usr.bin/grep/grep.c | 223 +++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 261 insertions(+), 20 deletions(-) (limited to 'gnu/usr.bin/grep') diff --git a/gnu/usr.bin/grep/Makefile b/gnu/usr.bin/grep/Makefile index a7811a3..0cfcf6b 100644 --- a/gnu/usr.bin/grep/Makefile +++ b/gnu/usr.bin/grep/Makefile @@ -2,7 +2,7 @@ PROG= grep SRCS= dfa.c grep.c getopt.c kwset.c obstack.c search.c CFLAGS+=-DGREP -DHAVE_STRING_H=1 -DHAVE_SYS_PARAM_H=1 -DHAVE_UNISTD_H=1 \ -DHAVE_GETPAGESIZE=1 -DHAVE_MEMCHR=1 -DHAVE_STRERROR=1 \ - -DHAVE_VALLOC=1 + -DHAVE_VALLOC=1 -DHAVE_MMAP=1 -DHAVE_FTS=1 LINKS+= ${BINDIR}/grep ${BINDIR}/egrep \ ${BINDIR}/grep ${BINDIR}/fgrep diff --git a/gnu/usr.bin/grep/grep.1 b/gnu/usr.bin/grep/grep.1 index 27c6b0e..22e96e8 100644 --- a/gnu/usr.bin/grep/grep.1 +++ b/gnu/usr.bin/grep/grep.1 @@ -3,22 +3,13 @@ grep, egrep, fgrep \- print lines matching a pattern .SH SYNOPOSIS .B grep -[ -.BR \- [[ AB "] ]\c" -.I "num" -] -[ -.BR \- [ CEFGVBchilnsvwx ] -] -[ -.B \-e -] -.I pattern -| -.BI \-f file -] [ -.I files... -] +[\-[AB] num] +[\-HRPS] +[\-CEFGLVabchilnqsvwx] +[\-e expr] +[\-f file] +files... + .SH DESCRIPTION .PP .B Grep @@ -102,6 +93,9 @@ Print the version number of to standard error. This version number should be included in all bug reports (see below). .TP +.B \-a +Don't search in binary files. +.TP .B \-b Print the byte offset within the input file before each line of output. @@ -165,6 +159,36 @@ characters are letters, digits, and the underscore. .TP .B \-x Select only those matches that exactly match the whole line. + +.PP +Following options only avaible if compiled with FTS library: +.PD 0 +.TP +.BI \-H +If the +.I \-R +option is specified, symbolic links on the command line +are followed. (Symbolic links encountered in the tree traversal +are not followed.) +.TP + +.BI \-L +If the +.I \-R +option is specified, all symbolic links are followed. +.TP + +.BI \-P +If the +.I \-R +option is specified, no symbolic links are followed. +.TP + +.BI \-R +Search in the file hierarchies +rooted in the files instead of just the files themselves. +.TP + .PD .SH "REGULAR EXPRESSIONS" .PP diff --git a/gnu/usr.bin/grep/grep.c b/gnu/usr.bin/grep/grep.c index d7edf12..2576e3d 100644 --- a/gnu/usr.bin/grep/grep.c +++ b/gnu/usr.bin/grep/grep.c @@ -56,6 +56,7 @@ extern char *memchr(); #include #else #define O_RDONLY 0 +#define STDIN_FILENO 0 extern int open(), read(), close(); #endif @@ -94,6 +95,16 @@ memchr(vp, c, n) } #endif +/* traverse a file hierarchy library */ +#ifdef HAVE_FTS +#include +#include +#include +#endif + +/* don't search in binary files */ +int aflag; + /* Define flags declared in grep.h. */ char *matcher; int match_icase; @@ -499,6 +510,40 @@ grepbuf(beg, lim) return nlines; } + +/* + * try to guess if fd belong to a binary file + */ + +int isBinaryFile(fd) + int fd; +{ +#define BINARY_BUF_LEN 32 + static unsigned char buf[BINARY_BUF_LEN]; + int i, n; + + /* pipe, socket, fifo */ + if (lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) + return(0); + + if ((n =(int) read(fd, buf, (size_t)BINARY_BUF_LEN)) == -1) + return(0); + + /* look for non-printable chars */ + for(i = 0; i < n; i++) + if (!isprint(buf[i]) && !isspace(buf[i])) + return(1); + + /* reset fd to begin of file */ + if (lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) + return(0); + + + return(0); +} + + + /* Search a given file. Return a count of lines printed. */ static int grep(fd) @@ -508,6 +553,10 @@ grep(fd) size_t residue, save; char *beg, *lim; + /* skip binary files */ + if (aflag && isBinaryFile(fd)) + return(0); + reset(fd); totalcc = 0; @@ -568,8 +617,15 @@ grep(fd) static char version[] = "GNU grep version 2.0"; +#ifdef HAVE_FTS #define USAGE \ - "usage: %s [-[[AB] ]] [-[CEFGVchilnqsvwx]] [-[ef]] []\n" +"usage: %s [-[AB] ] [-HRPS] [-CEFGLVabchilnqsvwx]\n\ + [-e ] [-f file] [files ...]\n" +#else +#define USAGE \ +"usage: %s [-[AB] ] [-CEFGLVabchilnqsvwx]\n\ + [-e ] [-f file] [files ...]\n" +#endif static void usage() @@ -608,6 +664,12 @@ main(argc, argv) FILE *fp; extern char *optarg; extern int optind; +#ifdef HAVE_FTS + int Rflag, Hflag, Pflag, Lflag; + FTS *ftsp; + FTSENT *ftsent; + int fts_options; +#endif #ifdef __FreeBSD__ (void) setlocale(LC_CTYPE, ""); @@ -624,9 +686,20 @@ main(argc, argv) list_files = 0; suppress_errors = 0; matcher = NULL; + aflag = 0; +#ifdef HAVE_FTS + Rflag = Hflag = Pflag = Lflag = 0; +#endif - while ((opt = getopt(argc, argv, "0123456789A:B:CEFGVX:bce:f:hiLlnqsvwxy")) - != EOF) + while ((opt = getopt(argc, argv, + +#ifndef HAVE_FTS +"0123456789A:B:CEFGVX:abce:f:hiLlnqsvwxy" +#else +"0123456789A:B:CEFGHLPRSVX:abce:f:hiLlnqsvwxy?" +#endif + +)) != EOF) switch (opt) { case '0': @@ -678,6 +751,34 @@ main(argc, argv) fatal("matcher already specified", 0); matcher = optarg; break; + +#ifdef HAVE_FTS + /* symbolic links on the command line are followed */ + case 'H': + Hflag = 1; + Lflag = Pflag = 0; + break; + + /* no symbolic links are followed */ + case 'P': + Pflag = 1; + Hflag = Lflag = 0; + break; + + /* traverse file hierarchies */ + case 'R': + Rflag = 1; + break; + + /* all symbolic links are followed */ + case 'S': + Lflag = 1; + Hflag = Pflag = 0; + break; +#endif + case 'a': + aflag = 1; + break; case 'b': out_byte = 1; break; @@ -775,12 +876,126 @@ main(argc, argv) (*compile)(keys, keycc); +#ifndef HAVE_FTS if (argc - optind > 1 && !no_filenames) +#else + if ((argc - optind > 1 || Rflag) && !no_filenames) +#endif out_file = 1; status = 1; +#if HAVE_FTS + if (Rflag) { + fts_options = FTS_PHYSICAL | FTS_NOCHDIR; + + if (Hflag) + fts_options |= FTS_COMFOLLOW; + + if (Lflag) { + fts_options |= FTS_LOGICAL; + fts_options &= ~FTS_PHYSICAL; + } + + if (Pflag) { + fts_options &= ~FTS_LOGICAL & ~FTS_COMFOLLOW; + fts_options |= FTS_PHYSICAL; + } + } + + if (Rflag && optind < argc) { + int i; + + /* replace "-" with "/dev/stdin" */ + for (i = optind; i < argc; i++) + if (strcmp(argv[i], "-") == 0) + *(argv + i) = "/dev/stdin"; + + if ((ftsp = fts_open(argv + optind, fts_options, + (int(*)())NULL)) == NULL) { + if (!suppress_errors) + error("", errno); + } else { + + while((ftsent = fts_read(ftsp)) != NULL) { + filename = ftsent->fts_accpath; + + switch(ftsent->fts_info) { + + /* regular file */ + case FTS_F: + break; + + /* directory */ + case FTS_D: + case FTS_DC: + case FTS_DP: + continue; break; + + /* errors */ + case FTS_DNR: + error(filename, errno); + continue; break; + + case FTS_ERR: + case FTS_NS: + error(filename, ftsent->fts_errno); + continue; break; + + /* dead symlink */ + case FTS_SLNONE: + continue; break; + + /* symlink, don't skip */ + case FTS_SL: + break; + + default: + /* + if (!suppress_errors) + fprintf(stderr, "%s: ignored\n", filename); + continue; break; + */ + + } + + if ((desc = open(filename, O_RDONLY)) == -1) { + error(filename, errno); + continue; + } + + count = grep(desc); + if (count_matches) + { + if (out_file) + printf("%s:", filename); + printf("%d\n", count); + } + if (count) + { + status = 0; + if (list_files == 1) + printf("%s\n", filename); + } + else if (list_files == -1) + printf("%s\n", filename); + + if (desc != STDIN_FILENO) + close(desc); + } + + if (fts_close(ftsp) == -1) + error("fts_close", errno); + } + + /* ! Rflag */ + } else + +#endif /* HAVE_FTS */ + + /* search in file names from arguments, not from stdin */ if (optind < argc) + while (optind < argc) { desc = strcmp(argv[optind], "-") ? open(argv[optind], O_RDONLY) : 0; @@ -812,6 +1027,8 @@ main(argc, argv) close(desc); ++optind; } + + /* read input from stdin */ else { filename = "(standard input)"; -- cgit v1.1