@@ -673,6 +673,46 @@ _comp_compgen_set()
673
673
eval -- " $_var ${_append: ++} =(\"\$ @\" )"
674
674
}
675
675
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
+
676
716
# Check if the argument looks like a path.
677
717
# @param $1 thing to check
678
718
# @return True (0) if it does, False (> 0) otherwise
@@ -1183,7 +1223,7 @@ _comp_variable_assignments()
1183
1223
_terms
1184
1224
;;
1185
1225
LANG | LC_* )
1186
- _comp_compgen -- -W ' $(locale -a 2>/dev/null)'
1226
+ _comp_compgen_split -- " $( locale -a 2> /dev/null) "
1187
1227
;;
1188
1228
LANGUAGE)
1189
1229
_comp_delimited : -W ' $(locale -a 2>/dev/null)'
@@ -1524,23 +1564,23 @@ _configured_interfaces()
1524
1564
# Debian system
1525
1565
_comp_expand_glob files ' /etc/network/interfaces /etc/network/interfaces.d/*'
1526
1566
(( ${# 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) "
1529
1569
elif [[ -f /etc/SuSE-release ]]; then
1530
1570
# SuSE system
1531
1571
_comp_expand_glob files ' /etc/sysconfig/network/ifcfg-*'
1532
1572
(( ${# files[@]} )) || return 0
1533
- _comp_compgen -- -W " $( printf ' %s\n' " ${files[@]} " |
1573
+ _comp_compgen_split -- " $( printf ' %s\n' " ${files[@]} " |
1534
1574
command sed -ne ' s|.*ifcfg-\([^*].*\)$|\1|p' ) "
1535
1575
elif [[ -f /etc/pld-release ]]; then
1536
1576
# PLD Linux
1537
- _comp_compgen -- -W " $( command ls -B /etc/sysconfig/interfaces |
1577
+ _comp_compgen_split -- " $( command ls -B /etc/sysconfig/interfaces |
1538
1578
command sed -ne ' s|.*ifcfg-\([^*].*\)$|\1|p' ) "
1539
1579
else
1540
1580
# Assume Red Hat
1541
1581
_comp_expand_glob files ' /etc/sysconfig/network-scripts/ifcfg-*'
1542
1582
(( ${# files[@]} )) || return 0
1543
- _comp_compgen -- -W " $( printf ' %s\n' " ${files[@]} " |
1583
+ _comp_compgen_split -- " $( printf ' %s\n' " ${files[@]} " |
1544
1584
command sed -ne ' s|.*ifcfg-\([^*].*\)$|\1|p' ) "
1545
1585
fi
1546
1586
}
@@ -1576,7 +1616,7 @@ _ip_addresses()
1576
1616
# TODO:API: rename per conventions
1577
1617
_kernel_versions ()
1578
1618
{
1579
- _comp_compgen -- -W ' $(command ls /lib/modules)'
1619
+ _comp_compgen_split -- " $( command ls /lib/modules) "
1580
1620
}
1581
1621
1582
1622
# This function completes on all available network interfaces
@@ -1694,26 +1734,26 @@ if [[ $OSTYPE == *@(solaris|aix)* ]]; then
1694
1734
# This function completes on process IDs.
1695
1735
_pids ()
1696
1736
{
1697
- _comp_compgen -- -W ' $(command ps -efo pid | command sed 1d)'
1737
+ _comp_compgen_split -- " $( command ps -efo pid | command sed 1d) "
1698
1738
}
1699
1739
1700
1740
_pgids ()
1701
1741
{
1702
- _comp_compgen -- -W ' $(command ps -efo pgid | command sed 1d)'
1742
+ _comp_compgen_split -- " $( command ps -efo pgid | command sed 1d) "
1703
1743
}
1704
1744
_pnames ()
1705
1745
{
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) "
1708
1748
}
1709
1749
else
1710
1750
_pids ()
1711
1751
{
1712
- _comp_compgen -- -W ' $(command ps ax -o pid=)'
1752
+ _comp_compgen_split -- " $( command ps ax -o pid=) "
1713
1753
}
1714
1754
_pgids ()
1715
1755
{
1716
- _comp_compgen -- -W ' $(command ps ax -o pgid=)'
1756
+ _comp_compgen_split -- " $( command ps ax -o pgid=) "
1717
1757
}
1718
1758
# @param $1 if -s, don't try to avoid truncated command names
1719
1759
_pnames ()
@@ -1772,12 +1812,12 @@ fi
1772
1812
_uids ()
1773
1813
{
1774
1814
if type getent & > /dev/null; then
1775
- _comp_compgen -- -W ' $(getent passwd | cut -d: -f3)'
1815
+ _comp_compgen_split -- " $( getent passwd | cut -d: -f3) "
1776
1816
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" }' ) "
1778
1818
else
1779
1819
# make do with /etc/passwd
1780
- _comp_compgen -- -W ' $(cut -d: -f3 /etc/passwd)'
1820
+ _comp_compgen_split -- " $( cut -d: -f3 /etc/passwd) "
1781
1821
fi
1782
1822
}
1783
1823
@@ -1787,12 +1827,12 @@ _uids()
1787
1827
_gids ()
1788
1828
{
1789
1829
if type getent & > /dev/null; then
1790
- _comp_compgen -- -W ' $(getent group | cut -d: -f3)'
1830
+ _comp_compgen_split -- " $( getent group | cut -d: -f3) "
1791
1831
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" }' ) "
1793
1833
else
1794
1834
# make do with /etc/group
1795
- _comp_compgen -- -W ' $(cut -d: -f3 /etc/group)'
1835
+ _comp_compgen_split -- " $( cut -d: -f3 /etc/group) "
1796
1836
fi
1797
1837
}
1798
1838
@@ -1862,9 +1902,9 @@ _service()
1862
1902
else
1863
1903
local sysvdirs
1864
1904
_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"
1868
1908
fi
1869
1909
} &&
1870
1910
complete -F _service service
@@ -1889,7 +1929,7 @@ _modules()
1889
1929
{
1890
1930
local modpath
1891
1931
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 |
1893
1933
command sed -ne ' s/^\(.*\)\.k\{0,1\}o\(\.[gx]z\)\{0,1\}$/\1/p' \
1894
1934
-e ' s/^\(.*\)\.ko\.zst$/\1/p' ) "
1895
1935
}
@@ -1899,7 +1939,7 @@ _modules()
1899
1939
# TODO:API: rename per conventions (+ include "kernel" in the name)
1900
1940
_installed_modules ()
1901
1941
{
1902
- _comp_compgen -c " $1 " -- -W " $( PATH=" $PATH :/sbin" lsmod |
1942
+ _comp_compgen -c " $1 " split -- " $( PATH=" $PATH :/sbin" lsmod |
1903
1943
awk ' {if (NR != 1) print $1}' ) "
1904
1944
}
1905
1945
@@ -1961,8 +2001,8 @@ _allowed_users()
1961
2001
if _complete_as_root; then
1962
2002
_comp_compgen -c " ${1:- $cur } " -- -u
1963
2003
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) "
1966
2006
fi
1967
2007
}
1968
2008
@@ -1972,17 +2012,16 @@ _allowed_groups()
1972
2012
if _complete_as_root; then
1973
2013
_comp_compgen -c " $1 " -- -g
1974
2014
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) "
1977
2017
fi
1978
2018
}
1979
2019
1980
2020
# @since 2.12
1981
2021
_comp_selinux_users ()
1982
2022
{
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 }' ) "
1986
2025
}
1987
2026
1988
2027
# This function completes on valid shells
@@ -2107,15 +2146,16 @@ _count_args()
2107
2146
# TODO:API: rename per conventions
2108
2147
_pci_ids ()
2109
2148
{
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}' ) "
2111
2151
}
2112
2152
2113
2153
# This function completes on USB IDs
2114
2154
#
2115
2155
# TODO:API: rename per conventions
2116
2156
_usb_ids ()
2117
2157
{
2118
- _comp_compgen -a -- -W " $( PATH=" $PATH :/sbin" lsusb | awk ' {print $6}' ) "
2158
+ _comp_compgen -a split -- " $( PATH=" $PATH :/sbin" lsusb | awk ' {print $6}' ) "
2119
2159
}
2120
2160
2121
2161
# CD device names
@@ -2136,7 +2176,7 @@ _dvd_devices()
2136
2176
# TODO:API: rename per conventions
2137
2177
_terms ()
2138
2178
{
2139
- _comp_compgen -a -- -W " $( {
2179
+ _comp_compgen -a split -- " $( {
2140
2180
command sed -ne ' s/^\([^[:space:]#|]\{2,\}\)|.*/\1/p' /etc/termcap
2141
2181
{
2142
2182
toe -a || toe
@@ -2694,7 +2734,7 @@ _comp_longopt()
2694
2734
[[ $was_split ]] && return
2695
2735
2696
2736
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 |
2698
2738
while read -r line; do
2699
2739
[[ $line =~ --[A-Za-z0-9]+ ([-_][A-Za-z0-9]+)* = ? ]] &&
2700
2740
printf ' %s\n' " ${BASH_REMATCH[0]} "
0 commit comments