grep.c revision 256281
1193323Sed/* grep.c - main driver file for grep. 2193323Sed Copyright 1992, 1997-1999, 2000 Free Software Foundation, Inc. 3193323Sed 4193323Sed This program is free software; you can redistribute it and/or modify 5193323Sed it under the terms of the GNU General Public License as published by 6193323Sed the Free Software Foundation; either version 2, or (at your option) 7193323Sed any later version. 8193323Sed 9193323Sed This program is distributed in the hope that it will be useful, 10193323Sed but WITHOUT ANY WARRANTY; without even the implied warranty of 11193323Sed MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12193323Sed GNU General Public License for more details. 13193323Sed 14193323Sed You should have received a copy of the GNU General Public License 15193323Sed along with this program; if not, write to the Free Software 16193323Sed Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 17193323Sed 02111-1307, USA. */ 18193323Sed 19193323Sed/* Written July 1992 by Mike Haertel. */ 20193323Sed/* Builtin decompression 1997 by Wolfram Schneider <wosch@FreeBSD.org>. */ 21193323Sed 22193323Sed/* $FreeBSD: stable/10/gnu/usr.bin/grep/grep.c 254093 2013-08-08 11:53:47Z ache $ */ 23193323Sed 24193323Sed#ifdef HAVE_CONFIG_H 25193323Sed# include <config.h> 26193323Sed#endif 27193323Sed#include <sys/types.h> 28193323Sed#include <sys/stat.h> 29193323Sed#if defined(HAVE_MMAP) 30193323Sed# include <sys/mman.h> 31193323Sed#endif 32193323Sed#if defined(HAVE_SETRLIMIT) 33193323Sed# include <sys/time.h> 34193323Sed# include <sys/resource.h> 35198090Srdivacky#endif 36193323Sed#if defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H && defined HAVE_MBRTOWC 37198090Srdivacky/* We can handle multibyte string. */ 38193323Sed# define MBS_SUPPORT 39193323Sed# include <wchar.h> 40193323Sed# include <wctype.h> 41193323Sed#endif 42193323Sed#include <stdio.h> 43193323Sed#include "system.h" 44193323Sed#include "getopt.h" 45193323Sed#include "getpagesize.h" 46193323Sed#include "grep.h" 47193323Sed#include "savedir.h" 48193323Sed#include "xstrtol.h" 49193323Sed#include "xalloc.h" 50193323Sed#include "error.h" 51193323Sed#include "exclude.h" 52193323Sed#include "closeout.h" 53193323Sed 54193323Sed#undef MAX 55193323Sed#define MAX(A,B) ((A) > (B) ? (A) : (B)) 56193323Sed 57193323Sedstruct stats 58207618Srdivacky{ 59207618Srdivacky struct stats const *parent; 60207618Srdivacky struct stat stat; 61193323Sed}; 62193323Sed 63193323Sed/* base of chain of stat buffers, used to detect directory loops */ 64193323Sedstatic struct stats stats_base; 65193323Sed 66207618Srdivacky/* if non-zero, display usage information and exit */ 67207618Srdivackystatic int show_help; 68207618Srdivacky 69193323Sed/* If non-zero, print the version on standard output and exit. */ 70193323Sedstatic int show_version; 71193323Sed 72195098Sed/* If nonzero, suppress diagnostics for nonexistent or unreadable files. */ 73193323Sedstatic int suppress_errors; 74193323Sed 75207618Srdivacky/* If nonzero, use mmap if possible. */ 76198892Srdivackystatic int mmap_option; 77198090Srdivacky 78193323Sed/* If zero, output nulls after filenames. */ 79193323Sedstatic int filename_mask; 80193323Sed 81198892Srdivacky/* If nonzero, use grep_color marker. */ 82193323Sedstatic int color_option; 83195098Sed 84195098Sed/* If nonzero, show only the part of a line matching the expression. */ 85207618Srdivackystatic int only_matching; 86195098Sed 87195098Sed/* The color string used. The user can overwrite it using the environment 88195098Sed variable GREP_COLOR. The default is to print red. */ 89195098Sedstatic const char *grep_color = "01;31"; 90195098Sed 91195098Sedstatic struct exclude *excluded_patterns; 92195098Sedstatic struct exclude *included_patterns; 93207618Srdivacky/* Short options. */ 94195098Sedstatic char const short_options[] = 95195098Sed"0123456789A:B:C:D:EFGHIJPUVX:abcd:e:f:hiKLlm:noqRrsuvwxyZz"; 96195098Sed 97195098Sed/* Non-boolean long options that have no corresponding short equivalents. */ 98195098Sedenum 99195098Sed{ 100207618Srdivacky BINARY_FILES_OPTION = CHAR_MAX + 1, 101195098Sed COLOR_OPTION, 102193323Sed INCLUDE_OPTION, 103193323Sed EXCLUDE_OPTION, 104202375Srdivacky EXCLUDE_FROM_OPTION, 105207618Srdivacky LINE_BUFFERED_OPTION, 106207618Srdivacky LABEL_OPTION 107207618Srdivacky}; 108198090Srdivacky 109202375Srdivacky/* Long options equivalences. */ 110207618Srdivackystatic struct option const long_options[] = 111198090Srdivacky{ 112198090Srdivacky {"after-context", required_argument, NULL, 'A'}, 113198090Srdivacky {"basic-regexp", no_argument, NULL, 'G'}, 114198090Srdivacky {"before-context", required_argument, NULL, 'B'}, 115198090Srdivacky {"binary-files", required_argument, NULL, BINARY_FILES_OPTION}, 116202375Srdivacky {"byte-offset", no_argument, NULL, 'b'}, 117202375Srdivacky {"context", required_argument, NULL, 'C'}, 118198090Srdivacky {"color", optional_argument, NULL, COLOR_OPTION}, 119198090Srdivacky {"colour", optional_argument, NULL, COLOR_OPTION}, 120198090Srdivacky {"count", no_argument, NULL, 'c'}, 121198090Srdivacky {"devices", required_argument, NULL, 'D'}, 122202375Srdivacky {"directories", required_argument, NULL, 'd'}, 123202375Srdivacky {"extended-regexp", no_argument, NULL, 'E'}, 124198090Srdivacky {"exclude", required_argument, NULL, EXCLUDE_OPTION}, 125198090Srdivacky {"exclude-from", required_argument, NULL, EXCLUDE_FROM_OPTION}, 126198090Srdivacky {"file", required_argument, NULL, 'f'}, 127202375Srdivacky {"files-with-matches", no_argument, NULL, 'l'}, 128202375Srdivacky {"files-without-match", no_argument, NULL, 'L'}, 129198090Srdivacky {"fixed-regexp", no_argument, NULL, 'F'}, 130198090Srdivacky {"fixed-strings", no_argument, NULL, 'F'}, 131202375Srdivacky {"help", no_argument, &show_help, 1}, 132198090Srdivacky {"include", required_argument, NULL, INCLUDE_OPTION}, 133202375Srdivacky {"ignore-case", no_argument, NULL, 'i'}, 134202375Srdivacky {"label", required_argument, NULL, LABEL_OPTION}, 135193323Sed {"line-buffered", no_argument, NULL, LINE_BUFFERED_OPTION}, 136193323Sed {"line-number", no_argument, NULL, 'n'}, 137193323Sed {"line-regexp", no_argument, NULL, 'x'}, 138193323Sed {"max-count", required_argument, NULL, 'm'}, 139193323Sed {"mmap", no_argument, &mmap_option, 1}, 140193323Sed {"no-filename", no_argument, NULL, 'h'}, 141193323Sed {"no-messages", no_argument, NULL, 's'}, 142193323Sed {"bz2decompress", no_argument, NULL, 'J'}, 143193323Sed#if HAVE_LIBZ > 0 144198892Srdivacky {"decompress", no_argument, NULL, 'Z'}, 145193323Sed {"null", no_argument, &filename_mask, 0}, 146193323Sed#else 147207618Srdivacky {"null", no_argument, NULL, 'Z'}, 148193323Sed#endif 149193323Sed {"null-data", no_argument, NULL, 'z'}, 150193323Sed {"only-matching", no_argument, NULL, 'o'}, 151193323Sed {"perl-regexp", no_argument, NULL, 'P'}, 152193323Sed {"quiet", no_argument, NULL, 'q'}, 153193323Sed {"recursive", no_argument, NULL, 'r'}, 154193323Sed {"recursive", no_argument, NULL, 'R'}, 155193323Sed {"regexp", required_argument, NULL, 'e'}, 156193323Sed {"invert-match", no_argument, NULL, 'v'}, 157193323Sed {"silent", no_argument, NULL, 'q'}, 158193323Sed {"text", no_argument, NULL, 'a'}, 159193323Sed {"binary", no_argument, NULL, 'U'}, 160193399Sed {"unix-byte-offsets", no_argument, NULL, 'u'}, 161193399Sed {"version", no_argument, NULL, 'V'}, 162193323Sed {"with-filename", no_argument, NULL, 'H'}, 163193323Sed {"word-regexp", no_argument, NULL, 'w'}, 164193323Sed {0, 0, 0, 0} 165193323Sed}; 166193323Sed 167193323Sed/* Define flags declared in grep.h. */ 168207618Srdivackyint match_icase; 169193323Sedint match_words; 170203954Srdivackyint match_lines; 171193323Sedunsigned char eolbyte; 172204642Srdivacky 173203954Srdivacky/* For error messages. */ 174193323Sed/* The name the program was run with, stripped of any leading path. */ 175193323Sedchar *program_name; 176193323Sedstatic char const *filename; 177193323Sedstatic int errseen; 178202375Srdivacky 179193323Sed/* How to handle directories. */ 180198090Srdivackystatic enum 181193323Sed { 182193323Sed READ_DIRECTORIES, 183193323Sed RECURSE_DIRECTORIES, 184193323Sed SKIP_DIRECTORIES 185198090Srdivacky } directories = READ_DIRECTORIES; 186198090Srdivacky 187198090Srdivacky/* How to handle devices. */ 188193323Sedstatic enum 189202375Srdivacky { 190193323Sed READ_DEVICES, 191193323Sed SKIP_DEVICES 192202375Srdivacky } devices = READ_DEVICES; 193210299Sed 194210299Sedstatic int grepdir PARAMS ((char const *, struct stats const *)); 195202375Srdivacky#if defined(HAVE_DOS_FILE_CONTENTS) 196210299Sedstatic inline int undossify_input PARAMS ((register char *, size_t)); 197210299Sed#endif 198204642Srdivacky 199204642Srdivacky/* Functions we'll use to search. */ 200193323Sedstatic void (*compile) PARAMS ((char const *, size_t)); 201193323Sedstatic size_t (*execute) PARAMS ((char const *, size_t, size_t *, int)); 202204642Srdivacky 203204642Srdivacky/* Like error, but suppress the diagnostic if requested. */ 204202375Srdivackystatic void 205193323Sedsuppressible_error (char const *mesg, int errnum) 206193323Sed{ 207193323Sed if (! suppress_errors) 208204642Srdivacky error (0, errnum, "%s", mesg); 209193323Sed errseen = 1; 210193323Sed} 211193323Sed 212193323Sed/* Convert STR to a positive integer, storing the result in *OUT. 213193323Sed STR must be a valid context length argument; report an error if it 214193323Sed isn't. */ 215193323Sedstatic void 216193323Sedcontext_length_arg (char const *str, int *out) 217193323Sed{ 218193323Sed uintmax_t value; 219193323Sed if (! (xstrtoumax (str, 0, 10, &value, "") == LONGINT_OK 220193323Sed && 0 <= (*out = value) 221207618Srdivacky && *out == value)) 222207618Srdivacky { 223193323Sed error (2, 0, "%s: %s\n", str, _("invalid context length argument")); 224193323Sed } 225193323Sed} 226193323Sed 227193323Sed 228210299Sed/* Hairy buffering mechanism for grep. The intent is to keep 229210299Sed all reads aligned on a page boundary and multiples of the 230195098Sed page size, unless a read yields a partial page. */ 231193323Sed 232193323Sedstatic char *buffer; /* Base of buffer. */ 233195098Sedstatic size_t bufalloc; /* Allocated buffer size, counting slop. */ 234193323Sed#define INITIAL_BUFSIZE 32768 /* Initial buffer size, not counting slop. */ 235195098Sedstatic int bufdesc; /* File descriptor. */ 236193323Sedstatic char *bufbeg; /* Beginning of user-visible stuff. */ 237195098Sedstatic char *buflim; /* Limit of user-visible stuff. */ 238198892Srdivackystatic size_t pagesize; /* alignment of memory pages */ 239199989Srdivackystatic off_t bufoffset; /* Read offset; defined on regular files. */ 240199989Srdivackystatic off_t after_last_match; /* Pointer after last matching line that 241193323Sed would have been output if we were 242193323Sed outputting characters. */ 243193323Sed 244193323Sed#if defined(HAVE_MMAP) 245193323Sedstatic int bufmapped; /* True if buffer is memory-mapped. */ 246193323Sedstatic off_t initial_bufoffset; /* Initial value of bufoffset. */ 247193323Sed#else 248193323Sed# define bufmapped 0 249193323Sed#endif 250193323Sed 251193323Sed#include <bzlib.h> 252193323Sedstatic BZFILE* bzbufdesc; /* libbz2 file handle. */ 253193323Sedstatic int BZflag; /* uncompress before searching. */ 254193323Sed#if HAVE_LIBZ > 0 255193323Sed#include <zlib.h> 256193323Sedstatic gzFile gzbufdesc; /* zlib file descriptor. */ 257193323Sedstatic int Zflag; /* uncompress before searching. */ 258193323Sed#endif 259193323Sed 260193323Sed/* Return VAL aligned to the next multiple of ALIGNMENT. VAL can be 261193323Sed an integer or a pointer. Both args must be free of side effects. */ 262193323Sed#define ALIGN_TO(val, alignment) \ 263193323Sed ((size_t) (val) % (alignment) == 0 \ 264193323Sed ? (val) \ 265193323Sed : (val) + ((alignment) - (size_t) (val) % (alignment))) 266193323Sed 267193323Sed/* Reset the buffer for a new file, returning zero if we should skip it. 268193323Sed Initialize on the first time through. */ 269193323Sedstatic int 270193323Sedreset (int fd, char const *file, struct stats *stats) 271193323Sed{ 272193323Sed if (! pagesize) 273193323Sed { 274193399Sed pagesize = getpagesize (); 275193399Sed if (pagesize == 0 || 2 * pagesize + 1 <= pagesize) 276193399Sed abort (); 277193399Sed bufalloc = ALIGN_TO (INITIAL_BUFSIZE, pagesize) + pagesize + 1; 278193399Sed buffer = xmalloc (bufalloc); 279193399Sed } 280193399Sed if (BZflag) 281193399Sed { 282193399Sed bzbufdesc = BZ2_bzdopen(fd, "r"); 283193399Sed if (bzbufdesc == NULL) 284193399Sed error(2, 0, _("memory exhausted")); 285193323Sed } 286193323Sed#if HAVE_LIBZ > 0 287193323Sed if (Zflag) 288193323Sed { 289203954Srdivacky gzbufdesc = gzdopen(fd, "r"); 290203954Srdivacky if (gzbufdesc == NULL) 291193323Sed error(2, 0, _("memory exhausted")); 292193323Sed } 293203954Srdivacky#endif 294203954Srdivacky 295203954Srdivacky bufbeg = buflim = ALIGN_TO (buffer + 1, pagesize); 296203954Srdivacky bufbeg[-1] = eolbyte; 297203954Srdivacky bufdesc = fd; 298203954Srdivacky 299203954Srdivacky if (fstat (fd, &stats->stat) != 0) 300203954Srdivacky { 301193323Sed error (0, errno, "fstat"); 302193323Sed return 0; 303202375Srdivacky } 304202375Srdivacky if (fd != STDIN_FILENO) { 305202375Srdivacky if (directories == SKIP_DIRECTORIES && S_ISDIR (stats->stat.st_mode)) 306202375Srdivacky return 0; 307202375Srdivacky#ifndef DJGPP 308193323Sed if (devices == SKIP_DEVICES && (S_ISCHR(stats->stat.st_mode) || S_ISBLK(stats->stat.st_mode) || S_ISSOCK(stats->stat.st_mode) || S_ISFIFO(stats->stat.st_mode))) 309193323Sed#else 310193323Sed if (devices == SKIP_DEVICES && (S_ISCHR(stats->stat.st_mode) || S_ISBLK(stats->stat.st_mode))) 311193323Sed#endif 312193323Sed return 0; 313193323Sed } 314193323Sed if ( 315193323Sed BZflag || 316193323Sed#if HAVE_LIBZ > 0 317193323Sed Zflag || 318193323Sed#endif 319193323Sed S_ISREG (stats->stat.st_mode)) 320193323Sed { 321193323Sed if (file) 322193323Sed bufoffset = 0; 323193323Sed else 324193323Sed { 325193323Sed bufoffset = lseek (fd, 0, SEEK_CUR); 326193323Sed if (bufoffset < 0) 327193323Sed { 328193323Sed error (0, errno, "lseek"); 329193323Sed return 0; 330193323Sed } 331193323Sed } 332193323Sed#if defined(HAVE_MMAP) 333193323Sed initial_bufoffset = bufoffset; 334193323Sed bufmapped = mmap_option && bufoffset % pagesize == 0; 335193323Sed#endif 336193323Sed } 337193323Sed else 338193323Sed { 339193323Sed#if defined(HAVE_MMAP) 340193323Sed bufmapped = 0; 341193323Sed#endif 342193323Sed } 343193323Sed return 1; 344193323Sed} 345193323Sed 346193323Sed/* Read new stuff into the buffer, saving the specified 347203954Srdivacky amount of old stuff. When we're done, 'bufbeg' points 348193323Sed to the beginning of the buffer contents, and 'buflim' 349203954Srdivacky points just after the end. Return zero if there's an error. */ 350203954Srdivackystatic int 351203954Srdivackyfillbuf (size_t save, struct stats const *stats) 352205218Srdivacky{ 353205218Srdivacky size_t fillsize = 0; 354205218Srdivacky int cc = 1; 355205218Srdivacky char *readbuf; 356193323Sed size_t readsize; 357205218Srdivacky 358193323Sed /* Offset from start of buffer to start of old stuff 359193323Sed that we want to save. */ 360193323Sed size_t saved_offset = buflim - save - buffer; 361193323Sed 362205218Srdivacky if (pagesize <= buffer + bufalloc - buflim) 363193323Sed { 364193323Sed readbuf = buflim; 365193323Sed bufbeg = buflim - save; 366193323Sed } 367193323Sed else 368193323Sed { 369193323Sed size_t minsize = save + pagesize; 370193323Sed size_t newsize; 371193323Sed size_t newalloc; 372193323Sed char *newbuf; 373193323Sed 374205218Srdivacky /* Grow newsize until it is at least as great as minsize. */ 375205218Srdivacky for (newsize = bufalloc - pagesize - 1; newsize < minsize; newsize *= 2) 376210299Sed if (newsize * 2 < newsize || newsize * 2 + pagesize + 1 < newsize * 2) 377210299Sed xalloc_die (); 378193323Sed 379193323Sed /* Try not to allocate more memory than the file size indicates, 380193323Sed as that might cause unnecessary memory exhaustion if the file 381193323Sed is large. However, do not use the original file size as a 382193323Sed heuristic if we've already read past the file end, as most 383210299Sed likely the file is growing. */ 384193323Sed if (S_ISREG (stats->stat.st_mode)) 385193323Sed { 386193323Sed off_t to_be_read = stats->stat.st_size - bufoffset; 387193323Sed off_t maxsize_off = save + to_be_read; 388193323Sed if (0 <= to_be_read && to_be_read <= maxsize_off 389205218Srdivacky && maxsize_off == (size_t) maxsize_off 390205218Srdivacky && minsize <= (size_t) maxsize_off 391205218Srdivacky && (size_t) maxsize_off < newsize) 392193323Sed newsize = maxsize_off; 393193323Sed } 394193323Sed 395193323Sed /* Add enough room so that the buffer is aligned and has room 396193323Sed for byte sentinels fore and aft. */ 397193323Sed newalloc = newsize + pagesize + 1; 398193323Sed 399193323Sed newbuf = bufalloc < newalloc ? xmalloc (bufalloc = newalloc) : buffer; 400193323Sed readbuf = ALIGN_TO (newbuf + 1 + save, pagesize); 401193323Sed bufbeg = readbuf - save; 402205218Srdivacky memmove (bufbeg, buffer + saved_offset, save); 403193323Sed bufbeg[-1] = eolbyte; 404193323Sed if (newbuf != buffer) 405193323Sed { 406193323Sed free (buffer); 407205218Srdivacky buffer = newbuf; 408205218Srdivacky } 409205218Srdivacky } 410193323Sed 411193323Sed readsize = buffer + bufalloc - readbuf; 412193323Sed readsize -= readsize % pagesize; 413198090Srdivacky 414198090Srdivacky#if defined(HAVE_MMAP) 415193323Sed if (bufmapped) 416193323Sed { 417193323Sed size_t mmapsize = readsize; 418193323Sed 419204642Srdivacky /* Don't mmap past the end of the file; some hosts don't allow this. 420204792Srdivacky Use `read' on the last page. */ 421204642Srdivacky if (stats->stat.st_size - bufoffset < mmapsize) 422204642Srdivacky { 423204642Srdivacky mmapsize = stats->stat.st_size - bufoffset; 424204642Srdivacky mmapsize -= mmapsize % pagesize; 425204642Srdivacky } 426193323Sed 427205218Srdivacky if (mmapsize 428205218Srdivacky && (mmap ((caddr_t) readbuf, mmapsize, 429205218Srdivacky PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, 430193323Sed bufdesc, bufoffset) 431193323Sed != (caddr_t) -1)) 432193323Sed { 433193323Sed /* Do not bother to use madvise with MADV_SEQUENTIAL or 434193323Sed MADV_WILLNEED on the mmapped memory. One might think it 435193323Sed would help, but it slows us down about 30% on SunOS 4.1. */ 436193323Sed fillsize = mmapsize; 437193323Sed } 438193323Sed else 439193323Sed { 440193323Sed /* Stop using mmap on this file. Synchronize the file 441193323Sed offset. Do not warn about mmap failures. On some hosts 442193323Sed (e.g. Solaris 2.5) mmap can fail merely because some 443193323Sed other process has an advisory read lock on the file. 444193323Sed There's no point alarming the user about this misfeature. */ 445193323Sed bufmapped = 0; 446193323Sed if (bufoffset != initial_bufoffset 447193323Sed && lseek (bufdesc, bufoffset, SEEK_SET) < 0) 448193323Sed { 449205218Srdivacky error (0, errno, "lseek"); 450204642Srdivacky cc = 0; 451204642Srdivacky } 452205218Srdivacky } 453193323Sed } 454205218Srdivacky#endif /*HAVE_MMAP*/ 455193323Sed 456193323Sed if (! fillsize) 457193323Sed { 458204642Srdivacky ssize_t bytesread; 459204642Srdivacky do 460204642Srdivacky if (BZflag && bzbufdesc) 461204642Srdivacky { 462204642Srdivacky int bzerr; 463204642Srdivacky bytesread = BZ2_bzRead (&bzerr, bzbufdesc, readbuf, readsize); 464204642Srdivacky 465204642Srdivacky switch (bzerr) 466204642Srdivacky { 467193323Sed case BZ_OK: 468193323Sed case BZ_STREAM_END: 469193323Sed /* ok */ 470193323Sed break; 471193323Sed case BZ_DATA_ERROR_MAGIC: 472198090Srdivacky BZ2_bzReadClose (&bzerr, bzbufdesc); bzbufdesc = NULL; 473198090Srdivacky lseek (bufdesc, 0, SEEK_SET); 474193323Sed bytesread = read (bufdesc, readbuf, readsize); 475193323Sed break; 476193323Sed default: 477193323Sed bytesread = 0; 478193323Sed break; 479193323Sed } 480193323Sed } 481193323Sed else 482193323Sed#if HAVE_LIBZ > 0 483193323Sed if (Zflag) 484193323Sed bytesread = gzread (gzbufdesc, readbuf, readsize); 485193323Sed else 486193323Sed#endif 487193323Sed bytesread = read (bufdesc, readbuf, readsize); 488193323Sed while (bytesread < 0 && errno == EINTR); 489193323Sed if (bytesread < 0) 490193323Sed cc = 0; 491198090Srdivacky else 492193323Sed fillsize = bytesread; 493193323Sed } 494193323Sed 495193323Sed bufoffset += fillsize; 496193323Sed#if defined(HAVE_DOS_FILE_CONTENTS) 497193323Sed if (fillsize) 498193323Sed fillsize = undossify_input (readbuf, fillsize); 499193323Sed#endif 500193323Sed buflim = readbuf + fillsize; 501193323Sed return cc; 502193323Sed} 503203954Srdivacky 504203954Srdivacky/* Flags controlling the style of output. */ 505210299Sedstatic enum 506203954Srdivacky{ 507193323Sed BINARY_BINARY_FILES, 508193323Sed TEXT_BINARY_FILES, 509193323Sed WITHOUT_MATCH_BINARY_FILES 510193323Sed} binary_files; /* How to handle binary files. */ 511193323Sed 512193323Sedstatic int filename_mask; /* If zero, output nulls after filenames. */ 513193323Sedstatic int out_quiet; /* Suppress all normal output. */ 514193323Sedstatic int out_invert; /* Print nonmatching stuff. */ 515193323Sedstatic int out_file; /* Print filenames. */ 516193323Sedstatic int out_line; /* Print line numbers. */ 517193323Sedstatic int out_byte; /* Print byte offsets. */ 518193323Sedstatic int out_before; /* Lines of leading context. */ 519193323Sedstatic int out_after; /* Lines of trailing context. */ 520193323Sedstatic int count_matches; /* Count matching lines. */ 521193323Sedstatic int list_files; /* List matching files. */ 522193323Sedstatic int no_filenames; /* Suppress file names. */ 523193323Sedstatic off_t max_count; /* Stop after outputting this many 524193323Sed lines from an input file. */ 525193323Sedstatic int line_buffered; /* If nonzero, use line buffering, i.e. 526193323Sed fflush everyline out. */ 527193323Sedstatic char *label = NULL; /* Fake filename for stdin */ 528193323Sed 529206124Srdivacky 530193323Sed/* Internal variables to keep track of byte count, context, etc. */ 531193323Sedstatic uintmax_t totalcc; /* Total character count before bufbeg. */ 532193323Sedstatic char const *lastnl; /* Pointer after last newline counted. */ 533207618Srdivackystatic char const *lastout; /* Pointer after last character output; 534193323Sed NULL if no character has been output 535207618Srdivacky or if it's conceptually before bufbeg. */ 536207618Srdivackystatic uintmax_t totalnl; /* Total newline count before lastnl. */ 537207618Srdivackystatic off_t outleft; /* Maximum number of lines to be output. */ 538193323Sedstatic int pending; /* Pending lines of output. 539193323Sed Always kept 0 if out_quiet is true. */ 540193323Sedstatic int done_on_match; /* Stop scanning file on first match. */ 541193323Sedstatic int exit_on_match; /* Exit on first match. */ 542193323Sed 543193323Sed#if defined(HAVE_DOS_FILE_CONTENTS) 544193323Sed# include "dosbuf.c" 545193323Sed#endif 546193323Sed 547193323Sed/* Add two numbers that count input bytes or lines, and report an 548193323Sed error if the addition overflows. */ 549193323Sedstatic uintmax_t 550193323Sedadd_count (uintmax_t a, uintmax_t b) 551193323Sed{ 552193323Sed uintmax_t sum = a + b; 553193323Sed if (sum < a) 554193323Sed error (2, 0, _("input is too large to count")); 555193323Sed return sum; 556193323Sed} 557193323Sed 558193323Sedstatic void 559193323Sednlscan (char const *lim) 560193323Sed{ 561193323Sed size_t newlines = 0; 562193323Sed char const *beg; 563193323Sed for (beg = lastnl; beg != lim; beg = memchr (beg, eolbyte, lim - beg), beg++) 564193323Sed newlines++; 565193323Sed totalnl = add_count (totalnl, newlines); 566193323Sed lastnl = lim; 567195098Sed} 568195098Sed 569195098Sed/* Print a byte offset, followed by a character separator. */ 570198090Srdivackystatic void 571193323Sedprint_offset_sep (uintmax_t pos, char sep) 572195098Sed{ 573195098Sed /* Do not rely on printf to print pos, since uintmax_t may be longer 574193323Sed than long, and long long is not portable. */ 575193323Sed 576193323Sed char buf[sizeof pos * CHAR_BIT]; 577193323Sed char *p = buf + sizeof buf - 1; 578198090Srdivacky *p = sep; 579198090Srdivacky 580195098Sed do 581195098Sed *--p = '0' + pos % 10; 582195098Sed while ((pos /= 10) != 0); 583195098Sed 584195098Sed fwrite (p, 1, buf + sizeof buf - p, stdout); 585195098Sed} 586198090Srdivacky 587195098Sedstatic void 588195098Sedprline (char const *beg, char const *lim, int sep) 589195098Sed{ 590195098Sed if (out_file) 591195098Sed printf ("%s%c", filename, sep & filename_mask); 592198090Srdivacky if (out_line) 593195098Sed { 594195098Sed nlscan (beg); 595195098Sed totalnl = add_count (totalnl, 1); 596195098Sed print_offset_sep (totalnl, sep); 597195098Sed lastnl = lim; 598198090Srdivacky } 599195098Sed if (out_byte) 600195098Sed { 601195098Sed uintmax_t pos = add_count (totalcc, beg - bufbeg); 602195098Sed#if defined(HAVE_DOS_FILE_CONTENTS) 603195098Sed pos = dossified_pos (pos); 604195098Sed#endif 605195098Sed print_offset_sep (pos, sep); 606198892Srdivacky } 607195098Sed if (only_matching) 608195098Sed { 609198892Srdivacky size_t match_size; 610198892Srdivacky size_t match_offset; 611199989Srdivacky while ((match_offset = (*execute) (beg, lim - beg, &match_size, 1)) 612193323Sed != (size_t) -1) 613198090Srdivacky { 614195098Sed char const *b = beg + match_offset; 615195098Sed if (b == lim) 616195098Sed break; 617195098Sed if (match_size == 0) 618195098Sed break; 619195098Sed if(color_option) 620195098Sed printf("\33[%sm", grep_color); 621195098Sed fwrite(b, sizeof (char), match_size, stdout); 622195098Sed if(color_option) 623198090Srdivacky fputs("\33[00m", stdout); 624195098Sed fputs("\n", stdout); 625195098Sed beg = b + match_size; 626195098Sed } 627195098Sed lastout = lim; 628195098Sed if(line_buffered) 629195098Sed fflush(stdout); 630193323Sed return; 631193323Sed } 632195098Sed if (color_option) 633195098Sed { 634195098Sed size_t match_size; 635195098Sed size_t match_offset; 636195098Sed while (lim-beg && (match_offset = (*execute) (beg, lim - beg, &match_size, 1)) 637198892Srdivacky != (size_t) -1) 638195098Sed { 639195098Sed char const *b = beg + match_offset; 640198892Srdivacky /* Avoid matching the empty line at the end of the buffer. */ 641198892Srdivacky if (b == lim) 642199989Srdivacky break; 643193323Sed /* Avoid hanging on grep --color "" foo */ 644193323Sed if (match_size == 0) 645193323Sed break; 646193323Sed fwrite (beg, sizeof (char), match_offset, stdout); 647193323Sed printf ("\33[%sm", grep_color); 648193323Sed fwrite (b, sizeof (char), match_size, stdout); 649193323Sed fputs ("\33[00m", stdout); 650193323Sed beg = b + match_size; 651193323Sed } 652193323Sed fputs ("\33[K", stdout); 653198090Srdivacky } 654210299Sed fwrite (beg, 1, lim - beg, stdout); 655198090Srdivacky if (ferror (stdout)) 656198090Srdivacky error (0, errno, _("writing output")); 657198090Srdivacky lastout = lim; 658198090Srdivacky if (line_buffered) 659198090Srdivacky fflush (stdout); 660198090Srdivacky} 661207618Srdivacky 662207618Srdivacky/* Print pending lines of trailing context prior to LIM. Trailing context ends 663198090Srdivacky at the next matching line when OUTLEFT is 0. */ 664198090Srdivackystatic void 665198090Srdivackyprpending (char const *lim) 666198090Srdivacky{ 667198090Srdivacky if (!lastout) 668198090Srdivacky lastout = bufbeg; 669198090Srdivacky while (pending > 0 && lastout < lim) 670198090Srdivacky { 671198090Srdivacky char const *nl = memchr (lastout, eolbyte, lim - lastout); 672198090Srdivacky size_t match_size; 673207618Srdivacky --pending; 674198090Srdivacky if (outleft 675198090Srdivacky || (((*execute) (lastout, nl - lastout, &match_size, 0) == (size_t) -1) 676198090Srdivacky == !out_invert)) 677207618Srdivacky prline (lastout, nl + 1, '-'); 678198090Srdivacky else 679198090Srdivacky pending = 0; 680198090Srdivacky } 681198090Srdivacky} 682207618Srdivacky 683207618Srdivacky/* Print the lines between BEG and LIM. Deal with context crap. 684207618Srdivacky If NLINESP is non-null, store a count of lines between BEG and LIM. */ 685207618Srdivackystatic void 686207618Srdivackyprtext (char const *beg, char const *lim, int *nlinesp) 687207618Srdivacky{ 688207618Srdivacky static int used; /* avoid printing "--" before any output */ 689207618Srdivacky char const *bp, *p; 690207618Srdivacky char eol = eolbyte; 691207618Srdivacky int i, n; 692207618Srdivacky 693207618Srdivacky if (!out_quiet && pending > 0) 694207618Srdivacky prpending (beg); 695207618Srdivacky 696207618Srdivacky p = beg; 697207618Srdivacky 698207618Srdivacky if (!out_quiet) 699207618Srdivacky { 700207618Srdivacky /* Deal with leading context crap. */ 701198090Srdivacky 702198090Srdivacky bp = lastout ? lastout : bufbeg; 703193323Sed for (i = 0; i < out_before; ++i) 704193323Sed if (p > bp) 705198090Srdivacky do 706202375Srdivacky --p; 707198090Srdivacky while (p[-1] != eol); 708198090Srdivacky 709193323Sed /* We only print the "--" separator if our output is 710193323Sed discontiguous from the last output in the file. */ 711193323Sed if ((out_before || out_after) && used && p != lastout) 712198090Srdivacky puts ("--"); 713198090Srdivacky 714198090Srdivacky while (p < beg) 715195098Sed { 716195098Sed char const *nl = memchr (p, eol, beg - p); 717193323Sed nl++; 718195098Sed prline (p, nl, '-'); 719195098Sed p = nl; 720195098Sed } 721195098Sed } 722195098Sed 723198090Srdivacky if (nlinesp) 724195098Sed { 725195098Sed /* Caller wants a line count. */ 726198090Srdivacky for (n = 0; p < lim && n < outleft; n++) 727198090Srdivacky { 728195098Sed char const *nl = memchr (p, eol, lim - p); 729193323Sed nl++; 730193323Sed if (!out_quiet) 731193323Sed prline (p, nl, ':'); 732193323Sed p = nl; 733193323Sed } 734193323Sed *nlinesp = n; 735193323Sed 736193323Sed /* relying on it that this function is never called when outleft = 0. */ 737193323Sed after_last_match = bufoffset - (buflim - p); 738193323Sed } 739198090Srdivacky else 740198090Srdivacky if (!out_quiet) 741198090Srdivacky prline (beg, lim, ':'); 742193323Sed 743193323Sed pending = out_quiet ? 0 : out_after; 744193323Sed used = 1; 745193323Sed} 746193323Sed 747193323Sed/* Scan the specified portion of the buffer, matching lines (or 748193323Sed between matching lines if OUT_INVERT is true). Return a count of 749193323Sed lines printed. */ 750193323Sedstatic int 751193323Sedgrepbuf (char const *beg, char const *lim) 752193323Sed{ 753193323Sed int nlines, n; 754195098Sed register char const *p; 755193323Sed size_t match_offset; 756193323Sed size_t match_size; 757193323Sed 758193323Sed nlines = 0; 759193323Sed p = beg; 760193323Sed while ((match_offset = (*execute) (p, lim - p, &match_size, 0)) != (size_t) -1) 761193323Sed { 762193323Sed char const *b = p + match_offset; 763193323Sed char const *endp = b + match_size; 764193323Sed /* Avoid matching the empty line at the end of the buffer. */ 765193323Sed if (b == lim) 766207618Srdivacky break; 767193323Sed if (!out_invert) 768207618Srdivacky { 769193323Sed prtext (b, endp, (int *) 0); 770193323Sed nlines++; 771193323Sed outleft--; 772193323Sed if (!outleft || done_on_match) 773193323Sed { 774195098Sed if (exit_on_match) 775193323Sed exit (0); 776193323Sed after_last_match = bufoffset - (buflim - endp); 777193323Sed return nlines; 778193323Sed } 779193323Sed } 780198090Srdivacky else if (p < b) 781198090Srdivacky { 782198090Srdivacky prtext (p, b, &n); 783198090Srdivacky nlines += n; 784193323Sed outleft -= n; 785193323Sed if (!outleft) 786193323Sed return nlines; 787193323Sed } 788193323Sed p = endp; 789193323Sed } 790193323Sed if (out_invert && p < lim) 791207618Srdivacky { 792193323Sed prtext (p, lim, &n); 793193323Sed nlines += n; 794193323Sed outleft -= n; 795193323Sed } 796198090Srdivacky return nlines; 797198090Srdivacky} 798198090Srdivacky 799193323Sed/* Search a given file. Normally, return a count of lines printed; 800193323Sed but if the file is a directory and we search it recursively, then 801193323Sed return -2 if there was a match, and -1 otherwise. */ 802193323Sedstatic int 803193323Sedgrep (int fd, char const *file, struct stats *stats) 804193323Sed{ 805193323Sed int nlines, i; 806193323Sed int not_text; 807193323Sed size_t residue, save; 808193323Sed char oldc; 809193323Sed char *beg; 810193323Sed char *lim; 811193323Sed char eol = eolbyte; 812193323Sed 813193323Sed if (!reset (fd, file, stats)) 814193323Sed return 0; 815193323Sed 816193323Sed if (file && directories == RECURSE_DIRECTORIES 817193323Sed && S_ISDIR (stats->stat.st_mode)) 818193323Sed { 819207618Srdivacky /* Close fd now, so that we don't open a lot of file descriptors 820195098Sed when we recurse deeply. */ 821193323Sed if (BZflag && bzbufdesc) 822193323Sed BZ2_bzclose(bzbufdesc); 823193323Sed else 824193323Sed#if HAVE_LIBZ > 0 825193323Sed if (Zflag) 826193323Sed gzclose(gzbufdesc); 827193323Sed else 828193323Sed#endif 829193323Sed if (close (fd) != 0) 830193323Sed error (0, errno, "%s", file); 831193323Sed return grepdir (file, stats) - 2; 832193323Sed } 833193323Sed 834193323Sed totalcc = 0; 835193323Sed lastout = 0; 836193323Sed totalnl = 0; 837193323Sed outleft = max_count; 838193323Sed after_last_match = 0; 839193323Sed pending = 0; 840198090Srdivacky 841198090Srdivacky nlines = 0; 842198090Srdivacky residue = 0; 843193323Sed save = 0; 844193323Sed 845193323Sed if (! fillbuf (save, stats)) 846193323Sed { 847193323Sed if (! is_EISDIR (errno, file)) 848193323Sed suppressible_error (filename, errno); 849193323Sed return 0; 850207618Srdivacky } 851193323Sed 852193323Sed not_text = (((binary_files == BINARY_BINARY_FILES && !out_quiet) 853193323Sed || binary_files == WITHOUT_MATCH_BINARY_FILES) 854193323Sed && memchr (bufbeg, eol ? '\0' : '\200', buflim - bufbeg)); 855193323Sed if (not_text && binary_files == WITHOUT_MATCH_BINARY_FILES) 856193323Sed return 0; 857193323Sed done_on_match += not_text; 858193323Sed out_quiet += not_text; 859193323Sed 860193323Sed for (;;) 861193323Sed { 862193323Sed lastnl = bufbeg; 863193323Sed if (lastout) 864210299Sed lastout = bufbeg; 865210299Sed 866210299Sed beg = bufbeg + save; 867210299Sed 868193323Sed /* no more data to scan (eof) except for maybe a residue -> break */ 869193323Sed if (beg == buflim) 870210299Sed break; 871193323Sed 872193323Sed /* Determine new residue (the length of an incomplete line at the end of 873193323Sed the buffer, 0 means there is no incomplete last line). */ 874193323Sed oldc = beg[-1]; 875195098Sed beg[-1] = eol; 876193323Sed for (lim = buflim; lim[-1] != eol; lim--) 877193323Sed continue; 878193323Sed beg[-1] = oldc; 879205407Srdivacky if (lim == beg) 880193323Sed lim = beg - residue; 881210299Sed beg -= residue; 882193323Sed residue = buflim - lim; 883193323Sed 884193323Sed if (beg < lim) 885193323Sed { 886193323Sed if (outleft) 887193323Sed nlines += grepbuf (beg, lim); 888193323Sed if (pending) 889193323Sed prpending (lim); 890193323Sed if((!outleft && !pending) || (nlines && done_on_match && !out_invert)) 891193323Sed goto finish_grep; 892193323Sed } 893193323Sed 894193323Sed /* The last OUT_BEFORE lines at the end of the buffer will be needed as 895207618Srdivacky leading context if there is a matching line at the begin of the 896207618Srdivacky next data. Make beg point to their begin. */ 897193323Sed i = 0; 898193323Sed beg = lim; 899193323Sed while (i < out_before && beg > bufbeg && beg != lastout) 900193323Sed { 901193323Sed ++i; 902193323Sed do 903193323Sed --beg; 904193323Sed while (beg[-1] != eol); 905193323Sed } 906193323Sed 907193323Sed /* detect if leading context is discontinuous from last printed line. */ 908193323Sed if (beg != lastout) 909193323Sed lastout = 0; 910193323Sed 911193323Sed /* Handle some details and read more data to scan. */ 912193323Sed save = residue + lim - beg; 913193323Sed if (out_byte) 914193323Sed totalcc = add_count (totalcc, buflim - bufbeg - save); 915193323Sed if (out_line) 916193323Sed nlscan (beg); 917193323Sed if (! fillbuf (save, stats)) 918193323Sed { 919193323Sed if (! is_EISDIR (errno, file)) 920193323Sed suppressible_error (filename, errno); 921193323Sed goto finish_grep; 922193323Sed } 923193323Sed } 924193323Sed if (residue) 925193323Sed { 926193323Sed *buflim++ = eol; 927193323Sed if (outleft) 928193323Sed nlines += grepbuf (bufbeg + save - residue, buflim); 929193323Sed if (pending) 930193323Sed prpending (buflim); 931193323Sed } 932210299Sed 933210299Sed finish_grep: 934210299Sed done_on_match -= not_text; 935210299Sed out_quiet -= not_text; 936210299Sed if ((not_text & ~out_quiet) && nlines != 0) 937210299Sed printf (_("Binary file %s matches\n"), filename); 938193323Sed return nlines; 939210299Sed} 940210299Sed 941210299Sedstatic int 942210299Sedgrepfile (char const *file, struct stats *stats) 943210299Sed{ 944210299Sed int desc; 945205407Srdivacky int count; 946205407Srdivacky int status; 947210299Sed int flags; 948210299Sed 949210299Sed if (! file) 950193323Sed { 951210299Sed desc = 0; 952210299Sed filename = label ? label : _("(standard input)"); 953193323Sed } 954193323Sed else 955193323Sed { 956193323Sed while ((desc = open (file, O_RDONLY | O_NONBLOCK)) < 0 && errno == EINTR) 957193323Sed continue; 958207618Srdivacky 959195098Sed if (desc < 0) 960210299Sed { 961210299Sed int e = errno; 962193323Sed 963193323Sed if (is_EISDIR (e, file) && directories == RECURSE_DIRECTORIES) 964193323Sed { 965193323Sed if (stat (file, &stats->stat) != 0) 966193323Sed { 967193323Sed error (0, errno, "%s", file); 968193323Sed return 1; 969193323Sed } 970207618Srdivacky 971193323Sed return grepdir (file, stats); 972207618Srdivacky } 973193323Sed 974205407Srdivacky if (!suppress_errors) 975193323Sed { 976210299Sed if (directories == SKIP_DIRECTORIES) 977193323Sed switch (e) 978193323Sed { 979193323Sed#if defined(EISDIR) 980198090Srdivacky case EISDIR: 981198090Srdivacky return 1; 982205407Srdivacky#endif 983193323Sed case EACCES: 984193323Sed /* When skipping directories, don't worry about 985193323Sed directories that can't be opened. */ 986193323Sed if (isdir (file)) 987193323Sed return 1; 988193323Sed break; 989193323Sed } 990193323Sed } 991193323Sed 992193323Sed suppressible_error (file, e); 993193323Sed return 1; 994193323Sed } 995193323Sed 996193323Sed flags = fcntl(desc, F_GETFL); 997193323Sed flags &= ~O_NONBLOCK; 998193323Sed fcntl(desc, F_SETFL, flags); 999193323Sed filename = file; 1000193323Sed } 1001193323Sed 1002193323Sed#if defined(SET_BINARY) 1003193323Sed /* Set input to binary mode. Pipes are simulated with files 1004193323Sed on DOS, so this includes the case of "foo | grep bar". */ 1005193323Sed if (!isatty (desc)) 1006193323Sed SET_BINARY (desc); 1007193323Sed#endif 1008193323Sed 1009193323Sed count = grep (desc, file, stats); 1010193323Sed if (count < 0) 1011193323Sed status = count + 2; 1012193323Sed else 1013193323Sed { 1014193323Sed if (count_matches) 1015193323Sed { 1016193323Sed if (out_file) 1017193323Sed printf ("%s%c", filename, ':' & filename_mask); 1018193323Sed printf ("%d\n", count); 1019193323Sed } 1020193323Sed 1021193323Sed status = !count; 1022193323Sed if (list_files == 1 - 2 * status) 1023193323Sed printf ("%s%c", filename, '\n' & filename_mask); 1024193323Sed 1025193323Sed if (BZflag && bzbufdesc) 1026193323Sed BZ2_bzclose(bzbufdesc); 1027193323Sed else 1028193323Sed#if HAVE_LIBZ > 0 1029193323Sed if (Zflag) 1030193323Sed gzclose(gzbufdesc); 1031193323Sed else 1032193323Sed#endif 1033193323Sed if (! file) 1034193323Sed { 1035193323Sed off_t required_offset = outleft ? bufoffset : after_last_match; 1036193323Sed if ((bufmapped || required_offset != bufoffset) 1037193323Sed && lseek (desc, required_offset, SEEK_SET) < 0 1038193323Sed && S_ISREG (stats->stat.st_mode)) 1039193323Sed error (0, errno, "%s", filename); 1040193323Sed } 1041193323Sed else 1042193323Sed while (close (desc) != 0) 1043193323Sed if (errno != EINTR) 1044193323Sed { 1045193323Sed error (0, errno, "%s", file); 1046193323Sed break; 1047193323Sed } 1048193323Sed } 1049193323Sed 1050193323Sed return status; 1051193323Sed} 1052193323Sed 1053210299Sedstatic int 1054193323Sedgrepdir (char const *dir, struct stats const *stats) 1055193323Sed{ 1056193323Sed int status = 1; 1057193323Sed struct stats const *ancestor; 1058193323Sed char *name_space; 1059193323Sed 1060193323Sed /* Mingw32 does not support st_ino. No known working hosts use zero 1061193323Sed for st_ino, so assume that the Mingw32 bug applies if it's zero. */ 1062193323Sed if (stats->stat.st_ino) 1063193323Sed for (ancestor = stats; (ancestor = ancestor->parent) != 0; ) 1064193323Sed if (ancestor->stat.st_ino == stats->stat.st_ino 1065193323Sed && ancestor->stat.st_dev == stats->stat.st_dev) 1066193323Sed { 1067193323Sed if (!suppress_errors) 1068193323Sed error (0, 0, _("warning: %s: %s"), dir, 1069193323Sed _("recursive directory loop")); 1070193323Sed return 1; 1071193323Sed } 1072193323Sed 1073193323Sed name_space = savedir (dir, stats->stat.st_size, included_patterns, 1074193323Sed excluded_patterns); 1075193323Sed 1076193323Sed if (! name_space) 1077193323Sed { 1078193323Sed if (errno) 1079193323Sed suppressible_error (dir, errno); 1080193323Sed else 1081193323Sed xalloc_die (); 1082193323Sed } 1083193323Sed else 1084193323Sed { 1085193323Sed size_t dirlen = strlen (dir); 1086193323Sed int needs_slash = ! (dirlen == FILESYSTEM_PREFIX_LEN (dir) 1087193323Sed || IS_SLASH (dir[dirlen - 1])); 1088193323Sed char *file = NULL; 1089193323Sed char const *namep = name_space; 1090193323Sed struct stats child; 1091193323Sed child.parent = stats; 1092193323Sed out_file += !no_filenames; 1093193323Sed while (*namep) 1094193323Sed { 1095193323Sed size_t namelen = strlen (namep); 1096193323Sed file = xrealloc (file, dirlen + 1 + namelen + 1); 1097193323Sed strcpy (file, dir); 1098193323Sed file[dirlen] = '/'; 1099193323Sed strcpy (file + dirlen + needs_slash, namep); 1100193323Sed namep += namelen + 1; 1101193323Sed status &= grepfile (file, &child); 1102193323Sed } 1103193323Sed out_file -= !no_filenames; 1104210299Sed if (file) 1105193323Sed free (file); 1106193323Sed free (name_space); 1107193323Sed } 1108193323Sed 1109193323Sed return status; 1110193323Sed} 1111193323Sed 1112193323Sedstatic void 1113193323Sedusage (int status) 1114193323Sed{ 1115193323Sed if (status != 0) 1116193323Sed { 1117193323Sed fprintf (stderr, _("Usage: %s [OPTION]... PATTERN [FILE]...\n"), 1118193323Sed program_name); 1119207618Srdivacky fprintf (stderr, _("Try `%s --help' for more information.\n"), 1120193323Sed program_name); 1121195098Sed } 1122193323Sed else 1123193323Sed { 1124193323Sed printf (_("Usage: %s [OPTION]... PATTERN [FILE] ...\n"), program_name); 1125193323Sed printf (_("\ 1126193323SedSearch for PATTERN in each FILE or standard input.\n\ 1127193323SedExample: %s -i 'hello world' menu.h main.c\n\ 1128193323Sed\n\ 1129193323SedRegexp selection and interpretation:\n"), program_name); 1130193323Sed printf (_("\ 1131193323Sed -E, --extended-regexp PATTERN is an extended regular expression\n\ 1132193323Sed -F, --fixed-strings PATTERN is a set of newline-separated strings\n\ 1133207618Srdivacky -G, --basic-regexp PATTERN is a basic regular expression\n\ 1134193323Sed -P, --perl-regexp PATTERN is a Perl regular expression\n")); 1135193323Sed printf (_("\ 1136193323Sed -e, --regexp=PATTERN use PATTERN as a regular expression\n\ 1137193323Sed -f, --file=FILE obtain PATTERN from FILE\n\ 1138193323Sed -i, --ignore-case ignore case distinctions\n\ 1139193323Sed -w, --word-regexp force PATTERN to match only whole words\n\ 1140202375Srdivacky -x, --line-regexp force PATTERN to match only whole lines\n\ 1141193323Sed -z, --null-data a data line ends in 0 byte, not newline\n")); 1142193323Sed printf (_("\ 1143193323Sed\n\ 1144201360SrdivackyMiscellaneous:\n\ 1145193323Sed -s, --no-messages suppress error messages\n\ 1146193323Sed -v, --invert-match select non-matching lines\n\ 1147198090Srdivacky -V, --version print version information and exit\n\ 1148193323Sed --help display this help and exit\n\ 1149207618Srdivacky -J, --bz2decompress decompress bzip2'ed input before searching\n\ 1150207618Srdivacky -Z, --decompress decompress input before searching (HAVE_LIBZ=1)\n\ 1151193323Sed --mmap use memory-mapped input if possible\n")); 1152193323Sed printf (_("\ 1153193323Sed\n\ 1154193323SedOutput control:\n\ 1155193323Sed -m, --max-count=NUM stop after NUM matches\n\ 1156193323Sed -b, --byte-offset print the byte offset with output lines\n\ 1157193323Sed -n, --line-number print line number with output lines\n\ 1158193323Sed --line-buffered flush output on every line\n\ 1159193323Sed -H, --with-filename print the filename for each match\n\ 1160193323Sed -h, --no-filename suppress the prefixing filename on output\n\ 1161193323Sed --label=LABEL print LABEL as filename for standard input\n\ 1162193323Sed -o, --only-matching show only the part of a line matching PATTERN\n\ 1163204642Srdivacky -q, --quiet, --silent suppress all normal output\n\ 1164204642Srdivacky --binary-files=TYPE assume that binary files are TYPE\n\ 1165204642Srdivacky TYPE is 'binary', 'text', or 'without-match'\n\ 1166204642Srdivacky -a, --text equivalent to --binary-files=text\n\ 1167204642Srdivacky -I equivalent to --binary-files=without-match\n\ 1168193323Sed -d, --directories=ACTION how to handle directories\n\ 1169193323Sed ACTION is 'read', 'recurse', or 'skip'\n\ 1170193323Sed -D, --devices=ACTION how to handle devices, FIFOs and sockets\n\ 1171204642Srdivacky ACTION is 'read' or 'skip'\n\ 1172193323Sed -R, -r, --recursive equivalent to --directories=recurse\n\ 1173204642Srdivacky --include=PATTERN files that match PATTERN will be examined\n\ 1174204642Srdivacky --exclude=PATTERN files that match PATTERN will be skipped.\n\ 1175204642Srdivacky --exclude-from=FILE files that match PATTERN in FILE will be skipped.\n\ 1176204642Srdivacky -L, --files-without-match only print FILE names containing no match\n\ 1177207618Srdivacky -l, --files-with-matches only print FILE names containing matches\n\ 1178204642Srdivacky -c, --count only print a count of matching lines per FILE\n\ 1179204642Srdivacky --null print 0 byte after FILE name\n")); 1180193323Sed printf (_("\ 1181193323Sed\n\ 1182193323SedContext control:\n\ 1183193323Sed -B, --before-context=NUM print NUM lines of leading context\n\ 1184193323Sed -A, --after-context=NUM print NUM lines of trailing context\n\ 1185193323Sed -C, --context=NUM print NUM lines of output context\n\ 1186193323Sed -NUM same as --context=NUM\n\ 1187193323Sed --color[=WHEN],\n\ 1188193323Sed --colour[=WHEN] use markers to distinguish the matching string\n\ 1189193323Sed WHEN may be `always', `never' or `auto'.\n\ 1190193323Sed -U, --binary do not strip CR characters at EOL (MSDOS)\n\ 1191193323Sed -u, --unix-byte-offsets report offsets as if CRs were not there (MSDOS)\n\ 1192204642Srdivacky\n\ 1193204642Srdivacky`egrep' means `grep -E'. `fgrep' means `grep -F'.\n\ 1194207618SrdivackyWith no FILE, or when FILE is -, read standard input. If less than\n\ 1195193323Sedtwo FILEs given, assume -h. Exit status is 0 if match, 1 if no match,\n\ 1196193323Sedand 2 if trouble.\n")); 1197204642Srdivacky printf (_("\nReport bugs to <bug-gnu-utils@gnu.org>.\n")); 1198193323Sed } 1199204642Srdivacky exit (status); 1200193323Sed} 1201193323Sed 1202193323Sed/* Set the matcher to M, reporting any conflicts. */ 1203193323Sedstatic void 1204193323Sedsetmatcher (char const *m) 1205193323Sed{ 1206193323Sed if (matcher && strcmp (matcher, m) != 0) 1207193323Sed error (2, 0, _("conflicting matchers specified")); 1208202375Srdivacky matcher = m; 1209193323Sed} 1210210299Sed 1211210299Sed/* Go through the matchers vector and look for the specified matcher. 1212193323Sed If we find it, install it in compile and execute, and return 1. */ 1213193323Sedstatic int 1214193323Sedinstall_matcher (char const *name) 1215193323Sed{ 1216193323Sed int i; 1217193323Sed#if defined(HAVE_SETRLIMIT) 1218193323Sed struct rlimit rlim; 1219193323Sed#endif 1220193323Sed 1221193323Sed for (i = 0; matchers[i].compile; i++) 1222193323Sed if (strcmp (name, matchers[i].name) == 0) 1223193323Sed { 1224198090Srdivacky compile = matchers[i].compile; 1225193323Sed execute = matchers[i].execute; 1226193323Sed#if defined(HAVE_SETRLIMIT) && defined(RLIMIT_STACK) 1227207618Srdivacky /* I think every platform needs to do this, so that regex.c 1228193323Sed doesn't oveflow the stack. The default value of 1229193323Sed `re_max_failures' is too large for some platforms: it needs 1230207618Srdivacky more than 3MB-large stack. 1231193323Sed 1232193323Sed The test for HAVE_SETRLIMIT should go into `configure'. */ 1233193323Sed if (!getrlimit (RLIMIT_STACK, &rlim)) 1234193323Sed { 1235193323Sed long newlim; 1236193323Sed extern long int re_max_failures; /* from regex.c */ 1237193323Sed 1238193323Sed /* Approximate the amount regex.c needs, plus some more. */ 1239193323Sed newlim = re_max_failures * 2 * 20 * sizeof (char *); 1240193323Sed if (newlim > rlim.rlim_max) 1241193323Sed { 1242193323Sed newlim = rlim.rlim_max; 1243193323Sed re_max_failures = newlim / (2 * 20 * sizeof (char *)); 1244193323Sed } 1245193323Sed if (rlim.rlim_cur < newlim) 1246193323Sed { 1247193323Sed rlim.rlim_cur = newlim; 1248193323Sed setrlimit (RLIMIT_STACK, &rlim); 1249193323Sed } 1250193323Sed } 1251193323Sed#endif 1252193323Sed return 1; 1253193323Sed } 1254193323Sed return 0; 1255193323Sed} 1256193323Sed 1257193323Sed/* Find the white-space-separated options specified by OPTIONS, and 1258207618Srdivacky using BUF to store copies of these options, set ARGV[0], ARGV[1], 1259193323Sed etc. to the option copies. Return the number N of options found. 1260193323Sed Do not set ARGV[N] to NULL. If ARGV is NULL, do not store ARGV[0] 1261198090Srdivacky etc. Backslash can be used to escape whitespace (and backslashes). */ 1262198090Srdivackystatic int 1263198090Srdivackyprepend_args (char const *options, char *buf, char **argv) 1264198090Srdivacky{ 1265198090Srdivacky char const *o = options; 1266198090Srdivacky char *b = buf; 1267193323Sed int n = 0; 1268193323Sed 1269194612Sed for (;;) 1270202375Srdivacky { 1271194612Sed while (ISSPACE ((unsigned char) *o)) 1272210299Sed o++; 1273194612Sed if (!*o) 1274194612Sed return n; 1275210299Sed if (argv) 1276194612Sed argv[n] = b; 1277194612Sed n++; 1278194612Sed 1279207618Srdivacky do 1280195098Sed if ((*b++ = *o++) == '\\' && *o) 1281195098Sed b[-1] = *o++; 1282194612Sed while (*o && ! ISSPACE ((unsigned char) *o)); 1283194612Sed 1284194612Sed *b++ = '\0'; 1285194612Sed } 1286194612Sed} 1287194612Sed 1288194612Sed/* Prepend the whitespace-separated options in OPTIONS to the argument 1289194612Sed vector of a main program with argument count *PARGC and argument 1290194612Sed vector *PARGV. */ 1291194612Sedstatic void 1292194612Sedprepend_default_options (char const *options, int *pargc, char ***pargv) 1293194612Sed{ 1294202375Srdivacky if (options) 1295193323Sed { 1296193323Sed char *buf = xmalloc (strlen (options) + 1); 1297193323Sed int prepended = prepend_args (options, buf, (char **) NULL); 1298204642Srdivacky int argc = *pargc; 1299204642Srdivacky char * const *argv = *pargv; 1300207618Srdivacky char **pp = (char **) xmalloc ((prepended + argc + 1) * sizeof *pp); 1301204642Srdivacky *pargc = prepended + argc; 1302204642Srdivacky *pargv = pp; 1303204642Srdivacky *pp++ = *argv++; 1304193323Sed pp += prepend_args (options, buf, pp); 1305193323Sed while ((*pp++ = *argv++)) 1306193323Sed continue; 1307193323Sed } 1308193323Sed} 1309193323Sed 1310193323Sed/* Get the next non-digit option from ARGC and ARGV. 1311193399Sed Return -1 if there are no more options. 1312193323Sed Process any digit options that were encountered on the way, 1313193323Sed and store the resulting integer into *DEFAULT_CONTEXT. */ 1314193323Sedstatic int 1315193323Sedget_nondigit_option (int argc, char *const *argv, int *default_context) 1316193323Sed{ 1317193323Sed int opt; 1318193323Sed char buf[sizeof (uintmax_t) * CHAR_BIT + 4]; 1319193323Sed char *p = buf; 1320193323Sed 1321193323Sed /* Set buf[0] to anything but '0', for the leading-zero test below. */ 1322193323Sed buf[0] = '\0'; 1323193323Sed 1324193323Sed while (opt = getopt_long (argc, argv, short_options, long_options, NULL), 1325193323Sed '0' <= opt && opt <= '9') 1326193323Sed { 1327193323Sed /* Suppress trivial leading zeros, to avoid incorrect 1328202375Srdivacky diagnostic on strings like 00000000000. */ 1329193323Sed p -= buf[0] == '0'; 1330198090Srdivacky 1331198090Srdivacky *p++ = opt; 1332198090Srdivacky if (p == buf + sizeof buf - 4) 1333198090Srdivacky { 1334198090Srdivacky /* Too many digits. Append "..." to make context_length_arg 1335198090Srdivacky complain about "X...", where X contains the digits seen 1336198090Srdivacky so far. */ 1337198090Srdivacky strcpy (p, "..."); 1338193323Sed p += 3; 1339193323Sed break; 1340198090Srdivacky } 1341198090Srdivacky } 1342198090Srdivacky if (p != buf) 1343198090Srdivacky { 1344198090Srdivacky *p = '\0'; 1345198090Srdivacky context_length_arg (buf, default_context); 1346198090Srdivacky } 1347198090Srdivacky 1348198090Srdivacky return opt; 1349198090Srdivacky} 1350198090Srdivacky 1351198090Srdivackyint 1352198090Srdivackymain (int argc, char **argv) 1353198090Srdivacky{ 1354202375Srdivacky char *keys; 1355198090Srdivacky size_t cc, keycc, oldcc, keyalloc; 1356198090Srdivacky int with_filenames; 1357198090Srdivacky int opt, status; 1358198090Srdivacky int default_context; 1359198090Srdivacky FILE *fp; 1360198090Srdivacky extern char *optarg; 1361198090Srdivacky extern int optind; 1362198090Srdivacky 1363198090Srdivacky initialize_main (&argc, &argv); 1364198090Srdivacky program_name = argv[0]; 1365198090Srdivacky if (program_name && strrchr (program_name, '/')) 1366198090Srdivacky program_name = strrchr (program_name, '/') + 1; 1367198090Srdivacky 1368198090Srdivacky if (program_name[0] == 'b' && program_name[1] == 'z') { 1369198090Srdivacky BZflag = 1; 1370198090Srdivacky program_name += 2; 1371198090Srdivacky } 1372198090Srdivacky#if HAVE_LIBZ > 0 1373198090Srdivacky else if (program_name[0] == 'z') { 1374198090Srdivacky Zflag = 1; 1375198090Srdivacky ++program_name; 1376198090Srdivacky } 1377198090Srdivacky#endif 1378198090Srdivacky 1379198090Srdivacky#if defined(__MSDOS__) || defined(_WIN32) 1380198090Srdivacky /* DOS and MS-Windows use backslashes as directory separators, and usually 1381198090Srdivacky have an .exe suffix. They also have case-insensitive filesystems. */ 1382198090Srdivacky if (program_name) 1383198090Srdivacky { 1384198090Srdivacky char *p = program_name; 1385198090Srdivacky char *bslash = strrchr (argv[0], '\\'); 1386198090Srdivacky 1387198090Srdivacky if (bslash && bslash >= program_name) /* for mixed forward/backslash case */ 1388198090Srdivacky program_name = bslash + 1; 1389198090Srdivacky else if (program_name == argv[0] 1390198090Srdivacky && argv[0][0] && argv[0][1] == ':') /* "c:progname" */ 1391198090Srdivacky program_name = argv[0] + 2; 1392198090Srdivacky 1393198090Srdivacky /* Collapse the letter-case, so `strcmp' could be used hence. */ 1394198090Srdivacky for ( ; *p; p++) 1395198090Srdivacky if (*p >= 'A' && *p <= 'Z') 1396198090Srdivacky *p += 'a' - 'A'; 1397198090Srdivacky 1398198090Srdivacky /* Remove the .exe extension, if any. */ 1399198090Srdivacky if ((p = strrchr (program_name, '.')) && strcmp (p, ".exe") == 0) 1400198090Srdivacky *p = '\0'; 1401198090Srdivacky } 1402198090Srdivacky#endif 1403198090Srdivacky 1404198090Srdivacky keys = NULL; 1405198090Srdivacky keycc = 0; 1406204642Srdivacky with_filenames = 0; 1407198090Srdivacky eolbyte = '\n'; 1408198090Srdivacky filename_mask = ~0; 1409198090Srdivacky 1410198090Srdivacky max_count = TYPE_MAXIMUM (off_t); 1411198090Srdivacky 1412198090Srdivacky /* The value -1 means to use DEFAULT_CONTEXT. */ 1413198090Srdivacky out_after = out_before = -1; 1414204642Srdivacky /* Default before/after context: chaged by -C/-NUM options */ 1415198090Srdivacky default_context = 0; 1416198090Srdivacky /* Changed by -o option */ 1417198090Srdivacky only_matching = 0; 1418198090Srdivacky 1419198090Srdivacky /* Internationalization. */ 1420198090Srdivacky#if defined(HAVE_SETLOCALE) 1421198090Srdivacky setlocale (LC_ALL, ""); 1422198090Srdivacky#endif 1423198090Srdivacky#if defined(ENABLE_NLS) 1424198090Srdivacky bindtextdomain (PACKAGE, LOCALEDIR); 1425198090Srdivacky textdomain (PACKAGE); 1426198090Srdivacky#endif 1427198090Srdivacky 1428198090Srdivacky atexit (close_stdout); 1429204642Srdivacky 1430198090Srdivacky prepend_default_options (getenv ("GREP_OPTIONS"), &argc, &argv); 1431198090Srdivacky 1432198090Srdivacky while ((opt = get_nondigit_option (argc, argv, &default_context)) != -1) 1433198090Srdivacky switch (opt) 1434198090Srdivacky { 1435198090Srdivacky case 'A': 1436198090Srdivacky context_length_arg (optarg, &out_after); 1437204642Srdivacky break; 1438198090Srdivacky 1439198090Srdivacky case 'B': 1440198090Srdivacky context_length_arg (optarg, &out_before); 1441198090Srdivacky break; 1442198090Srdivacky 1443198090Srdivacky case 'C': 1444198090Srdivacky /* Set output match context, but let any explicit leading or 1445198090Srdivacky trailing amount specified with -A or -B stand. */ 1446198090Srdivacky context_length_arg (optarg, &default_context); 1447198090Srdivacky break; 1448198090Srdivacky 1449198090Srdivacky case 'D': 1450198090Srdivacky if (strcmp (optarg, "read") == 0) 1451198090Srdivacky devices = READ_DEVICES; 1452198090Srdivacky else if (strcmp (optarg, "skip") == 0) 1453204642Srdivacky devices = SKIP_DEVICES; 1454198090Srdivacky else 1455198090Srdivacky error (2, 0, _("unknown devices method")); 1456198090Srdivacky break; 1457198090Srdivacky 1458198090Srdivacky case 'E': 1459198090Srdivacky setmatcher ("egrep"); 1460198090Srdivacky break; 1461204642Srdivacky 1462198090Srdivacky case 'F': 1463198090Srdivacky setmatcher ("fgrep"); 1464198090Srdivacky break; 1465198090Srdivacky 1466198090Srdivacky case 'P': 1467198090Srdivacky setmatcher ("perl"); 1468198090Srdivacky break; 1469198090Srdivacky 1470198090Srdivacky case 'G': 1471203954Srdivacky setmatcher ("grep"); 1472198090Srdivacky break; 1473198090Srdivacky 1474198090Srdivacky case 'H': 1475198090Srdivacky with_filenames = 1; 1476198090Srdivacky break; 1477198090Srdivacky 1478198090Srdivacky case 'I': 1479198090Srdivacky binary_files = WITHOUT_MATCH_BINARY_FILES; 1480198090Srdivacky break; 1481198090Srdivacky case 'J': 1482198090Srdivacky if (Zflag) 1483198090Srdivacky { 1484198090Srdivacky printf (_("Cannot mix -Z and -J.\n")); 1485198090Srdivacky usage (2); 1486198090Srdivacky } 1487198090Srdivacky BZflag = 1; 1488198090Srdivacky break; 1489198090Srdivacky 1490198090Srdivacky case 'U': 1491198090Srdivacky#if defined(HAVE_DOS_FILE_CONTENTS) 1492198090Srdivacky dos_use_file_type = DOS_BINARY; 1493198090Srdivacky#endif 1494198090Srdivacky break; 1495198090Srdivacky 1496198090Srdivacky case 'u': 1497198090Srdivacky#if defined(HAVE_DOS_FILE_CONTENTS) 1498198090Srdivacky dos_report_unix_offset = 1; 1499198090Srdivacky#endif 1500198090Srdivacky break; 1501198090Srdivacky 1502198090Srdivacky case 'V': 1503198090Srdivacky show_version = 1; 1504198090Srdivacky break; 1505198090Srdivacky 1506198090Srdivacky case 'X': 1507198090Srdivacky setmatcher (optarg); 1508198090Srdivacky break; 1509198090Srdivacky 1510198090Srdivacky case 'a': 1511198090Srdivacky binary_files = TEXT_BINARY_FILES; 1512198090Srdivacky break; 1513198090Srdivacky 1514198090Srdivacky case 'b': 1515198090Srdivacky out_byte = 1; 1516198090Srdivacky break; 1517203954Srdivacky 1518203954Srdivacky case 'c': 1519198090Srdivacky count_matches = 1; 1520198090Srdivacky break; 1521198090Srdivacky 1522198090Srdivacky case 'd': 1523198090Srdivacky if (strcmp (optarg, "read") == 0) 1524198090Srdivacky directories = READ_DIRECTORIES; 1525198090Srdivacky else if (strcmp (optarg, "skip") == 0) 1526198090Srdivacky directories = SKIP_DIRECTORIES; 1527198090Srdivacky else if (strcmp (optarg, "recurse") == 0) 1528198090Srdivacky directories = RECURSE_DIRECTORIES; 1529198090Srdivacky else 1530198090Srdivacky error (2, 0, _("unknown directories method")); 1531198090Srdivacky break; 1532198090Srdivacky 1533198090Srdivacky case 'e': 1534198090Srdivacky cc = strlen (optarg); 1535198090Srdivacky keys = xrealloc (keys, keycc + cc + 1); 1536198090Srdivacky strcpy (&keys[keycc], optarg); 1537198090Srdivacky keycc += cc; 1538198090Srdivacky keys[keycc++] = '\n'; 1539198090Srdivacky break; 1540198090Srdivacky 1541198090Srdivacky case 'f': 1542198090Srdivacky fp = strcmp (optarg, "-") != 0 ? fopen (optarg, "r") : stdin; 1543198090Srdivacky if (!fp) 1544198090Srdivacky error (2, errno, "%s", optarg); 1545198090Srdivacky for (keyalloc = 1; keyalloc <= keycc + 1; keyalloc *= 2) 1546198090Srdivacky ; 1547198090Srdivacky keys = xrealloc (keys, keyalloc); 1548198090Srdivacky oldcc = keycc; 1549198090Srdivacky while (!feof (fp) 1550198090Srdivacky && (cc = fread (keys + keycc, 1, keyalloc - 1 - keycc, fp)) > 0) 1551198090Srdivacky { 1552202375Srdivacky keycc += cc; 1553198090Srdivacky if (keycc == keyalloc - 1) 1554193323Sed keys = xrealloc (keys, keyalloc *= 2); 1555193323Sed } 1556193323Sed if (fp != stdin) 1557193323Sed fclose(fp); 1558204642Srdivacky /* Append final newline if file ended in non-newline. */ 1559193323Sed if (oldcc != keycc && keys[keycc - 1] != '\n') 1560193323Sed keys[keycc++] = '\n'; 1561204642Srdivacky break; 1562193323Sed 1563193323Sed case 'h': 1564193323Sed no_filenames = 1; 1565193323Sed break; 1566198090Srdivacky 1567198090Srdivacky case 'i': 1568198090Srdivacky case 'y': /* For old-timers . . . */ 1569193323Sed match_icase = 1; 1570198090Srdivacky break; 1571198090Srdivacky 1572198090Srdivacky case 'L': 1573198090Srdivacky /* Like -l, except list files that don't contain matches. 1574198090Srdivacky Inspired by the same option in Hume's gre. */ 1575198090Srdivacky list_files = -1; 1576198090Srdivacky break; 1577198090Srdivacky 1578198090Srdivacky case 'l': 1579198090Srdivacky list_files = 1; 1580198090Srdivacky break; 1581198090Srdivacky 1582198090Srdivacky case 'm': 1583198090Srdivacky { 1584193323Sed uintmax_t value; 1585198090Srdivacky switch (xstrtoumax (optarg, 0, 10, &value, "")) 1586198090Srdivacky { 1587198090Srdivacky case LONGINT_OK: 1588198090Srdivacky max_count = value; 1589198090Srdivacky if (0 <= max_count && max_count == value) 1590198090Srdivacky break; 1591193323Sed /* Fall through. */ 1592198090Srdivacky case LONGINT_OVERFLOW: 1593198090Srdivacky max_count = TYPE_MAXIMUM (off_t); 1594198090Srdivacky break; 1595198090Srdivacky 1596193323Sed default: 1597198090Srdivacky error (2, 0, _("invalid max count")); 1598198090Srdivacky } 1599198090Srdivacky } 1600198090Srdivacky break; 1601198090Srdivacky 1602198090Srdivacky case 'n': 1603198090Srdivacky out_line = 1; 1604198090Srdivacky break; 1605193323Sed 1606198090Srdivacky case 'o': 1607198090Srdivacky only_matching = 1; 1608198090Srdivacky break; 1609198090Srdivacky 1610198090Srdivacky case 'q': 1611198090Srdivacky exit_on_match = 1; 1612198090Srdivacky close_stdout_set_status(0); 1613193323Sed break; 1614198090Srdivacky 1615193323Sed case 'R': 1616198090Srdivacky case 'r': 1617198090Srdivacky directories = RECURSE_DIRECTORIES; 1618198090Srdivacky break; 1619198090Srdivacky 1620198090Srdivacky case 's': 1621198090Srdivacky suppress_errors = 1; 1622198090Srdivacky break; 1623198090Srdivacky 1624193323Sed case 'v': 1625198090Srdivacky out_invert = 1; 1626202375Srdivacky break; 1627198090Srdivacky 1628198090Srdivacky case 'w': 1629202375Srdivacky match_words = 1; 1630198090Srdivacky break; 1631198090Srdivacky 1632198090Srdivacky case 'x': 1633193323Sed match_lines = 1; 1634198090Srdivacky break; 1635198090Srdivacky 1636198090Srdivacky case 'Z': 1637198090Srdivacky#if HAVE_LIBZ > 0 1638198090Srdivacky if (BZflag) 1639198090Srdivacky { 1640198090Srdivacky printf (_("Cannot mix -J and -Z.\n")); 1641198090Srdivacky usage (2); 1642198090Srdivacky } 1643198090Srdivacky Zflag = 1; 1644198090Srdivacky#else 1645198090Srdivacky filename_mask = 0; 1646198090Srdivacky#endif 1647198090Srdivacky break; 1648198090Srdivacky 1649198090Srdivacky case 'z': 1650198090Srdivacky eolbyte = '\0'; 1651210299Sed break; 1652210299Sed 1653210299Sed case BINARY_FILES_OPTION: 1654210299Sed if (strcmp (optarg, "binary") == 0) 1655210299Sed binary_files = BINARY_BINARY_FILES; 1656210299Sed else if (strcmp (optarg, "text") == 0) 1657210299Sed binary_files = TEXT_BINARY_FILES; 1658210299Sed else if (strcmp (optarg, "without-match") == 0) 1659210299Sed binary_files = WITHOUT_MATCH_BINARY_FILES; 1660210299Sed else 1661210299Sed error (2, 0, _("unknown binary-files type")); 1662210299Sed break; 1663210299Sed 1664210299Sed case COLOR_OPTION: 1665210299Sed if(optarg) { 1666210299Sed if(!strcasecmp(optarg, "always") || !strcasecmp(optarg, "yes") || 1667210299Sed !strcasecmp(optarg, "force")) 1668210299Sed color_option = 1; 1669210299Sed else if(!strcasecmp(optarg, "never") || !strcasecmp(optarg, "no") || 1670210299Sed !strcasecmp(optarg, "none")) 1671198090Srdivacky color_option = 0; 1672202375Srdivacky else if(!strcasecmp(optarg, "auto") || !strcasecmp(optarg, "tty") || 1673198090Srdivacky !strcasecmp(optarg, "if-tty")) 1674198090Srdivacky color_option = 2; 1675198090Srdivacky else 1676202375Srdivacky show_help = 1; 1677204642Srdivacky } else 1678198090Srdivacky color_option = 2; 1679198090Srdivacky if(color_option == 2) { 1680202375Srdivacky if(isatty(STDOUT_FILENO) && getenv("TERM") && 1681210299Sed strcmp(getenv("TERM"), "dumb")) 1682210299Sed color_option = 1; 1683210299Sed else 1684202375Srdivacky color_option = 0; 1685204642Srdivacky } 1686198090Srdivacky break; 1687193323Sed 1688198090Srdivacky case EXCLUDE_OPTION: 1689198090Srdivacky if (!excluded_patterns) 1690193323Sed excluded_patterns = new_exclude (); 1691198090Srdivacky add_exclude (excluded_patterns, optarg); 1692198090Srdivacky break; 1693198090Srdivacky 1694198090Srdivacky case EXCLUDE_FROM_OPTION: 1695193323Sed if (!excluded_patterns) 1696198090Srdivacky excluded_patterns = new_exclude (); 1697198090Srdivacky if (add_exclude_file (add_exclude, excluded_patterns, optarg, '\n') 1698198090Srdivacky != 0) 1699198090Srdivacky { 1700198090Srdivacky error (2, errno, "%s", optarg); 1701198090Srdivacky } 1702198090Srdivacky break; 1703198090Srdivacky 1704193323Sed case INCLUDE_OPTION: 1705198090Srdivacky if (!included_patterns) 1706198090Srdivacky included_patterns = new_exclude (); 1707198090Srdivacky add_exclude (included_patterns, optarg); 1708198090Srdivacky break; 1709198090Srdivacky 1710198090Srdivacky case LINE_BUFFERED_OPTION: 1711198090Srdivacky line_buffered = 1; 1712198090Srdivacky break; 1713198090Srdivacky 1714193323Sed case LABEL_OPTION: 1715201360Srdivacky label = optarg; 1716198090Srdivacky break; 1717198090Srdivacky 1718198090Srdivacky case 0: 1719198090Srdivacky /* long options */ 1720201360Srdivacky break; 1721198090Srdivacky 1722198090Srdivacky default: 1723198090Srdivacky usage (2); 1724198090Srdivacky break; 1725198090Srdivacky 1726202375Srdivacky } 1727198090Srdivacky 1728198090Srdivacky /* POSIX.2 says that -q overrides -l, which in turn overrides the 1729198090Srdivacky other output options. */ 1730201360Srdivacky if (exit_on_match) 1731198090Srdivacky list_files = 0; 1732198090Srdivacky if (exit_on_match | list_files) 1733198090Srdivacky { 1734198090Srdivacky count_matches = 0; 1735201360Srdivacky done_on_match = 1; 1736202375Srdivacky } 1737198090Srdivacky out_quiet = count_matches | done_on_match; 1738198090Srdivacky 1739198090Srdivacky if (out_after < 0) 1740193323Sed out_after = default_context; 1741198090Srdivacky if (out_before < 0) 1742202375Srdivacky out_before = default_context; 1743198090Srdivacky 1744198090Srdivacky if (color_option) 1745198090Srdivacky { 1746198090Srdivacky char *userval = getenv ("GREP_COLOR"); 1747198090Srdivacky if (userval != NULL && *userval != '\0') 1748198090Srdivacky grep_color = userval; 1749198090Srdivacky } 1750202375Srdivacky 1751198090Srdivacky if (! matcher) 1752198090Srdivacky matcher = program_name; 1753198090Srdivacky 1754198090Srdivacky if (show_version) 1755198090Srdivacky { 1756198090Srdivacky printf (_("%s (GNU grep) %s\n"), matcher, VERSION); 1757198090Srdivacky printf ("\n"); 1758193323Sed printf (_("\ 1759198090SrdivackyCopyright 1988, 1992-1999, 2000, 2001 Free Software Foundation, Inc.\n")); 1760198090Srdivacky printf (_("\ 1761198090SrdivackyThis is free software; see the source for copying conditions. There is NO\n\ 1762198090Srdivackywarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n")); 1763198090Srdivacky printf ("\n"); 1764198090Srdivacky exit (0); 1765198090Srdivacky } 1766198090Srdivacky 1767198090Srdivacky if (show_help) 1768198090Srdivacky usage (0); 1769198090Srdivacky 1770198090Srdivacky if (keys) 1771193323Sed { 1772198090Srdivacky if (keycc == 0) 1773198090Srdivacky { 1774198090Srdivacky /* No keys were specified (e.g. -f /dev/null). Match nothing. */ 1775202375Srdivacky out_invert ^= 1; 1776202375Srdivacky match_lines = match_words = 0; 1777201360Srdivacky } 1778198090Srdivacky else 1779193323Sed /* Strip trailing newline. */ 1780198090Srdivacky --keycc; 1781193323Sed } 1782198090Srdivacky else 1783198090Srdivacky if (optind < argc) 1784198090Srdivacky { 1785198090Srdivacky keys = argv[optind++]; 1786198090Srdivacky keycc = strlen (keys); 1787198090Srdivacky } 1788198090Srdivacky else 1789198090Srdivacky usage (2); 1790198090Srdivacky 1791198090Srdivacky if (!install_matcher (matcher) && !install_matcher ("default")) 1792198090Srdivacky abort (); 1793198090Srdivacky 1794198090Srdivacky#ifdef MBS_SUPPORT 1795198090Srdivacky if (MB_CUR_MAX != 1 && match_icase) 1796210299Sed { 1797210299Sed wchar_t wc; 1798210299Sed mbstate_t cur_state, prev_state; 1799210299Sed int i, len = strlen(keys); 1800210299Sed 1801210299Sed memset(&cur_state, 0, sizeof(mbstate_t)); 1802210299Sed for (i = 0; i <= len ;) 1803210299Sed { 1804210299Sed size_t mbclen; 1805210299Sed mbclen = mbrtowc(&wc, keys + i, len - i, &cur_state); 1806210299Sed if (mbclen == (size_t) -1 || mbclen == (size_t) -2 || mbclen == 0) 1807210299Sed { 1808210299Sed /* An invalid sequence, or a truncated multibyte character. 1809210299Sed We treat it as a singlebyte character. */ 1810210299Sed mbclen = 1; 1811210299Sed } 1812210299Sed else 1813210299Sed { 1814210299Sed if (iswupper((wint_t)wc)) 1815210299Sed { 1816210299Sed wc = towlower((wint_t)wc); 1817210299Sed wcrtomb(keys + i, wc, &cur_state); 1818210299Sed } 1819198090Srdivacky } 1820202375Srdivacky i += mbclen; 1821198090Srdivacky } 1822198090Srdivacky } 1823198090Srdivacky#endif /* MBS_SUPPORT */ 1824202375Srdivacky 1825204642Srdivacky (*compile)(keys, keycc); 1826198090Srdivacky 1827198090Srdivacky if ((argc - optind > 1 && !no_filenames) || with_filenames) 1828202375Srdivacky out_file = 1; 1829210299Sed 1830210299Sed#ifdef SET_BINARY 1831210299Sed /* Output is set to binary mode because we shouldn't convert 1832202375Srdivacky NL to CR-LF pairs, especially when grepping binary files. */ 1833204642Srdivacky if (!isatty (1)) 1834198090Srdivacky SET_BINARY (1); 1835198090Srdivacky#endif 1836198090Srdivacky 1837193323Sed if (max_count == 0) 1838198090Srdivacky exit (1); 1839198090Srdivacky 1840198090Srdivacky if (optind < argc) 1841198090Srdivacky { 1842198090Srdivacky status = 1; 1843198090Srdivacky do 1844207618Srdivacky { 1845207618Srdivacky char *file = argv[optind]; 1846207618Srdivacky if ((included_patterns || excluded_patterns) 1847198090Srdivacky && !isdir (file)) 1848198090Srdivacky { 1849198090Srdivacky if (included_patterns && 1850198090Srdivacky ! excluded_filename (included_patterns, file, 0)) 1851198090Srdivacky continue; 1852198090Srdivacky if (excluded_patterns && 1853198090Srdivacky excluded_filename (excluded_patterns, file, 0)) 1854198090Srdivacky continue; 1855198090Srdivacky } 1856198090Srdivacky status &= grepfile (strcmp (file, "-") == 0 ? (char *) NULL : file, 1857198090Srdivacky &stats_base); 1858198090Srdivacky } 1859198090Srdivacky while ( ++optind < argc); 1860198090Srdivacky } 1861198090Srdivacky else 1862198090Srdivacky status = grepfile ((char *) NULL, &stats_base); 1863198090Srdivacky 1864198090Srdivacky /* We register via atexit() to test stdout. */ 1865198090Srdivacky exit (errseen ? 2 : status); 1866198090Srdivacky} 1867198090Srdivacky/* vim:set shiftwidth=2: */ 1868198090Srdivacky