Skip to content

Commit 523dd5d

Browse files
authored
Merge pull request #976 from Rogach/pr/optimize-ssh-includes
fix(ssh): optimize traversing ssh config includes
2 parents 77074a9 + 1f57833 commit 523dd5d

File tree

1 file changed

+39
-25
lines changed

1 file changed

+39
-25
lines changed

bash_completion

Lines changed: 39 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2272,33 +2272,47 @@ _included_ssh_config_files()
22722272
local configfile i files f
22732273
configfile=$1
22742274

2275+
# From man ssh_config:
2276+
# "Files without absolute paths are assumed to be in ~/.ssh if included
2277+
# in a user configuration file or /etc/ssh if included from the system
2278+
# configuration file."
2279+
# This behavior is not affected by the the including file location -
2280+
# if the system configuration file is included from the user's config,
2281+
# relative includes are still resolved in the user's ssh config directory.
2282+
local relative_include_base
2283+
if [[ $configfile == /etc/ssh* ]]; then
2284+
relative_include_base="/etc/ssh"
2285+
else
2286+
relative_include_base="$HOME/.ssh"
2287+
fi
2288+
2289+
local depth=1
22752290
local -a included
2276-
_comp_split included "$(command sed -ne 's/^[[:blank:]]*[Ii][Nn][Cc][Ll][Uu][Dd][Ee][[:blank:]]\(.*\)$/\1/p' "${configfile}")" || return
2277-
2278-
for i in "${included[@]}"; do
2279-
# Check the origin of $configfile to complete relative included paths on included
2280-
# files according to ssh_config(5):
2281-
# "[...] Files without absolute paths are assumed to be in ~/.ssh if included in a user
2282-
# configuration file or /etc/ssh if included from the system configuration file.[...]"
2283-
if ! [[ $i =~ ^\~.*|^\/.* ]]; then
2284-
if [[ $configfile =~ ^\/etc\/ssh.* ]]; then
2285-
i="/etc/ssh/$i"
2286-
else
2287-
i="$HOME/.ssh/$i"
2291+
local -a include_files
2292+
included=("$configfile")
2293+
2294+
# Max recursion depth per openssh's READCONF_MAX_DEPTH:
2295+
# https://github.com/openssh/openssh-portable/blob/5ec5504f1d328d5bfa64280cd617c3efec4f78f3/readconf.c#L2240
2296+
local max_depth=16
2297+
while ((${#included[@]} > 0 && depth++ < max_depth)); do
2298+
_comp_split include_files "$(command sed -ne 's/^[[:blank:]]*[Ii][Nn][Cc][Ll][Uu][Dd][Ee][[:blank:]]\(.*\)$/\1/p' "${included[@]}")" || return
2299+
included=()
2300+
for i in "${include_files[@]}"; do
2301+
if [[ $i != [~/]* ]]; then
2302+
i="${relative_include_base}/${i}"
22882303
fi
2289-
fi
2290-
__expand_tilde_by_ref i
2291-
# In case the expanded variable contains multiple paths
2292-
_comp_expand_glob files '$i'
2293-
if ((${#files[@]})); then
2294-
for f in "${files[@]}"; do
2295-
if [[ -r $f && ! -d $f ]]; then
2296-
config+=("$f")
2297-
# The Included file is processed to look for Included files in itself
2298-
_included_ssh_config_files "$f"
2299-
fi
2300-
done
2301-
fi
2304+
__expand_tilde_by_ref i
2305+
# In case the expanded variable contains multiple paths
2306+
_comp_expand_glob files '$i'
2307+
if ((${#files[@]})); then
2308+
for f in "${files[@]}"; do
2309+
if [[ -r $f && ! -d $f ]]; then
2310+
config+=("$f")
2311+
included+=("$f")
2312+
fi
2313+
done
2314+
fi
2315+
done
23022316
done
23032317
} # _included_ssh_config_files()
23042318

0 commit comments

Comments
 (0)