cleanup environment variables (#58)

all internally used variable names (e.g. the ones used while parsing
__usage and running the getopts loop) start with '__b3bp_tmp'. This
makes it easy to unset them all after the work is done.

additional bugfix: run getopts only if any options were actually
specified in __usage
This commit is contained in:
Manuel Streuhofer 2016-11-08 13:02:37 +01:00 committed by Kevin van Zonneveld
parent 86ab1128ed
commit 4445c181bb

145
main.sh
View File

@ -69,8 +69,12 @@ function help () {
echo "" 1>&2 echo "" 1>&2
echo " ${__usage:-No usage available}" 1>&2 echo " ${__usage:-No usage available}" 1>&2
echo "" 1>&2 echo "" 1>&2
echo " ${__helptext:-}" 1>&2
echo "" 1>&2 if [ -n "${__helptext:-}" ]; then
echo " ${__helptext}" 1>&2
echo "" 1>&2
fi
exit 1 exit 1
} }
@ -106,89 +110,102 @@ read -r -d '' __helptext <<-'EOF' || true # exits non-zero when EOF encountered
EOF EOF
# Translate usage string -> getopts arguments, and set $arg_<flag> defaults # Translate usage string -> getopts arguments, and set $arg_<flag> defaults
while read line; do while read __b3bp_tmp_line; do
# fetch single character version of option string # fetch single character version of option string
opt="$(echo "${line}" |awk '{print $1}' |sed -e 's#^-##')" __b3bp_tmp_opt="$(echo "${__b3bp_tmp_line}" |awk '{print $1}' |sed -e 's#^-##')"
# fetch long version if present # fetch long version if present
long_opt="$(echo "${line}" |awk '/\-\-/ {print $2}' |sed -e 's#^--##')" __b3bp_tmp_long_opt="$(echo "${__b3bp_tmp_line}" |awk '/\-\-/ {print $2}' |sed -e 's#^--##')"
long_opt_mangled="$(sed 's#-#_#g' <<< $long_opt)" __b3bp_tmp_long_opt_mangled="$(sed 's#-#_#g' <<< $__b3bp_tmp_long_opt)"
# map long name back to short name # map long name back to short name
varname="short_opt_${long_opt_mangled}" __b3bp_tmp_varname="__b3bp_tmp_short_opt_${__b3bp_tmp_long_opt_mangled}"
eval "${varname}=\"${opt}\"" eval "${__b3bp_tmp_varname}=\"${__b3bp_tmp_opt}\""
# check if option takes an argument # check if option takes an argument
varname="has_arg_${opt}" __b3bp_tmp_varname="__b3bp_tmp_has_arg_${__b3bp_tmp_opt}"
if ! echo "${line}" |egrep '\[.*\]' >/dev/null 2>&1; then if ! echo "${__b3bp_tmp_line}" |egrep '\[.*\]' >/dev/null 2>&1; then
init="0" # it's a flag. init with 0 __b3bp_tmp_init="0" # it's a flag. init with 0
eval "${varname}=0" eval "${__b3bp_tmp_varname}=0"
else else
opt="${opt}:" # add : if opt has arg __b3bp_tmp_opt="${__b3bp_tmp_opt}:" # add : if opt has arg
init="" # it has an arg. init with "" __b3bp_tmp_init="" # it has an arg. init with ""
eval "${varname}=1" eval "${__b3bp_tmp_varname}=1"
fi fi
opts="${opts:-}${opt}" __b3bp_tmp_opts="${__b3bp_tmp_opts:-}${__b3bp_tmp_opt}"
varname="arg_${opt:0:1}" __b3bp_tmp_varname="arg_${__b3bp_tmp_opt:0:1}"
if ! echo "${line}" |egrep '\. Default=' >/dev/null 2>&1; then if ! echo "${__b3bp_tmp_line}" |egrep '\. Default=' >/dev/null 2>&1; then
eval "${varname}=\"${init}\"" eval "${__b3bp_tmp_varname}=\"${__b3bp_tmp_init}\""
else else
match="$(echo "${line}" |sed 's#^.*Default=\(\)#\1#g')" __b3bp_tmp_match="$(echo "${__b3bp_tmp_line}" |sed 's#^.*Default=\(\)#\1#g')"
eval "${varname}=\"${match}\"" eval "${__b3bp_tmp_varname}=\"${__b3bp_tmp_match}\""
fi fi
done <<< "${__usage}" done <<< "${__usage:-}"
# Allow long options like --this # run getopts only if options were specified in __usage
opts="${opts}-:" if [ -n "${__b3bp_tmp_opts:-}" ]; then
# Allow long options like --this
__b3bp_tmp_opts="${__b3bp_tmp_opts}-:"
# Reset in case getopts has been used previously in the shell. # Reset in case getopts has been used previously in the shell.
OPTIND=1 OPTIND=1
# start parsing command line # start parsing command line
set +o nounset # unexpected arguments will cause unbound variables set +o nounset # unexpected arguments will cause unbound variables
# to be dereferenced # to be dereferenced
# Overwrite $arg_<flag> defaults with the actual CLI options # Overwrite $arg_<flag> defaults with the actual CLI options
while getopts "${opts}" opt; do while getopts "${__b3bp_tmp_opts}" __b3bp_tmp_opt; do
[ "${opt}" = "?" ] && help "Invalid use of script: ${@} " [ "${__b3bp_tmp_opt}" = "?" ] && help "Invalid use of script: ${@} "
if [ "${opt}" = "-" ]; then if [ "${__b3bp_tmp_opt}" = "-" ]; then
# OPTARG is long-option-name or long-option=value # OPTARG is long-option-name or long-option=value
if [[ "${OPTARG}" =~ .*=.* ]]; then if [[ "${OPTARG}" =~ .*=.* ]]; then
# --key=value format # --key=value format
long=${OPTARG/=*/} __b3bp_tmp_long_opt=${OPTARG/=*/}
long_mangled="$(sed 's#-#_#g' <<< $long)" __b3bp_tmp_long_opt_mangled="$(sed 's#-#_#g' <<< $__b3bp_tmp_long_opt)"
# Set opt to the short option corresponding to the long option # Set opt to the short option corresponding to the long option
eval "opt=\"\${short_opt_${long_mangled}}\"" eval "__b3bp_tmp_opt=\"\${__b3bp_tmp_short_opt_${__b3bp_tmp_long_opt_mangled}}\""
OPTARG=${OPTARG#*=} OPTARG=${OPTARG#*=}
else else
# --key value format # --key value format
# Map long name to short version of option # Map long name to short version of option
long_mangled="$(sed 's#-#_#g' <<< $OPTARG)" __b3bp_tmp_long_opt_mangled="$(sed 's#-#_#g' <<< $OPTARG)"
eval "opt=\"\${short_opt_${long_mangled}}\"" eval "__b3bp_tmp_opt=\"\${__b3bp_tmp_short_opt_${__b3bp_tmp_long_opt_mangled}}\""
# Only assign OPTARG if option takes an argument # Only assign OPTARG if option takes an argument
eval "OPTARG=\"\${@:OPTIND:\${has_arg_${opt}}}\"" eval "OPTARG=\"\${@:OPTIND:\${__b3bp_tmp_has_arg_${__b3bp_tmp_opt}}}\""
# shift over the argument if argument is expected # shift over the argument if argument is expected
((OPTIND+=has_arg_${opt})) ((OPTIND+=__b3bp_tmp_has_arg_${__b3bp_tmp_opt}))
fi
# we have set opt/OPTARG to the short value and the argument as OPTARG if it exists
fi fi
# we have set opt/OPTARG to the short value and the argument as OPTARG if it exists __b3bp_tmp_varname="arg_${__b3bp_tmp_opt:0:1}"
fi __b3bp_tmp_default="${!__b3bp_tmp_varname}"
varname="arg_${opt:0:1}"
default="${!varname}"
value="${OPTARG}" __b3bp_tmp_value="${OPTARG}"
if [ -z "${OPTARG}" ] && [ "${default}" = "0" ]; then if [ -z "${OPTARG}" ] && [ "${__b3bp_tmp_default}" = "0" ]; then
value="1" __b3bp_tmp_value="1"
fi fi
eval "${varname}=\"${value}\"" eval "${__b3bp_tmp_varname}=\"${__b3bp_tmp_value}\""
debug "cli arg ${varname} = ($default) -> ${!varname}" debug "cli arg ${__b3bp_tmp_varname} = ($__b3bp_tmp_default) -> ${!__b3bp_tmp_varname}"
done
set -o nounset # no more unbound variable references expected
shift $((OPTIND-1))
[ "${1:-}" = "--" ] && shift
fi
### Cleanup Environment variables
##############################################################################
for __tmp_varname in ${!__b3bp_tmp_*}; do
eval "unset ${__tmp_varname}"
done done
set -o nounset # no more unbound variable references expected
shift $((OPTIND-1)) unset __tmp_varname
[ "${1:-}" = "--" ] && shift
### Command-line argument switches (like -d for debugmode, -h for showing helppage) ### Command-line argument switches (like -d for debugmode, -h for showing helppage)