#! /bin/bash
usage()
{
echo "script [-all] [-?] [-help] [-version] envvar pattern(s)"
}
usage_and_exit()
{
usage
exit 1
}
version()
{
echo $PROGRAM has version: $VERSION
}
# We output the current parameters user put in
# to compare those parameters with correct way to use
error()
{
echo "$@" 1>&2
usage_and_exit 1
}
# We use EXITCODE to track the number of warnings script
# has produced. EXITCODE is increased by one every time
# in this function. expr's role is doing the arithmetic
# expression
warning()
{
echo "$@" 1>&2
EXITCODE=`expr $EXITCODE + 1`
}
# We setup the IFS by ourvelves in case any security attack
# Attacking way:
# Change the field separator IFS to change the way of script
# interpreting the input
IFS="
"
# Another attacking way:
# Fool the script to run intended command at provided path.
# We change the PATH to simplest version and export it to avoid this attack.
# Exporting PATH can make sure all inherited process from this
# script get the this PATH variable.
OPATH="$PATH"
PATH=/bin:/usr/bin
export PATH
all=no
envvar=
EXITCODE=0
PROGRAM=`basename $0`
#echo $0: ./script_1
#echo $PRGORAM: script_1
#basename is the command used to strip off leading path
VERSION=1.0
while [ $# -gt 0 ]
do
case $1 in
-all | -al | -a)
all=yes
;;
'-?' | -help | -hel | -he | -h)
usage_and_exit
;;
-version | -ver | -v)
version
exit 0
;;
-*)
error "Unrecognized option:" $1
;;
*) # We have to provide this option here, otherwise envvar option will be ignored
break
;;
esac
shift
done
# Assume the parameter after the option is the "envvar"
# and *) option above, make script get out of while loop, and
# come over here to process the envvar option
# We assign that value to envvar, and then if there is still
# more parameters, we use "shift" to get rid of it.
# If user doesn't specify the environment variable, then we use
# default PATH pattern, which is assigned and exported above
if [ $# -le 0 ]
then
envvar=PATH
else
envvar=$1
test $# -gt 0 && shift
fi
# If user provide "PATH" as the envvar, then we use the saved
# PATH vriable content as the environment path variable
test "x$envvar" = "xPATH" && envvar=OPATH
# dirpath is expanded from the envvar, then get used to search
# files from there.
# $envvar will firstly be expanded into "OPATH", and then it becomes
# dirpath=`eval echo ${OPATH} | tr : ' '`
# Then it will look up variable OPATH in the environment, expand it
# lastly transform all ":" to space.
# The role of "eval" is making sure the following command is with
# the correct shell parsing order
dirpath=`eval echo '${'"$envvar"'}' | tr : ' '`
# For the PATH we defined above, output:
# /bin /user/bin
# A few checks:
# 1. What if $envvar is empty
# 2. What if $envvar is not expanded
# 3. What if $envvar is expanded but empty
# 4. If all above 3 get passed, then what if there are no
# files specified to be found
if test -z "$envvar"
then
error missing environment variable
elif test "x$dirpath" = "x$envvar"
then
error current shell can not expand envvar
elif test -z "$dirpath"
# we have to add double quote here to make it be ONE ARGUMENT,
# otherwise $dirpath will be replaced by multiple paths separated by space,
# making command test complain too many arguments
then
error empty directory search path
elif test $# -eq 0
then
exit 0
fi
# For each user provided file pattern, script will search them
# in each expanded directory. If the file is found (test -f),
# then script will output the path and file name to standard
# output. Per variable $all, script will decide whether to move
# on to look for all occurances of file, or just "break 2" to look
# for next pattern
for filepattern in "$@"
# We have to use double quote on "$@", otherwise the script won't
# accept names with spaces. For example "name with spaces", with
# double quote on "$@", it will just interpret as ONE NAME, instead of
# three names "name" "with" and "spaces"
do
result=
for searchPath in $dirpath
do
for file in $searchPath/$filepattern
do
if test -f $file
then
result=$file
echo $result
test $all = "no" && break 2
fi
done
done
# If result is empty, it means that the user provided pattern is not
# found at the given path. warning function will increase variable
# EXITCODE to indicate the number of unfound file pattern.
test -z $result && warning "$filepattern not found"
done
# Per Unix convention, return code has to be 0~127, since 126 and 127 are
# already reserved by unix system, we setup the 125 as the upper limit here.
# 0: success
# 126: found the command but not having permission
# 127: failed to find the command
test $EXITCODE -gt 125 && EXITCODE=125
exit $EXITCODE
terminal:
No comments:
Post a Comment