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