summaryrefslogtreecommitdiffstats
path: root/gnu
diff options
context:
space:
mode:
authorwosch <wosch@FreeBSD.org>1996-02-02 06:45:26 +0000
committerwosch <wosch@FreeBSD.org>1996-02-02 06:45:26 +0000
commit114c8c73e7cd7d1622a679aa729dc421f6de3c58 (patch)
tree4dba842be53d2cfbb558e635cb4cd5bd9b1da57a /gnu
parent64d13f8d9c21f962cd83fe8c57055c9bcf1add65 (diff)
downloadFreeBSD-src-114c8c73e7cd7d1622a679aa729dc421f6de3c58.zip
FreeBSD-src-114c8c73e7cd7d1622a679aa729dc421f6de3c58.tar.gz
recursive grep, enabled with -DHAVE_FTS=1
enable mmap (-DHAVE_MMAP=1)
Diffstat (limited to 'gnu')
-rw-r--r--gnu/usr.bin/grep/Makefile2
-rw-r--r--gnu/usr.bin/grep/grep.156
-rw-r--r--gnu/usr.bin/grep/grep.c223
3 files changed, 261 insertions, 20 deletions
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 <unistd.h>
#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 <sys/types.h>
+#include <sys/stat.h>
+#include <fts.h>
+#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] ]<num>] [-[CEFGVchilnqsvwx]] [-[ef]] <expr> [<files...>]\n"
+"usage: %s [-[AB] <num>] [-HRPS] [-CEFGLVabchilnqsvwx]\n\
+ [-e <expr>] [-f file] [files ...]\n"
+#else
+#define USAGE \
+"usage: %s [-[AB] <num>] [-CEFGLVabchilnqsvwx]\n\
+ [-e <expr>] [-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)";
OpenPOWER on IntegriCloud