:
##########################################################################
# Title      :	rgrep - recursive grep
# Author     :	Heiner Steven <heiner.steven@odn.de>
# Date       :	1996-02-12
# Category   :	File Utilities
# Requires   :	egrep, find [xargs]
# SCCS-Id.   :	@(#) rgrep	1.7 06/03/28
##########################################################################
# Description
#	This script basically executes the following command:
#	    find . -print | xargs egrep searchstring
#
#	It tries to figure out additional arguments, and constructs the
#	pipeline above. Care is taken to correctly handle files and
#	directories with whitespace characters.
# Caveats
#    o	The argument relaying for "egrep" and "find" assumes that these
#	commands accept the same arguments as the Solaris 8 version
##########################################################################

PN=`basename "$0"`			# Program name
VER='1.7'

##########################################################################
# Configuration section
#
# grep and grep options (taken from Solaris 2.8 "egrep" manual page)
#
GREP=egrep
GREPFLAGS=bchilnsv		# Option flags
GREPARGS=e:f:			# Switches requiring an argument

#
# find and options (without and with argument)
# (taken from Solaris 2.8 "find" manual page)
#

findtype=	# Set to disable auto-configuration {default|posix|gnu}
FIND=find
FINDFLAGS="-depth -follow -local -ls -mount -nogroup - nouser -print \
	-prune - xdev"
FINDARGS="-atime -cpio -ctime -exec -fstype -group -inum -links -mtime \
	-name -cpio -newer -ok -perm -size -type -user"
# End of configuration section
##########################################################################

FindOpts="-follow -type f"
GrepOpts=

Usage () {
    echo >&2 "$PN - recursive grep, $VER
usage: $PN [-hd] [grep_opts | find_opts] SearchString [file | directory] ...
    -h:	print this usage summary
    -d: debugging output

    grep_opts:	Options for $GREP (the default is \"$GrepOpts\")
    find_opts:	Options for find (the default is \"$FindOpts\").

Options consisting of a single letter are considered to be $GREP
options, longer options are interpreted as find options."
    exit 1
}

Msg () {
    for i
    do echo "$PN: $i" >&2
    done
}

Fatal () { Msg "$@"; exit 1; }

True ()  { return 0; }
False () { return 1; }

Args=
Debug=False				# True/False
while [ $# -gt 0 ]
do
    case "$1" in

	--)	shift; break;;
	-h)	Usage;;
	-d)	Debug=True;;

    	-??*)				# Long find option
	    case "$FINDARGS" in
		*"$1"*)
		    $Debug && echo >&2 "$1 is find option with argument"
		    Args="${Args:+$Args }$1 \"$2\""
		    shift 2
		    continue
		    ;;
	    esac
	    case "$FINDFLAGS" in
		*"$1"*)
		    $Debug && echo >&2 "$1 is find option without argument"
		    Args="${Args:+$Args }$1"
		    shift
		    continue
		    ;;
	    esac
	    ;;

    	-*)				# Short grep option
	    if getopt "$GREPARGS" "$1" "$2" >/dev/null 2>&1
	    then
		$Debug && echo >&2 "$1 is grep option"
		GrepOpts="${GrepOpts:+$GrepOpts }$1 \"$2\""
		shift
	    elif getopt "$GREPFLAGS" "$1" >/dev/null 2>&1
	    then
		$Debug && echo >&2 "$1 is grep option"
		GrepOpts="${GrepOpts:+$GrepOpts }$1"
	    else
	    	Fatal "unknown option: $1"
	    fi
	    ;;

	*)	break;;			# Search string
    esac
    shift
done

[ -n "$Args" ] && FindOpts="$Args"

[ $# -lt 1 ] && Usage
Search="$1"; shift

[ $# -lt 1 ] && set -- .		# Default search directory

$Debug && set -x

##########################################################################
# We could use the sequence "find . -exec grep {} \;" which is portable
# to almost all systems, but it is very slow because one "grep" process
# is started for each file.
#
# The command line "find . -print | xargs grep" is much faster and
# fairly portable, but does not handle whitespace in directory or file
# names correctly.
# POSIX and GNU have solved that problem differently:
#	POSIX:	find . -exec grep {} +	# (internal xargs)
#	GNU:    find . -print0 | xargs -0 grep	# (delimiter is zero)
#
# To get the fastest possible method we are prepared to select one of
# the two methods. If none of them is available, we use the slow (but
# safe) command line.
##########################################################################

if [ -z "$findtype" ]
then
    #findtype=	# {default|posix|gnu}

    # Guess type of "find" command by looking at the operating system.
    # This is faster than actually trying "find" features.

    case `uname | tr '[a-z]' '[A-Z]'` in
	SUNOS)
	    case `uname -r` in
	    	5*)	findtype=posix;;	# Solaris
		4*)	findtype=default;;	# SunOS
	    esac;;
	LINUX)	findtype=gnu;;
    esac

    findtype=	# DEBUG

    # Unknown operating system: try which of the features work. This is very
    # slow.
    if [ -z "$findtype" ]
    then
	if find . -type d -name "." -exec echo {} + >/dev/null 2>&1
	then findtype=posix
	else
	    if find . -type d -name "." -print0 >/dev/null 2>&1
	    then findtype=gnu
	    else findtype=default
	    fi
	fi
    fi
fi

#echo >&2 "DEBUG: findtype=$findtype"

find='"$FIND" "$@" '$FindOpts
grep='"$GREP" '$GrepOpts' "$Search" /dev/null'
case "$findtype" in
    posix) cmd=$find' -exec '$grep' {} +';;
    gnu) cmd=$find' -print0 | xargs -0 '$grep;;
    *)   cmd=$find' -exec '$grep' \;';;
esac
eval "$cmd"
