fix: parse SSH config entries with tabs as well as spaces
resolve_ssh_alias() now extracts tokens with 'read -r', which
collapses tabs and spaces uniformly. Two bugs were at play:
1. The previous parser split on literal spaces
(key="${line%% *}") and used '${line#Host }' to drop the
Host directive, so configs that used tab indentation
(e.g. '\tHostName 10.60.16.35') ended up with key being the
whole line and never matching the case branches. Result:
'has no HostName in ~/.ssh/config' even when one was present.
2. The script's global IFS is $'\n\t' (no space), which made
'read' unable to split on spaces at all. Fixed by restoring
space-aware IFS locally inside the loop.
Verified against tabbed, spaced, mixed, indented-comment and
Host\tname configs; behavior with the original space-separated
configs is unchanged.
This commit is contained in:
+17
-12
@@ -130,15 +130,19 @@ resolve_ssh_alias() {
|
|||||||
[[ -f "$config" ]] \
|
[[ -f "$config" ]] \
|
||||||
|| die "Cannot resolve '$alias': $config not found and value has no '@'."
|
|| die "Cannot resolve '$alias': $config not found and value has no '@'."
|
||||||
|
|
||||||
local in_block=0 hostname="" user="" port="" identity="" line key value p
|
local in_block=0 hostname="" user="" port="" identity="" line first p
|
||||||
local -a patterns
|
local -a patterns
|
||||||
while IFS= read -r line || [[ -n "$line" ]]; do
|
# Force whitespace-aware splitting (the script's global IFS excludes spaces).
|
||||||
line="${line#"${line%%[![:space:]]*}"}"
|
local IFS=$' \t\n'
|
||||||
[[ -z "$line" || "${line:0:1}" == "#" ]] && continue
|
while read -r line || [[ -n "$line" ]]; do
|
||||||
key="${line%% *}"
|
# First whitespace-separated token (tabs and spaces collapse uniformly).
|
||||||
if [[ "$key" == "Host" ]]; then
|
read -r first _ <<< "$line"
|
||||||
|
[[ -z "$first" || "$first" == "#" ]] && continue
|
||||||
|
|
||||||
|
if [[ "$first" == "Host" ]]; then
|
||||||
if (( in_block )); then break; fi
|
if (( in_block )); then break; fi
|
||||||
read -r -a patterns <<< "${line#Host }"
|
read -r -a patterns <<< "$line"
|
||||||
|
patterns=("${patterns[@]:1}")
|
||||||
in_block=0
|
in_block=0
|
||||||
for p in "${patterns[@]}"; do
|
for p in "${patterns[@]}"; do
|
||||||
if [[ "$p" == "$alias" ]]; then
|
if [[ "$p" == "$alias" ]]; then
|
||||||
@@ -149,12 +153,13 @@ resolve_ssh_alias() {
|
|||||||
done
|
done
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if (( in_block )); then
|
if (( in_block )); then
|
||||||
case "$key" in
|
case "$first" in
|
||||||
HostName) hostname="${line#* }" ;;
|
HostName) read -r _ hostname <<< "$line" ;;
|
||||||
User) user="${line#* }" ;;
|
User) read -r _ user <<< "$line" ;;
|
||||||
Port) port="${line#* }" ;;
|
Port) read -r _ port <<< "$line" ;;
|
||||||
IdentityFile) identity="${line#* }" ;;
|
IdentityFile) read -r _ identity <<< "$line" ;;
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
done < "$config"
|
done < "$config"
|
||||||
|
|||||||
Reference in New Issue
Block a user