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