grep.c revision 56233
1/* grep.c - main driver file for grep.
2   Copyright (C) 1992, 1997, 1998, 1999 Free Software Foundation, Inc.
3
4   This program is free software; you can redistribute it and/or modify
5   it under the terms of the GNU General Public License as published by
6   the Free Software Foundation; either version 2, or (at your option)
7   any later version.
8
9   This program is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   GNU General Public License for more details.
13
14   You should have received a copy of the GNU General Public License
15   along with this program; if not, write to the Free Software
16   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
17   02111-1307, USA.  */
18
19/* Written July 1992 by Mike Haertel.  */
20/* Builtin decompression 1997 by Wolfram Schneider <wosch@FreeBSD.org>.  */
21
22/* $FreeBSD: head/gnu/usr.bin/grep/grep.c 56233 2000-01-18 09:46:39Z ru $ */
23
24#ifdef HAVE_CONFIG_H
25# include <config.h>
26#endif
27#include <sys/types.h>
28#include <sys/stat.h>
29#if defined(HAVE_MMAP)
30# include <sys/mman.h>
31#endif
32#if defined(HAVE_SETRLIMIT)
33# include <sys/time.h>
34# include <sys/resource.h>
35#endif
36#include <stdio.h>
37#include "system.h"
38#include "getopt.h"
39#include "getpagesize.h"
40#include "grep.h"
41#include "savedir.h"
42
43#undef MAX
44#define MAX(A,B) ((A) > (B) ? (A) : (B))
45
46struct stats
47{
48  struct stats *parent;
49  struct stat stat;
50};
51
52/* base of chain of stat buffers, used to detect directory loops */
53static struct stats stats_base;
54
55/* if non-zero, display usage information and exit */
56static int show_help;
57
58/* If non-zero, print the version on standard output and exit.  */
59static int show_version;
60
61/* If nonzero, use mmap if possible.  */
62static int mmap_option;
63
64/* If zero, output nulls after filenames.  */
65static int filename_mask;
66
67/* Short options.  */
68static char const short_options[] =
69"0123456789A:B:C::EFGHUVX:abcd:e:f:hiLlnqrsuvwxyZz";
70
71/* Non-boolean long options that have no corresponding short equivalents.  */
72enum
73{
74  BINARY_FILES_OPTION = CHAR_MAX + 1
75};
76
77/* Long options equivalences. */
78static struct option long_options[] =
79{
80  {"after-context", required_argument, NULL, 'A'},
81  {"basic-regexp", no_argument, NULL, 'G'},
82  {"before-context", required_argument, NULL, 'B'},
83  {"binary-files", required_argument, NULL, BINARY_FILES_OPTION},
84  {"byte-offset", no_argument, NULL, 'b'},
85  {"context", optional_argument, NULL, 'C'},
86  {"count", no_argument, NULL, 'c'},
87  {"directories", required_argument, NULL, 'd'},
88  {"extended-regexp", no_argument, NULL, 'E'},
89  {"file", required_argument, NULL, 'f'},
90  {"files-with-matches", no_argument, NULL, 'l'},
91  {"files-without-match", no_argument, NULL, 'L'},
92  {"fixed-regexp", no_argument, NULL, 'F'},
93  {"fixed-strings", no_argument, NULL, 'F'},
94  {"help", no_argument, &show_help, 1},
95  {"ignore-case", no_argument, NULL, 'i'},
96  {"line-number", no_argument, NULL, 'n'},
97  {"line-regexp", no_argument, NULL, 'x'},
98  {"mmap", no_argument, &mmap_option, 1},
99  {"no-filename", no_argument, NULL, 'h'},
100  {"no-messages", no_argument, NULL, 's'},
101#if HAVE_LIBZ > 0
102  {"decompress", no_argument, NULL, 'Z'},
103  {"null", no_argument, &filename_mask, 0},
104#else
105  {"null", no_argument, NULL, 'Z'},
106#endif
107  {"null-data", no_argument, NULL, 'z'},
108  {"quiet", no_argument, NULL, 'q'},
109  {"recursive", no_argument, NULL, 'r'},
110  {"regexp", required_argument, NULL, 'e'},
111  {"invert-match", no_argument, NULL, 'v'},
112  {"silent", no_argument, NULL, 'q'},
113  {"text", no_argument, NULL, 'a'},
114  {"binary", no_argument, NULL, 'U'},
115  {"unix-byte-offsets", no_argument, NULL, 'u'},
116  {"version", no_argument, NULL, 'V'},
117  {"with-filename", no_argument, NULL, 'H'},
118  {"word-regexp", no_argument, NULL, 'w'},
119  {0, 0, 0, 0}
120};
121
122/* Define flags declared in grep.h. */
123char const *matcher;
124int match_icase;
125int match_words;
126int match_lines;
127unsigned char eolbyte;
128
129/* For error messages. */
130static char *prog;
131static char const *filename;
132static int errseen;
133
134/* How to handle directories.  */
135static enum
136  {
137    READ_DIRECTORIES,
138    RECURSE_DIRECTORIES,
139    SKIP_DIRECTORIES
140  } directories;
141
142static int  ck_atoi PARAMS ((char const *, int *));
143static void usage PARAMS ((int)) __attribute__((noreturn));
144static void error PARAMS ((const char *, int));
145static void setmatcher PARAMS ((char const *));
146static int  install_matcher PARAMS ((char const *));
147static int  prepend_args PARAMS ((char const *, char *, char **));
148static void prepend_default_options PARAMS ((char const *, int *, char ***));
149static char *page_alloc PARAMS ((size_t, char **));
150static int  reset PARAMS ((int, char const *, struct stats *));
151static int  fillbuf PARAMS ((size_t, struct stats *));
152static int  grepbuf PARAMS ((char *, char *));
153static void prtext PARAMS ((char *, char *, int *));
154static void prpending PARAMS ((char *));
155static void prline PARAMS ((char *, char *, int));
156static void print_offset_sep PARAMS ((off_t, int));
157static void nlscan PARAMS ((char *));
158static int  grep PARAMS ((int, char const *, struct stats *));
159static int  grepdir PARAMS ((char const *, struct stats *));
160static int  grepfile PARAMS ((char const *, struct stats *));
161#if O_BINARY
162static inline int undossify_input PARAMS ((register char *, size_t));
163#endif
164
165/* Functions we'll use to search. */
166static void (*compile) PARAMS ((char *, size_t));
167static char *(*execute) PARAMS ((char *, size_t, char **));
168
169/* Print a message and possibly an error string.  Remember
170   that something awful happened. */
171static void
172error (mesg, errnum)
173     const char *mesg;
174     int errnum;
175{
176  if (errnum)
177    fprintf (stderr, "%s: %s: %s\n", prog, mesg, strerror (errnum));
178  else
179    fprintf (stderr, "%s: %s\n", prog, mesg);
180  errseen = 1;
181}
182
183/* Like error (), but die horribly after printing. */
184void
185fatal (mesg, errnum)
186     const char *mesg;
187     int errnum;
188{
189  error (mesg, errnum);
190  exit (2);
191}
192
193/* Interface to handle errors and fix library lossage. */
194char *
195xmalloc (size)
196     size_t size;
197{
198  char *result;
199
200  result = malloc (size);
201  if (size && !result)
202    fatal (_("memory exhausted"), 0);
203  return result;
204}
205
206/* Interface to handle errors and fix some library lossage. */
207char *
208xrealloc (ptr, size)
209     char *ptr;
210     size_t size;
211{
212  char *result;
213
214  if (ptr)
215    result = realloc (ptr, size);
216  else
217    result = malloc (size);
218  if (size && !result)
219    fatal (_("memory exhausted"), 0);
220  return result;
221}
222
223/* Convert STR to a positive integer, storing the result in *OUT.
224   If STR is not a valid integer, return -1 (otherwise 0). */
225static int
226ck_atoi (str, out)
227     char const *str;
228     int *out;
229{
230  char const *p;
231  for (p = str; *p; p++)
232    if (*p < '0' || *p > '9')
233      return -1;
234
235  *out = atoi (optarg);
236  return 0;
237}
238
239
240/* Hairy buffering mechanism for grep.  The intent is to keep
241   all reads aligned on a page boundary and multiples of the
242   page size. */
243
244static char *ubuffer;		/* Unaligned base of buffer. */
245static char *buffer;		/* Base of buffer. */
246static size_t bufsalloc;	/* Allocated size of buffer save region. */
247static size_t bufalloc;		/* Total buffer size. */
248#define PREFERRED_SAVE_FACTOR 5	/* Preferred value of bufalloc / bufsalloc.  */
249static int bufdesc;		/* File descriptor. */
250static char *bufbeg;		/* Beginning of user-visible stuff. */
251static char *buflim;		/* Limit of user-visible stuff. */
252static size_t pagesize;		/* alignment of memory pages */
253static off_t bufoffset;		/* Read offset; defined on regular files.  */
254
255#if defined(HAVE_MMAP)
256static int bufmapped;		/* True if buffer is memory-mapped.  */
257static off_t initial_bufoffset;	/* Initial value of bufoffset. */
258#endif
259
260#if HAVE_LIBZ > 0
261#include <zlib.h>
262static gzFile gzbufdesc;	/* zlib file descriptor. */
263static int Zflag;		/* uncompress before searching. */
264#endif
265
266/* Return VAL aligned to the next multiple of ALIGNMENT.  VAL can be
267   an integer or a pointer.  Both args must be free of side effects.  */
268#define ALIGN_TO(val, alignment) \
269  ((size_t) (val) % (alignment) == 0 \
270   ? (val) \
271   : (val) + ((alignment) - (size_t) (val) % (alignment)))
272
273/* Return the address of a page-aligned buffer of size SIZE,
274   reallocating it from *UP.  Set *UP to the newly allocated (but
275   possibly unaligned) buffer used to build the aligned buffer.  To
276   free the buffer, free (*UP).  */
277static char *
278page_alloc (size, up)
279     size_t size;
280     char **up;
281{
282  size_t asize = size + pagesize - 1;
283  if (size <= asize)
284    {
285      char *p = *up ? realloc (*up, asize) : malloc (asize);
286      if (p)
287	{
288	  *up = p;
289	  return ALIGN_TO (p, pagesize);
290	}
291    }
292  return NULL;
293}
294
295/* Reset the buffer for a new file, returning zero if we should skip it.
296   Initialize on the first time through. */
297static int
298reset (fd, file, stats)
299     int fd;
300     char const *file;
301     struct stats *stats;
302{
303  if (pagesize)
304    bufsalloc = ALIGN_TO (bufalloc / PREFERRED_SAVE_FACTOR, pagesize);
305  else
306    {
307      size_t ubufsalloc;
308      pagesize = getpagesize ();
309      if (pagesize == 0)
310	abort ();
311#ifndef BUFSALLOC
312      ubufsalloc = MAX (8192, pagesize);
313#else
314      ubufsalloc = BUFSALLOC;
315#endif
316      bufsalloc = ALIGN_TO (ubufsalloc, pagesize);
317      bufalloc = PREFERRED_SAVE_FACTOR * bufsalloc;
318      /* The 1 byte of overflow is a kludge for dfaexec(), which
319	 inserts a sentinel newline at the end of the buffer
320	 being searched.  There's gotta be a better way... */
321      if (bufsalloc < ubufsalloc
322	  || bufalloc / PREFERRED_SAVE_FACTOR != bufsalloc
323	  || bufalloc + 1 < bufalloc
324	  || ! (buffer = page_alloc (bufalloc + 1, &ubuffer)))
325	fatal (_("memory exhausted"), 0);
326    }
327#if HAVE_LIBZ > 0
328  if (Zflag)
329    {
330    gzbufdesc = gzdopen(fd, "r");
331    if (gzbufdesc == NULL)
332      fatal(_("memory exhausted"), 0);
333    }
334#endif
335
336  buflim = buffer;
337  bufdesc = fd;
338
339  if (fstat (fd, &stats->stat) != 0)
340    {
341      error ("fstat", errno);
342      return 0;
343    }
344  if (directories == SKIP_DIRECTORIES && S_ISDIR (stats->stat.st_mode))
345    return 0;
346  if (
347#if HAVE_LIBZ > 0
348      Zflag ||
349#endif
350      S_ISREG (stats->stat.st_mode))
351    {
352      if (file)
353	bufoffset = 0;
354      else
355	{
356	  bufoffset = lseek (fd, 0, SEEK_CUR);
357	  if (bufoffset < 0)
358	    {
359	      error ("lseek", errno);
360	      return 0;
361	    }
362	}
363#ifdef HAVE_MMAP
364      initial_bufoffset = bufoffset;
365      bufmapped = mmap_option && bufoffset % pagesize == 0;
366#endif
367    }
368  else
369    {
370#ifdef HAVE_MMAP
371      bufmapped = 0;
372#endif
373    }
374  return 1;
375}
376
377/* Read new stuff into the buffer, saving the specified
378   amount of old stuff.  When we're done, 'bufbeg' points
379   to the beginning of the buffer contents, and 'buflim'
380   points just after the end.  Return zero if there's an error.  */
381static int
382fillbuf (save, stats)
383     size_t save;
384     struct stats *stats;
385{
386  size_t fillsize = 0;
387  int cc = 1;
388  size_t readsize;
389
390  /* Offset from start of unaligned buffer to start of old stuff
391     that we want to save.  */
392  size_t saved_offset = buflim - ubuffer - save;
393
394  if (bufsalloc < save)
395    {
396      size_t aligned_save = ALIGN_TO (save, pagesize);
397      size_t maxalloc = (size_t) -1;
398      size_t newalloc;
399
400      if (S_ISREG (stats->stat.st_mode))
401	{
402	  /* Calculate an upper bound on how much memory we should allocate.
403	     We can't use ALIGN_TO here, since off_t might be longer than
404	     size_t.  Watch out for arithmetic overflow.  */
405	  off_t to_be_read = stats->stat.st_size - bufoffset;
406	  size_t slop = to_be_read % pagesize;
407	  off_t aligned_to_be_read = to_be_read + (slop ? pagesize - slop : 0);
408	  off_t maxalloc_off = aligned_save + aligned_to_be_read;
409	  if (0 <= maxalloc_off && maxalloc_off == (size_t) maxalloc_off)
410	    maxalloc = maxalloc_off;
411	}
412
413      /* Grow bufsalloc until it is at least as great as `save'; but
414	 if there is an overflow, just grow it to the next page boundary.  */
415      while (bufsalloc < save)
416	if (bufsalloc < bufsalloc * 2)
417	  bufsalloc *= 2;
418	else
419	  {
420	    bufsalloc = aligned_save;
421	    break;
422	  }
423
424      /* Grow the buffer size to be PREFERRED_SAVE_FACTOR times
425	 bufsalloc....  */
426      newalloc = PREFERRED_SAVE_FACTOR * bufsalloc;
427      if (maxalloc < newalloc)
428	{
429	  /* ... except don't grow it more than a pagesize past the
430	     file size, as that might cause unnecessary memory
431	     exhaustion if the file is large.  */
432	  newalloc = maxalloc;
433	  bufsalloc = aligned_save;
434	}
435
436      /* Check that the above calculations made progress, which might
437         not occur if there is arithmetic overflow.  If there's no
438	 progress, or if the new buffer size is larger than the old
439	 and buffer reallocation fails, report memory exhaustion.  */
440      if (bufsalloc < save || newalloc < save
441	  || (newalloc == save && newalloc != maxalloc)
442	  || (bufalloc < newalloc
443	      && ! (buffer
444		    = page_alloc ((bufalloc = newalloc) + 1, &ubuffer))))
445	fatal (_("memory exhausted"), 0);
446    }
447
448  bufbeg = buffer + bufsalloc - save;
449  memmove (bufbeg, ubuffer + saved_offset, save);
450  readsize = bufalloc - bufsalloc;
451
452#if defined(HAVE_MMAP)
453  if (bufmapped)
454    {
455      size_t mmapsize = readsize;
456
457      /* Don't mmap past the end of the file; some hosts don't allow this.
458	 Use `read' on the last page.  */
459      if (stats->stat.st_size - bufoffset < mmapsize)
460	{
461	  mmapsize = stats->stat.st_size - bufoffset;
462	  mmapsize -= mmapsize % pagesize;
463	}
464
465      if (mmapsize
466	  && (mmap ((caddr_t) (buffer + bufsalloc), mmapsize,
467		    PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED,
468		    bufdesc, bufoffset)
469	      != (caddr_t) -1))
470	{
471	  /* Do not bother to use madvise with MADV_SEQUENTIAL or
472	     MADV_WILLNEED on the mmapped memory.  One might think it
473	     would help, but it slows us down about 30% on SunOS 4.1.  */
474	  fillsize = mmapsize;
475	}
476      else
477	{
478	  /* Stop using mmap on this file.  Synchronize the file
479	     offset.  Do not warn about mmap failures.  On some hosts
480	     (e.g. Solaris 2.5) mmap can fail merely because some
481	     other process has an advisory read lock on the file.
482	     There's no point alarming the user about this misfeature.  */
483	  bufmapped = 0;
484	  if (bufoffset != initial_bufoffset
485	      && lseek (bufdesc, bufoffset, SEEK_SET) < 0)
486	    {
487	      error ("lseek", errno);
488	      cc = 0;
489	    }
490	}
491    }
492#endif /*HAVE_MMAP*/
493
494  if (! fillsize)
495    {
496      ssize_t bytesread;
497      do
498#if HAVE_LIBZ > 0
499	if (Zflag)
500	  bytesread = gzread (gzbufdesc, buffer + bufsalloc, readsize);
501	else
502#endif
503	  bytesread = read (bufdesc, buffer + bufsalloc, readsize);
504      while (bytesread < 0 && errno == EINTR);
505      if (bytesread < 0)
506	cc = 0;
507      else
508	fillsize = bytesread;
509    }
510
511  bufoffset += fillsize;
512#if O_BINARY
513  if (fillsize)
514    fillsize = undossify_input (buffer + bufsalloc, fillsize);
515#endif
516  buflim = buffer + bufsalloc + fillsize;
517  return cc;
518}
519
520/* Flags controlling the style of output. */
521static enum
522  {
523    BINARY_BINARY_FILES,
524    TEXT_BINARY_FILES,
525    WITHOUT_MATCH_BINARY_FILES
526  } binary_files;		/* How to handle binary files.  */
527static int out_quiet;		/* Suppress all normal output. */
528static int out_invert;		/* Print nonmatching stuff. */
529static int out_file;		/* Print filenames. */
530static int out_line;		/* Print line numbers. */
531static int out_byte;		/* Print byte offsets. */
532static int out_before;		/* Lines of leading context. */
533static int out_after;		/* Lines of trailing context. */
534static int count_matches;	/* Count matching lines.  */
535static int list_files;		/* List matching files.  */
536static int no_filenames;	/* Suppress file names.  */
537static int suppress_errors;	/* Suppress diagnostics.  */
538
539/* Internal variables to keep track of byte count, context, etc. */
540static off_t totalcc;		/* Total character count before bufbeg. */
541static char *lastnl;		/* Pointer after last newline counted. */
542static char *lastout;		/* Pointer after last character output;
543				   NULL if no character has been output
544				   or if it's conceptually before bufbeg. */
545static off_t totalnl;		/* Total newline count before lastnl. */
546static int pending;		/* Pending lines of output. */
547static int done_on_match;		/* Stop scanning file on first match */
548
549#if O_BINARY
550# include "dosbuf.c"
551#endif
552
553static void
554nlscan (lim)
555     char *lim;
556{
557  char *beg;
558  for (beg = lastnl;  (beg = memchr (beg, eolbyte, lim - beg));  beg++)
559    totalnl++;
560  lastnl = lim;
561}
562
563static void
564print_offset_sep (pos, sep)
565     off_t pos;
566     int sep;
567{
568  /* Do not rely on printf to print pos, since off_t may be longer than long,
569     and long long is not portable.  */
570
571  char buf[sizeof pos * CHAR_BIT];
572  char *p = buf + sizeof buf - 1;
573  *p = sep;
574
575  do
576    *--p = '0' + pos % 10;
577  while ((pos /= 10) != 0);
578
579  fwrite (p, 1, buf + sizeof buf - p, stdout);
580}
581
582static void
583prline (beg, lim, sep)
584     char *beg;
585     char *lim;
586     int sep;
587{
588  if (out_file)
589    printf ("%s%c", filename, sep & filename_mask);
590  if (out_line)
591    {
592      nlscan (beg);
593      print_offset_sep (++totalnl, sep);
594      lastnl = lim;
595    }
596  if (out_byte)
597    {
598      off_t pos = totalcc + (beg - bufbeg);
599#if O_BINARY
600      pos = dossified_pos (pos);
601#endif
602      print_offset_sep (pos, sep);
603    }
604  fwrite (beg, 1, lim - beg, stdout);
605  if (ferror (stdout))
606    error (_("writing output"), errno);
607  lastout = lim;
608}
609
610/* Print pending lines of trailing context prior to LIM. */
611static void
612prpending (lim)
613     char *lim;
614{
615  char *nl;
616
617  if (!lastout)
618    lastout = bufbeg;
619  while (pending > 0 && lastout < lim)
620    {
621      --pending;
622      if ((nl = memchr (lastout, eolbyte, lim - lastout)) != 0)
623	++nl;
624      else
625	nl = lim;
626      prline (lastout, nl, '-');
627    }
628}
629
630/* Print the lines between BEG and LIM.  Deal with context crap.
631   If NLINESP is non-null, store a count of lines between BEG and LIM. */
632static void
633prtext (beg, lim, nlinesp)
634     char *beg;
635     char *lim;
636     int *nlinesp;
637{
638  static int used;		/* avoid printing "--" before any output */
639  char *bp, *p, *nl;
640  char eol = eolbyte;
641  int i, n;
642
643  if (!out_quiet && pending > 0)
644    prpending (beg);
645
646  p = beg;
647
648  if (!out_quiet)
649    {
650      /* Deal with leading context crap. */
651
652      bp = lastout ? lastout : bufbeg;
653      for (i = 0; i < out_before; ++i)
654	if (p > bp)
655	  do
656	    --p;
657	  while (p > bp && p[-1] != eol);
658
659      /* We only print the "--" separator if our output is
660	 discontiguous from the last output in the file. */
661      if ((out_before || out_after) && used && p != lastout)
662	puts ("--");
663
664      while (p < beg)
665	{
666	  nl = memchr (p, eol, beg - p);
667	  prline (p, nl + 1, '-');
668	  p = nl + 1;
669	}
670    }
671
672  if (nlinesp)
673    {
674      /* Caller wants a line count. */
675      for (n = 0; p < lim; ++n)
676	{
677	  if ((nl = memchr (p, eol, lim - p)) != 0)
678	    ++nl;
679	  else
680	    nl = lim;
681	  if (!out_quiet)
682	    prline (p, nl, ':');
683	  p = nl;
684	}
685      *nlinesp = n;
686    }
687  else
688    if (!out_quiet)
689      prline (beg, lim, ':');
690
691  pending = out_quiet ? 0 : out_after;
692  used = 1;
693}
694
695/* Scan the specified portion of the buffer, matching lines (or
696   between matching lines if OUT_INVERT is true).  Return a count of
697   lines printed. */
698static int
699grepbuf (beg, lim)
700     char *beg;
701     char *lim;
702{
703  int nlines, n;
704  register char *p, *b;
705  char *endp;
706  char eol = eolbyte;
707
708  nlines = 0;
709  p = beg;
710  while ((b = (*execute)(p, lim - p, &endp)) != 0)
711    {
712      /* Avoid matching the empty line at the end of the buffer. */
713      if (b == lim && ((b > beg && b[-1] == eol) || b == beg))
714	break;
715      if (!out_invert)
716	{
717	  prtext (b, endp, (int *) 0);
718	  nlines += 1;
719	  if (done_on_match)
720	    return nlines;
721	}
722      else if (p < b)
723	{
724	  prtext (p, b, &n);
725	  nlines += n;
726	}
727      p = endp;
728    }
729  if (out_invert && p < lim)
730    {
731      prtext (p, lim, &n);
732      nlines += n;
733    }
734  return nlines;
735}
736
737/* Search a given file.  Normally, return a count of lines printed;
738   but if the file is a directory and we search it recursively, then
739   return -2 if there was a match, and -1 otherwise.  */
740static int
741grep (fd, file, stats)
742     int fd;
743     char const *file;
744     struct stats *stats;
745{
746  int nlines, i;
747  int not_text;
748  size_t residue, save;
749  char *beg, *lim;
750  char eol = eolbyte;
751
752  if (!reset (fd, file, stats))
753    return 0;
754
755  if (file && directories == RECURSE_DIRECTORIES
756      && S_ISDIR (stats->stat.st_mode))
757    {
758      /* Close fd now, so that we don't open a lot of file descriptors
759	 when we recurse deeply.  */
760#if HAVE_LIBZ > 0
761      if (Zflag)
762	gzclose(gzbufdesc);
763      else
764#endif
765      if (close (fd) != 0)
766	error (file, errno);
767      return grepdir (file, stats) - 2;
768    }
769
770  totalcc = 0;
771  lastout = 0;
772  totalnl = 0;
773  pending = 0;
774
775  nlines = 0;
776  residue = 0;
777  save = 0;
778
779  if (! fillbuf (save, stats))
780    {
781      if (! (is_EISDIR (errno, file) && suppress_errors))
782	error (filename, errno);
783      return 0;
784    }
785
786  not_text = (((binary_files == BINARY_BINARY_FILES && !out_quiet)
787	       || binary_files == WITHOUT_MATCH_BINARY_FILES)
788	      && memchr (bufbeg, eol ? '\0' : '\200', buflim - bufbeg));
789  if (not_text && binary_files == WITHOUT_MATCH_BINARY_FILES)
790    return 0;
791  done_on_match += not_text;
792  out_quiet += not_text;
793
794  for (;;)
795    {
796      lastnl = bufbeg;
797      if (lastout)
798	lastout = bufbeg;
799      if (buflim - bufbeg == save)
800	break;
801      beg = bufbeg + save - residue;
802      for (lim = buflim; lim > beg && lim[-1] != eol; --lim)
803	;
804      residue = buflim - lim;
805      if (beg < lim)
806	{
807	  nlines += grepbuf (beg, lim);
808	  if (pending)
809	    prpending (lim);
810	  if (nlines && done_on_match && !out_invert)
811	    goto finish_grep;
812	}
813      i = 0;
814      beg = lim;
815      while (i < out_before && beg > bufbeg && beg != lastout)
816	{
817	  ++i;
818	  do
819	    --beg;
820	  while (beg > bufbeg && beg[-1] != eol);
821	}
822      if (beg != lastout)
823	lastout = 0;
824      save = residue + lim - beg;
825      totalcc += buflim - bufbeg - save;
826      if (out_line)
827	nlscan (beg);
828      if (! fillbuf (save, stats))
829	{
830	  if (! (is_EISDIR (errno, file) && suppress_errors))
831	    error (filename, errno);
832	  goto finish_grep;
833	}
834    }
835  if (residue)
836    {
837      nlines += grepbuf (bufbeg + save - residue, buflim);
838      if (pending)
839	prpending (buflim);
840    }
841
842 finish_grep:
843  done_on_match -= not_text;
844  out_quiet -= not_text;
845  if ((not_text & ~out_quiet) && nlines != 0)
846    printf (_("Binary file %s matches\n"), filename);
847  return nlines;
848}
849
850static int
851grepfile (file, stats)
852     char const *file;
853     struct stats *stats;
854{
855  int desc;
856  int count;
857  int status;
858
859  if (! file)
860    {
861      desc = 0;
862      filename = _("(standard input)");
863    }
864  else
865    {
866      while ((desc = open (file, O_RDONLY)) < 0 && errno == EINTR)
867	continue;
868
869      if (desc < 0)
870	{
871	  int e = errno;
872
873	  if (is_EISDIR (e, file) && directories == RECURSE_DIRECTORIES)
874	    {
875	      if (stat (file, &stats->stat) != 0)
876		{
877		  error (file, errno);
878		  return 1;
879		}
880
881	      return grepdir (file, stats);
882	    }
883
884	  if (!suppress_errors)
885	    {
886	      if (directories == SKIP_DIRECTORIES)
887		switch (e)
888		  {
889#ifdef EISDIR
890		  case EISDIR:
891		    return 1;
892#endif
893		  case EACCES:
894		    /* When skipping directories, don't worry about
895		       directories that can't be opened.  */
896		    if (stat (file, &stats->stat) == 0
897			&& S_ISDIR (stats->stat.st_mode))
898		      return 1;
899		    break;
900		  }
901
902	      error (file, e);
903	    }
904
905	  return 1;
906	}
907
908      filename = file;
909    }
910
911#if O_BINARY
912  /* Set input to binary mode.  Pipes are simulated with files
913     on DOS, so this includes the case of "foo | grep bar".  */
914  if (!isatty (desc))
915    SET_BINARY (desc);
916#endif
917
918  count = grep (desc, file, stats);
919  if (count < 0)
920    status = count + 2;
921  else
922    {
923      if (count_matches)
924	{
925	  if (out_file)
926	    printf ("%s%c", filename, ':' & filename_mask);
927	  printf ("%d\n", count);
928	}
929
930      status = !count;
931      if (list_files == 1 - 2 * status)
932	printf ("%s%c", filename, '\n' & filename_mask);
933
934#if HAVE_LIBZ > 0
935      if (Zflag)
936	gzclose(gzbufdesc);
937      else
938#endif
939      if (file)
940	while (close (desc) != 0)
941	  if (errno != EINTR)
942	    {
943	      error (file, errno);
944	      break;
945	    }
946    }
947
948  return status;
949}
950
951static int
952grepdir (dir, stats)
953     char const *dir;
954     struct stats *stats;
955{
956  int status = 1;
957  struct stats *ancestor;
958  char *name_space;
959
960  for (ancestor = stats;  (ancestor = ancestor->parent) != 0;  )
961    if (ancestor->stat.st_ino == stats->stat.st_ino
962	&& ancestor->stat.st_dev == stats->stat.st_dev)
963      {
964	if (!suppress_errors)
965	  fprintf (stderr, _("%s: warning: %s: %s\n"), prog, dir,
966		   _("recursive directory loop"));
967	return 1;
968      }
969
970  name_space = savedir (dir, (unsigned) stats->stat.st_size);
971
972  if (! name_space)
973    {
974      if (errno)
975	{
976	  if (!suppress_errors)
977	    error (dir, errno);
978	}
979      else
980	fatal (_("Memory exhausted"), 0);
981    }
982  else
983    {
984      size_t dirlen = strlen (dir);
985      int needs_slash = ! (dirlen == FILESYSTEM_PREFIX_LEN (dir)
986			   || IS_SLASH (dir[dirlen - 1]));
987      char *file = NULL;
988      char *namep = name_space;
989      struct stats child;
990      child.parent = stats;
991      out_file += !no_filenames;
992      while (*namep)
993	{
994	  size_t namelen = strlen (namep);
995	  file = xrealloc (file, dirlen + 1 + namelen + 1);
996	  strcpy (file, dir);
997	  file[dirlen] = '/';
998	  strcpy (file + dirlen + needs_slash, namep);
999	  namep += namelen + 1;
1000	  status &= grepfile (file, &child);
1001	}
1002      out_file -= !no_filenames;
1003      if (file)
1004        free (file);
1005      free (name_space);
1006    }
1007
1008  return status;
1009}
1010
1011static void
1012usage(status)
1013int status;
1014{
1015  if (status != 0)
1016    {
1017      fprintf (stderr, _("Usage: %s [OPTION]... PATTERN [FILE]...\n"), prog);
1018      fprintf (stderr, _("Try `%s --help' for more information.\n"), prog);
1019    }
1020  else
1021    {
1022      printf (_("Usage: %s [OPTION]... PATTERN [FILE] ...\n"), prog);
1023      printf (_("\
1024Search for PATTERN in each FILE or standard input.\n\
1025Example: %s -i 'hello.*world' menu.h main.c\n\
1026\n\
1027Regexp selection and interpretation:\n"), prog);
1028      printf (_("\
1029  -E, --extended-regexp     PATTERN is an extended regular expression\n\
1030  -F, --fixed-strings       PATTERN is a set of newline-separated strings\n\
1031  -G, --basic-regexp        PATTERN is a basic regular expression\n"));
1032      printf (_("\
1033  -e, --regexp=PATTERN      use PATTERN as a regular expression\n\
1034  -f, --file=FILE           obtain PATTERN from FILE\n\
1035  -i, --ignore-case         ignore case distinctions\n\
1036  -w, --word-regexp         force PATTERN to match only whole words\n\
1037  -x, --line-regexp         force PATTERN to match only whole lines\n\
1038  -z, --null-data           a data line ends in 0 byte, not newline\n"));
1039      printf (_("\
1040\n\
1041Miscellaneous:\n\
1042  -s, --no-messages         suppress error messages\n\
1043  -v, --invert-match        select non-matching lines\n\
1044  -V, --version             print version information and exit\n\
1045      --help                display this help and exit\n\
1046  -Z, --decompress          decompress input before searching (HAVE_LIBZ=1)\n\
1047      --mmap                use memory-mapped input if possible\n"));
1048      printf (_("\
1049\n\
1050Output control:\n\
1051  -b, --byte-offset         print the byte offset with output lines\n\
1052  -n, --line-number         print line number with output lines\n\
1053  -H, --with-filename       print the filename for each match\n\
1054  -h, --no-filename         suppress the prefixing filename on output\n\
1055  -q, --quiet, --silent     suppress all normal output\n\
1056  -a, --text                equivalent to --binary-files=text\n\
1057      --binary-files=TYPE   assume that binary files are TYPE\n\
1058                            TYPE is 'binary', 'text', or 'without-match'.\n\
1059  -d, --directories=ACTION  how to handle directories\n\
1060                            ACTION is 'read', 'recurse', or 'skip'.\n\
1061  -r, --recursive           equivalent to --directories=recurse.\n\
1062  -L, --files-without-match only print FILE names containing no match\n\
1063  -l, --files-with-matches  only print FILE names containing matches\n\
1064  -c, --count               only print a count of matching lines per FILE\n\
1065      --null                print 0 byte after FILE name\n"));
1066      printf (_("\
1067\n\
1068Context control:\n\
1069  -B, --before-context=NUM  print NUM lines of leading context\n\
1070  -A, --after-context=NUM   print NUM lines of trailing context\n\
1071  -C, --context[=NUM]       print NUM (default 2) lines of output context\n\
1072                            unless overridden by -A or -B\n\
1073  -NUM                      same as --context=NUM\n\
1074  -U, --binary              do not strip CR characters at EOL (MSDOS)\n\
1075  -u, --unix-byte-offsets   report offsets as if CRs were not there (MSDOS)\n\
1076\n\
1077`egrep' means `grep -E'.  `fgrep' means `grep -F'.\n\
1078With no FILE, or when FILE is -, read standard input.  If less than\n\
1079two FILEs given, assume -h.  Exit status is 0 if match, 1 if no match,\n\
1080and 2 if trouble.\n"));
1081      printf (_("\nReport bugs to <bug-gnu-utils@gnu.org>.\n"));
1082    }
1083  exit (status);
1084}
1085
1086/* Set the matcher to M, reporting any conflicts.  */
1087static void
1088setmatcher (m)
1089     char const *m;
1090{
1091  if (matcher && strcmp (matcher, m) != 0)
1092    fatal (_("conflicting matchers specified"), 0);
1093  matcher = m;
1094}
1095
1096/* Go through the matchers vector and look for the specified matcher.
1097   If we find it, install it in compile and execute, and return 1.  */
1098static int
1099install_matcher (name)
1100     char const *name;
1101{
1102  int i;
1103#ifdef HAVE_SETRLIMIT
1104  struct rlimit rlim;
1105#endif
1106
1107  for (i = 0; matchers[i].name; ++i)
1108    if (strcmp (name, matchers[i].name) == 0)
1109      {
1110	compile = matchers[i].compile;
1111	execute = matchers[i].execute;
1112#if HAVE_SETRLIMIT && defined(RLIMIT_STACK)
1113	/* I think every platform needs to do this, so that regex.c
1114	   doesn't oveflow the stack.  The default value of
1115	   `re_max_failures' is too large for some platforms: it needs
1116	   more than 3MB-large stack.
1117
1118	   The test for HAVE_SETRLIMIT should go into `configure'.  */
1119	if (!getrlimit (RLIMIT_STACK, &rlim))
1120	  {
1121	    long newlim;
1122	    extern long int re_max_failures; /* from regex.c */
1123
1124	    /* Approximate the amount regex.c needs, plus some more.  */
1125	    newlim = re_max_failures * 2 * 20 * sizeof (char *);
1126	    if (newlim > rlim.rlim_max)
1127	      {
1128		newlim = rlim.rlim_max;
1129		re_max_failures = newlim / (2 * 20 * sizeof (char *));
1130	      }
1131	    if (rlim.rlim_cur < newlim)
1132	      rlim.rlim_cur = newlim;
1133
1134	    setrlimit (RLIMIT_STACK, &rlim);
1135	  }
1136#endif
1137	return 1;
1138      }
1139  return 0;
1140}
1141
1142/* Find the white-space-separated options specified by OPTIONS, and
1143   using BUF to store copies of these options, set ARGV[0], ARGV[1],
1144   etc. to the option copies.  Return the number N of options found.
1145   Do not set ARGV[N] to NULL.  If ARGV is NULL, do not store ARGV[0]
1146   etc.  Backslash can be used to escape whitespace (and backslashes).  */
1147static int
1148prepend_args (options, buf, argv)
1149     char const *options;
1150     char *buf;
1151     char **argv;
1152{
1153  char const *o = options;
1154  char *b = buf;
1155  int n = 0;
1156
1157  for (;;)
1158    {
1159      while (ISSPACE ((unsigned char) *o))
1160	o++;
1161      if (!*o)
1162	return n;
1163      if (argv)
1164	argv[n] = b;
1165      n++;
1166
1167      do
1168	if ((*b++ = *o++) == '\\' && *o)
1169	  b[-1] = *o++;
1170      while (*o && ! ISSPACE ((unsigned char) *o));
1171
1172      *b++ = '\0';
1173    }
1174}
1175
1176/* Prepend the whitespace-separated options in OPTIONS to the argument
1177   vector of a main program with argument count *PARGC and argument
1178   vector *PARGV.  */
1179static void
1180prepend_default_options (options, pargc, pargv)
1181     char const *options;
1182     int *pargc;
1183     char ***pargv;
1184{
1185  if (options)
1186    {
1187      char *buf = xmalloc (strlen (options) + 1);
1188      int prepended = prepend_args (options, buf, (char **) NULL);
1189      int argc = *pargc;
1190      char * const *argv = *pargv;
1191      char **pp = (char **) xmalloc ((prepended + argc + 1) * sizeof *pp);
1192      *pargc = prepended + argc;
1193      *pargv = pp;
1194      *pp++ = *argv++;
1195      pp += prepend_args (options, buf, pp);
1196      while ((*pp++ = *argv++))
1197	continue;
1198    }
1199}
1200
1201int
1202main (argc, argv)
1203     int argc;
1204     char *argv[];
1205{
1206  char *keys;
1207  size_t keycc, oldcc, keyalloc;
1208  int with_filenames;
1209  int opt, cc, status;
1210  unsigned digit_args_val, default_context;
1211  FILE *fp;
1212  extern char *optarg;
1213  extern int optind;
1214
1215  initialize_main (&argc, &argv);
1216  prog = argv[0];
1217  if (prog && strrchr (prog, '/'))
1218    prog = strrchr (prog, '/') + 1;
1219
1220#if HAVE_LIBZ > 0
1221  if (prog[0] == 'z') {
1222    Zflag = 1;
1223    ++prog;
1224  }
1225#endif
1226
1227#if defined(__MSDOS__) || defined(_WIN32)
1228  /* DOS and MS-Windows use backslashes as directory separators, and usually
1229     have an .exe suffix.  They also have case-insensitive filesystems.  */
1230  if (prog)
1231    {
1232      char *p = prog;
1233      char *bslash = strrchr (argv[0], '\\');
1234
1235      if (bslash && bslash >= prog) /* for mixed forward/backslash case */
1236	prog = bslash + 1;
1237      else if (prog == argv[0]
1238	       && argv[0][0] && argv[0][1] == ':') /* "c:progname" */
1239	prog = argv[0] + 2;
1240
1241      /* Collapse the letter-case, so `strcmp' could be used hence.  */
1242      for ( ; *p; p++)
1243	if (*p >= 'A' && *p <= 'Z')
1244	  *p += 'a' - 'A';
1245
1246      /* Remove the .exe extension, if any.  */
1247      if ((p = strrchr (prog, '.')) && strcmp (p, ".exe") == 0)
1248	*p = '\0';
1249    }
1250#endif
1251
1252  keys = NULL;
1253  keycc = 0;
1254  with_filenames = 0;
1255  eolbyte = '\n';
1256  filename_mask = ~0;
1257
1258  /* The value -1 means to use DEFAULT_CONTEXT. */
1259  out_after = out_before = -1;
1260  /* Default before/after context: chaged by -C/-NUM options */
1261  default_context = 0;
1262  /* Accumulated value of individual digits in a -NUM option */
1263  digit_args_val = 0;
1264
1265
1266/* Internationalization. */
1267#if HAVE_SETLOCALE
1268  setlocale (LC_ALL, "");
1269#endif
1270#if ENABLE_NLS
1271  bindtextdomain (PACKAGE, LOCALEDIR);
1272  textdomain (PACKAGE);
1273#endif
1274
1275  prepend_default_options (getenv ("GREP_OPTIONS"), &argc, &argv);
1276
1277  while ((opt = getopt_long (argc, argv, short_options, long_options, NULL))
1278	 != -1)
1279    switch (opt)
1280      {
1281      case '0':
1282      case '1':
1283      case '2':
1284      case '3':
1285      case '4':
1286      case '5':
1287      case '6':
1288      case '7':
1289      case '8':
1290      case '9':
1291	digit_args_val = 10 * digit_args_val + opt - '0';
1292	default_context = digit_args_val;
1293	break;
1294      case 'A':
1295	if (optarg)
1296	  {
1297	    if (ck_atoi (optarg, &out_after))
1298	      fatal (_("invalid context length argument"), 0);
1299	  }
1300	break;
1301      case 'B':
1302	if (optarg)
1303	  {
1304	    if (ck_atoi (optarg, &out_before))
1305	      fatal (_("invalid context length argument"), 0);
1306	  }
1307	break;
1308      case 'C':
1309	/* Set output match context, but let any explicit leading or
1310	   trailing amount specified with -A or -B stand. */
1311	if (optarg)
1312	  {
1313	    if (ck_atoi (optarg, &default_context))
1314	      fatal (_("invalid context length argument"), 0);
1315	  }
1316	else
1317	  default_context = 2;
1318	break;
1319      case 'E':
1320	setmatcher ("egrep");
1321	break;
1322      case 'F':
1323	setmatcher ("fgrep");
1324	break;
1325      case 'G':
1326	setmatcher ("grep");
1327	break;
1328      case 'H':
1329	with_filenames = 1;
1330	break;
1331      case 'U':
1332#if O_BINARY
1333	dos_use_file_type = DOS_BINARY;
1334#endif
1335	break;
1336      case 'u':
1337#if O_BINARY
1338	dos_report_unix_offset = 1;
1339#endif
1340	break;
1341      case 'V':
1342	show_version = 1;
1343	break;
1344      case 'X':
1345	setmatcher (optarg);
1346	break;
1347      case 'a':
1348	binary_files = TEXT_BINARY_FILES;
1349	break;
1350      case 'b':
1351	out_byte = 1;
1352	break;
1353      case 'c':
1354	out_quiet = 1;
1355	count_matches = 1;
1356	break;
1357      case 'd':
1358	if (strcmp (optarg, "read") == 0)
1359	  directories = READ_DIRECTORIES;
1360	else if (strcmp (optarg, "skip") == 0)
1361	  directories = SKIP_DIRECTORIES;
1362	else if (strcmp (optarg, "recurse") == 0)
1363	  directories = RECURSE_DIRECTORIES;
1364	else
1365	  fatal (_("unknown directories method"), 0);
1366	break;
1367      case 'e':
1368	cc = strlen (optarg);
1369	keys = xrealloc (keys, keycc + cc + 1);
1370	strcpy (&keys[keycc], optarg);
1371	keycc += cc;
1372	keys[keycc++] = '\n';
1373	break;
1374      case 'f':
1375	fp = strcmp (optarg, "-") != 0 ? fopen (optarg, "r") : stdin;
1376	if (!fp)
1377	  fatal (optarg, errno);
1378	for (keyalloc = 1; keyalloc <= keycc + 1; keyalloc *= 2)
1379	  ;
1380	keys = xrealloc (keys, keyalloc);
1381	oldcc = keycc;
1382	while (!feof (fp)
1383	       && (cc = fread (keys + keycc, 1, keyalloc - 1 - keycc, fp)) > 0)
1384	  {
1385	    keycc += cc;
1386	    if (keycc == keyalloc - 1)
1387	      keys = xrealloc (keys, keyalloc *= 2);
1388	  }
1389	if (fp != stdin)
1390	  fclose(fp);
1391	/* Append final newline if file ended in non-newline. */
1392	if (oldcc != keycc && keys[keycc - 1] != '\n')
1393	  keys[keycc++] = '\n';
1394	break;
1395      case 'h':
1396	no_filenames = 1;
1397	break;
1398      case 'i':
1399      case 'y':			/* For old-timers . . . */
1400	match_icase = 1;
1401	break;
1402      case 'L':
1403	/* Like -l, except list files that don't contain matches.
1404	   Inspired by the same option in Hume's gre. */
1405	out_quiet = 1;
1406	list_files = -1;
1407	done_on_match = 1;
1408	break;
1409      case 'l':
1410	out_quiet = 1;
1411	list_files = 1;
1412	done_on_match = 1;
1413	break;
1414      case 'n':
1415	out_line = 1;
1416	break;
1417      case 'q':
1418	done_on_match = 1;
1419	out_quiet = 1;
1420	break;
1421      case 'R':
1422      case 'r':
1423	directories = RECURSE_DIRECTORIES;
1424	break;
1425      case 's':
1426	suppress_errors = 1;
1427	break;
1428      case 'v':
1429	out_invert = 1;
1430	break;
1431      case 'w':
1432	match_words = 1;
1433	break;
1434      case 'x':
1435	match_lines = 1;
1436	break;
1437      case 'Z':
1438#if HAVE_LIBZ > 0
1439	Zflag = 1;
1440#else
1441	filename_mask = 0;
1442#endif
1443	break;
1444      case 'z':
1445	eolbyte = '\0';
1446	break;
1447      case BINARY_FILES_OPTION:
1448	if (strcmp (optarg, "binary") == 0)
1449	  binary_files = BINARY_BINARY_FILES;
1450	else if (strcmp (optarg, "text") == 0)
1451	  binary_files = TEXT_BINARY_FILES;
1452	else if (strcmp (optarg, "without-match") == 0)
1453	  binary_files = WITHOUT_MATCH_BINARY_FILES;
1454	else
1455	  fatal (_("unknown binary-files type"), 0);
1456	break;
1457      case 0:
1458	/* long options */
1459	break;
1460      default:
1461	usage (2);
1462	break;
1463      }
1464
1465  if (out_after < 0)
1466    out_after = default_context;
1467  if (out_before < 0)
1468    out_before = default_context;
1469
1470  if (! matcher)
1471    matcher = prog;
1472
1473  if (show_version)
1474    {
1475      printf (_("%s (GNU grep) %s\n"), matcher, VERSION);
1476      printf ("\n");
1477      printf (_("\
1478Copyright (C) 1988, 1992-1998, 1999 Free Software Foundation, Inc.\n"));
1479      printf (_("\
1480This is free software; see the source for copying conditions. There is NO\n\
1481warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"));
1482      printf ("\n");
1483      exit (0);
1484    }
1485
1486  if (show_help)
1487    usage (0);
1488
1489  if (keys)
1490    {
1491      if (keycc == 0)
1492	/* No keys were specified (e.g. -f /dev/null).  Match nothing.  */
1493        out_invert ^= 1;
1494      else
1495	/* Strip trailing newline. */
1496        --keycc;
1497    }
1498  else
1499    if (optind < argc)
1500      {
1501	keys = argv[optind++];
1502	keycc = strlen (keys);
1503      }
1504    else
1505      usage (2);
1506
1507  if (!install_matcher (matcher) && !install_matcher ("default"))
1508    abort ();
1509
1510  (*compile)(keys, keycc);
1511
1512  if ((argc - optind > 1 && !no_filenames) || with_filenames)
1513    out_file = 1;
1514
1515#if O_BINARY
1516  /* Output is set to binary mode because we shouldn't convert
1517     NL to CR-LF pairs, especially when grepping binary files.  */
1518  if (!isatty (1))
1519    SET_BINARY (1);
1520#endif
1521
1522
1523  if (optind < argc)
1524    {
1525	status = 1;
1526	do
1527	{
1528	  char *file = argv[optind];
1529	  status &= grepfile (strcmp (file, "-") == 0 ? (char *) NULL : file,
1530			      &stats_base);
1531	}
1532	while ( ++optind < argc);
1533    }
1534  else
1535    status = grepfile ((char *) NULL, &stats_base);
1536
1537  if (fclose (stdout) == EOF)
1538    error (_("writing output"), errno);
1539
1540  exit (errseen ? 2 : status);
1541}
1542