Skip to content

Commit a3345c6

Browse files
authored
Merge pull request #989 from akinomyoga/_comp_compgen-6
feat(_comp_compgen_split): use `_comp_compgen_split` for `-W '$(...)'`
2 parents cb24709 + f488f96 commit a3345c6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

131 files changed

+666
-592
lines changed

bash_completion

Lines changed: 75 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,46 @@ _comp_compgen_set()
673673
eval -- "$_var${_append:++}=(\"\$@\")"
674674
}
675675

676+
# Simply split the text and generate completions. This function should be used
677+
# instead of `_comp_compgen -- -W "$(command)"`, which is vulnerable because
678+
# option -W evaluates the shell expansions included in the option argument.
679+
# Options:
680+
# -F sep Specify the separators. The default is $' \t\n'
681+
# -l The same as -F $'\n'
682+
# -X arg The same as the compgen option -X.
683+
# -S arg The same as the compgen option -S.
684+
# -P arg The same as the compgen option -P.
685+
# -o arg The same as the compgen option -o.
686+
# @param $1 String to split
687+
# @since 2.12
688+
_comp_compgen_split()
689+
{
690+
local _ifs=$' \t\n'
691+
local -a _compgen_options=()
692+
693+
local OPTIND=1 OPTARG="" OPTERR=0 _opt
694+
while getopts ':lF:X:S:P:o:' _opt "$@"; do
695+
case $_opt in
696+
l) _ifs=$'\n' ;;
697+
F) _ifs=$OPTARG ;;
698+
[XSPo]) _compgen_options+=("-$_opt" "$OPTARG") ;;
699+
*)
700+
printf 'bash_completion: usage: %s [-l|-F sep] [--] str\n' "$FUNCNAME" >&2
701+
return 2
702+
;;
703+
esac
704+
done
705+
shift "$((OPTIND - 1))"
706+
if (($# != 1)); then
707+
printf 'bash_completion: %s: unexpected number of arguments.\n' "$FUNCNAME" >&2
708+
printf 'usage: %s [-l|-F sep] [--] str' "$FUNCNAME" >&2
709+
return 2
710+
fi
711+
712+
local _split_input=$1 IFS=$' \t\n'
713+
_comp_compgen -F "$_ifs" -- ${_compgen_options[@]+"${_compgen_options[@]}"} -W '$_split_input'
714+
}
715+
676716
# Check if the argument looks like a path.
677717
# @param $1 thing to check
678718
# @return True (0) if it does, False (> 0) otherwise
@@ -1183,7 +1223,7 @@ _comp_variable_assignments()
11831223
_terms
11841224
;;
11851225
LANG | LC_*)
1186-
_comp_compgen -- -W '$(locale -a 2>/dev/null)'
1226+
_comp_compgen_split -- "$(locale -a 2>/dev/null)"
11871227
;;
11881228
LANGUAGE)
11891229
_comp_delimited : -W '$(locale -a 2>/dev/null)'
@@ -1524,23 +1564,23 @@ _configured_interfaces()
15241564
# Debian system
15251565
_comp_expand_glob files '/etc/network/interfaces /etc/network/interfaces.d/*'
15261566
((${#files[@]})) || return 0
1527-
_comp_compgen -- -W "$(command sed -ne 's|^iface \([^ ]\{1,\}\).*$|\1|p' \
1528-
"${files[@]}" 2>/dev/null)"
1567+
_comp_compgen_split -- "$(command sed -ne \
1568+
's|^iface \([^ ]\{1,\}\).*$|\1|p' "${files[@]}" 2>/dev/null)"
15291569
elif [[ -f /etc/SuSE-release ]]; then
15301570
# SuSE system
15311571
_comp_expand_glob files '/etc/sysconfig/network/ifcfg-*'
15321572
((${#files[@]})) || return 0
1533-
_comp_compgen -- -W "$(printf '%s\n' "${files[@]}" |
1573+
_comp_compgen_split -- "$(printf '%s\n' "${files[@]}" |
15341574
command sed -ne 's|.*ifcfg-\([^*].*\)$|\1|p')"
15351575
elif [[ -f /etc/pld-release ]]; then
15361576
# PLD Linux
1537-
_comp_compgen -- -W "$(command ls -B /etc/sysconfig/interfaces |
1577+
_comp_compgen_split -- "$(command ls -B /etc/sysconfig/interfaces |
15381578
command sed -ne 's|.*ifcfg-\([^*].*\)$|\1|p')"
15391579
else
15401580
# Assume Red Hat
15411581
_comp_expand_glob files '/etc/sysconfig/network-scripts/ifcfg-*'
15421582
((${#files[@]})) || return 0
1543-
_comp_compgen -- -W "$(printf '%s\n' "${files[@]}" |
1583+
_comp_compgen_split -- "$(printf '%s\n' "${files[@]}" |
15441584
command sed -ne 's|.*ifcfg-\([^*].*\)$|\1|p')"
15451585
fi
15461586
}
@@ -1576,7 +1616,7 @@ _ip_addresses()
15761616
# TODO:API: rename per conventions
15771617
_kernel_versions()
15781618
{
1579-
_comp_compgen -- -W '$(command ls /lib/modules)'
1619+
_comp_compgen_split -- "$(command ls /lib/modules)"
15801620
}
15811621

15821622
# This function completes on all available network interfaces
@@ -1694,26 +1734,26 @@ if [[ $OSTYPE == *@(solaris|aix)* ]]; then
16941734
# This function completes on process IDs.
16951735
_pids()
16961736
{
1697-
_comp_compgen -- -W '$(command ps -efo pid | command sed 1d)'
1737+
_comp_compgen_split -- "$(command ps -efo pid | command sed 1d)"
16981738
}
16991739

17001740
_pgids()
17011741
{
1702-
_comp_compgen -- -W '$(command ps -efo pgid | command sed 1d)'
1742+
_comp_compgen_split -- "$(command ps -efo pgid | command sed 1d)"
17031743
}
17041744
_pnames()
17051745
{
1706-
_comp_compgen -- -X '<defunct>' -W '$(command ps -efo comm | \
1707-
command sed -e 1d -e "s:.*/::" -e "s/^-//" | sort -u)'
1746+
_comp_compgen_split -X '<defunct>' -- "$(command ps -efo comm |
1747+
command sed -e 1d -e 's:.*/::' -e 's/^-//' | sort -u)"
17081748
}
17091749
else
17101750
_pids()
17111751
{
1712-
_comp_compgen -- -W '$(command ps ax -o pid=)'
1752+
_comp_compgen_split -- "$(command ps ax -o pid=)"
17131753
}
17141754
_pgids()
17151755
{
1716-
_comp_compgen -- -W '$(command ps ax -o pgid=)'
1756+
_comp_compgen_split -- "$(command ps ax -o pgid=)"
17171757
}
17181758
# @param $1 if -s, don't try to avoid truncated command names
17191759
_pnames()
@@ -1772,12 +1812,12 @@ fi
17721812
_uids()
17731813
{
17741814
if type getent &>/dev/null; then
1775-
_comp_compgen -- -W '$(getent passwd | cut -d: -f3)'
1815+
_comp_compgen_split -- "$(getent passwd | cut -d: -f3)"
17761816
elif type perl &>/dev/null; then
1777-
_comp_compgen -- -W '$(perl -e '"'"'while (($uid) = (getpwent)[2]) { print $uid . "\n" }'"'"')'
1817+
_comp_compgen_split -- "$(perl -e 'while (($uid) = (getpwent)[2]) { print $uid . "\n" }')"
17781818
else
17791819
# make do with /etc/passwd
1780-
_comp_compgen -- -W '$(cut -d: -f3 /etc/passwd)'
1820+
_comp_compgen_split -- "$(cut -d: -f3 /etc/passwd)"
17811821
fi
17821822
}
17831823

@@ -1787,12 +1827,12 @@ _uids()
17871827
_gids()
17881828
{
17891829
if type getent &>/dev/null; then
1790-
_comp_compgen -- -W '$(getent group | cut -d: -f3)'
1830+
_comp_compgen_split -- "$(getent group | cut -d: -f3)"
17911831
elif type perl &>/dev/null; then
1792-
_comp_compgen -- -W '$(perl -e '"'"'while (($gid) = (getgrent)[2]) { print $gid . "\n" }'"'"')'
1832+
_comp_compgen_split -- "$(perl -e 'while (($gid) = (getgrent)[2]) { print $gid . "\n" }')"
17931833
else
17941834
# make do with /etc/group
1795-
_comp_compgen -- -W '$(cut -d: -f3 /etc/group)'
1835+
_comp_compgen_split -- "$(cut -d: -f3 /etc/group)"
17961836
fi
17971837
}
17981838

@@ -1862,9 +1902,9 @@ _service()
18621902
else
18631903
local sysvdirs
18641904
_comp_sysvdirs
1865-
_comp_compgen -l -- -W '$(command sed -e "y/|/ /" \
1866-
-ne "s/^.*\(U\|msg_u\)sage.*{\(.*\)}.*$/\2/p" \
1867-
${sysvdirs[0]}/${prev##*/} 2>/dev/null) start stop'
1905+
_comp_compgen_split -l -- "$(command sed -e 'y/|/ /' \
1906+
-ne 's/^.*\(U\|msg_u\)sage.*{\(.*\)}.*$/\2/p' \
1907+
"${sysvdirs[0]}/${prev##*/}" 2>/dev/null) start stop"
18681908
fi
18691909
} &&
18701910
complete -F _service service
@@ -1889,7 +1929,7 @@ _modules()
18891929
{
18901930
local modpath
18911931
modpath=/lib/modules/$1
1892-
_comp_compgen -- -W "$(command ls -RL "$modpath" 2>/dev/null |
1932+
_comp_compgen_split -- "$(command ls -RL "$modpath" 2>/dev/null |
18931933
command sed -ne 's/^\(.*\)\.k\{0,1\}o\(\.[gx]z\)\{0,1\}$/\1/p' \
18941934
-e 's/^\(.*\)\.ko\.zst$/\1/p')"
18951935
}
@@ -1899,7 +1939,7 @@ _modules()
18991939
# TODO:API: rename per conventions (+ include "kernel" in the name)
19001940
_installed_modules()
19011941
{
1902-
_comp_compgen -c "$1" -- -W "$(PATH="$PATH:/sbin" lsmod |
1942+
_comp_compgen -c "$1" split -- "$(PATH="$PATH:/sbin" lsmod |
19031943
awk '{if (NR != 1) print $1}')"
19041944
}
19051945

