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 50struct 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 */ 64static struct stats stats_base; 65 66/* if non-zero, display usage information and exit */ 67static int show_help; 68 69/* If non-zero, print the version on standard output and exit. */ 70static int show_version; 71 72/* If nonzero, suppress diagnostics for nonexistent or unreadable files. */ 73static int suppress_errors; 74 75/* If nonzero, use mmap if possible. */ 76static int mmap_option; 77 78/* If nonzero, use grep_color marker. */ 79static int color_option; 80 81/* If nonzero, show only the part of a line matching the expression. */ 82static 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. */ 86static const char *grep_color = "01;31"; 87 88static struct exclude *excluded_patterns; 89static struct exclude *included_patterns; 90/* Short options. */ 91static 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. */ 95enum 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. */ 107static 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. */ 159int match_icase; 160int match_words; 161int match_lines; 162unsigned char eolbyte; 163 164/* For error messages. */ 165/* The name the program was run with, stripped of any leading path. */ 166char *program_name; 167static char const *filename; 168static int errseen; 169 170/* How to handle directories. */ 171static enum 172 { 173 READ_DIRECTORIES, 174 RECURSE_DIRECTORIES, 175 SKIP_DIRECTORIES 176 } directories = READ_DIRECTORIES; 177 178/* How to handle devices. */ 179static enum 180 { 181 READ_DEVICES, 182 SKIP_DEVICES 183 } devices = READ_DEVICES; 184 185static int grepdir PARAMS ((char const *, struct stats const *)); 186#if defined(HAVE_DOS_FILE_CONTENTS) 187static inline int undossify_input PARAMS ((register char *, size_t)); 188#endif 189 190/* Functions we'll use to search. */ 191static void (*compile) PARAMS ((char const *, size_t)); 192static size_t (*execute) PARAMS ((char const *, size_t, size_t *, int)); 193 194/* Like error, but suppress the diagnostic if requested. */ 195static void 196suppressible_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. */ 206static void 207context_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 223static char *buffer; /* Base of buffer. */ 224static size_t bufalloc; /* Allocated buffer size, counting slop. */ 225#define INITIAL_BUFSIZE 32768 /* Initial buffer size, not counting slop. */ 226static int bufdesc; /* File descriptor. */ 227static char *bufbeg; /* Beginning of user-visible stuff. */ 228static char *buflim; /* Limit of user-visible stuff. */ 229static size_t pagesize; /* alignment of memory pages */ 230static off_t bufoffset; /* Read offset; defined on regular files. */ 231static 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) 236static int bufmapped; /* True if buffer is memory-mapped. */ 237static 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. */ 251static int 252reset (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. */ 315static int 316fillbuf (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. */ 443static enum 444{ 445 BINARY_BINARY_FILES, 446 TEXT_BINARY_FILES, 447 WITHOUT_MATCH_BINARY_FILES 448} binary_files; /* How to handle binary files. */ 449 450static int filename_mask; /* If zero, output nulls after filenames. */ 451static int out_quiet; /* Suppress all normal output. */ 452static int out_invert; /* Print nonmatching stuff. */ 453static int out_file; /* Print filenames. */ 454static int out_line; /* Print line numbers. */ 455static int out_byte; /* Print byte offsets. */ 456static int out_before; /* Lines of leading context. */ 457static int out_after; /* Lines of trailing context. */ 458static int count_matches; /* Count matching lines. */ 459static int list_files; /* List matching files. */ 460static int no_filenames; /* Suppress file names. */ 461static off_t max_count; /* Stop after outputting this many 462 lines from an input file. */ 463static int line_buffered; /* If nonzero, use line buffering, i.e. 464 fflush everyline out. */ 465static char *label = NULL; /* Fake filename for stdin */ 466 467 468/* Internal variables to keep track of byte count, context, etc. */ 469static uintmax_t totalcc; /* Total character count before bufbeg. */ 470static char const *lastnl; /* Pointer after last newline counted. */ 471static char const *lastout; /* Pointer after last character output; 472 NULL if no character has been output 473 or if it's conceptually before bufbeg. */ 474static uintmax_t totalnl; /* Total newline count before lastnl. */ 475static off_t outleft; /* Maximum number of lines to be output. */ 476static int pending; /* Pending lines of output. 477 Always kept 0 if out_quiet is true. */ 478static int done_on_match; /* Stop scanning file on first match. */ 479static 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. */ 487static uintmax_t 488add_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 496static void 497nlscan (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. */ 508static void 509print_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 525static void 526prline (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. */ 631static void 632prpending (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. */ 652static void 653prtext (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. */ 717static int 718grepbuf (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. */ 769static int 770grep (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 900static int 901grepfile (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 1003static int 1004grepdir (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 1062static void 1063usage (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 (_("\ 1076Search for PATTERN in each FILE or standard input.\n\ 1077Example: %s -i 'hello world' menu.h main.c\n\ 1078\n\ 1079Regexp 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\ 1097Miscellaneous:\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\ 1105Output 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\ 1133Context 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\ 1145With no FILE, or when FILE is -, read standard input. If less than\n\ 1146two FILEs given, assume -h. Exit status is 0 if match, 1 if no match,\n\ 1147and 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. */ 1154static void 1155setmatcher (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. */ 1164static int 1165install_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). */ 1213static int 1214prepend_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. */ 1242static void 1243prepend_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. */ 1265static int 1266get_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 1302int 1303main (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 (_("\ 1694Copyright 1988, 1992-1999, 2000, 2001 Free Software Foundation, Inc.\n")); 1695 printf (_("\ 1696This is free software; see the source for copying conditions. There is NO\n\ 1697warranty; 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