@@ -260,6 +260,55 @@ _upvars()
260260 done
261261}
262262
263+ # Get the list of filenames that match with the specified glob pattern.
264+ # This function does the globbing in a controlled environment, avoiding
265+ # interference from user's shell options/settings or environment variables.
266+ # @param $1 array_name Array name
267+ # The array name should not start with the double underscores "__". The
268+ # array name should not be "GLOBIGNORE".
269+ # @param $2 pattern Pattern string to be evaluated.
270+ # This pattern string will be evaluated using "eval", so brace expansions,
271+ # parameter expansions, command substitutions, and other expansions will be
272+ # processed. The user-provided strings should not be directly specified to
273+ # this argument.
274+ _comp_expand_glob ()
275+ {
276+ if (( $# != 2 )) ; then
277+ printf ' bash-completion: %s: unexpected number of arguments\n' " $FUNCNAME " >&2
278+ printf ' usage: %s ARRAY_NAME PATTERN\n' " $FUNCNAME " >&2
279+ return 2
280+ elif [[ $1 == @ (GLOBIGNORE| __* | * [^_a-zA-Z0-9]* | [0-9]* | ' ' ) ]]; then
281+ printf ' bash-completion: %s: invalid array name "%s"\n' " $FUNCNAME " " $1 " >&2
282+ return 2
283+ fi
284+
285+ # Save and adjust the settings.
286+ local __original_opts=$SHELLOPTS :$BASHOPTS
287+ set +o noglob
288+ shopt -s nullglob
289+ shopt -u failglob dotglob
290+
291+ # Also the user's GLOBIGNORE may affect the result of pathname expansions.
292+ local GLOBIGNORE=
293+
294+ eval -- " $1 =()" # a fallback in case that the next line fails.
295+ eval -- " $1 =($2 )"
296+
297+ # Restore the settings. Note: Changing GLOBIGNORE affects the state of
298+ # "shopt -q dotglob", so we need to explicitly restore the original state
299+ # of "shopt -q dotglob".
300+ _comp_unlocal GLOBIGNORE
301+ if [[ :$__original_opts : == * :dotglob:* ]]; then
302+ shopt -s dotglob
303+ else
304+ shopt -u dotglob
305+ fi
306+ [[ :$__original_opts : == * :nullglob:* ]] || shopt -u nullglob
307+ [[ :$__original_opts : == * :failglob:* ]] && shopt -s failglob
308+ [[ :$__original_opts : == * :noglob:* ]] && set -o noglob
309+ return 0
310+ }
311+
263312# Reassemble command line words, excluding specified characters from the
264313# list of word completion separators (COMP_WORDBREAKS).
265314# @param $1 chars Characters out of $COMP_WORDBREAKS which should
@@ -1099,15 +1148,20 @@ _mac_addresses()
10991148#
11001149_configured_interfaces ()
11011150{
1151+ local -a files
11021152 if [[ -f /etc/debian_version ]]; then
11031153 # Debian system
1154+ _comp_expand_glob files ' /etc/network/interfaces /etc/network/interfaces.d/*'
1155+ (( ${# files[@]} )) || return 0
11041156 COMPREPLY=($( compgen -W " $( command sed -ne ' s|^iface \([^ ]\{1,\}\).*$|\1|p' \
1105- /etc/network/interfaces /etc/network/interfaces.d/ * 2> /dev/null) " \
1157+ " ${files[@]} " 2> /dev/null) " \
11061158 -- " $cur " ) )
11071159 elif [[ -f /etc/SuSE-release ]]; then
11081160 # SuSE system
1161+ _comp_expand_glob files ' /etc/sysconfig/network/ifcfg-*'
1162+ (( ${# files[@]} )) || return 0
11091163 COMPREPLY=($( compgen -W " $( printf ' %s\n' \
1110- /etc/sysconfig/network/ifcfg- * |
1164+ " ${files[@]} " |
11111165 command sed -ne ' s|.*ifcfg-\([^*].*\)$|\1|p' ) " -- " $cur " ) )
11121166 elif [[ -f /etc/pld-release ]]; then
11131167 # PLD Linux
@@ -1116,8 +1170,10 @@ _configured_interfaces()
11161170 command sed -ne ' s|.*ifcfg-\([^*].*\)$|\1|p' ) " -- " $cur " ) )
11171171 else
11181172 # Assume Red Hat
1173+ _comp_expand_glob files ' /etc/sysconfig/network-scripts/ifcfg-*'
1174+ (( ${# files[@]} )) || return 0
11191175 COMPREPLY=($( compgen -W " $( printf ' %s\n' \
1120- /etc/sysconfig/network-scripts/ifcfg- * |
1176+ " ${files[@]} " |
11211177 command sed -ne ' s|.*ifcfg-\([^*].*\)$|\1|p' ) " -- " $cur " ) )
11221178 fi
11231179}
@@ -1373,12 +1429,12 @@ _xinetd_services()
13731429{
13741430 local xinetddir=${_comp__test_xinetd_dir:-/ etc/ xinetd.d}
13751431 if [[ -d $xinetddir ]]; then
1376- local IFS=$' \t\n ' reset=$( shopt -p nullglob)
1377- shopt -s nullglob
1378- local -a svcs=($xinetddir /! ($_comp_backup_glob ))
1379- $reset
1380- (( ! ${# svcs[@]} )) ||
1432+ local -a svcs
1433+ _comp_expand_glob svcs ' $xinetddir/!($_comp_backup_glob)'
1434+ if (( ${# svcs[@]} )) ; then
1435+ local IFS=$' \n '
13811436 COMPREPLY+=($( compgen -W ' "${svcs[@]#$xinetddir/}"' -- " ${cur-} " ) )
1437+ fi
13821438 fi
13831439}
13841440
@@ -1389,12 +1445,9 @@ _services()
13891445 local sysvdirs
13901446 _sysvdirs
13911447
1392- local IFS=$' \t\n ' reset=$( shopt -p nullglob)
1393- shopt -s nullglob
1394- COMPREPLY=(
1395- $( printf ' %s\n' ${sysvdirs[0]} /! ($_comp_backup_glob | functions| README)) )
1396- $reset
1448+ _comp_expand_glob COMPREPLY ' ${sysvdirs[0]}/!($_comp_backup_glob|functions|README)'
13971449
1450+ local IFS=$' \n '
13981451 COMPREPLY+=($( {
13991452 systemctl list-units --full --all ||
14001453 systemctl list-unit-files
@@ -1425,7 +1478,7 @@ _service()
14251478 _services
14261479 [[ -e /etc/mandrake-release ]] && _xinetd_services
14271480 else
1428- local sysvdirs
1481+ local IFS= $' \n ' sysvdirs
14291482 _sysvdirs
14301483 COMPREPLY=($( compgen -W ' `command sed -e "y/|/ /" \
14311484 -ne "s/^.*\(U\|msg_u\)sage.*{\(.*\)}.*$/\2/p" \
@@ -1677,7 +1730,9 @@ _terms()
16771730 {
16781731 toe -a || toe
16791732 } | awk ' { print $1 }'
1680- find /{etc,lib,usr/lib,usr/share}/terminfo/? -type f -maxdepth 1 |
1733+ _comp_expand_glob dirs ' /{etc,lib,usr/lib,usr/share}/terminfo/?'
1734+ (( ${# dirs[@]} )) &&
1735+ find " ${dirs[@]} " -type f -maxdepth 1 |
16811736 awk -F/ ' { print $NF }'
16821737 } 2> /dev/null) " -- " $cur " ) )
16831738}
@@ -1737,7 +1792,7 @@ _included_ssh_config_files()
17371792{
17381793 (( $# < 1 )) &&
17391794 echo " bash_completion: $FUNCNAME : missing mandatory argument CONFIG" >&2
1740- local configfile i f
1795+ local configfile i files f
17411796 configfile=$1
17421797
17431798 local IFS=$' \t\n ' reset=$( shopt -po noglob)
@@ -1760,15 +1815,16 @@ _included_ssh_config_files()
17601815 fi
17611816 __expand_tilde_by_ref i
17621817 # In case the expanded variable contains multiple paths
1763- set +o noglob
1764- for f in $i ; do
1765- if [[ -r $f ]]; then
1766- config+=(" $f " )
1767- # The Included file is processed to look for Included files in itself
1768- _included_ssh_config_files $f
1769- fi
1770- done
1771- $reset
1818+ _comp_expand_glob files ' $i'
1819+ if (( ${# files[@]} )) ; then
1820+ for f in " ${files[@]} " ; do
1821+ if [[ -r $f ]]; then
1822+ config+=(" $f " )
1823+ # The Included file is processed to look for Included files in itself
1824+ _included_ssh_config_files $f
1825+ fi
1826+ done
1827+ fi
17721828 done
17731829} # _included_ssh_config_files()
17741830
0 commit comments