@@ -1961,8 +2001,8 @@ _allowed_users()
19612001
if _complete_as_root; then
19622002
_comp_compgen -c "${1:-$cur}" -- -u
19632003
else
1964-
_comp_compgen -c "${1:-$cur}" -- -W \
1965-
"$(id -un 2>/dev/null || whoami 2>/dev/null)"
2004+
_comp_compgen -c "${1:-$cur}" split -- "$(id -un 2>/dev/null ||
2005+
whoami 2>/dev/null)"
19662006
fi
19672007
}
19682008

@@ -1972,17 +2012,16 @@ _allowed_groups()
19722012
if _complete_as_root; then
19732013
_comp_compgen -c "$1" -- -g
19742014
else
1975-
_comp_compgen -c "$1" -- -W \
1976-
"$(id -Gn 2>/dev/null || groups 2>/dev/null)"
2015+
_comp_compgen -c "$1" split -- "$(id -Gn 2>/dev/null ||
2016+
groups 2>/dev/null)"
19772017
fi
19782018
}
19792019

19802020
# @since 2.12
19812021
_comp_selinux_users()
19822022
{
1983-
_comp_compgen -a -- -W '$(
1984-
semanage user -nl 2>/dev/null | awk "{ print \$1 }"
1985-
)'
2023+
_comp_compgen -a split -- "$(semanage user -nl 2>/dev/null |
2024+
awk '{ print $1 }')"
19862025
}
19872026

