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