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