19882027
# This function completes on valid shells
@@ -2107,15 +2146,16 @@ _count_args()
21072146
# TODO:API: rename per conventions
21082147
_pci_ids()
21092148
{
2110-
_comp_compgen -a -- -W "$(PATH="$PATH:/sbin" lspci -n | awk '{print $3}')"
2149+
_comp_compgen -a split -- "$(PATH="$PATH:/sbin" lspci -n |
2150+
awk '{print $3}')"
21112151
}
21122152

21132153
# This function completes on USB IDs
21142154
#
21152155
# TODO:API: rename per conventions
21162156
_usb_ids()
21172157
{
2118-
_comp_compgen -a -- -W "$(PATH="$PATH:/sbin" lsusb | awk '{print $6}')"
2158+
_comp_compgen -a split -- "$(PATH="$PATH:/sbin" lsusb | awk '{print $6}')"
21192159
}
21202160

21212161
# CD device names
@@ -2136,7 +2176,7 @@ _dvd_devices()
21362176
# TODO:API: rename per conventions
21372177
_terms()
21382178
{
2139-
_comp_compgen -a -- -W "$({
2179+
_comp_compgen -a split -- "$({
21402180
command sed -ne 's/^\([^[:space:]#|]\{2,\}\)|.*/\1/p' /etc/termcap
21412181
{
21422182
toe -a || toe
@@ -2694,7 +2734,7 @@ _comp_longopt()
26942734
[[ $was_split ]] && return
26952735

26962736
if [[ $cur == -* ]]; then
2697-
_comp_compgen -- -W "$(LC_ALL=C $1 --help 2>&1 |
2737+
_comp_compgen_split -- "$(LC_ALL=C $1 --help 2>&1 |
26982738
while read -r line; do
26992739
[[ $line =~ --[A-Za-z0-9]+([-_][A-Za-z0-9]+)*=? ]] &&
27002740
printf '%s\n' "${BASH_REMATCH[0]}"

completions/2to3

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ _comp_cmd_2to3()
1010
return
1111
;;
1212
-f | --fix | -x | --nofix)
13-
COMPREPLY=($(compgen -W \
14-
"$("$1" --list-fixes 2>/dev/null | command sed -e 1d)" -- "$cur"))
13+
_comp_compgen_split -- "$(
14+
"$1" --list-fixes 2>/dev/null | command sed -e 1d
15+
)"
1516
return
1617
;;
1718
-j | --processes)

