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