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