completions/7z

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,10 @@ _comp_cmd_7z()
101101
_comp_compgen -a filedir '@(7z?(.001)|arj|bz2|cab|cb7|chm|cpio|deb|dmg|flv|gem|img|iso|lz[ah]|lzma?(86)|msi|pmd|[rx]ar|rpm|sw[fm]|?(g)tar|taz|?(t)[bglx]z|tb?(z)2|vhd|wim|Z)'
102102
else
103103
if [[ ${words[1]} == d ]]; then
104-
local IFS=$'\n'
105-
COMPREPLY=($(compgen -W "$("$1" l "${words[2]}" \
106-
-slt 2>/dev/null | command sed -n '/^Path =/s/^Path = \(.*\)$/\1/p' \
107-
2>/dev/null | tail -n+2)" -- "$cur"))
104+
_comp_compgen_split -l -- "$(
105+
"$1" l "${words[2]}" -slt 2>/dev/null | command sed -n \
106+
'/^Path =/s/^Path = \(.*\)$/\1/p' 2>/dev/null | tail -n+2
107+
)"
108108
compopt -o filenames
109109
else
110110
_comp_compgen_filedir

completions/_look

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ _comp_cmd_look()
99
_comp_initialize -- "$@" || return
1010

1111
if ((cword == 1)); then
12-
COMPREPLY=($(compgen -W '$(look "$cur" 2>/dev/null)' -- "$cur"))
12+
_comp_compgen_split -- "$(look "$cur" 2>/dev/null)"
1313
fi
1414
} &&
1515
complete -F _comp_cmd_look -o default look

completions/_mock

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ _comp_cmd_mock()
2727
return
2828
;;
2929
-r | --root)
30-
COMPREPLY=($(compgen -W "$(command ls "$cfgdir")" -- "$cur"))
30+
_comp_compgen_split -- "$(command ls "$cfgdir")"
3131
COMPREPLY=(${COMPREPLY[@]/%.cfg/})
3232
return
3333
;;
@@ -44,9 +44,8 @@ _comp_cmd_mock()
4444
# (e.g. ix86 chroot builds in x86_64 mock host)
4545
# This would actually depend on what the target root
4646
# can be used to build for...
47-
COMPREPLY=($(compgen -W "$(command rpm --showrc |
48-
command sed -ne 's/^\s*compatible\s\s*archs\s*:\s*\(.*\)/\1/i p')" \
49-
-- "$cur"))
47+
_comp_compgen_split -- "$(command rpm --showrc | command sed -ne \
48+
's/^\s*compatible\s\s*archs\s*:\s*\(.*\)/\1/i p')"
5049
return
5150
;;
5251
--enable-plugin | --disable-plugin)

