Skip to content

fix: replace unquoted array assignments with _comp_{split,compgen_split,expand_glob} #1085

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jan 14, 2024
36 changes: 16 additions & 20 deletions bash_completion
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,8 @@ _comp_upvars()
# parameter expansions, command substitutions, and other expansions will be
# processed. The user-provided strings should not be directly specified to
# this argument.
# @return 0 if at least one path is generated, 1 if no path is generated, or 2
# if the usage is incorrect.
# @since 2.12
_comp_expand_glob()
{
Expand Down Expand Up @@ -361,7 +363,7 @@ _comp_expand_glob()
[[ :$_original_opts: == *:nullglob:* ]] || shopt -u nullglob
[[ :$_original_opts: == *:failglob:* ]] && shopt -s failglob
[[ :$_original_opts: == *:noglob:* ]] && set -o noglob
return 0
eval "((\${#$1[@]}))"
}

# Split a string and assign to an array. This function basically performs
Expand Down Expand Up @@ -1652,14 +1654,12 @@ _comp_compgen_configured_interfaces()
local -a files
if [[ -f /etc/debian_version ]]; then
# Debian system
_comp_expand_glob files '/etc/network/interfaces /etc/network/interfaces.d/*'
((${#files[@]})) || return 0
_comp_expand_glob files '/etc/network/interfaces /etc/network/interfaces.d/*' || return 0
_comp_compgen -U files split -- "$(command sed -ne \
's|^iface \([^ ]\{1,\}\).*$|\1|p' "${files[@]}" 2>/dev/null)"
elif [[ -f /etc/SuSE-release ]]; then
# SuSE system
_comp_expand_glob files '/etc/sysconfig/network/ifcfg-*'
((${#files[@]})) || return 0
_comp_expand_glob files '/etc/sysconfig/network/ifcfg-*' || return 0
_comp_compgen -U files split -- "$(printf '%s\n' "${files[@]}" |
command sed -ne 's|.*ifcfg-\([^*].*\)$|\1|p')"
elif [[ -f /etc/pld-release ]]; then
Expand All @@ -1668,8 +1668,7 @@ _comp_compgen_configured_interfaces()
command sed -ne 's|.*ifcfg-\([^*].*\)$|\1|p')"
else
# Assume Red Hat
_comp_expand_glob files '/etc/sysconfig/network-scripts/ifcfg-*'
((${#files[@]})) || return 0
_comp_expand_glob files '/etc/sysconfig/network-scripts/ifcfg-*' || return 0
_comp_compgen -U files split -- "$(printf '%s\n' "${files[@]}" |
command sed -ne 's|.*ifcfg-\([^*].*\)$|\1|p')"
fi
Expand Down Expand Up @@ -1951,8 +1950,7 @@ _comp_compgen_xinetd_services()
local xinetddir=${_comp__test_xinetd_dir:-/etc/xinetd.d}
if [[ -d $xinetddir ]]; then
local -a svcs
_comp_expand_glob svcs '$xinetddir/!($_comp_backup_glob)'
if ((${#svcs[@]})); then
if _comp_expand_glob svcs '$xinetddir/!($_comp_backup_glob)'; then
_comp_compgen -U svcs -U xinetddir -- -W '"${svcs[@]#$xinetddir/}"'
fi
fi
Expand Down Expand Up @@ -2018,10 +2016,11 @@ _comp__init_set_up_service_completions()
local sysvdirs svc svcdir svcs
_comp_sysvdirs &&
for svcdir in "${sysvdirs[@]}"; do
_comp_expand_glob svcs '"$svcdir"/!($_comp_backup_glob)'
for svc in "${svcs[@]}"; do
[[ -x $svc ]] && complete -F _comp_complete_service "$svc"
done
if _comp_expand_glob svcs '"$svcdir"/!($_comp_backup_glob)'; then
for svc in "${svcs[@]}"; do
[[ -x $svc ]] && complete -F _comp_complete_service "$svc"
done
fi
done
unset -f "$FUNCNAME"
}
Expand Down Expand Up @@ -2355,8 +2354,7 @@ _comp_compgen_terms()
{
toe -a || toe
} | _comp_awk '{ print $1 }'
_comp_expand_glob dirs '/{etc,lib,usr/lib,usr/share}/terminfo/?'
((${#dirs[@]})) &&
_comp_expand_glob dirs '/{etc,lib,usr/lib,usr/share}/terminfo/?' &&
find "${dirs[@]}" -type f -maxdepth 1 |
_comp_awk -F / '{ print $NF }'
} 2>/dev/null)"
Expand Down Expand Up @@ -2455,9 +2453,8 @@ _comp__included_ssh_config_files()
i="${relative_include_base}/${i}"
fi
_comp_expand_tilde "$i"
_comp_expand_glob files '$REPLY'
# In case the expanded variable contains multiple paths
if ((${#files[@]})); then
if _comp_expand_glob files '$REPLY'; then
# In case the expanded variable contains multiple paths
for f in "${files[@]}"; do
if [[ -r $f && ! -d $f ]]; then
config+=("$f")
Expand Down Expand Up @@ -2592,8 +2589,7 @@ _comp_compgen_known_hosts__impl()
done
for i in /etc/ssh2/knownhosts ~/.ssh2/hostkeys; do
[[ -d $i ]] || continue
_comp_expand_glob tmpkh '"$i"/*.pub'
((${#tmpkh[@]})) && khd+=("${tmpkh[@]}")
_comp_expand_glob tmpkh '"$i"/*.pub' && khd+=("${tmpkh[@]}")
done
fi

Expand Down
2 changes: 1 addition & 1 deletion completions/_adb
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ _comp_cmd_adb()
_comp_compgen -av tmp help -- help
fi
if [[ ! $cur || $cur != -* ]]; then
tmp+=($("$1" help 2>&1 | _comp_awk '$1 == "adb" { print $2 }'))
_comp_split -a tmp "$("$1" help 2>&1 | _comp_awk '$1 == "adb" { print $2 }')"
tmp+=(devices connect disconnect sideload)
fi
((${#tmp[@]})) &&
Expand Down
2 changes: 1 addition & 1 deletion completions/_mock
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ _comp_cmd_mock()
;;
-r | --root)
_comp_compgen_split -- "$(command ls "$cfgdir")" &&
COMPREPLY=(${COMPREPLY[@]/%.cfg/})
COMPREPLY=("${COMPREPLY[@]/%.cfg/}")
return
;;
--configdir | --resultdir)
Expand Down
3 changes: 1 addition & 2 deletions completions/_rtcwake
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ _comp_cmd_rtcwake()
return
;;
--device | -d)
_comp_expand_glob COMPREPLY '/dev/rtc?*'
((${#COMPREPLY[@]})) &&
_comp_expand_glob COMPREPLY '/dev/rtc?*' &&
_comp_compgen -- -W '"${COMPREPLY[@]#/dev/}"'
return
;;
Expand Down
3 changes: 1 addition & 2 deletions completions/_yum
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ _comp_cmd_yum__compgen_repolist()
_comp_cmd_yum__compgen_plugins()
{
local -a files
_comp_expand_glob files '/usr/lib/yum-plugins/*.py{,c,o}'
((${#files[@]})) || return
_comp_expand_glob files '/usr/lib/yum-plugins/*.py{,c,o}' || return
_comp_compgen -U files split -- "$(
printf '%s\n' "${files[@]}" |
command sed -ne 's|.*/\([^./]*\)\.py[co]\{0,1\}$|\1|p' | sort -u
Expand Down
2 changes: 1 addition & 1 deletion completions/aspell
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ _comp_cmd_aspell__dictionary()
COMPREPLY=("${COMPREPLY[@]#$datadir/}")
fi
# Then, add the canonical dicts
COMPREPLY+=($("$aspell" dicts 2>/dev/null))
_comp_split -a COMPREPLY "$("$aspell" dicts 2>/dev/null)"
((${#COMPREPLY[@]})) &&
_comp_compgen -- -X '\*' -W '"${COMPREPLY[@]}"'
}
Expand Down
4 changes: 1 addition & 3 deletions completions/complete
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ _comp_cmd_complete()
return
;;
-*p | -*r)
COMPREPLY=($(complete -p | command sed -e 's|.* ||'))
((${#COMPREPLY[@]})) &&
_comp_compgen -- -W '"${COMPREPLY[@]}"'
_comp_compgen_split -l -- "$(complete -p | command sed -e 's|.* ||')"
return
;;
esac
Expand Down
8 changes: 3 additions & 5 deletions completions/curl
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,9 @@ _comp_cmd_curl()
return
;;
--help | -${noargopts}h)
local x categories=(
$("$1" --help non-existent-category 2>&1 |
_comp_awk '/^[ \t]/ {print $1}')
)
if ((${#categories[@]})); then
local x categories
if _comp_split categories "$("$1" --help non-existent-category 2>&1 |
_comp_awk '/^[ \t]/ {print $1}')"; then
for x in "${categories[@]}"; do
# Looks like an option? Likely no --help category support
[[ $x != -* ]] || return
Expand Down
90 changes: 39 additions & 51 deletions completions/cvs
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,21 @@
_comp_deprecate_var 2.12 \
COMP_CVS_REMOTE BASH_COMPLETION_CMD_CVS_REMOTE

_comp_cmd_cvs__entries()
# Usage: _comp_cmd_cvs__compgen_entries [base_path]
# @param[opt] $1
# shellcheck disable=SC2120
_comp_cmd_cvs__compgen_entries()
{
local prefix=${cur%/*}/ IFS=$'\n'
[[ -e ${prefix-}CVS/Entries ]] || prefix=""
entries=($(cut -d/ -f2 -s "${prefix-}CVS/Entries" 2>/dev/null))
if ((${#entries[@]})); then
_comp_compgen -Rv entries -- -P "${prefix-}" -W '"${entries[@]}"'
local base_path=${1-$cur}
local _prefix=${base_path%/*}/
[[ -e ${_prefix-}CVS/Entries ]] || _prefix=""
_comp_compgen -c "${cur#"$_prefix"}" split -lP "$_prefix" -- "$(cut -d/ -f2 -s "${_prefix-}CVS/Entries" 2>/dev/null)" &&
compopt -o filenames
fi
}

_comp_cmd_cvs__modules()
{
COMPREPLY=($(command ls -d "${cvsroot}${prefix:+/$prefix}"/!(CVSROOT)))
_comp_expand_glob COMPREPLY '"$cvsroot${prefix:+/$prefix}"/!(CVSROOT)'
}

_comp_cmd_cvs__compgen_commands()
Expand All @@ -41,7 +42,7 @@ _comp_xfunc_cvs_compgen_roots()
{
local -a cvsroots=()
[[ -v CVSROOT ]] && cvsroots=("$CVSROOT")
[[ -r ~/.cvspass ]] && cvsroots+=($(_comp_awk '{ print $2 }' ~/.cvspass))
[[ -r ~/.cvspass ]] && _comp_split -a cvsroots "$(_comp_awk '{ print $2 }' ~/.cvspass)"
[[ -r CVS/Root ]] && mapfile -tO "${#cvsroots[@]}" cvsroots <CVS/Root
((${#cvsroots[@]})) &&
_comp_compgen -U cvsroots -- -W '"${cvsroots[@]}"'
Expand All @@ -56,7 +57,7 @@ _comp_cmd_cvs()
_comp_initialize -n : -- "$@" || return

local count mode="" i cvsroot="" has_cvsroot="" pwd
local -a flags files entries changed newremoved
local -a flags files entries

local noargopts='!(-*|*[d]*)'
count=0
Expand Down Expand Up @@ -140,7 +141,7 @@ _comp_cmd_cvs()
;;
esac
elif [[ $i == -* ]]; then
flags+=($i)
flags+=("$i")
fi
((count++))
done
Expand All @@ -159,9 +160,12 @@ _comp_cmd_cvs()
esac

if [[ $cur != -* ]]; then
_comp_cmd_cvs__entries
[[ ! $cur ]] && files=(!(CVS)) ||
files=($(command ls -d "${cur}"* 2>/dev/null))
_comp_compgen -Rv entries -i cvs entries "${cur-}"
if [[ ! $cur ]]; then
_comp_expand_glob files '!(CVS)'
else
_comp_expand_glob files '"${cur}"*'
fi
local f
for i in "${!files[@]}"; do
if [[ ${files[i]} == ?(*/)CVS ]]; then
Expand Down Expand Up @@ -201,9 +205,7 @@ _comp_cmd_cvs()
if [[ $cur == -* ]]; then
_comp_cmd_cvs__compgen_command_options "$1" "$mode"
else
_comp_cmd_cvs__entries
((${#entries[@]})) &&
_comp_compgen -- -W '"${entries[@]}"'
_comp_cmd_cvs__compgen_entries
fi
;;
annotate)
Expand All @@ -212,9 +214,7 @@ _comp_cmd_cvs()
if [[ $cur == -* ]]; then
_comp_cmd_cvs__compgen_command_options "$1" "$mode"
else
_comp_cmd_cvs__entries
((${#entries[@]})) &&
_comp_compgen -- -W '"${entries[@]}"'
_comp_cmd_cvs__compgen_entries
fi
;;
checkout)
Expand All @@ -235,10 +235,8 @@ _comp_cmd_cvs()

if [[ $cur != -* ]]; then
[[ ! $has_cvsroot ]] && cvsroot=${CVSROOT-}
COMPREPLY=($(cvs -d "$cvsroot" co -c 2>/dev/null |
_comp_awk '{print $1}'))
((${#COMPREPLY[@]})) &&
_comp_compgen -- -W '"${COMPREPLY[@]}"'
_comp_compgen_split -- "$(cvs -d "$cvsroot" co -c 2>/dev/null |
_comp_awk '{print $1}')"
else
_comp_cmd_cvs__compgen_command_options "$1" "$mode"
fi
Expand All @@ -262,19 +260,16 @@ _comp_cmd_cvs()
if [[ ${BASH_COMPLETION_CMD_CVS_REMOTE-} ]]; then
# this is the least computationally intensive way found so
# far, but other changes (something other than
# changed/removed/new) may be missing
changed=($(cvs -q diff --brief 2>&1 |
command sed -ne 's/^Files [^ ]* and \([^ ]*\) differ$/\1/p'))
newremoved=($(cvs -q diff --brief 2>&1 |
command sed -ne 's/^cvs diff: \([^ ]*\) .*, no comparison available$/\1/p'))
((${#changed[@]})) && COMPREPLY+=("${changed[@]}")
((${#newremoved[@]})) && COMPREPLY+=("${newremoved[@]}")
((${#COMPREPLY[@]})) &&
_comp_compgen -- -W '"${COMPREPLY[@]}"'
# changed/removed/new) may be missing.
_comp_compgen -a split -- "$(cvs -q diff --brief 2>&1 |
command sed -ne '
# changed
s/^Files [^ ]* and \([^ ]*\) differ$/\1/p
# new/removed
s/^cvs diff: \([^ ]*\) .*, no comparison available$/\1/p
')"
else
_comp_cmd_cvs__entries
((${#entries[@]})) &&
_comp_compgen -- -W '"${entries[@]}"'
_comp_cmd_cvs__compgen_entries
fi
else
_comp_cmd_cvs__compgen_command_options "$1" "$mode"
Expand All @@ -288,18 +283,14 @@ _comp_cmd_cvs()
_comp_cmd_cvs__compgen_command_options "$1" "$mode"
[[ ${COMPREPLY-} == *= ]] && compopt -o nospace
else
_comp_cmd_cvs__entries
((${#entries[@]})) &&
_comp_compgen -- -W '"${entries[@]}"'
_comp_cmd_cvs__compgen_entries
fi
;;
editors | watchers)
if [[ $cur == -* ]]; then
_comp_cmd_cvs__compgen_command_options "$1" "$mode"
else
_comp_cmd_cvs__entries
((${#entries[@]})) &&
_comp_compgen -- -W '"${entries[@]}"'
_comp_cmd_cvs__compgen_entries
fi
;;
export)
Expand All @@ -320,9 +311,8 @@ _comp_cmd_cvs()

if [[ $cur != -* ]]; then
[[ ! $has_cvsroot ]] && cvsroot=${CVSROOT-}
COMPREPLY=($(cvs -d "$cvsroot" co -c | _comp_awk '{print $1}'))
((${#COMPREPLY[@]})) &&
_comp_compgen -- -W '"${COMPREPLY[@]}"'
_comp_compgen_split -- "$(cvs -d "$cvsroot" co -c |
_comp_awk '{print $1}')"
else
_comp_cmd_cvs__compgen_command_options "$1" "$mode"
fi
Expand All @@ -345,8 +335,8 @@ _comp_cmd_cvs()
local prefix=${cur%/*}
if [[ -r ${cvsroot}/${prefix} ]]; then
_comp_cmd_cvs__modules
COMPREPLY=(${COMPREPLY[@]#"$cvsroot"})
COMPREPLY=(${COMPREPLY[@]#\/})
COMPREPLY=("${COMPREPLY[@]#"$cvsroot"}")
COMPREPLY=("${COMPREPLY[@]#\/}")
fi
pwd=$(pwd)
pwd=${pwd##*/}
Expand All @@ -359,7 +349,7 @@ _comp_cmd_cvs()
;;
remove)
if [[ $cur != -* ]]; then
_comp_cmd_cvs__entries
_comp_compgen -Rv entries -i cvs entries "${cur-}"
if [[ $prev != -f ]]; then
# find out what files are missing
for i in "${!entries[@]}"; do
Expand Down Expand Up @@ -387,9 +377,7 @@ _comp_cmd_cvs()
if [[ $cur == -* ]]; then
_comp_cmd_cvs__compgen_command_options "$1" "$mode"
else
_comp_cmd_cvs__entries
((${#entries[@]})) &&
_comp_compgen -- -W '"${entries[@]}"'
_comp_cmd_cvs__compgen_entries
fi
;;
"")
Expand Down
2 changes: 1 addition & 1 deletion completions/declare
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ _comp_cmd_declare()
_comp_compgen -Rv opts usage -c help -s "$1"
# Most options also have a '+' form.
# We'll exclude the ones that don't with compgen.
opts+=(${opts[*]/-/+})
opts+=("${opts[@]/-/+}")
_comp_compgen -- -W "${opts[*]}" -X '+[Ffgp]'
return
fi
Expand Down
Loading