17bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes/*	$NetBSD: grep.c,v 1.12 2014/07/11 16:30:45 christos Exp $	*/
23e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey/* 	$FreeBSD: head/usr.bin/grep/grep.c 211519 2010-08-19 22:55:17Z delphij $	*/
33e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey/*	$OpenBSD: grep.c,v 1.42 2010/07/02 22:18:03 tedu Exp $	*/
43e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
53e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey/*-
63e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey * Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav
73e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey * Copyright (C) 2008-2009 Gabor Kovesdan <gabor@FreeBSD.org>
83e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey * All rights reserved.
93e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey *
103e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey * Redistribution and use in source and binary forms, with or without
113e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey * modification, are permitted provided that the following conditions
123e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey * are met:
133e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey * 1. Redistributions of source code must retain the above copyright
143e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey *    notice, this list of conditions and the following disclaimer.
153e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey * 2. Redistributions in binary form must reproduce the above copyright
163e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey *    notice, this list of conditions and the following disclaimer in the
173e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey *    documentation and/or other materials provided with the distribution.
183e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey *
193e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
203e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
213e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
223e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
233e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
243e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
253e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
263e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
273e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
283e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
293e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey * SUCH DAMAGE.
303e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey */
313e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
323e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey#if HAVE_NBTOOL_CONFIG_H
333e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey#include "nbtool_config.h"
343e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey#endif
353e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
363e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey#include <sys/cdefs.h>
377bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes__RCSID("$NetBSD: grep.c,v 1.12 2014/07/11 16:30:45 christos Exp $");
383e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
393e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey#include <sys/stat.h>
403e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey#include <sys/types.h>
413e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
423e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey#include <ctype.h>
433e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey#include <err.h>
443e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey#include <errno.h>
453e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey#include <getopt.h>
463e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey#include <limits.h>
473e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey#include <libgen.h>
483e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey#include <locale.h>
493e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey#include <stdbool.h>
503e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey#include <stdio.h>
513e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey#include <stdlib.h>
523e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey#include <string.h>
533e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey#include <unistd.h>
543e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
553e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey#include "grep.h"
563e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
573e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey#ifndef WITHOUT_NLS
583e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey#include <nl_types.h>
593e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeynl_catd	 catalog;
603e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey#endif
613e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
623e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey/*
633e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey * Default messags to use when NLS is disabled or no catalogue
643e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey * is found.
653e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey */
663e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyconst char	*errstr[] = {
673e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	"",
683e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey/* 1*/	"(standard input)",
693e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey/* 2*/	"cannot read bzip2 compressed file",
703e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey/* 3*/	"unknown %s option",
713e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey/* 4*/	"usage: %s [-abcDEFGHhIiJLlmnOoPqRSsUVvwxZz] [-A num] [-B num] [-C[num]]\n",
723e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey/* 5*/	"\t[-e pattern] [-f file] [--binary-files=value] [--color=when]\n",
733e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey/* 6*/	"\t[--context[=num]] [--directories=action] [--label] [--line-buffered]\n",
743e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey/* 7*/	"\t[pattern] [file ...]\n",
753e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey/* 8*/	"Binary file %s matches\n",
763e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey/* 9*/	"%s (BSD grep) %s\n",
773e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey};
783e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
793e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey/* Flags passed to regcomp() and regexec() */
803e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyint		 cflags = 0;
813e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyint		 eflags = REG_STARTEND;
823e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
833e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey/* Searching patterns */
843e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyunsigned int	 patterns, pattern_sz;
853e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeychar		**pattern;
863e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyregex_t		*r_pattern;
873e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyfastgrep_t	*fg_pattern;
883e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
893e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey/* Filename exclusion/inclusion patterns */
903e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyunsigned int	 fpatterns, fpattern_sz;
913e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyunsigned int	 dpatterns, dpattern_sz;
923e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeystruct epat	*dpattern, *fpattern;
933e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
943e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey/* For regex errors  */
953e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeychar	 re_error[RE_ERROR_BUF + 1];
963e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
973e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey/* Command-line flags */
983e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyunsigned long long Aflag;	/* -A x: print x lines trailing each match */
993e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyunsigned long long Bflag;	/* -B x: print x lines leading each match */
1003e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeybool	 Hflag;		/* -H: always print file name */
1013e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeybool	 Lflag;		/* -L: only show names of files with no matches */
1023e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeybool	 bflag;		/* -b: show block numbers for each match */
1033e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeybool	 cflag;		/* -c: only show a count of matching lines */
1043e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeybool	 hflag;		/* -h: don't print filename headers */
1053e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeybool	 iflag;		/* -i: ignore case */
1063e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeybool	 lflag;		/* -l: only show names of files with matches */
1073e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeybool	 mflag;		/* -m x: stop reading the files after x matches */
1083e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyunsigned long long mcount;	/* count for -m */
1093e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeybool	 nflag;		/* -n: show line numbers in front of matching lines */
1103e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeybool	 oflag;		/* -o: print only matching part */
1113e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeybool	 qflag;		/* -q: quiet mode (don't output anything) */
1123e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeybool	 sflag;		/* -s: silent mode (ignore errors) */
1133e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeybool	 vflag;		/* -v: only show non-matching lines */
1143e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeybool	 wflag;		/* -w: pattern must start and end on word boundaries */
1153e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeybool	 xflag;		/* -x: pattern must match entire line */
1163e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeybool	 lbflag;	/* --line-buffered */
1173e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeybool	 nullflag;	/* --null */
1183e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeybool	 nulldataflag;	/* --null-data */
1193e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyunsigned char line_sep = '\n';	/* 0 for --null-data */
1203e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeychar	*label;		/* --label */
1213e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyconst char *color;	/* --color */
1223e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyint	 grepbehave = GREP_BASIC;	/* -EFGP: type of the regex */
1233e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyint	 binbehave = BINFILE_BIN;	/* -aIU: handling of binary files */
1243e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyint	 filebehave = FILE_STDIO;	/* -JZ: normal, gzip or bzip2 file */
1253e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyint	 devbehave = DEV_READ;		/* -D: handling of devices */
1263e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyint	 dirbehave = DIR_READ;		/* -dRr: handling of directories */
1273e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyint	 linkbehave = LINK_READ;	/* -OpS: handling of symlinks */
1283e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
1293e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeybool	 dexclude, dinclude;	/* --exclude-dir and --include-dir */
1303e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeybool	 fexclude, finclude;	/* --exclude and --include */
1313e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
1323e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyenum {
1333e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	BIN_OPT = CHAR_MAX + 1,
1343e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	COLOR_OPT,
1353e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	DECOMPRESS_OPT,
1363e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	HELP_OPT,
1373e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	MMAP_OPT,
1383e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	LINEBUF_OPT,
1393e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	LABEL_OPT,
1403e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	R_EXCLUDE_OPT,
1413e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	R_INCLUDE_OPT,
1423e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	R_DEXCLUDE_OPT,
1433e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	R_DINCLUDE_OPT
1443e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey};
1453e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
1463e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeystatic inline const char	*init_color(const char *);
1473e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
1483e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey/* Housekeeping */
1493e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyint	 tail;		/* lines left to print */
1503e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeybool	 notfound;	/* file not found */
1513e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
1523e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyextern char	*__progname;
1533e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
1543e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey/*
1553e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey * Prints usage information and returns 2.
1563e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey */
1573e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey__dead static void
1583e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyusage(void)
1593e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey{
1603e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	fprintf(stderr, getstr(4), __progname);
1613e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	fprintf(stderr, "%s", getstr(5));
1623e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	fprintf(stderr, "%s", getstr(6));
1633e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	fprintf(stderr, "%s", getstr(7));
1643e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	exit(2);
1653e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey}
1663e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
1673e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeystatic const char optstr[] =
1683e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey    "0123456789A:B:C:D:EFGHIJLOPSRUVZabcd:e:f:hilm:nopqrsuvwxyz";
1693e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
1703e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeystruct option long_options[] =
1713e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey{
1723e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"binary-files",	required_argument,	NULL, BIN_OPT},
1733e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"decompress",          no_argument,            NULL, DECOMPRESS_OPT},
1743e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"help",		no_argument,		NULL, HELP_OPT},
1753e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"mmap",		no_argument,		NULL, MMAP_OPT},
1763e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"line-buffered",	no_argument,		NULL, LINEBUF_OPT},
1773e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"label",		required_argument,	NULL, LABEL_OPT},
1783e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"color",		optional_argument,	NULL, COLOR_OPT},
1793e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"colour",		optional_argument,	NULL, COLOR_OPT},
1803e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"exclude",		required_argument,	NULL, R_EXCLUDE_OPT},
1813e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"include",		required_argument,	NULL, R_INCLUDE_OPT},
1823e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"exclude-dir",		required_argument,	NULL, R_DEXCLUDE_OPT},
1833e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"include-dir",		required_argument,	NULL, R_DINCLUDE_OPT},
1843e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"after-context",	required_argument,	NULL, 'A'},
1853e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"text",		no_argument,		NULL, 'a'},
1863e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"before-context",	required_argument,	NULL, 'B'},
1873e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"byte-offset",		no_argument,		NULL, 'b'},
1883e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"context",		optional_argument,	NULL, 'C'},
1893e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"count",		no_argument,		NULL, 'c'},
1903e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"devices",		required_argument,	NULL, 'D'},
1913e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey        {"directories",		required_argument,	NULL, 'd'},
1923e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"extended-regexp",	no_argument,		NULL, 'E'},
1933e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"regexp",		required_argument,	NULL, 'e'},
1943e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"fixed-strings",	no_argument,		NULL, 'F'},
1953e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"file",		required_argument,	NULL, 'f'},
1963e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"basic-regexp",	no_argument,		NULL, 'G'},
1973e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"no-filename",		no_argument,		NULL, 'h'},
1983e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"with-filename",	no_argument,		NULL, 'H'},
1993e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"ignore-case",		no_argument,		NULL, 'i'},
2003e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"bz2decompress",	no_argument,		NULL, 'J'},
2013e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"files-with-matches",	no_argument,		NULL, 'l'},
2023e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"files-without-match", no_argument,            NULL, 'L'},
2033e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"max-count",		required_argument,	NULL, 'm'},
2043e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"line-number",		no_argument,		NULL, 'n'},
2053e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"only-matching",	no_argument,		NULL, 'o'},
2063e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"quiet",		no_argument,		NULL, 'q'},
2073e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"silent",		no_argument,		NULL, 'q'},
2083e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"recursive",		no_argument,		NULL, 'r'},
2093e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"no-messages",		no_argument,		NULL, 's'},
2103e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"binary",		no_argument,		NULL, 'U'},
2113e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"unix-byte-offsets",	no_argument,		NULL, 'u'},
2123e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"invert-match",	no_argument,		NULL, 'v'},
2133e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"version",		no_argument,		NULL, 'V'},
2143e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"word-regexp",		no_argument,		NULL, 'w'},
2153e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"line-regexp",		no_argument,		NULL, 'x'},
2163e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"null",		no_argument,		NULL, 'Z'},
2173e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"null-data",		no_argument,		NULL, 'z'},
2183e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{NULL,			no_argument,		NULL, 0}
2193e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey};
2203e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
2213e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey/*
2223e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey * Adds a searching pattern to the internal array.
2233e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey */
2243e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeystatic void
2253e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyadd_pattern(char *pat, size_t len)
2263e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey{
2273e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
2283e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	/* TODO: Check for empty patterns and shortcut */
2293e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
2303e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	/* Increase size if necessary */
2313e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	if (patterns == pattern_sz) {
2323e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		pattern_sz *= 2;
2333e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		pattern = grep_realloc(pattern, ++pattern_sz *
2343e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		    sizeof(*pattern));
2353e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	}
2363e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	if (len > 0 && pat[len - 1] == '\n')
2373e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		--len;
2383e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	/* pat may not be NUL-terminated */
2393e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	pattern[patterns] = grep_malloc(len + 1);
2403e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	memcpy(pattern[patterns], pat, len);
2413e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	pattern[patterns][len] = '\0';
2423e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	++patterns;
2433e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey}
2443e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
2453e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey/*
2463e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey * Adds a file include/exclude pattern to the internal array.
2473e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey */
2483e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeystatic void
2493e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyadd_fpattern(const char *pat, int mode)
2503e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey{
2513e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
2523e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	/* Increase size if necessary */
2533e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	if (fpatterns == fpattern_sz) {
2543e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		fpattern_sz *= 2;
2553e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		fpattern = grep_realloc(fpattern, ++fpattern_sz *
2563e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		    sizeof(struct epat));
2573e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	}
2583e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	fpattern[fpatterns].pat = grep_strdup(pat);
2593e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	fpattern[fpatterns].mode = mode;
2603e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	++fpatterns;
2613e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey}
2623e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
2633e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey/*
2643e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey * Adds a directory include/exclude pattern to the internal array.
2653e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey */
2663e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeystatic void
2673e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyadd_dpattern(const char *pat, int mode)
2683e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey{
2693e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
2703e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	/* Increase size if necessary */
2713e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	if (dpatterns == dpattern_sz) {
2723e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		dpattern_sz *= 2;
2733e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		dpattern = grep_realloc(dpattern, ++dpattern_sz *
2743e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		    sizeof(struct epat));
2753e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	}
2763e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	dpattern[dpatterns].pat = grep_strdup(pat);
2773e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	dpattern[dpatterns].mode = mode;
2783e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	++dpatterns;
2793e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey}
2803e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
2813e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey/*
2823e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey * Reads searching patterns from a file and adds them with add_pattern().
2833e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey */
2843e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeystatic void
2853e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyread_patterns(const char *fn)
2863e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey{
2873e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	FILE *f;
2883e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	char *line;
2893e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	size_t len;
2903e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	ssize_t rlen;
2913e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
2923e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	if ((f = fopen(fn, "r")) == NULL)
2933e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		err(2, "%s", fn);
2943e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	line = NULL;
2953e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	len = 0;
2963e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	while ((rlen = getline(&line, &len, f)) != -1)
2973e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		add_pattern(line, *line == '\n' ? 0 : (size_t)rlen);
2983e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	free(line);
2993e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	if (ferror(f))
3003e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		err(2, "%s", fn);
3013e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	fclose(f);
3023e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey}
3033e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
3043e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeystatic inline const char *
3053e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyinit_color(const char *d)
3063e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey{
3073e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	char *c;
3083e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
3093e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	c = getenv("GREP_COLOR");
3103e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	return (c != NULL ? c : d);
3113e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey}
3123e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
3133e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyint
3147bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesmain(int argc, char *argv[])
3153e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey{
3163e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	char **aargv, **eargv, *eopts;
3173e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	char *ep;
3183e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	unsigned long long l;
3193e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	unsigned int aargc, eargc, i, j;
3203e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	int c, lastc, needpattern, newarg, prevoptind;
3213e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
3223e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	setlocale(LC_ALL, "");
3233e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
3243e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey#ifndef WITHOUT_NLS
3253e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	catalog = catopen("grep", NL_CAT_LOCALE);
3263e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey#endif
3273e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
3283e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	/* Check what is the program name of the binary.  In this
3293e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	   way we can have all the funcionalities in one binary
3303e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	   without the need of scripting and using ugly hacks. */
3313e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	switch (__progname[0]) {
3323e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	case 'e':
3333e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		grepbehave = GREP_EXTENDED;
3343e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		break;
3353e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	case 'f':
3363e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		grepbehave = GREP_FIXED;
3373e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		break;
3383e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	case 'g':
3393e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		grepbehave = GREP_BASIC;
3403e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		break;
3413e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	case 'z':
3423e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		filebehave = FILE_GZIP;
3433e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		switch(__progname[1]) {
3443e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'e':
3453e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			grepbehave = GREP_EXTENDED;
3463e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
3473e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'f':
3483e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			grepbehave = GREP_FIXED;
3493e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
3503e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'g':
3513e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			grepbehave = GREP_BASIC;
3523e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
3533e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		}
3543e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		break;
3553e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	}
3563e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
3573e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	lastc = '\0';
3583e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	newarg = 1;
3593e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	prevoptind = 1;
3603e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	needpattern = 1;
3613e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
3623e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	eopts = getenv("GREP_OPTIONS");
3633e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
3643e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	/* support for extra arguments in GREP_OPTIONS */
3653e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	eargc = 0;
3663e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	if (eopts != NULL) {
3673e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		char *str;
3683e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
3693e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		/* make an estimation of how many extra arguments we have */
3703e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		for (j = 0; j < strlen(eopts); j++)
3713e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			if (eopts[j] == ' ')
3723e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				eargc++;
3733e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
3743e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		eargv = (char **)grep_malloc(sizeof(char *) * (eargc + 1));
3753e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
3763e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		eargc = 0;
3773e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		/* parse extra arguments */
3783e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		while ((str = strsep(&eopts, " ")) != NULL)
3793e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			eargv[eargc++] = grep_strdup(str);
3803e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
3813e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		aargv = (char **)grep_calloc(eargc + argc + 1,
3823e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		    sizeof(char *));
3833e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
3843e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		aargv[0] = argv[0];
3853e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		for (i = 0; i < eargc; i++)
3863e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			aargv[i + 1] = eargv[i];
3873e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		for (j = 1; j < (unsigned int)argc; j++, i++)
3883e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			aargv[i + 1] = argv[j];
3893e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
3903e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		aargc = eargc + argc;
3913e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	} else {
3923e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		aargv = argv;
3933e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		aargc = argc;
3943e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	}
3953e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
3963e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	while (((c = getopt_long(aargc, aargv, optstr, long_options, NULL)) !=
3973e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	    -1)) {
3983e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		switch (c) {
3993e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case '0': case '1': case '2': case '3': case '4':
4003e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case '5': case '6': case '7': case '8': case '9':
4013e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			if (newarg || !isdigit(lastc))
4023e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				Aflag = 0;
4033e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			else if (Aflag > LLONG_MAX / 10) {
4043e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				errno = ERANGE;
40504650ef7f6167d59aad19d4cd6fc78b2d84c83e5Elliott Hughes				err(2, NULL);
4063e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			}
4073e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			Aflag = Bflag = (Aflag * 10) + (c - '0');
4083e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
4093e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'C':
4103e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			if (optarg == NULL) {
4113e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				Aflag = Bflag = 2;
4123e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				break;
4133e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			}
4143e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			/* FALLTHROUGH */
4153e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'A':
4163e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			/* FALLTHROUGH */
4173e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'B':
4183e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			errno = 0;
4193e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			l = strtoull(optarg, &ep, 10);
4203e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			if (((errno == ERANGE) && (l == ULLONG_MAX)) ||
4213e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			    ((errno == EINVAL) && (l == 0)))
42204650ef7f6167d59aad19d4cd6fc78b2d84c83e5Elliott Hughes				err(2, NULL);
4233e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			else if (ep[0] != '\0') {
4243e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				errno = EINVAL;
42504650ef7f6167d59aad19d4cd6fc78b2d84c83e5Elliott Hughes				err(2, NULL);
4263e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			}
4273e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			if (c == 'A')
4283e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				Aflag = l;
4293e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			else if (c == 'B')
4303e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				Bflag = l;
4313e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			else
4323e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				Aflag = Bflag = l;
4333e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
4343e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'a':
4353e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			binbehave = BINFILE_TEXT;
4363e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
4373e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'b':
4383e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			bflag = true;
4393e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
4403e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'c':
4413e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			cflag = true;
4423e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
4433e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'D':
4443e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			if (strcasecmp(optarg, "skip") == 0)
4453e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				devbehave = DEV_SKIP;
4463e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			else if (strcasecmp(optarg, "read") == 0)
4473e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				devbehave = DEV_READ;
4483e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			else
4493e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				errx(2, getstr(3), "--devices");
4503e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
4513e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'd':
4523e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			if (strcasecmp("recurse", optarg) == 0) {
4533e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				Hflag = true;
4543e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				dirbehave = DIR_RECURSE;
4553e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			} else if (strcasecmp("skip", optarg) == 0)
4563e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				dirbehave = DIR_SKIP;
4573e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			else if (strcasecmp("read", optarg) == 0)
4583e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				dirbehave = DIR_READ;
4593e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			else
4603e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				errx(2, getstr(3), "--directories");
4613e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
4623e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'E':
4633e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			grepbehave = GREP_EXTENDED;
4643e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
4653e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'e':
4663e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			add_pattern(optarg, strlen(optarg));
4673e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			needpattern = 0;
4683e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
4693e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'F':
4703e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			grepbehave = GREP_FIXED;
4713e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
4723e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'f':
4733e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			read_patterns(optarg);
4743e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			needpattern = 0;
4753e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
4763e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'G':
4773e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			grepbehave = GREP_BASIC;
4783e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
4793e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'H':
4803e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			Hflag = true;
4813e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
4823e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'h':
4833e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			Hflag = false;
4843e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			hflag = true;
4853e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
4863e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'I':
4873e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			binbehave = BINFILE_SKIP;
4883e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
4893e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'i':
4903e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'y':
4913e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			iflag =  true;
4923e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			cflags |= REG_ICASE;
4933e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
4943e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'J':
4953e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			filebehave = FILE_BZIP;
4963e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
4973e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'L':
4983e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			lflag = false;
4993e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			Lflag = true;
5003e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5013e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'l':
5023e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			Lflag = false;
5033e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			lflag = true;
5043e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5053e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'm':
5063e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			mflag = true;
5073e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			errno = 0;
5083e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			mcount = strtoull(optarg, &ep, 10);
5093e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			if (((errno == ERANGE) && (mcount == ULLONG_MAX)) ||
5103e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			    ((errno == EINVAL) && (mcount == 0)))
51104650ef7f6167d59aad19d4cd6fc78b2d84c83e5Elliott Hughes				err(2, NULL);
5123e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			else if (ep[0] != '\0') {
5133e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				errno = EINVAL;
51404650ef7f6167d59aad19d4cd6fc78b2d84c83e5Elliott Hughes				err(2, NULL);
5153e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			}
5163e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5173e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'n':
5183e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			nflag = true;
5193e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5203e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'O':
5213e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			linkbehave = LINK_EXPLICIT;
5223e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5233e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'o':
5243e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			oflag = true;
5253e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5263e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'p':
5273e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			linkbehave = LINK_SKIP;
5283e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5293e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'q':
5303e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			qflag = true;
5313e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5323e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'S':
5333e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			linkbehave = LINK_READ;
5343e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5353e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'R':
5363e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'r':
5373e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			dirbehave = DIR_RECURSE;
5383e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			Hflag = true;
5393e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5403e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 's':
5413e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			sflag = true;
5423e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5433e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'U':
5443e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			binbehave = BINFILE_BIN;
5453e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5463e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'u':
5473e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case MMAP_OPT:
5483e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			/* noop, compatibility */
5493e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5503e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'V':
5513e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			printf(getstr(9), __progname, VERSION);
5523e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			exit(0);
5533e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'v':
5543e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			vflag = true;
5553e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5563e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'w':
5573e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			wflag = true;
5583e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5593e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'x':
5603e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			xflag = true;
5613e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5623e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'Z':
5633e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			nullflag = true;
5643e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5653e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'z':
5663e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			nulldataflag = true;
5673e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			line_sep = '\0';
5683e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5693e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case BIN_OPT:
5703e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			if (strcasecmp("binary", optarg) == 0)
5713e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				binbehave = BINFILE_BIN;
5723e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			else if (strcasecmp("without-match", optarg) == 0)
5733e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				binbehave = BINFILE_SKIP;
5743e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			else if (strcasecmp("text", optarg) == 0)
5753e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				binbehave = BINFILE_TEXT;
5763e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			else
5773e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				errx(2, getstr(3), "--binary-files");
5783e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5793e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case COLOR_OPT:
5803e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			color = NULL;
5813e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			if (optarg == NULL || strcasecmp("auto", optarg) == 0 ||
5823e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			    strcasecmp("tty", optarg) == 0 ||
5833e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			    strcasecmp("if-tty", optarg) == 0) {
5843e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				char *term;
5853e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
5863e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				term = getenv("TERM");
5873e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				if (isatty(STDOUT_FILENO) && term != NULL &&
5883e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				    strcasecmp(term, "dumb") != 0)
5893e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey					color = init_color("01;31");
5903e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			} else if (strcasecmp("always", optarg) == 0 ||
5913e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			    strcasecmp("yes", optarg) == 0 ||
5923e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			    strcasecmp("force", optarg) == 0) {
5933e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				color = init_color("01;31");
5943e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			} else if (strcasecmp("never", optarg) != 0 &&
5953e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			    strcasecmp("none", optarg) != 0 &&
5963e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			    strcasecmp("no", optarg) != 0)
5973e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				errx(2, getstr(3), "--color");
5983e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5993e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case DECOMPRESS_OPT:
6003e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			filebehave = FILE_GZIP;
6013e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
6023e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case LABEL_OPT:
6033e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			label = optarg;
6043e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
6053e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case LINEBUF_OPT:
6063e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			lbflag = true;
6073e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
6083e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case R_INCLUDE_OPT:
6093e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			finclude = true;
6103e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			add_fpattern(optarg, INCL_PAT);
6113e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
6123e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case R_EXCLUDE_OPT:
6133e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			fexclude = true;
6143e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			add_fpattern(optarg, EXCL_PAT);
6153e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
6163e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case R_DINCLUDE_OPT:
6173e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			dinclude = true;
6183e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			add_dpattern(optarg, INCL_PAT);
6193e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
6203e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case R_DEXCLUDE_OPT:
6213e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			dexclude = true;
6223e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			add_dpattern(optarg, EXCL_PAT);
6233e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
6243e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case HELP_OPT:
6253e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		default:
6263e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			usage();
6273e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		}
6283e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		lastc = c;
6293e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		newarg = optind != prevoptind;
6303e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		prevoptind = optind;
6313e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	}
6323e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	aargc -= optind;
6333e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	aargv += optind;
6343e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
6353e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	/* Fail if we don't have any pattern */
6363e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	if (aargc == 0 && needpattern)
6373e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		usage();
6383e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
6393e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	/* Process patterns from command line */
6403e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	if (aargc != 0 && needpattern) {
6413e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		add_pattern(*aargv, strlen(*aargv));
6423e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		--aargc;
6433e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		++aargv;
6443e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	}
6453e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
6463e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	switch (grepbehave) {
6473e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	case GREP_FIXED:
6483e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	case GREP_BASIC:
6493e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		break;
6503e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	case GREP_EXTENDED:
6513e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		cflags |= REG_EXTENDED;
6523e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		break;
6533e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	default:
6543e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		/* NOTREACHED */
6553e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		usage();
6563e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	}
6573e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
6583e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	fg_pattern = grep_calloc(patterns, sizeof(*fg_pattern));
6593e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	r_pattern = grep_calloc(patterns, sizeof(*r_pattern));
6603e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey/*
6613e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey * XXX: fgrepcomp() and fastcomp() are workarounds for regexec() performance.
6623e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey * Optimizations should be done there.
6633e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey */
6643e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		/* Check if cheating is allowed (always is for fgrep). */
6653e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	if (grepbehave == GREP_FIXED) {
6663e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		for (i = 0; i < patterns; ++i)
6673e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			fgrepcomp(&fg_pattern[i], pattern[i]);
6683e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	} else {
6693e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		for (i = 0; i < patterns; ++i) {
6703e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			if (fastcomp(&fg_pattern[i], pattern[i])) {
6713e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				/* Fall back to full regex library */
6723e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				c = regcomp(&r_pattern[i], pattern[i], cflags);
6733e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				if (c != 0) {
6743e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey					regerror(c, &r_pattern[i], re_error,
6753e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey					    RE_ERROR_BUF);
6763e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey					errx(2, "%s", re_error);
6773e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				}
6783e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			}
6793e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		}
6803e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	}
6813e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
6823e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	if (lbflag)
6833e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		setlinebuf(stdout);
6843e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
6853e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	if ((aargc == 0 || aargc == 1) && !Hflag)
6863e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		hflag = true;
6873e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
6883e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	if (aargc == 0)
6893e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		exit(!procfile("-"));
6903e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
6913e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	if (dirbehave == DIR_RECURSE)
6923e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		c = grep_tree(aargv);
6933e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	else
6943e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		for (c = 0; aargc--; ++aargv) {
6953e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			if ((finclude || fexclude) && !file_matching(*aargv))
6963e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				continue;
6973e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			c+= procfile(*aargv);
6983e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		}
6993e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
7003e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey#ifndef WITHOUT_NLS
7013e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	catclose(catalog);
7023e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey#endif
7033e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
7043e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	/* Find out the correct return value according to the
7053e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	   results and the command line option. */
7063e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	exit(c ? (notfound ? (qflag ? 0 : 2) : 0) : (notfound ? 2 : 1));
7073e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey}
708