completions/_mount

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,9 @@ _comp_cmd_mount()
3333
if [[ $cur == *:* ]]; then
3434
for sm in "$(type -P showmount)" {,/usr}/{,s}bin/showmount; do
3535
[[ -x $sm ]] || continue
36-
COMPREPLY=($(compgen -W "$("$sm" -e ${cur%%:*} |
37-
awk 'NR>1 {print $1}')" -- "${cur#*:}"))
36+
_comp_compgen -c "${cur#*:}" split -- "$(
37+
"$sm" -e ${cur%%:*} | awk 'NR>1 {print $1}'
38+
)"
3839
return
3940
done
4041
fi
@@ -43,21 +44,27 @@ _comp_cmd_mount()
4344
host=${cur#//}
4445
host=${host%%/*}
4546
if [[ $host ]]; then
46-
COMPREPLY=($(compgen -P "//$host" -W \
47-
"$(smbclient -d 0 -NL "$host" 2>/dev/null |
47+
_comp_compgen -c "${cur#//"$host"}" split -P "//$host" -- "$(
48+
smbclient -d 0 -NL "$host" 2>/dev/null |
4849
command sed -ne '/^[[:blank:]]*Sharename/,/^$/p' |
49-
command sed -ne '3,$s|^[^A-Za-z]*\([^[:blank:]]*\).*$|/\1|p')" \
50-
-- "${cur#//"$host"}"))
50+
command sed -ne '3,$s|^[^A-Za-z]*\([^[:blank:]]*\).*$|/\1|p'
51+
)"
5152
fi
5253
elif [[ -r /etc/vfstab ]]; then
5354
# Solaris
54-
COMPREPLY=($(compgen -W "$(awk '! /^[ \t]*#/ {if ($3 ~ /\//) print $3}' /etc/vfstab)" -- "$cur"))
55+
_comp_compgen_split -- "$(
56+
awk '! /^[ \t]*#/ {if ($3 ~ /\//) print $3}' /etc/vfstab
57+
)"
5558
elif [[ ! -e /etc/fstab ]]; then
5659
# probably Cygwin
57-
COMPREPLY=($(compgen -W "$("$1" | awk '! /^[ \t]*#/ {if ($3 ~ /\//) print $3}')" -- "$cur"))
60+
_comp_compgen_split -- "$(
61+
"$1" | awk '! /^[ \t]*#/ {if ($3 ~ /\//) print $3}'
62+
)"
5863
else
5964
# probably BSD
60-
COMPREPLY=($(compgen -W "$(awk '! /^[ \t]*#/ {if ($2 ~ /\//) print $2}' /etc/fstab)" -- "$cur"))
65+
_comp_compgen_split -- "$(
66+
awk '! /^[ \t]*#/ {if ($2 ~ /\//) print $2}' /etc/fstab
67+
)"
6168
fi
6269
} &&
6370
complete -F _comp_cmd_mount -o default -o dirnames mount

completions/_mount.linux

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,9 @@ _comp_cmd_mount()
223223
if [[ $cur == *:* ]]; then
224224
for sm in "$(type -P showmount)" {,/usr}/{,s}bin/showmount; do
225225
[[ -x $sm ]] || continue
226-
COMPREPLY=($(compgen -W "$("$sm" -e ${cur%%:*} |
227-
awk 'NR>1 {print $1}')" -- "${cur#*:}"))
226+
_comp_compgen -c "${cur#*:}" split -- "$(
227+
"$sm" -e ${cur%%:*} | awk 'NR>1 {print $1}'
228+
)"
228229
return
229230
done
230231
fi
@@ -233,11 +234,11 @@ _comp_cmd_mount()
233234
host=${cur#//}
234235
host=${host%%/*}
235236
if [[ $host ]]; then
236-
COMPREPLY=($(compgen -P "//$host" -W \
237-
"$(smbclient -d 0 -NL "$host" 2>/dev/null |
237+
_comp_compgen -c "${cur#//"$host"}" split -P "//$host" -- "$(
238+
smbclient -d 0 -NL "$host" 2>/dev/null |
238239
command sed -ne '/^[[:blank:]]*Sharename/,/^$/p' |
239-
command sed -ne '3,$s|^[^A-Za-z]*\([^[:blank:]]*\).*$|/\1|p')" \
240-
-- "${cur#//"$host"}"))
240+
command sed -ne '3,$s|^[^A-Za-z]*\([^[:blank:]]*\).*$|/\1|p'
241+
)"
241242
fi
242243
fi
243244

0 commit comments

Comments
 (0)