# This function performs host completion based on ssh's known_hosts files, # defaulting to standard host completion if they don't exist. # _known_hosts() { local cur ocur user suffix aliases global_kh user_kh hosts local -a kh config COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} ocur=$cur [ "$1" = -a ] || [ "$2" = -a ] && aliases='yes' [ "$1" = -c ] || [ "$2" = -c ] && suffix=':' [[ $cur == address@hidden ]] && address@hidden@ && address@hidden kh=() # ssh config files [ -r /etc/ssh/ssh_config ] && config[0]=/etc/ssh/ssh_config [ -r ~/.ssh/config ] && config[1]=~/.ssh/config if [ address@hidden -gt 0 ]; then # expand path (if present) to global known hosts file global_kh=$( eval echo $( sed -ne 's/^[Gg][Ll][Oo][Bb][Aa][Ll][Kk][Nn][Oo][Ww][Nn][Hh][Oo][Ss][Tt][Ss][Ff][Ii][Ll][Ee]['$'\t '']*\(.*\)$/\1/p' address@hidden ) ) # expand path (if present) to user known hosts file user_kh=$( eval echo $( sed -ne 's/^[Uu][Ss][Ee][Rr][Kk][Nn][Oo][Ww][Nn][Hh][Oo][Ss][Tt][Ss][Ff][Ii][Ll][Ee]['$'\t '']*\(.*\)$/\1/p' address@hidden ) ) fi # choose which global known hosts file to use if [ -r "$global_kh" ]; then kh=( "$global_kh" ) else [ -r /etc/known_hosts ] && kh[0]=/etc/known_hosts [ -r /etc/known_hosts2 ] && kh[1]=/etc/known_hosts2 fi # choose which user known hosts file to use if [ -r "$user_kh" ]; then kh=( address@hidden "$user_kh" ) else [ -r ~/.ssh/known_hosts ] && kh=( address@hidden ~/.ssh/known_hosts ) [ -r ~/.ssh/known_hosts2 ] && kh=( address@hidden ~/.ssh/known_hosts2 ) fi # If we have known_hosts files to use if [ address@hidden -gt 0 ]; then # Escape slashes and dots in paths for awk cur=${cur//\//\\\/} cur=${cur//\./\\\.} if [[ "$cur" == [0-9]*.* ]]; then # Digits followed by a dot - just search for that cur="^$cur.*" elif [[ "$cur" == [0-9]* ]]; then # Digits followed by no dot - search for digits followed # by a dot cur="^$cur.*\." elif [ -z "$cur" ]; then # A blank - search for a dot or an alpha character cur="[a-z.]" else cur="^$cur" fi # FS needs to look for a comma separated list COMPREPLY=( $( awk 'BEGIN {FS=","} {for (i=1; i<=2; ++i) { \ gsub(" .*$", "", $i); \ if ($i ~ /'$cur'/) {print $i} \ }}' address@hidden ) ) # append any available aliases from config files if [ address@hidden -gt 0 ] && [ -n "$aliases" ]; then hosts=$( compgen -W "$( echo $( sed -ne "s/^[Hh][Oo][Ss][Tt]["$'\t '"]*\([^*?]*\)$/\1/p" address@hidden ) )" -- $ocur ) COMPREPLY=( address@hidden $hosts ) fi # apply suffix for (( i=0; i < address@hidden; i++ )); do COMPREPLY[i]=$user${COMPREPLY[i]}$suffix done else # Just do normal hostname completion COMPREPLY=( $( compgen -A hostname -S "$suffix" -- $cur ) ) fi return 0 } complete -F _known_hosts traceroute ping fping telnet host nslookup rsh \ rlogin ftp # ssh(1) completion # _ssh() { local cur prev local -a config COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} case "$prev" in -*c) COMPREPLY=( $( compgen -W 'blowfish 3des 3des-cbc blowfish-cbc \ arcfour cast128-cbc' -- $cur ) ) ;; -*l) COMPREPLY=( $( compgen -u -- $cur ) ) ;; *) _known_hosts -a [ $COMP_CWORD -eq 1 ] || \ COMPREPLY=( address@hidden $( compgen -c -- $cur ) ) esac return 0 } shopt -u hostcomplete && complete -F _ssh ssh slogin sftp