#!/bin/ksh
# @(#) where.ksh 1.1 94/01/01
# 91/01/12 john h. dubois iii (john@armory.com)
# 92/08/10 Only print executable *files*.
# 92/10/06 Print err msg if no match found.
# 92/11/27 Added implicit *
# 93/06/24 Reduced number of evals to one per arg
# 93/07/23 Print help only if -h is given.
# 94/01/01 Added -x option

name=${0##*/}
Usage="Usage: $name [-hx] 'pattern' ..."
typeset -i exact=0

alias istrue="test 0 -ne"
alias isfalse="test 0 -eq"

if [ "$1" = -x ]; then
    exact=1
    shift
fi

if [ $# -eq 0 ]; then
    print -u2 "$Usage\nUse -h for help."
    exit 1
fi

if [ "$1" = -h ]; then
    echo \
"$name: find executable files in PATH that match patterns.
$Usage
$name searches each directory specified in the PATH environment variable
for executable files that match the specified patterns.  Patterns are
given as Korn shell filename patterns.  They are surrounded by implicit
'*' characters, so that \"foo\" will match any executble file whose name
contains contains \"foo\".  This can be overridden by using '^' and '$' to
force a match to start at the beginning and end at the end of a filename
respectively.  Characters that are special to the shell must generally
be protected from the shell by surrounding them with quotes.
Examples:
$name foo
lists all executable files in PATH that contain foo.
$name '^bar@(ba|fi)z'
lists all executable files in PATH that start with barbaz or barfiz.
See ksh(C) for a description of Korn shell patterns.  
An error message is printed if a no matching file is found for a pattern.
Options:
-h: Print this help.
-x: Find exact matches only; equivalent to putting ^ and $ at the start
    and end of each pattern."
    exit 0
fi

set +f			# make sure filename globbing is on
set -A Args "$@"	# save args

OIFS=$IFS
IFS="$IFS:"		# Make PATH be split on :
set -A Paths $PATH
IFS=$OIFS

for arg in "${Args[@]}"; do
    if [[ "$arg" = ^* ]] || istrue exact; then
	[[ "$arg" = ^* ]] && arg=${arg#?}
    else
	arg="*$arg"
    fi
    if [[ "$arg" = *\$ ]] || istrue exact; then
	[[ "$arg" = *\$ ]] && arg=${arg%?}
    else
	arg="$arg*"
    fi
    found=0
    Patterns=
    for PathElem in "${Paths[@]}"; do
	Patterns="$Patterns $PathElem/$arg"
    done
    for file in `eval echo $Patterns`; do
	if [ -x "$file" -a -f "$file" ]; then
	    echo "$file"
	    found=1
	fi
    done
    if [ $found = 0 ]; then
	print -u2 "$arg: not found."
    fi
done
