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