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