source: trunk/grep/src/grep.c@ 2754

Last change on this file since 2754 was 2557, checked in by bird, 19 years ago

grep 2.5.1a

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