1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
|
commit 71ac42b98c0eba39819fb8478d6443032c6ef6f1
Author: Ville Skyttä <ville.skytta@iki.fi>
Date: Mon Mar 19 18:58:09 2018 +0200
_known_hosts_real: Reimplement known hosts file parsing in pure bash
diff --git a/bash_completion b/bash_completion
index ca84b01d..98d277bd 100644
--- a/bash_completion
+++ b/bash_completion
@@ -1482,9 +1482,9 @@ _included_ssh_config_files()
# Return: Completions, starting with CWORD, are added to COMPREPLY[]
_known_hosts_real()
{
- local configfile flag prefix
- local cur curd awkcur user suffix aliases i host ipv4 ipv6
- local -a kh khd config
+ local configfile flag prefix OIFS=$IFS
+ local cur user suffix aliases i host ipv4 ipv6
+ local -a kh tmpkh khd config
# TODO remove trailing %foo from entries
@@ -1523,8 +1523,7 @@ _known_hosts_real()
# Known hosts files from configs
if [[ ${#config[@]} -gt 0 ]]; then
- local OIFS=$IFS IFS=$'\n' j
- local -a tmpkh
+ local IFS=$'\n' j
# expand paths (if present) to global and user known hosts files
# TODO(?): try to make known hosts files with more than one consecutive
# spaces in their name work (watch out for ~ expansion
@@ -1561,35 +1560,31 @@ _known_hosts_real()
# If we have known_hosts files to use
if [[ ${#kh[@]} -gt 0 || ${#khd[@]} -gt 0 ]]; then
- # Escape slashes and dots in paths for awk
- awkcur=${cur//\//\\\/}
- awkcur=${awkcur//\./\\\.}
- curd=$awkcur
-
- if [[ "$awkcur" == [0-9]*[.:]* ]]; then
- # Digits followed by a dot or a colon - just search for that
- awkcur="^$awkcur[.:]*"
- elif [[ "$awkcur" == [0-9]* ]]; then
- # Digits followed by no dot or colon - search for digits followed
- # by a dot or a colon
- awkcur="^$awkcur.*[.:]"
- elif [[ -z $awkcur ]]; then
- # A blank - search for a dot, a colon, or an alpha character
- awkcur="[a-z.:]"
- else
- awkcur="^$awkcur"
- fi
-
if [[ ${#kh[@]} -gt 0 ]]; then
- # FS needs to look for a comma separated list
- COMPREPLY+=( $( awk 'BEGIN {FS=","}
- /^\s*[^|\#]/ {
- sub("^@[^ ]+ +", ""); \
- sub(" .*$", ""); \
- for (i=1; i<=NF; ++i) { \
- sub("^\\[", "", $i); sub("\\](:[0-9]+)?$", "", $i); \
- if ($i !~ /[*?]/ && $i ~ /'"$awkcur"'/) {print $i} \
- }}' "${kh[@]}" 2>/dev/null ) )
+ # https://man.openbsd.org/sshd.8#SSH_KNOWN_HOSTS_FILE_FORMAT
+ for i in "${kh[@]}"; do
+ while read -ra tmpkh; do
+ set -- "${tmpkh[@]}"
+ # Skip entries starting with | (hashed) and # (comment)
+ [[ $1 == [\|\#]* ]] && continue
+ # Ignore leading @foo (markers)
+ [[ $1 == @* ]] && shift
+ # Split entry on commas
+ local IFS=,
+ for host in $1; do
+ # Skip hosts containing wildcards
+ [[ $host == *[*?]* ]] && continue
+ # Remove leading [
+ host="${host#[}"
+ # Remove trailing ] + optional :port
+ host="${host%]?(:+([0-9]))}"
+ # Add host to candidates
+ COMPREPLY+=( $host )
+ done
+ IFS=$OIFS
+ done < "$i"
+ done
+ COMPREPLY=( $( compgen -W '${COMPREPLY[@]}' -- "$cur" ) )
fi
if [[ ${#khd[@]} -gt 0 ]]; then
# Needs to look for files called
@@ -1597,7 +1592,7 @@ _known_hosts_real()
# dont fork any processes, because in a cluster environment,
# there can be hundreds of hostkeys
for i in "${khd[@]}" ; do
- if [[ "$i" == *key_22_$curd*.pub && -r "$i" ]]; then
+ if [[ "$i" == *key_22_$cur*.pub && -r "$i" ]]; then
host=${i/#*key_22_/}
host=${host/%.pub/}
COMPREPLY+=( $host )
|