No empty .Rs/.Re
[netbsd-mini2440.git] / gnu / dist / grep / src / grep.c
blobbe1864c790b2c9568c2dc708e61ff4465abb6635
1 /* $NetBSD: grep.c,v 1.11 2006/01/19 17:50:33 wiz Exp $ */
3 /* grep.c - main driver file for grep.
4 Copyright 1992, 1997-1999, 2000 Free Software Foundation, Inc.
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.
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.
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. */
21 /* Written July 1992 by Mike Haertel. */
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"
47 #undef MAX
48 #define MAX(A,B) ((A) > (B) ? (A) : (B))
50 struct stats
52 struct stats const *parent;
53 struct stat stat;
56 /* base of chain of stat buffers, used to detect directory loops */
57 static struct stats stats_base;
59 /* if non-zero, display usage information and exit */
60 static int show_help;
62 /* If non-zero, print the version on standard output and exit. */
63 static int show_version;
65 /* If nonzero, suppress diagnostics for nonexistent or unreadable files. */
66 static int suppress_errors;
68 /* If nonzero, use mmap if possible. */
69 static int mmap_option;
71 /* If nonzero, use grep_color marker. */
72 static int color_option;
74 /* If nonzero, show only the part of a line matching the expression. */
75 static int only_matching;
77 /* The color string used. The user can overwrite it using the environment
78 variable GREP_COLOR. The default is to print red. */
79 static const char *grep_color = "01;31";
81 static struct exclude *excluded_patterns;
82 static struct exclude *included_patterns;
83 /* Short options. */
84 static char const short_options[] =
85 "0123456789A:B:C:D:EFGHIPUVX:abcd:e:f:hiKLlm:noqRrsuvwxyZz";
87 /* Non-boolean long options that have no corresponding short equivalents. */
88 enum
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
99 /* Long options equivalences. */
100 static struct option const long_options[] =
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}
151 /* Define flags declared in grep.h. */
152 int match_icase;
153 int match_words;
154 int match_lines;
155 unsigned char eolbyte;
157 /* For error messages. */
158 /* The name the program was run with, stripped of any leading path. */
159 char *program_name;
160 static char const *filename;
161 static int errseen;
163 /* How to handle directories. */
164 static enum
166 READ_DIRECTORIES,
167 RECURSE_DIRECTORIES,
168 SKIP_DIRECTORIES
169 } directories = READ_DIRECTORIES;
171 /* How to handle devices. */
172 static enum
174 READ_DEVICES,
175 SKIP_DEVICES
176 } devices = READ_DEVICES;
178 static int grepdir PARAMS ((char const *, struct stats const *));
179 #if defined(HAVE_DOS_FILE_CONTENTS)
180 static inline int undossify_input PARAMS ((register char *, size_t));
181 #endif
183 /* Functions we'll use to search. */
184 static void (*compile) PARAMS ((char const *, size_t));
185 static size_t (*execute) PARAMS ((char const *, size_t, size_t *, int));
187 /* Like error, but suppress the diagnostic if requested. */
188 static void
189 suppressible_error (char const *mesg, int errnum)
191 if (! suppress_errors)
192 error (0, errnum, "%s", mesg);
193 errseen = 1;
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. */
199 static void
200 context_length_arg (char const *str, int *out)
202 uintmax_t value;
203 if (! (xstrtoumax (str, 0, 10, &value, "") == LONGINT_OK
204 && 0 <= (*out = value)
205 && *out == value))
207 error (2, 0, "%s: %s", str, _("invalid context length argument"));
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. */
216 static char *buffer; /* Base of buffer. */
217 static size_t bufalloc; /* Allocated buffer size, counting slop. */
218 #define INITIAL_BUFSIZE 32768 /* Initial buffer size, not counting slop. */
219 static int bufdesc; /* File descriptor. */
220 static char *bufbeg; /* Beginning of user-visible stuff. */
221 static char *buflim; /* Limit of user-visible stuff. */
222 static size_t pagesize; /* alignment of memory pages */
223 static off_t bufoffset; /* Read offset; defined on regular files. */
224 static off_t after_last_match; /* Pointer after last matching line that
225 would have been output if we were
226 outputting characters. */
228 #if defined(HAVE_MMAP)
229 static int bufmapped; /* True if buffer is memory-mapped. */
230 static off_t initial_bufoffset; /* Initial value of bufoffset. */
231 #else
232 # define bufmapped 0
233 #endif
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)))
242 /* Reset the buffer for a new file, returning zero if we should skip it.
243 Initialize on the first time through. */
244 static int
245 reset (int fd, char const *file, struct stats *stats)
247 if (! pagesize)
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);
256 bufbeg = buflim = ALIGN_TO (buffer + 1, pagesize);
257 bufbeg[-1] = eolbyte;
258 bufdesc = fd;
260 if (fstat (fd, &stats->stat) != 0)
262 error (0, errno, "fstat");
263 return 0;
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))
275 if (file)
276 bufoffset = 0;
277 else
279 bufoffset = lseek (fd, 0, SEEK_CUR);
280 if (bufoffset < 0)
282 error (0, errno, "lseek");
283 return 0;
286 #if defined(HAVE_MMAP)
287 initial_bufoffset = bufoffset;
288 bufmapped = mmap_option && bufoffset % pagesize == 0;
289 #endif
291 else
293 #if defined(HAVE_MMAP)
294 bufmapped = 0;
295 #endif
297 return 1;
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. */
304 static int
305 fillbuf (size_t save, struct stats const *stats)
307 size_t fillsize = 0;
308 int cc = 1;
309 char *readbuf;
310 size_t readsize;
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;
316 if (pagesize <= buffer + bufalloc - buflim)
318 readbuf = buflim;
319 bufbeg = buflim - save;
321 else
323 size_t minsize = save + pagesize;
324 size_t newsize;
325 size_t newalloc;
326 char *newbuf;
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 ();
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))
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;
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;
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)
360 free (buffer);
361 buffer = newbuf;
365 readsize = buffer + bufalloc - readbuf;
366 readsize -= readsize % pagesize;
368 #if defined(HAVE_MMAP)
369 if (bufmapped)
371 size_t mmapsize = readsize;
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)
377 mmapsize = stats->stat.st_size - bufoffset;
378 mmapsize -= mmapsize % pagesize;
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))
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;
392 else
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)
403 error (0, errno, "lseek");
404 cc = 0;
408 #endif /*HAVE_MMAP*/
410 if (! fillsize)
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;
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;
431 /* Flags controlling the style of output. */
432 static enum
434 BINARY_BINARY_FILES,
435 TEXT_BINARY_FILES,
436 WITHOUT_MATCH_BINARY_FILES
437 } binary_files; /* How to handle binary files. */
439 static int filename_mask; /* If zero, output nulls after filenames. */
440 static int out_quiet; /* Suppress all normal output. */
441 static int out_invert; /* Print nonmatching stuff. */
442 static int out_file; /* Print filenames. */
443 static int out_line; /* Print line numbers. */
444 static int out_byte; /* Print byte offsets. */
445 static int out_before; /* Lines of leading context. */
446 static int out_after; /* Lines of trailing context. */
447 static int count_matches; /* Count matching lines. */
448 static int list_files; /* List matching files. */
449 static int no_filenames; /* Suppress file names. */
450 static off_t max_count; /* Stop after outputting this many
451 lines from an input file. */
452 static int line_buffered; /* If nonzero, use line buffering, i.e.
453 fflush everyline out. */
454 static char *label = NULL; /* Fake filename for stdin */
457 /* Internal variables to keep track of byte count, context, etc. */
458 static uintmax_t totalcc; /* Total character count before bufbeg. */
459 static char const *lastnl; /* Pointer after last newline counted. */
460 static char const *lastout; /* Pointer after last character output;
461 NULL if no character has been output
462 or if it's conceptually before bufbeg. */
463 static uintmax_t totalnl; /* Total newline count before lastnl. */
464 static off_t outleft; /* Maximum number of lines to be output. */
465 static int pending; /* Pending lines of output.
466 Always kept 0 if out_quiet is true. */
467 static int done_on_match; /* Stop scanning file on first match. */
468 static int exit_on_match; /* Exit on first match. */
470 #if defined(HAVE_DOS_FILE_CONTENTS)
471 # include "dosbuf.c"
472 #endif
474 /* Add two numbers that count input bytes or lines, and report an
475 error if the addition overflows. */
476 static uintmax_t
477 add_count (uintmax_t a, uintmax_t b)
479 uintmax_t sum = a + b;
480 if (sum < a)
481 error (2, 0, _("input is too large to count"));
482 return sum;
485 static void
486 nlscan (char const *lim)
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;
496 /* Print a byte offset, followed by a character separator. */
497 static void
498 print_offset_sep (uintmax_t pos, char sep)
500 /* Do not rely on printf to print pos, since uintmax_t may be longer
501 than long, and long long is not portable. */
503 char buf[sizeof pos * CHAR_BIT];
504 char *p = buf + sizeof buf - 1;
505 *p = sep;
508 *--p = '0' + pos % 10;
509 while ((pos /= 10) != 0);
511 fwrite (p, 1, buf + sizeof buf - p, stdout);
514 static void
515 prline (char const *beg, char const *lim, int sep)
517 if (out_file)
518 printf ("%s%c", filename, sep & filename_mask);
519 if (out_line)
521 nlscan (beg);
522 totalnl = add_count (totalnl, 1);
523 print_offset_sep (totalnl, sep);
524 lastnl = lim;
526 if (out_byte)
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);
534 if (only_matching)
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)
541 char const *b = beg + match_offset;
542 if (b == lim)
543 break;
544 if (match_size == 0)
545 break;
546 if(color_option)
547 printf("\33[%sm", grep_color);
548 fwrite(b, sizeof (char), match_size, stdout);
549 if(color_option)
550 fputs("\33[00m", stdout);
551 fputs("\n", stdout);
552 beg = b + match_size;
554 lastout = lim;
555 if(line_buffered)
556 fflush(stdout);
557 return;
559 if (color_option)
561 size_t match_size;
562 size_t match_offset;
563 if(match_icase)
565 /* Yuck, this is tricky */
566 char *buf = (char*) xmalloc (lim - beg);
567 char *ibeg = buf;
568 char *ilim = ibeg + (lim - beg);
569 int i;
570 for (i = 0; i < lim - beg; i++)
571 ibeg[i] = tolower (beg[i]);
572 while ((match_offset = (*execute) (ibeg, ilim-ibeg, &match_size, 1))
573 != (size_t) -1)
575 char const *b = beg + match_offset;
576 if (b == lim)
577 break;
578 fwrite (beg, sizeof (char), match_offset, stdout);
579 printf ("\33[%sm", grep_color);
580 fwrite (b, sizeof (char), match_size, stdout);
581 fputs ("\33[00m", stdout);
582 beg = b + match_size;
583 ibeg = ibeg + match_offset + match_size;
585 fwrite (beg, 1, lim - beg, stdout);
586 free (buf);
587 lastout = lim;
588 return;
590 while (lim-beg && (match_offset = (*execute) (beg, lim - beg, &match_size, 1))
591 != (size_t) -1)
593 char const *b = beg + match_offset;
594 /* Avoid matching the empty line at the end of the buffer. */
595 if (b == lim)
596 break;
597 /* Avoid hanging on grep --color "" foo */
598 if (match_size == 0)
599 break;
600 fwrite (beg, sizeof (char), match_offset, stdout);
601 printf ("\33[%sm", grep_color);
602 fwrite (b, sizeof (char), match_size, stdout);
603 fputs ("\33[00m", stdout);
604 beg = b + match_size;
607 fwrite (beg, 1, lim - beg, stdout);
608 if (ferror (stdout))
609 error (0, errno, _("writing output"));
610 lastout = lim;
611 if (line_buffered)
612 fflush (stdout);
615 /* Print pending lines of trailing context prior to LIM. Trailing context ends
616 at the next matching line when OUTLEFT is 0. */
617 static void
618 prpending (char const *lim)
620 if (!lastout)
621 lastout = bufbeg;
622 while (pending > 0 && lastout < lim)
624 char const *nl = memchr (lastout, eolbyte, lim - lastout);
625 size_t match_size;
626 --pending;
627 if (outleft
628 || (((*execute) (lastout, nl - lastout, &match_size, 0) == (size_t) -1)
629 == !out_invert))
630 prline (lastout, nl + 1, '-');
631 else
632 pending = 0;
636 /* Print the lines between BEG and LIM. Deal with context crap.
637 If NLINESP is non-null, store a count of lines between BEG and LIM. */
638 static void
639 prtext (char const *beg, char const *lim, int *nlinesp)
641 static int used; /* avoid printing "--" before any output */
642 char const *bp, *p;
643 char eol = eolbyte;
644 int i, n;
646 if (!out_quiet && pending > 0)
647 prpending (beg);
649 p = beg;
651 if (!out_quiet)
653 /* Deal with leading context crap. */
655 bp = lastout ? lastout : bufbeg;
656 for (i = 0; i < out_before; ++i)
657 if (p > bp)
659 --p;
660 while (p[-1] != eol);
662 /* We only print the "--" separator if our output is
663 discontiguous from the last output in the file. */
664 if ((out_before || out_after) && used && p != lastout)
665 puts ("--");
667 while (p < beg)
669 char const *nl = memchr (p, eol, beg - p);
670 nl++;
671 prline (p, nl, '-');
672 p = nl;
676 if (nlinesp)
678 /* Caller wants a line count. */
679 for (n = 0; p < lim && n < outleft; n++)
681 char const *nl = memchr (p, eol, lim - p);
682 nl++;
683 if (!out_quiet)
684 prline (p, nl, ':');
685 p = nl;
687 *nlinesp = n;
689 /* relying on it that this function is never called when outleft = 0. */
690 after_last_match = bufoffset - (buflim - p);
692 else
693 if (!out_quiet)
694 prline (beg, lim, ':');
696 pending = out_quiet ? 0 : out_after;
697 used = 1;
700 /* Scan the specified portion of the buffer, matching lines (or
701 between matching lines if OUT_INVERT is true). Return a count of
702 lines printed. */
703 static int
704 grepbuf (char const *beg, char const *lim)
706 int nlines, n;
707 register char const *p;
708 size_t match_offset;
709 size_t match_size;
711 nlines = 0;
712 p = beg;
713 while ((match_offset = (*execute) (p, lim - p, &match_size, 0)) != (size_t) -1)
715 char const *b = p + match_offset;
716 char const *endp = b + match_size;
717 /* Avoid matching the empty line at the end of the buffer. */
718 if (b == lim)
719 break;
720 if (!out_invert)
722 prtext (b, endp, (int *) 0);
723 nlines++;
724 outleft--;
725 if (!outleft || done_on_match)
727 if (exit_on_match)
728 exit (0);
729 after_last_match = bufoffset - (buflim - endp);
730 return nlines;
733 else if (p < b)
735 prtext (p, b, &n);
736 nlines += n;
737 outleft -= n;
738 if (!outleft)
739 return nlines;
741 p = endp;
743 if (out_invert && p < lim)
745 prtext (p, lim, &n);
746 nlines += n;
747 outleft -= n;
749 return nlines;
752 /* Search a given file. Normally, return a count of lines printed;
753 but if the file is a directory and we search it recursively, then
754 return -2 if there was a match, and -1 otherwise. */
755 static int
756 grep (int fd, char const *file, struct stats *stats)
758 int nlines, i;
759 int not_text;
760 size_t residue, save;
761 char oldc;
762 char *beg;
763 char *lim;
764 char eol = eolbyte;
766 if (!reset (fd, file, stats))
767 return 0;
769 if (file && directories == RECURSE_DIRECTORIES
770 && S_ISDIR (stats->stat.st_mode))
772 /* Close fd now, so that we don't open a lot of file descriptors
773 when we recurse deeply. */
774 if (close (fd) != 0)
775 error (0, errno, "%s", file);
776 return grepdir (file, stats) - 2;
779 totalcc = 0;
780 lastout = 0;
781 totalnl = 0;
782 outleft = max_count;
783 after_last_match = 0;
784 pending = 0;
786 nlines = 0;
787 residue = 0;
788 save = 0;
790 if (! fillbuf (save, stats))
792 if (! is_EISDIR (errno, file))
793 suppressible_error (filename, errno);
794 return 0;
797 not_text = (((binary_files == BINARY_BINARY_FILES && !out_quiet)
798 || binary_files == WITHOUT_MATCH_BINARY_FILES)
799 && memchr (bufbeg, eol ? '\0' : '\200', buflim - bufbeg));
800 if (not_text && binary_files == WITHOUT_MATCH_BINARY_FILES)
801 return 0;
802 done_on_match += not_text;
803 out_quiet += not_text;
805 for (;;)
807 lastnl = bufbeg;
808 if (lastout)
809 lastout = bufbeg;
811 beg = bufbeg + save;
813 /* no more data to scan (eof) except for maybe a residue -> break */
814 if (beg == buflim)
815 break;
817 /* Determine new residue (the length of an incomplete line at the end of
818 the buffer, 0 means there is no incomplete last line). */
819 oldc = beg[-1];
820 beg[-1] = eol;
821 for (lim = buflim; lim[-1] != eol; lim--)
822 continue;
823 beg[-1] = oldc;
824 if (lim == beg)
825 lim = beg - residue;
826 beg -= residue;
827 residue = buflim - lim;
829 if (beg < lim)
831 if (outleft)
832 nlines += grepbuf (beg, lim);
833 if (pending)
834 prpending (lim);
835 if((!outleft && !pending) || (nlines && done_on_match && !out_invert))
836 goto finish_grep;
839 /* The last OUT_BEFORE lines at the end of the buffer will be needed as
840 leading context if there is a matching line at the begin of the
841 next data. Make beg point to their begin. */
842 i = 0;
843 beg = lim;
844 while (i < out_before && beg > bufbeg && beg != lastout)
846 ++i;
848 --beg;
849 while (beg[-1] != eol);
852 /* detect if leading context is discontinuous from last printed line. */
853 if (beg != lastout)
854 lastout = 0;
856 /* Handle some details and read more data to scan. */
857 save = residue + lim - beg;
858 if (out_byte)
859 totalcc = add_count (totalcc, buflim - bufbeg - save);
860 if (out_line)
861 nlscan (beg);
862 if (! fillbuf (save, stats))
864 if (! is_EISDIR (errno, file))
865 suppressible_error (filename, errno);
866 goto finish_grep;
869 if (residue)
871 *buflim++ = eol;
872 if (outleft)
873 nlines += grepbuf (bufbeg + save - residue, buflim);
874 if (pending)
875 prpending (buflim);
878 finish_grep:
879 done_on_match -= not_text;
880 out_quiet -= not_text;
881 if ((not_text & ~out_quiet) && nlines != 0)
882 printf (_("Binary file %s matches\n"), filename);
883 return nlines;
886 static int
887 grepfile (char const *file, struct stats *stats)
889 int desc;
890 int count;
891 int status;
893 if (! file)
895 desc = 0;
896 filename = label ? label : _("(standard input)");
898 else
900 while ((desc = open (file, O_RDONLY)) < 0 && errno == EINTR)
901 continue;
903 if (desc < 0)
905 int e = errno;
907 if (is_EISDIR (e, file) && directories == RECURSE_DIRECTORIES)
909 if (stat (file, &stats->stat) != 0)
911 error (0, errno, "%s", file);
912 return 1;
915 return grepdir (file, stats);
918 if (!suppress_errors)
920 if (directories == SKIP_DIRECTORIES)
921 switch (e)
923 #if defined(EISDIR)
924 case EISDIR:
925 return 1;
926 #endif
927 case EACCES:
928 /* When skipping directories, don't worry about
929 directories that can't be opened. */
930 if (isdir (file))
931 return 1;
932 break;
936 suppressible_error (file, e);
937 return 1;
940 filename = file;
943 #if defined(SET_BINARY)
944 /* Set input to binary mode. Pipes are simulated with files
945 on DOS, so this includes the case of "foo | grep bar". */
946 if (!isatty (desc))
947 SET_BINARY (desc);
948 #endif
950 count = grep (desc, file, stats);
951 if (count < 0)
952 status = count + 2;
953 else
955 if (count_matches)
957 if (out_file)
958 printf ("%s%c", filename, ':' & filename_mask);
959 printf ("%d\n", count);
962 status = !count;
963 if (list_files == 1 - 2 * status)
964 printf ("%s%c", filename, '\n' & filename_mask);
966 if (! file)
968 off_t required_offset = outleft ? bufoffset : after_last_match;
969 if ((bufmapped || required_offset != bufoffset)
970 && lseek (desc, required_offset, SEEK_SET) < 0
971 && S_ISREG (stats->stat.st_mode))
972 error (0, errno, "%s", filename);
974 else
975 while (close (desc) != 0)
976 if (errno != EINTR)
978 error (0, errno, "%s", file);
979 break;
983 return status;
986 static int
987 grepdir (char const *dir, struct stats const *stats)
989 int status = 1;
990 struct stats const *ancestor;
991 char *name_space;
993 /* Mingw32 does not support st_ino. No known working hosts use zero
994 for st_ino, so assume that the Mingw32 bug applies if it's zero. */
995 if (stats->stat.st_ino)
996 for (ancestor = stats; (ancestor = ancestor->parent) != 0; )
997 if (ancestor->stat.st_ino == stats->stat.st_ino
998 && ancestor->stat.st_dev == stats->stat.st_dev)
1000 if (!suppress_errors)
1001 error (0, 0, _("warning: %s: %s"), dir,
1002 _("recursive directory loop"));
1003 return 1;
1006 name_space = savedir (dir, stats->stat.st_size, included_patterns,
1007 excluded_patterns);
1009 if (! name_space)
1011 if (errno)
1012 suppressible_error (dir, errno);
1013 else
1014 xalloc_die ();
1016 else
1018 size_t dirlen = strlen (dir);
1019 int needs_slash = ! (dirlen == FILESYSTEM_PREFIX_LEN (dir)
1020 || IS_SLASH (dir[dirlen - 1]));
1021 char *file = NULL;
1022 char const *namep = name_space;
1023 struct stats child;
1024 child.parent = stats;
1025 out_file += !no_filenames;
1026 while (*namep)
1028 size_t namelen = strlen (namep);
1029 file = xrealloc (file, dirlen + 1 + namelen + 1);
1030 strcpy (file, dir);
1031 file[dirlen] = '/';
1032 strcpy (file + dirlen + needs_slash, namep);
1033 namep += namelen + 1;
1034 status &= grepfile (file, &child);
1036 out_file -= !no_filenames;
1037 if (file)
1038 free (file);
1039 free (name_space);
1042 return status;
1045 static void
1046 usage (int status)
1048 if (status != 0)
1050 fprintf (stderr, _("Usage: %s [OPTION]... PATTERN [FILE]...\n"),
1051 program_name);
1052 fprintf (stderr, _("Try `%s --help' for more information.\n"),
1053 program_name);
1055 else
1057 printf (_("Usage: %s [OPTION]... PATTERN [FILE] ...\n"), program_name);
1058 printf (_("\
1059 Search for PATTERN in each FILE or standard input.\n\
1060 Example: %s -i 'hello world' menu.h main.c\n\
1062 Regexp selection and interpretation:\n"), program_name);
1063 printf (_("\
1064 -E, --extended-regexp PATTERN is an extended regular expression\n\
1065 -F, --fixed-strings PATTERN is a set of newline-separated strings\n\
1066 -G, --basic-regexp PATTERN is a basic regular expression\n\
1067 -P, --perl-regexp PATTERN is a Perl regular expression\n"));
1068 printf (_("\
1069 -e, --regexp=PATTERN use PATTERN as a regular expression\n\
1070 -f, --file=FILE obtain PATTERN from FILE\n\
1071 -i, --ignore-case ignore case distinctions\n\
1072 -w, --word-regexp force PATTERN to match only whole words\n\
1073 -x, --line-regexp force PATTERN to match only whole lines\n\
1074 -z, --null-data a data line ends in 0 byte, not newline\n"));
1075 printf (_("\
1077 Miscellaneous:\n\
1078 -s, --no-messages suppress error messages\n\
1079 -v, --invert-match select non-matching lines\n\
1080 -V, --version print version information and exit\n\
1081 --help display this help and exit\n\
1082 --mmap use memory-mapped input if possible\n"));
1083 printf (_("\
1085 Output control:\n\
1086 -m, --max-count=NUM stop after NUM matches\n\
1087 -b, --byte-offset print the byte offset with output lines\n\
1088 -n, --line-number print line number with output lines\n\
1089 --line-buffered flush output on every line\n\
1090 -H, --with-filename print the filename for each match\n\
1091 -h, --no-filename suppress the prefixing filename on output\n\
1092 --label=LABEL print LABEL as filename for standard input\n\
1093 -o, --only-matching show only the part of a line matching PATTERN\n\
1094 -q, --quiet, --silent suppress all normal output\n\
1095 --binary-files=TYPE assume that binary files are TYPE\n\
1096 TYPE is 'binary', 'text', or 'without-match'\n\
1097 -a, --text equivalent to --binary-files=text\n\
1098 -I equivalent to --binary-files=without-match\n\
1099 -d, --directories=ACTION how to handle directories\n\
1100 ACTION is 'read', 'recurse', or 'skip'\n\
1101 -D, --devices=ACTION how to handle devices, FIFOs and sockets\n\
1102 ACTION is 'read' or 'skip'\n\
1103 -R, -r, --recursive equivalent to --directories=recurse\n\
1104 --include=PATTERN files that match PATTERN will be examined\n\
1105 --exclude=PATTERN files that match PATTERN will be skipped.\n\
1106 --exclude-from=FILE files that match PATTERN in FILE will be skipped.\n\
1107 -L, --files-without-match only print FILE names containing no match\n\
1108 -l, --files-with-matches only print FILE names containing matches\n\
1109 -c, --count only print a count of matching lines per FILE\n\
1110 -Z, --null print 0 byte after FILE name\n"));
1111 printf (_("\
1113 Context control:\n\
1114 -B, --before-context=NUM print NUM lines of leading context\n\
1115 -A, --after-context=NUM print NUM lines of trailing context\n\
1116 -C, --context=NUM print NUM lines of output context\n\
1117 -NUM same as --context=NUM\n\
1118 --color[=WHEN],\n\
1119 --colour[=WHEN] use markers to distinguish the matching string\n\
1120 WHEN may be `always', `never' or `auto'.\n\
1121 -U, --binary do not strip CR characters at EOL (MSDOS)\n\
1122 -u, --unix-byte-offsets report offsets as if CRs were not there (MSDOS)\n\
1124 `egrep' means `grep -E'. `fgrep' means `grep -F'.\n\
1125 With no FILE, or when FILE is -, read standard input. If less than\n\
1126 two FILEs given, assume -h. Exit status is 0 if match, 1 if no match,\n\
1127 and 2 if trouble.\n"));
1128 printf (_("\nReport bugs to <bug-gnu-utils@gnu.org>.\n"));
1130 exit (status);
1133 /* Set the matcher to M, reporting any conflicts. */
1134 static void
1135 setmatcher (char const *m)
1137 if (matcher && strcmp (matcher, m) != 0)
1138 error (2, 0, _("conflicting matchers specified"));
1139 matcher = m;
1142 /* Go through the matchers vector and look for the specified matcher.
1143 If we find it, install it in compile and execute, and return 1. */
1144 static int
1145 install_matcher (char const *name)
1147 int i;
1148 #if defined(HAVE_SETRLIMIT)
1149 struct rlimit rlim;
1150 #endif
1152 for (i = 0; matchers[i].compile; i++)
1153 if (strcmp (name, matchers[i].name) == 0)
1155 compile = matchers[i].compile;
1156 execute = matchers[i].execute;
1157 #if defined(HAVE_SETRLIMIT) && defined(RLIMIT_STACK)
1158 /* I think every platform needs to do this, so that regex.c
1159 doesn't oveflow the stack. The default value of
1160 `re_max_failures' is too large for some platforms: it needs
1161 more than 3MB-large stack.
1163 The test for HAVE_SETRLIMIT should go into `configure'. */
1164 if (!getrlimit (RLIMIT_STACK, &rlim))
1166 long newlim;
1167 extern long int re_max_failures; /* from regex.c */
1169 /* Approximate the amount regex.c needs, plus some more. */
1170 newlim = re_max_failures * 2 * 20 * sizeof (char *);
1171 if (newlim > rlim.rlim_max)
1173 newlim = rlim.rlim_max;
1174 re_max_failures = newlim / (2 * 20 * sizeof (char *));
1176 if (rlim.rlim_cur < newlim)
1178 rlim.rlim_cur = newlim;
1179 setrlimit (RLIMIT_STACK, &rlim);
1182 #endif
1183 return 1;
1185 return 0;
1188 /* Find the white-space-separated options specified by OPTIONS, and
1189 using BUF to store copies of these options, set ARGV[0], ARGV[1],
1190 etc. to the option copies. Return the number N of options found.
1191 Do not set ARGV[N] to NULL. If ARGV is NULL, do not store ARGV[0]
1192 etc. Backslash can be used to escape whitespace (and backslashes). */
1193 static int
1194 prepend_args (char const *options, char *buf, char **argv)
1196 char const *o = options;
1197 char *b = buf;
1198 int n = 0;
1200 for (;;)
1202 while (ISSPACE ((unsigned char) *o))
1203 o++;
1204 if (!*o)
1205 return n;
1206 if (argv)
1207 argv[n] = b;
1208 n++;
1211 if ((*b++ = *o++) == '\\' && *o)
1212 b[-1] = *o++;
1213 while (*o && ! ISSPACE ((unsigned char) *o));
1215 *b++ = '\0';
1219 /* Prepend the whitespace-separated options in OPTIONS to the argument
1220 vector of a main program with argument count *PARGC and argument
1221 vector *PARGV. */
1222 static void
1223 prepend_default_options (char const *options, int *pargc, char ***pargv)
1225 if (options)
1227 char *buf = xmalloc (strlen (options) + 1);
1228 int prepended = prepend_args (options, buf, (char **) NULL);
1229 int argc = *pargc;
1230 char * const *argv = *pargv;
1231 char **pp = (char **) xmalloc ((prepended + argc + 1) * sizeof *pp);
1232 *pargc = prepended + argc;
1233 *pargv = pp;
1234 *pp++ = *argv++;
1235 pp += prepend_args (options, buf, pp);
1236 while ((*pp++ = *argv++))
1237 continue;
1241 /* Get the next non-digit option from ARGC and ARGV.
1242 Return -1 if there are no more options.
1243 Process any digit options that were encountered on the way,
1244 and store the resulting integer into *DEFAULT_CONTEXT. */
1245 static int
1246 get_nondigit_option (int argc, char *const *argv, int *default_context)
1248 int opt;
1249 char buf[sizeof (uintmax_t) * CHAR_BIT + 4];
1250 char *p = buf;
1252 /* Set buf[0] to anything but '0', for the leading-zero test below. */
1253 buf[0] = '\0';
1255 while (opt = getopt_long (argc, argv, short_options, long_options, NULL),
1256 '0' <= opt && opt <= '9')
1258 /* Suppress trivial leading zeros, to avoid incorrect
1259 diagnostic on strings like 00000000000. */
1260 p -= buf[0] == '0';
1262 *p++ = opt;
1263 if (p == buf + sizeof buf - 4)
1265 /* Too many digits. Append "..." to make context_length_arg
1266 complain about "X...", where X contains the digits seen
1267 so far. */
1268 strcpy (p, "...");
1269 p += 3;
1270 break;
1273 if (p != buf)
1275 *p = '\0';
1276 context_length_arg (buf, default_context);
1279 return opt;
1283 main (int argc, char **argv)
1285 char *keys;
1286 size_t keycc, oldcc, keyalloc;
1287 int with_filenames;
1288 int opt, cc, status;
1289 int default_context;
1290 FILE *fp;
1291 extern char *optarg;
1292 extern int optind;
1293 #ifdef __NetBSD__
1294 extern char *__progname;
1295 #endif
1297 initialize_main (&argc, &argv);
1298 program_name = argv[0];
1299 if (program_name && strrchr (program_name, '/'))
1300 program_name = strrchr (program_name, '/') + 1;
1302 if (!strcmp(program_name, "egrep"))
1303 setmatcher ("egrep");
1304 if (!strcmp(program_name, "fgrep"))
1305 setmatcher ("fgrep");
1307 #if defined(__MSDOS__) || defined(_WIN32)
1308 /* DOS and MS-Windows use backslashes as directory separators, and usually
1309 have an .exe suffix. They also have case-insensitive filesystems. */
1310 if (program_name)
1312 char *p = program_name;
1313 char *bslash = strrchr (argv[0], '\\');
1315 if (bslash && bslash >= program_name) /* for mixed forward/backslash case */
1316 program_name = bslash + 1;
1317 else if (program_name == argv[0]
1318 && argv[0][0] && argv[0][1] == ':') /* "c:progname" */
1319 program_name = argv[0] + 2;
1321 /* Collapse the letter-case, so `strcmp' could be used hence. */
1322 for ( ; *p; p++)
1323 if (*p >= 'A' && *p <= 'Z')
1324 *p += 'a' - 'A';
1326 /* Remove the .exe extension, if any. */
1327 if ((p = strrchr (program_name, '.')) && strcmp (p, ".exe") == 0)
1328 *p = '\0';
1330 #endif
1332 keys = NULL;
1333 keycc = 0;
1334 with_filenames = 0;
1335 eolbyte = '\n';
1336 filename_mask = ~0;
1338 max_count = TYPE_MAXIMUM (off_t);
1340 /* The value -1 means to use DEFAULT_CONTEXT. */
1341 out_after = out_before = -1;
1342 /* Default before/after context: chaged by -C/-NUM options */
1343 default_context = 0;
1344 /* Changed by -o option */
1345 only_matching = 0;
1347 /* Internationalization. */
1348 #if defined(HAVE_SETLOCALE)
1349 setlocale (LC_ALL, "");
1350 #endif
1351 #if defined(ENABLE_NLS)
1352 bindtextdomain (PACKAGE, LOCALEDIR);
1353 textdomain (PACKAGE);
1354 #endif
1356 atexit (close_stdout);
1358 prepend_default_options (getenv ("GREP_OPTIONS"), &argc, &argv);
1360 while ((opt = get_nondigit_option (argc, argv, &default_context)) != -1)
1361 switch (opt)
1363 case 'A':
1364 context_length_arg (optarg, &out_after);
1365 break;
1367 case 'B':
1368 context_length_arg (optarg, &out_before);
1369 break;
1371 case 'C':
1372 /* Set output match context, but let any explicit leading or
1373 trailing amount specified with -A or -B stand. */
1374 context_length_arg (optarg, &default_context);
1375 break;
1377 case 'D':
1378 if (strcmp (optarg, "read") == 0)
1379 devices = READ_DEVICES;
1380 else if (strcmp (optarg, "skip") == 0)
1381 devices = SKIP_DEVICES;
1382 else
1383 error (2, 0, _("unknown devices method"));
1384 break;
1386 case 'E':
1387 setmatcher ("egrep");
1388 break;
1390 case 'F':
1391 setmatcher ("fgrep");
1392 break;
1394 case 'P':
1395 setmatcher ("perl");
1396 break;
1398 case 'G':
1399 setmatcher ("grep");
1400 break;
1402 case 'H':
1403 with_filenames = 1;
1404 break;
1406 case 'I':
1407 binary_files = WITHOUT_MATCH_BINARY_FILES;
1408 break;
1410 case 'U':
1411 #if defined(HAVE_DOS_FILE_CONTENTS)
1412 dos_use_file_type = DOS_BINARY;
1413 #endif
1414 break;
1416 case 'u':
1417 #if defined(HAVE_DOS_FILE_CONTENTS)
1418 dos_report_unix_offset = 1;
1419 #endif
1420 break;
1422 case 'V':
1423 show_version = 1;
1424 break;
1426 case 'X':
1427 setmatcher (optarg);
1428 break;
1430 case 'a':
1431 binary_files = TEXT_BINARY_FILES;
1432 break;
1434 case 'b':
1435 out_byte = 1;
1436 break;
1438 case 'c':
1439 count_matches = 1;
1440 break;
1442 case 'd':
1443 if (strcmp (optarg, "read") == 0)
1444 directories = READ_DIRECTORIES;
1445 else if (strcmp (optarg, "skip") == 0)
1446 directories = SKIP_DIRECTORIES;
1447 else if (strcmp (optarg, "recurse") == 0)
1448 directories = RECURSE_DIRECTORIES;
1449 else
1450 error (2, 0, _("unknown directories method"));
1451 break;
1453 case 'e':
1454 cc = strlen (optarg);
1455 keys = xrealloc (keys, keycc + cc + 1);
1456 strcpy (&keys[keycc], optarg);
1457 keycc += cc;
1458 keys[keycc++] = '\n';
1459 break;
1461 case 'f':
1462 fp = strcmp (optarg, "-") != 0 ? fopen (optarg, "r") : stdin;
1463 if (!fp)
1464 error (2, errno, "%s", optarg);
1465 for (keyalloc = 1; keyalloc <= keycc + 1; keyalloc *= 2)
1467 keys = xrealloc (keys, keyalloc);
1468 oldcc = keycc;
1469 while (!feof (fp)
1470 && (cc = fread (keys + keycc, 1, keyalloc - 1 - keycc, fp)) > 0)
1472 keycc += cc;
1473 if (keycc == keyalloc - 1)
1474 keys = xrealloc (keys, keyalloc *= 2);
1476 if (fp != stdin)
1477 fclose(fp);
1478 /* Append final newline if file ended in non-newline. */
1479 if (oldcc != keycc && keys[keycc - 1] != '\n')
1480 keys[keycc++] = '\n';
1481 break;
1483 case 'h':
1484 no_filenames = 1;
1485 break;
1487 case 'i':
1488 case 'y': /* For old-timers . . . */
1489 match_icase = 1;
1490 break;
1492 case 'L':
1493 /* Like -l, except list files that don't contain matches.
1494 Inspired by the same option in Hume's gre. */
1495 list_files = -1;
1496 break;
1498 case 'l':
1499 list_files = 1;
1500 break;
1502 case 'm':
1504 uintmax_t value;
1505 switch (xstrtoumax (optarg, 0, 10, &value, ""))
1507 case LONGINT_OK:
1508 max_count = value;
1509 if (0 <= max_count && max_count == value)
1510 break;
1511 /* Fall through. */
1512 case LONGINT_OVERFLOW:
1513 max_count = TYPE_MAXIMUM (off_t);
1514 break;
1516 default:
1517 error (2, 0, _("invalid max count"));
1520 break;
1522 case 'n':
1523 out_line = 1;
1524 break;
1526 case 'o':
1527 only_matching = 1;
1528 break;
1530 case 'q':
1531 exit_on_match = 1;
1532 close_stdout_set_status(0);
1533 break;
1535 case 'R':
1536 case 'r':
1537 directories = RECURSE_DIRECTORIES;
1538 break;
1540 case 's':
1541 suppress_errors = 1;
1542 break;
1544 case 'v':
1545 out_invert = 1;
1546 break;
1548 case 'w':
1549 match_words = 1;
1550 break;
1552 case 'x':
1553 match_lines = 1;
1554 break;
1556 case 'Z':
1557 filename_mask = 0;
1558 break;
1560 case 'z':
1561 eolbyte = '\0';
1562 break;
1564 case BINARY_FILES_OPTION:
1565 if (strcmp (optarg, "binary") == 0)
1566 binary_files = BINARY_BINARY_FILES;
1567 else if (strcmp (optarg, "text") == 0)
1568 binary_files = TEXT_BINARY_FILES;
1569 else if (strcmp (optarg, "without-match") == 0)
1570 binary_files = WITHOUT_MATCH_BINARY_FILES;
1571 else
1572 error (2, 0, _("unknown binary-files type"));
1573 break;
1575 case COLOR_OPTION:
1576 if(optarg) {
1577 if(!strcasecmp(optarg, "always") || !strcasecmp(optarg, "yes") ||
1578 !strcasecmp(optarg, "force"))
1579 color_option = 1;
1580 else if(!strcasecmp(optarg, "never") || !strcasecmp(optarg, "no") ||
1581 !strcasecmp(optarg, "none"))
1582 color_option = 0;
1583 else if(!strcasecmp(optarg, "auto") || !strcasecmp(optarg, "tty") ||
1584 !strcasecmp(optarg, "if-tty"))
1585 color_option = 2;
1586 else
1587 show_help = 1;
1588 } else
1589 color_option = 2;
1590 if(color_option == 2) {
1591 if(isatty(STDOUT_FILENO) && getenv("TERM") &&
1592 strcmp(getenv("TERM"), "dumb"))
1593 color_option = 1;
1594 else
1595 color_option = 0;
1597 break;
1599 case EXCLUDE_OPTION:
1600 if (!excluded_patterns)
1601 excluded_patterns = new_exclude ();
1602 add_exclude (excluded_patterns, optarg);
1603 break;
1605 case EXCLUDE_FROM_OPTION:
1606 if (!excluded_patterns)
1607 excluded_patterns = new_exclude ();
1608 if (add_exclude_file (add_exclude, excluded_patterns, optarg, '\n')
1609 != 0)
1611 error (2, errno, "%s", optarg);
1613 break;
1615 case INCLUDE_OPTION:
1616 if (!included_patterns)
1617 included_patterns = new_exclude ();
1618 add_exclude (included_patterns, optarg);
1619 break;
1621 case LINE_BUFFERED_OPTION:
1622 line_buffered = 1;
1623 break;
1625 case LABEL_OPTION:
1626 label = optarg;
1627 break;
1629 case 0:
1630 /* long options */
1631 break;
1633 default:
1634 usage (2);
1635 break;
1639 /* POSIX.2 says that -q overrides -l, which in turn overrides the
1640 other output options. */
1641 if (exit_on_match)
1642 list_files = 0;
1643 if (exit_on_match | list_files)
1645 count_matches = 0;
1646 done_on_match = 1;
1648 out_quiet = count_matches | done_on_match;
1650 if (out_after < 0)
1651 out_after = default_context;
1652 if (out_before < 0)
1653 out_before = default_context;
1655 if (color_option)
1657 char *userval = getenv ("GREP_COLOR");
1658 if (userval != NULL && *userval != '\0')
1659 grep_color = userval;
1662 if (! matcher)
1663 #ifdef __NetBSD__
1664 matcher = __progname;
1665 #else
1666 matcher = "grep";
1667 #endif
1669 if (show_version)
1671 printf (_("%s (GNU grep) %s\n"), matcher, VERSION);
1672 printf ("\n");
1673 printf (_("\
1674 Copyright 1988, 1992-1999, 2000, 2001 Free Software Foundation, Inc.\n"));
1675 printf (_("\
1676 This is free software; see the source for copying conditions. There is NO\n\
1677 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"));
1678 printf ("\n");
1679 exit (0);
1682 if (show_help)
1683 usage (0);
1685 if (keys)
1687 if (keycc == 0)
1689 /* No keys were specified (e.g. -f /dev/null). Match nothing. */
1690 out_invert ^= 1;
1691 match_lines = match_words = 0;
1693 else
1694 /* Strip trailing newline. */
1695 --keycc;
1697 else
1698 if (optind < argc)
1700 keys = argv[optind++];
1701 keycc = strlen (keys);
1703 else
1704 usage (2);
1706 if (!install_matcher (matcher) && !install_matcher ("default"))
1707 abort ();
1709 (*compile)(keys, keycc);
1711 if ((argc - optind > 1 && !no_filenames) || with_filenames)
1712 out_file = 1;
1714 #ifdef SET_BINARY
1715 /* Output is set to binary mode because we shouldn't convert
1716 NL to CR-LF pairs, especially when grepping binary files. */
1717 if (!isatty (1))
1718 SET_BINARY (1);
1719 #endif
1721 if (max_count == 0)
1722 exit (1);
1724 if (optind < argc)
1726 status = 1;
1729 char *file = argv[optind];
1730 if ((included_patterns || excluded_patterns)
1731 && !isdir (file))
1733 if (included_patterns &&
1734 ! excluded_filename (included_patterns, file, 0))
1735 continue;
1736 if (excluded_patterns &&
1737 excluded_filename (excluded_patterns, file, 0))
1738 continue;
1740 status &= grepfile (strcmp (file, "-") == 0 ? (char *) NULL : file,
1741 &stats_base);
1743 while ( ++optind < argc);
1745 else
1747 if (directories == RECURSE_DIRECTORIES) {
1748 error (0, 0, _("warning: recursive search of stdin"));
1750 status = grepfile ((char *) NULL, &stats_base);
1753 /* We register via atexit() to test stdout. */
1754 exit (errseen ? 2 : status);
1756 /* vim:set shiftwidth=2: */