source: trunk/essentials/sys-apps/grep/src/grep.c

Last change on this file was 3078, checked in by bird, 18 years ago

_wildcard+_response

File size: 45.9 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 defined(__OS2__) /* || defined windows */
1295 keys = strchr (program_name, '\0');
1296 while (keys > program_name && keys[-1] != '\\'
1297 && keys[-1] != '/' && keys[-1] != ':')
1298 keys--;
1299 program_name = keys;
1300 if ( !strnicmp (program_name, "egrep", 5)
1301 && (!program_name[5] || program_name[5] == '.'))
1302 setmatcher ("egrep");
1303 else if ( !strnicmp (program_name, "fgrep", 5)
1304 && (!program_name[5] || program_name[5] == '.'))
1305 setmatcher ("fgrep");
1306#else
1307 if (program_name && strrchr (program_name, '/'))
1308 program_name = strrchr (program_name, '/') + 1;
1309 if (!strcmp(program_name, "egrep"))
1310 setmatcher ("egrep");
1311 if (!strcmp(program_name, "fgrep"))
1312 setmatcher ("fgrep");
1313#endif
1314
1315#ifdef __EMX__
1316 /* expand arguments. */
1317 _wildcard (&argc, &argv);
1318 _response (&argc, &argv);
1319#endif
1320
1321#if defined(__MSDOS__) || defined(_WIN32)
1322 /* DOS and MS-Windows use backslashes as directory separators, and usually
1323 have an .exe suffix. They also have case-insensitive filesystems. */
1324 if (program_name)
1325 {
1326 char *p = program_name;
1327 char *bslash = strrchr (argv[0], '\\');
1328
1329 if (bslash && bslash >= program_name) /* for mixed forward/backslash case */
1330 program_name = bslash + 1;
1331 else if (program_name == argv[0]
1332 && argv[0][0] && argv[0][1] == ':') /* "c:progname" */
1333 program_name = argv[0] + 2;
1334
1335 /* Collapse the letter-case, so `strcmp' could be used hence. */
1336 for ( ; *p; p++)
1337 if (*p >= 'A' && *p <= 'Z')
1338 *p += 'a' - 'A';
1339
1340 /* Remove the .exe extension, if any. */
1341 if ((p = strrchr (program_name, '.')) && strcmp (p, ".exe") == 0)
1342 *p = '\0';
1343 }
1344#endif
1345
1346 keys = NULL;
1347 keycc = 0;
1348 with_filenames = 0;
1349 eolbyte = '\n';
1350 filename_mask = ~0;
1351
1352 max_count = TYPE_MAXIMUM (off_t);
1353
1354 /* The value -1 means to use DEFAULT_CONTEXT. */
1355 out_after = out_before = -1;
1356 /* Default before/after context: chaged by -C/-NUM options */
1357 default_context = 0;
1358 /* Changed by -o option */
1359 only_matching = 0;
1360
1361 /* Internationalization. */
1362#if defined(HAVE_SETLOCALE)
1363 setlocale (LC_ALL, "");
1364#endif
1365#if defined(ENABLE_NLS)
1366 bindtextdomain (PACKAGE, LOCALEDIR);
1367 textdomain (PACKAGE);
1368#endif
1369
1370 atexit (close_stdout);
1371
1372 prepend_default_options (getenv ("GREP_OPTIONS"), &argc, &argv);
1373
1374 while ((opt = get_nondigit_option (argc, argv, &default_context)) != -1)
1375 switch (opt)
1376 {
1377 case 'A':
1378 context_length_arg (optarg, &out_after);
1379 break;
1380
1381 case 'B':
1382 context_length_arg (optarg, &out_before);
1383 break;
1384
1385 case 'C':
1386 /* Set output match context, but let any explicit leading or
1387 trailing amount specified with -A or -B stand. */
1388 context_length_arg (optarg, &default_context);
1389 break;
1390
1391 case 'D':
1392 if (strcmp (optarg, "read") == 0)
1393 devices = READ_DEVICES;
1394 else if (strcmp (optarg, "skip") == 0)
1395 devices = SKIP_DEVICES;
1396 else
1397 error (2, 0, _("unknown devices method"));
1398 break;
1399
1400 case 'E':
1401 setmatcher ("egrep");
1402 break;
1403
1404 case 'F':
1405 setmatcher ("fgrep");
1406 break;
1407
1408 case 'P':
1409 setmatcher ("perl");
1410 break;
1411
1412 case 'G':
1413 setmatcher ("grep");
1414 break;
1415
1416 case 'H':
1417 with_filenames = 1;
1418 break;
1419
1420 case 'I':
1421 binary_files = WITHOUT_MATCH_BINARY_FILES;
1422 break;
1423
1424 case 'U':
1425#if defined(HAVE_DOS_FILE_CONTENTS)
1426 dos_use_file_type = DOS_BINARY;
1427#endif
1428 break;
1429
1430 case 'u':
1431#if defined(HAVE_DOS_FILE_CONTENTS)
1432 dos_report_unix_offset = 1;
1433#endif
1434 break;
1435
1436 case 'V':
1437 show_version = 1;
1438 break;
1439
1440 case 'X':
1441 setmatcher (optarg);
1442 break;
1443
1444 case 'a':
1445 binary_files = TEXT_BINARY_FILES;
1446 break;
1447
1448 case 'b':
1449 out_byte = 1;
1450 break;
1451
1452 case 'c':
1453 count_matches = 1;
1454 break;
1455
1456 case 'd':
1457 if (strcmp (optarg, "read") == 0)
1458 directories = READ_DIRECTORIES;
1459 else if (strcmp (optarg, "skip") == 0)
1460 directories = SKIP_DIRECTORIES;
1461 else if (strcmp (optarg, "recurse") == 0)
1462 directories = RECURSE_DIRECTORIES;
1463 else
1464 error (2, 0, _("unknown directories method"));
1465 break;
1466
1467 case 'e':
1468 cc = strlen (optarg);
1469 keys = xrealloc (keys, keycc + cc + 1);
1470 strcpy (&keys[keycc], optarg);
1471 keycc += cc;
1472 keys[keycc++] = '\n';
1473 break;
1474
1475 case 'f':
1476 fp = strcmp (optarg, "-") != 0 ? fopen (optarg, "r") : stdin;
1477 if (!fp)
1478 error (2, errno, "%s", optarg);
1479 for (keyalloc = 1; keyalloc <= keycc + 1; keyalloc *= 2)
1480 ;
1481 keys = xrealloc (keys, keyalloc);
1482 oldcc = keycc;
1483 while (!feof (fp)
1484 && (cc = fread (keys + keycc, 1, keyalloc - 1 - keycc, fp)) > 0)
1485 {
1486 keycc += cc;
1487 if (keycc == keyalloc - 1)
1488 keys = xrealloc (keys, keyalloc *= 2);
1489 }
1490 if (fp != stdin)
1491 fclose(fp);
1492 /* Append final newline if file ended in non-newline. */
1493 if (oldcc != keycc && keys[keycc - 1] != '\n')
1494 keys[keycc++] = '\n';
1495 break;
1496
1497 case 'h':
1498 no_filenames = 1;
1499 break;
1500
1501 case 'i':
1502 case 'y': /* For old-timers . . . */
1503 match_icase = 1;
1504 break;
1505
1506 case 'L':
1507 /* Like -l, except list files that don't contain matches.
1508 Inspired by the same option in Hume's gre. */
1509 list_files = -1;
1510 break;
1511
1512 case 'l':
1513 list_files = 1;
1514 break;
1515
1516 case 'm':
1517 {
1518 uintmax_t value;
1519 switch (xstrtoumax (optarg, 0, 10, &value, ""))
1520 {
1521 case LONGINT_OK:
1522 max_count = value;
1523 if (0 <= max_count && max_count == value)
1524 break;
1525 /* Fall through. */
1526 case LONGINT_OVERFLOW:
1527 max_count = TYPE_MAXIMUM (off_t);
1528 break;
1529
1530 default:
1531 error (2, 0, _("invalid max count"));
1532 }
1533 }
1534 break;
1535
1536 case 'n':
1537 out_line = 1;
1538 break;
1539
1540 case 'o':
1541 only_matching = 1;
1542 break;
1543
1544 case 'q':
1545 exit_on_match = 1;
1546 close_stdout_set_status(0);
1547 break;
1548
1549 case 'R':
1550 case 'r':
1551 directories = RECURSE_DIRECTORIES;
1552 break;
1553
1554 case 's':
1555 suppress_errors = 1;
1556 break;
1557
1558 case 'v':
1559 out_invert = 1;
1560 break;
1561
1562 case 'w':
1563 match_words = 1;
1564 break;
1565
1566 case 'x':
1567 match_lines = 1;
1568 break;
1569
1570 case 'Z':
1571 filename_mask = 0;
1572 break;
1573
1574 case 'z':
1575 eolbyte = '\0';
1576 break;
1577
1578 case BINARY_FILES_OPTION:
1579 if (strcmp (optarg, "binary") == 0)
1580 binary_files = BINARY_BINARY_FILES;
1581 else if (strcmp (optarg, "text") == 0)
1582 binary_files = TEXT_BINARY_FILES;
1583 else if (strcmp (optarg, "without-match") == 0)
1584 binary_files = WITHOUT_MATCH_BINARY_FILES;
1585 else
1586 error (2, 0, _("unknown binary-files type"));
1587 break;
1588
1589 case COLOR_OPTION:
1590 if(optarg) {
1591 if(!strcasecmp(optarg, "always") || !strcasecmp(optarg, "yes") ||
1592 !strcasecmp(optarg, "force"))
1593 color_option = 1;
1594 else if(!strcasecmp(optarg, "never") || !strcasecmp(optarg, "no") ||
1595 !strcasecmp(optarg, "none"))
1596 color_option = 0;
1597 else if(!strcasecmp(optarg, "auto") || !strcasecmp(optarg, "tty") ||
1598 !strcasecmp(optarg, "if-tty"))
1599 color_option = 2;
1600 else
1601 show_help = 1;
1602 } else
1603 color_option = 2;
1604 if(color_option == 2) {
1605 if(isatty(STDOUT_FILENO) && getenv("TERM") &&
1606 strcmp(getenv("TERM"), "dumb"))
1607 color_option = 1;
1608 else
1609 color_option = 0;
1610 }
1611 break;
1612
1613 case EXCLUDE_OPTION:
1614 if (!excluded_patterns)
1615 excluded_patterns = new_exclude ();
1616 add_exclude (excluded_patterns, optarg);
1617 break;
1618
1619 case EXCLUDE_FROM_OPTION:
1620 if (!excluded_patterns)
1621 excluded_patterns = new_exclude ();
1622 if (add_exclude_file (add_exclude, excluded_patterns, optarg, '\n')
1623 != 0)
1624 {
1625 error (2, errno, "%s", optarg);
1626 }
1627 break;
1628
1629 case INCLUDE_OPTION:
1630 if (!included_patterns)
1631 included_patterns = new_exclude ();
1632 add_exclude (included_patterns, optarg);
1633 break;
1634
1635 case LINE_BUFFERED_OPTION:
1636 line_buffered = 1;
1637 break;
1638
1639 case LABEL_OPTION:
1640 label = optarg;
1641 break;
1642
1643 case 0:
1644 /* long options */
1645 break;
1646
1647 default:
1648 usage (2);
1649 break;
1650
1651 }
1652
1653 /* POSIX.2 says that -q overrides -l, which in turn overrides the
1654 other output options. */
1655 if (exit_on_match)
1656 list_files = 0;
1657 if (exit_on_match | list_files)
1658 {
1659 count_matches = 0;
1660 done_on_match = 1;
1661 }
1662 out_quiet = count_matches | done_on_match;
1663
1664 if (out_after < 0)
1665 out_after = default_context;
1666 if (out_before < 0)
1667 out_before = default_context;
1668
1669 if (color_option)
1670 {
1671 char *userval = getenv ("GREP_COLOR");
1672 if (userval != NULL && *userval != '\0')
1673 grep_color = userval;
1674 }
1675
1676 if (! matcher)
1677 matcher = "grep";
1678
1679 if (show_version)
1680 {
1681 printf (_("%s (GNU grep) %s\n"), matcher, VERSION);
1682 printf ("\n");
1683 printf (_("\
1684Copyright 1988, 1992-1999, 2000, 2001 Free Software Foundation, Inc.\n"));
1685 printf (_("\
1686This is free software; see the source for copying conditions. There is NO\n\
1687warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"));
1688 printf ("\n");
1689 exit (0);
1690 }
1691
1692 if (show_help)
1693 usage (0);
1694
1695 if (keys)
1696 {
1697 if (keycc == 0)
1698 {
1699 /* No keys were specified (e.g. -f /dev/null). Match nothing. */
1700 out_invert ^= 1;
1701 match_lines = match_words = 0;
1702 }
1703 else
1704 /* Strip trailing newline. */
1705 --keycc;
1706 }
1707 else
1708 if (optind < argc)
1709 {
1710 keys = argv[optind++];
1711 keycc = strlen (keys);
1712 }
1713 else
1714 usage (2);
1715
1716 if (!install_matcher (matcher) && !install_matcher ("default"))
1717 abort ();
1718
1719 (*compile)(keys, keycc);
1720
1721 if ((argc - optind > 1 && !no_filenames) || with_filenames)
1722 out_file = 1;
1723
1724#ifdef SET_BINARY
1725 /* Output is set to binary mode because we shouldn't convert
1726 NL to CR-LF pairs, especially when grepping binary files. */
1727 if (!isatty (1))
1728 SET_BINARY (1);
1729#endif
1730
1731 if (max_count == 0)
1732 exit (1);
1733
1734 if (optind < argc)
1735 {
1736 status = 1;
1737 do
1738 {
1739 char *file = argv[optind];
1740 if ((included_patterns || excluded_patterns)
1741 && !isdir (file))
1742 {
1743 if (included_patterns &&
1744 ! excluded_filename (included_patterns, file, 0))
1745 continue;
1746 if (excluded_patterns &&
1747 excluded_filename (excluded_patterns, file, 0))
1748 continue;
1749 }
1750 status &= grepfile (strcmp (file, "-") == 0 ? (char *) NULL : file,
1751 &stats_base);
1752 }
1753 while ( ++optind < argc);
1754 }
1755 else
1756 status = grepfile ((char *) NULL, &stats_base);
1757
1758 /* We register via atexit() to test stdout. */
1759 exit (errseen ? 2 : status);
1760}
1761/* vim:set shiftwidth=2: */
Note: See TracBrowser for help on using the repository browser.