13e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey/*	$NetBSD: grep.c,v 1.11 2012/05/06 22:27:00 joerg 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>
373e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey__RCSID("$NetBSD: grep.c,v 1.11 2012/05/06 22:27:00 joerg 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(5));
1633e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	fprintf(stderr, "%s", getstr(6));
1643e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	fprintf(stderr, "%s", getstr(7));
1653e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	exit(2);
1663e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey}
1673e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
1683e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeystatic const char optstr[] =
1693e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey    "0123456789A:B:C:D:EFGHIJLOPSRUVZabcd:e:f:hilm:nopqrsuvwxyz";
1703e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
1713e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeystruct option long_options[] =
1723e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey{
1733e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"binary-files",	required_argument,	NULL, BIN_OPT},
1743e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"decompress",          no_argument,            NULL, DECOMPRESS_OPT},
1753e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"help",		no_argument,		NULL, HELP_OPT},
1763e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"mmap",		no_argument,		NULL, MMAP_OPT},
1773e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"line-buffered",	no_argument,		NULL, LINEBUF_OPT},
1783e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"label",		required_argument,	NULL, LABEL_OPT},
1793e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"color",		optional_argument,	NULL, COLOR_OPT},
1803e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"colour",		optional_argument,	NULL, COLOR_OPT},
1813e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"exclude",		required_argument,	NULL, R_EXCLUDE_OPT},
1823e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"include",		required_argument,	NULL, R_INCLUDE_OPT},
1833e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"exclude-dir",		required_argument,	NULL, R_DEXCLUDE_OPT},
1843e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"include-dir",		required_argument,	NULL, R_DINCLUDE_OPT},
1853e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"after-context",	required_argument,	NULL, 'A'},
1863e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"text",		no_argument,		NULL, 'a'},
1873e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"before-context",	required_argument,	NULL, 'B'},
1883e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"byte-offset",		no_argument,		NULL, 'b'},
1893e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"context",		optional_argument,	NULL, 'C'},
1903e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"count",		no_argument,		NULL, 'c'},
1913e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"devices",		required_argument,	NULL, 'D'},
1923e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey        {"directories",		required_argument,	NULL, 'd'},
1933e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"extended-regexp",	no_argument,		NULL, 'E'},
1943e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"regexp",		required_argument,	NULL, 'e'},
1953e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"fixed-strings",	no_argument,		NULL, 'F'},
1963e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"file",		required_argument,	NULL, 'f'},
1973e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"basic-regexp",	no_argument,		NULL, 'G'},
1983e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"no-filename",		no_argument,		NULL, 'h'},
1993e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"with-filename",	no_argument,		NULL, 'H'},
2003e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"ignore-case",		no_argument,		NULL, 'i'},
2013e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"bz2decompress",	no_argument,		NULL, 'J'},
2023e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"files-with-matches",	no_argument,		NULL, 'l'},
2033e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"files-without-match", no_argument,            NULL, 'L'},
2043e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"max-count",		required_argument,	NULL, 'm'},
2053e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"line-number",		no_argument,		NULL, 'n'},
2063e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"only-matching",	no_argument,		NULL, 'o'},
2073e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"quiet",		no_argument,		NULL, 'q'},
2083e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"silent",		no_argument,		NULL, 'q'},
2093e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"recursive",		no_argument,		NULL, 'r'},
2103e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"no-messages",		no_argument,		NULL, 's'},
2113e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"binary",		no_argument,		NULL, 'U'},
2123e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"unix-byte-offsets",	no_argument,		NULL, 'u'},
2133e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"invert-match",	no_argument,		NULL, 'v'},
2143e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"version",		no_argument,		NULL, 'V'},
2153e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"word-regexp",		no_argument,		NULL, 'w'},
2163e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"line-regexp",		no_argument,		NULL, 'x'},
2173e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"null",		no_argument,		NULL, 'Z'},
2183e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{"null-data",		no_argument,		NULL, 'z'},
2193e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	{NULL,			no_argument,		NULL, 0}
2203e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey};
2213e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
2223e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey/*
2233e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey * Adds a searching pattern to the internal array.
2243e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey */
2253e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeystatic void
2263e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyadd_pattern(char *pat, size_t len)
2273e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey{
2283e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
2293e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	/* TODO: Check for empty patterns and shortcut */
2303e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
2313e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	/* Increase size if necessary */
2323e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	if (patterns == pattern_sz) {
2333e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		pattern_sz *= 2;
2343e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		pattern = grep_realloc(pattern, ++pattern_sz *
2353e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		    sizeof(*pattern));
2363e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	}
2373e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	if (len > 0 && pat[len - 1] == '\n')
2383e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		--len;
2393e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	/* pat may not be NUL-terminated */
2403e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	pattern[patterns] = grep_malloc(len + 1);
2413e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	memcpy(pattern[patterns], pat, len);
2423e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	pattern[patterns][len] = '\0';
2433e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	++patterns;
2443e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey}
2453e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
2463e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey/*
2473e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey * Adds a file include/exclude pattern to the internal array.
2483e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey */
2493e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeystatic void
2503e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyadd_fpattern(const char *pat, int mode)
2513e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey{
2523e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
2533e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	/* Increase size if necessary */
2543e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	if (fpatterns == fpattern_sz) {
2553e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		fpattern_sz *= 2;
2563e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		fpattern = grep_realloc(fpattern, ++fpattern_sz *
2573e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		    sizeof(struct epat));
2583e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	}
2593e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	fpattern[fpatterns].pat = grep_strdup(pat);
2603e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	fpattern[fpatterns].mode = mode;
2613e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	++fpatterns;
2623e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey}
2633e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
2643e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey/*
2653e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey * Adds a directory include/exclude pattern to the internal array.
2663e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey */
2673e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeystatic void
2683e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyadd_dpattern(const char *pat, int mode)
2693e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey{
2703e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
2713e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	/* Increase size if necessary */
2723e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	if (dpatterns == dpattern_sz) {
2733e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		dpattern_sz *= 2;
2743e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		dpattern = grep_realloc(dpattern, ++dpattern_sz *
2753e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		    sizeof(struct epat));
2763e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	}
2773e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	dpattern[dpatterns].pat = grep_strdup(pat);
2783e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	dpattern[dpatterns].mode = mode;
2793e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	++dpatterns;
2803e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey}
2813e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
2823e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey/*
2833e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey * Reads searching patterns from a file and adds them with add_pattern().
2843e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey */
2853e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeystatic void
2863e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyread_patterns(const char *fn)
2873e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey{
2883e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	FILE *f;
2893e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	char *line;
2903e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	size_t len;
2913e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	ssize_t rlen;
2923e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
2933e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	if ((f = fopen(fn, "r")) == NULL)
2943e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		err(2, "%s", fn);
2953e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	line = NULL;
2963e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	len = 0;
2973e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey#ifndef ANDROID
2983e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	while ((rlen = getline(&line, &len, f)) != -1)
2993e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		add_pattern(line, *line == '\n' ? 0 : (size_t)rlen);
3003e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey#endif
3013e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	free(line);
3023e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	if (ferror(f))
3033e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		err(2, "%s", fn);
3043e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	fclose(f);
3053e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey}
3063e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
3073e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeystatic inline const char *
3083e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyinit_color(const char *d)
3093e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey{
3103e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	char *c;
3113e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
3123e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	c = getenv("GREP_COLOR");
3133e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	return (c != NULL ? c : d);
3143e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey}
3153e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
3163e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeyint
3173e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkeygrep_main(int argc, char *argv[])
3183e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey{
3193e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	char **aargv, **eargv, *eopts;
3203e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	char *ep;
3213e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	unsigned long long l;
3223e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	unsigned int aargc, eargc, i, j;
3233e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	int c, lastc, needpattern, newarg, prevoptind;
3243e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
3253e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	setlocale(LC_ALL, "");
3263e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
3273e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey#ifndef WITHOUT_NLS
3283e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	catalog = catopen("grep", NL_CAT_LOCALE);
3293e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey#endif
3303e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
3313e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	/* Check what is the program name of the binary.  In this
3323e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	   way we can have all the funcionalities in one binary
3333e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	   without the need of scripting and using ugly hacks. */
3343e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	switch (__progname[0]) {
3353e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	case 'e':
3363e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		grepbehave = GREP_EXTENDED;
3373e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		break;
3383e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	case 'f':
3393e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		grepbehave = GREP_FIXED;
3403e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		break;
3413e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	case 'g':
3423e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		grepbehave = GREP_BASIC;
3433e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		break;
3443e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	case 'z':
3453e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		filebehave = FILE_GZIP;
3463e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		switch(__progname[1]) {
3473e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'e':
3483e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			grepbehave = GREP_EXTENDED;
3493e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
3503e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'f':
3513e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			grepbehave = GREP_FIXED;
3523e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
3533e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'g':
3543e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			grepbehave = GREP_BASIC;
3553e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
3563e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		}
3573e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		break;
3583e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	}
3593e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
3603e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	lastc = '\0';
3613e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	newarg = 1;
3623e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	prevoptind = 1;
3633e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	needpattern = 1;
3643e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
3653e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	eopts = getenv("GREP_OPTIONS");
3663e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
3673e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	/* support for extra arguments in GREP_OPTIONS */
3683e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	eargc = 0;
3693e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	if (eopts != NULL) {
3703e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		char *str;
3713e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
3723e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		/* make an estimation of how many extra arguments we have */
3733e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		for (j = 0; j < strlen(eopts); j++)
3743e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			if (eopts[j] == ' ')
3753e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				eargc++;
3763e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
3773e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		eargv = (char **)grep_malloc(sizeof(char *) * (eargc + 1));
3783e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
3793e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		eargc = 0;
3803e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		/* parse extra arguments */
3813e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		while ((str = strsep(&eopts, " ")) != NULL)
3823e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			eargv[eargc++] = grep_strdup(str);
3833e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
3843e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		aargv = (char **)grep_calloc(eargc + argc + 1,
3853e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		    sizeof(char *));
3863e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
3873e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		aargv[0] = argv[0];
3883e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		for (i = 0; i < eargc; i++)
3893e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			aargv[i + 1] = eargv[i];
3903e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		for (j = 1; j < (unsigned int)argc; j++, i++)
3913e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			aargv[i + 1] = argv[j];
3923e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
3933e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		aargc = eargc + argc;
3943e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	} else {
3953e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		aargv = argv;
3963e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		aargc = argc;
3973e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	}
3983e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
3993e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	while (((c = getopt_long(aargc, aargv, optstr, long_options, NULL)) !=
4003e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	    -1)) {
4013e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		switch (c) {
4023e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case '0': case '1': case '2': case '3': case '4':
4033e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case '5': case '6': case '7': case '8': case '9':
4043e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			if (newarg || !isdigit(lastc))
4053e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				Aflag = 0;
4063e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			else if (Aflag > LLONG_MAX / 10) {
4073e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				errno = ERANGE;
4083e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				err(2, NULL);
4093e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			}
4103e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			Aflag = Bflag = (Aflag * 10) + (c - '0');
4113e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
4123e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'C':
4133e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			if (optarg == NULL) {
4143e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				Aflag = Bflag = 2;
4153e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				break;
4163e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			}
4173e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			/* FALLTHROUGH */
4183e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'A':
4193e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			/* FALLTHROUGH */
4203e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'B':
4213e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			errno = 0;
4223e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			l = strtoull(optarg, &ep, 10);
4233e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			if (((errno == ERANGE) && (l == ULLONG_MAX)) ||
4243e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			    ((errno == EINVAL) && (l == 0)))
4253e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				err(2, NULL);
4263e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			else if (ep[0] != '\0') {
4273e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				errno = EINVAL;
4283e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				err(2, NULL);
4293e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			}
4303e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			if (c == 'A')
4313e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				Aflag = l;
4323e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			else if (c == 'B')
4333e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				Bflag = l;
4343e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			else
4353e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				Aflag = Bflag = l;
4363e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
4373e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'a':
4383e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			binbehave = BINFILE_TEXT;
4393e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
4403e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'b':
4413e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			bflag = true;
4423e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
4433e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'c':
4443e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			cflag = true;
4453e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
4463e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'D':
4473e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			if (strcasecmp(optarg, "skip") == 0)
4483e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				devbehave = DEV_SKIP;
4493e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			else if (strcasecmp(optarg, "read") == 0)
4503e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				devbehave = DEV_READ;
4513e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			else
4523e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				errx(2, getstr(3), "--devices");
4533e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
4543e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'd':
4553e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			if (strcasecmp("recurse", optarg) == 0) {
4563e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				Hflag = true;
4573e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				dirbehave = DIR_RECURSE;
4583e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			} else if (strcasecmp("skip", optarg) == 0)
4593e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				dirbehave = DIR_SKIP;
4603e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			else if (strcasecmp("read", optarg) == 0)
4613e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				dirbehave = DIR_READ;
4623e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			else
4633e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				errx(2, getstr(3), "--directories");
4643e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
4653e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'E':
4663e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			grepbehave = GREP_EXTENDED;
4673e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
4683e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'e':
4693e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			add_pattern(optarg, strlen(optarg));
4703e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			needpattern = 0;
4713e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
4723e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'F':
4733e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			grepbehave = GREP_FIXED;
4743e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
4753e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'f':
4763e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			read_patterns(optarg);
4773e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			needpattern = 0;
4783e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
4793e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'G':
4803e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			grepbehave = GREP_BASIC;
4813e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
4823e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'H':
4833e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			Hflag = true;
4843e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
4853e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'h':
4863e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			Hflag = false;
4873e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			hflag = true;
4883e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
4893e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'I':
4903e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			binbehave = BINFILE_SKIP;
4913e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
4923e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'i':
4933e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'y':
4943e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			iflag =  true;
4953e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			cflags |= REG_ICASE;
4963e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
4973e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'J':
4983e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			filebehave = FILE_BZIP;
4993e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5003e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'L':
5013e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			lflag = false;
5023e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			Lflag = true;
5033e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5043e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'l':
5053e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			Lflag = false;
5063e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			lflag = true;
5073e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5083e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'm':
5093e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			mflag = true;
5103e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			errno = 0;
5113e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			mcount = strtoull(optarg, &ep, 10);
5123e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			if (((errno == ERANGE) && (mcount == ULLONG_MAX)) ||
5133e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			    ((errno == EINVAL) && (mcount == 0)))
5143e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				err(2, NULL);
5153e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			else if (ep[0] != '\0') {
5163e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				errno = EINVAL;
5173e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				err(2, NULL);
5183e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			}
5193e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5203e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'n':
5213e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			nflag = true;
5223e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5233e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'O':
5243e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			linkbehave = LINK_EXPLICIT;
5253e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5263e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'o':
5273e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			oflag = true;
5283e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5293e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'p':
5303e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			linkbehave = LINK_SKIP;
5313e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5323e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'q':
5333e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			qflag = true;
5343e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5353e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'S':
5363e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			linkbehave = LINK_READ;
5373e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5383e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'R':
5393e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'r':
5403e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			dirbehave = DIR_RECURSE;
5413e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			Hflag = true;
5423e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5433e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 's':
5443e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			sflag = true;
5453e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5463e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'U':
5473e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			binbehave = BINFILE_BIN;
5483e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5493e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'u':
5503e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case MMAP_OPT:
5513e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			/* noop, compatibility */
5523e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5533e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'V':
5543e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			printf(getstr(9), __progname, VERSION);
5553e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			exit(0);
5563e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'v':
5573e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			vflag = true;
5583e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5593e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'w':
5603e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			wflag = true;
5613e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5623e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'x':
5633e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			xflag = true;
5643e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5653e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'Z':
5663e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			nullflag = true;
5673e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5683e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case 'z':
5693e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			nulldataflag = true;
5703e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			line_sep = '\0';
5713e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5723e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case BIN_OPT:
5733e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			if (strcasecmp("binary", optarg) == 0)
5743e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				binbehave = BINFILE_BIN;
5753e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			else if (strcasecmp("without-match", optarg) == 0)
5763e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				binbehave = BINFILE_SKIP;
5773e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			else if (strcasecmp("text", optarg) == 0)
5783e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				binbehave = BINFILE_TEXT;
5793e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			else
5803e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				errx(2, getstr(3), "--binary-files");
5813e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
5823e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case COLOR_OPT:
5833e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			color = NULL;
5843e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			if (optarg == NULL || strcasecmp("auto", optarg) == 0 ||
5853e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			    strcasecmp("tty", optarg) == 0 ||
5863e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			    strcasecmp("if-tty", optarg) == 0) {
5873e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				char *term;
5883e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
5893e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				term = getenv("TERM");
5903e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				if (isatty(STDOUT_FILENO) && term != NULL &&
5913e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				    strcasecmp(term, "dumb") != 0)
5923e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey					color = init_color("01;31");
5933e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			} else if (strcasecmp("always", optarg) == 0 ||
5943e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			    strcasecmp("yes", optarg) == 0 ||
5953e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			    strcasecmp("force", optarg) == 0) {
5963e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				color = init_color("01;31");
5973e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			} else if (strcasecmp("never", optarg) != 0 &&
5983e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			    strcasecmp("none", optarg) != 0 &&
5993e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			    strcasecmp("no", optarg) != 0)
6003e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				errx(2, getstr(3), "--color");
6013e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
6023e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case DECOMPRESS_OPT:
6033e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			filebehave = FILE_GZIP;
6043e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
6053e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case LABEL_OPT:
6063e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			label = optarg;
6073e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
6083e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case LINEBUF_OPT:
6093e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			lbflag = true;
6103e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
6113e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case R_INCLUDE_OPT:
6123e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			finclude = true;
6133e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			add_fpattern(optarg, INCL_PAT);
6143e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
6153e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case R_EXCLUDE_OPT:
6163e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			fexclude = true;
6173e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			add_fpattern(optarg, EXCL_PAT);
6183e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
6193e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case R_DINCLUDE_OPT:
6203e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			dinclude = true;
6213e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			add_dpattern(optarg, INCL_PAT);
6223e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
6233e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case R_DEXCLUDE_OPT:
6243e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			dexclude = true;
6253e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			add_dpattern(optarg, EXCL_PAT);
6263e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			break;
6273e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		case HELP_OPT:
6283e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		default:
6293e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			usage();
6303e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		}
6313e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		lastc = c;
6323e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		newarg = optind != prevoptind;
6333e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		prevoptind = optind;
6343e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	}
6353e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	aargc -= optind;
6363e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	aargv += optind;
6373e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
6383e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	/* Fail if we don't have any pattern */
6393e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	if (aargc == 0 && needpattern)
6403e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		usage();
6413e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
6423e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	/* Process patterns from command line */
6433e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	if (aargc != 0 && needpattern) {
6443e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		add_pattern(*aargv, strlen(*aargv));
6453e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		--aargc;
6463e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		++aargv;
6473e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	}
6483e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
6493e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	switch (grepbehave) {
6503e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	case GREP_FIXED:
6513e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	case GREP_BASIC:
6523e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		break;
6533e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	case GREP_EXTENDED:
6543e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		cflags |= REG_EXTENDED;
6553e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		break;
6563e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	default:
6573e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		/* NOTREACHED */
6583e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		usage();
6593e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	}
6603e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
6613e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	fg_pattern = grep_calloc(patterns, sizeof(*fg_pattern));
6623e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	r_pattern = grep_calloc(patterns, sizeof(*r_pattern));
6633e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey/*
6643e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey * XXX: fgrepcomp() and fastcomp() are workarounds for regexec() performance.
6653e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey * Optimizations should be done there.
6663e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey */
6673e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		/* Check if cheating is allowed (always is for fgrep). */
6683e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	if (grepbehave == GREP_FIXED) {
6693e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		for (i = 0; i < patterns; ++i)
6703e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			fgrepcomp(&fg_pattern[i], pattern[i]);
6713e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	} else {
6723e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		for (i = 0; i < patterns; ++i) {
6733e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			if (fastcomp(&fg_pattern[i], pattern[i])) {
6743e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				/* Fall back to full regex library */
6753e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				c = regcomp(&r_pattern[i], pattern[i], cflags);
6763e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				if (c != 0) {
6773e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey					regerror(c, &r_pattern[i], re_error,
6783e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey					    RE_ERROR_BUF);
6793e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey					errx(2, "%s", re_error);
6803e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				}
6813e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			}
6823e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		}
6833e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	}
6843e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
6853e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	if (lbflag)
6863e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		setlinebuf(stdout);
6873e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
6883e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	if ((aargc == 0 || aargc == 1) && !Hflag)
6893e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		hflag = true;
6903e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
6913e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	if (aargc == 0)
6923e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		exit(!procfile("-"));
6933e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
6943e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	if (dirbehave == DIR_RECURSE)
6953e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		c = grep_tree(aargv);
6963e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	else
6973e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		for (c = 0; aargc--; ++aargv) {
6983e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			if ((finclude || fexclude) && !file_matching(*aargv))
6993e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey				continue;
7003e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey			c+= procfile(*aargv);
7013e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey		}
7023e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
7033e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey#ifndef WITHOUT_NLS
7043e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	catclose(catalog);
7053e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey#endif
7063e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey
7073e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	/* Find out the correct return value according to the
7083e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	   results and the command line option. */
7093e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey	exit(c ? (notfound ? (qflag ? 0 : 2) : 0) : (notfound ? 2 : 1));
7103e8b1581ff0f2daa934eb9d6362dfe4e2b4fa8c9Jeff Sharkey}
711