PageRenderTime 5ms CodeModel.GetById 1ms app.highlight 1ms RepoModel.GetById 1ms app.codeStats 0ms

/bash_completion_lib/include/_known_hosts

http://github.com/brinkman83/bashrc
#! | 138 lines | 124 code | 14 blank | 0 comment | 0 complexity | d93ae1561e444fef83b5ca1b99e4c123 MD5 | raw file
  1# This function performs host completion based on ssh's known_hosts files,
  2# defaulting to standard host completion if they don't exist.
  3# Arguments:  -a             Use aliases
  4#             -c             Use `:' suffix
  5#             -F configfile  Use `configfile' for configuration settings
  6_known_hosts()
  7{
  8	local configfile cur curd ocur user suffix aliases global_kh user_kh hosts i host
  9	local -a kh khd config
 10
 11	COMPREPLY=()
 12	cur=`_get_cword`
 13	ocur=$cur
 14
 15	local OPTIND=1
 16	while getopts "acF:" flag "$@"; do 
 17	    case $flag in
 18		a) aliases='yes' ;;
 19		c) suffix=':' ;;
 20		F) configfile="$OPTARG" ;;
 21	    esac
 22	done
 23
 24	[[ $cur == *@* ]] && user=${cur%@*}@ && cur=${cur#*@}
 25	kh=()
 26
 27	# ssh config files
 28	if [ -n "$configfile" ]; then
 29	    [ -r "$configfile" ] && 
 30		config=( "${config[@]}" "$configfile" )
 31	else
 32	    [ -r /etc/ssh/ssh_config ] &&
 33		config=( "${config[@]}" "/etc/ssh/ssh_config" )
 34	    [ -r "${HOME}/.ssh/config" ] &&
 35		config=( "${config[@]}" "${HOME}/.ssh/config" )
 36	    [ -r "${HOME}/.ssh2/config" ] &&
 37		config=( "${config[@]}" "${HOME}/.ssh2/config" );
 38	fi
 39
 40	if [ ${#config[@]} -gt 0 ]; then
 41	    # expand path (if present) to global known hosts file
 42	    global_kh=$( eval echo "$( sed -ne 's/^[ \t]*[Gg][Ll][Oo][Bb][Aa][Ll][Kk][Nn][Oo][Ww][Nn][Hh][Oo][Ss][Tt][Ss][Ff][Ii][Ll][Ee]['"$'\t '"']*\(.*\)$/\1/p' "${config[@]}" )" )
 43	    # expand path (if present) to user known hosts file
 44	    user_kh=$( eval echo "$( sed -ne 's/^[ \t]*[Uu][Ss][Ee][Rr][Kk][Nn][Oo][Ww][Nn][Hh][Oo][Ss][Tt][Ss][Ff][Ii][Ll][Ee]['"$'\t '"']*\(.*\)$/\1/p' "${config[@]}" )" )
 45	fi
 46
 47	# Global known_hosts files
 48	[ -r "$global_kh" ] &&
 49		kh=( "${kh[@]}" "$global_kh" )
 50	if [ -z "$configfile" ]; then
 51	    [ -r /etc/ssh/ssh_known_hosts ] &&
 52		kh=( "${kh[@]}" /etc/ssh/ssh_known_hosts )
 53	    [ -r /etc/ssh/ssh_known_hosts2 ] &&
 54		kh=( "${kh[@]}" /etc/ssh/ssh_known_hosts2 )
 55	    [ -r /etc/known_hosts ] &&
 56		kh=( "${kh[@]}" /etc/known_hosts )
 57	    [ -r /etc/known_hosts2 ] &&
 58		kh=( "${kh[@]}" /etc/known_hosts2 )
 59	    [ -d /etc/ssh2/knownhosts ] &&
 60		khd=( "${khd[@]}" /etc/ssh2/knownhosts/*pub )
 61	fi
 62
 63	# User known_hosts files
 64	[ -r "$user_kh" ] &&
 65		kh=( "${kh[@]}" "$user_kh" )
 66	if [ -z "$configfile" ]; then
 67	    [ -r ~/.ssh/known_hosts ] &&
 68		kh=( "${kh[@]}" ~/.ssh/known_hosts )
 69	    [ -r ~/.ssh/known_hosts2 ] &&
 70		kh=( "${kh[@]}" ~/.ssh/known_hosts2 )
 71	    [ -d ~/.ssh2/hostkeys ] &&
 72		khd=( "${khd[@]}" ~/.ssh2/hostkeys/*pub )
 73	fi
 74
 75	# If we have known_hosts files to use
 76	if [ ${#kh[@]} -gt 0 -o ${#khd[@]} -gt 0 -o -n "$configfile" ]; then
 77	    # Escape slashes and dots in paths for awk
 78	    cur=${cur//\//\\\/}
 79	    cur=${cur//\./\\\.}
 80	    curd=$cur
 81
 82	    if [[ "$cur" == [0-9]*.* ]]; then
 83		# Digits followed by a dot - just search for that
 84		cur="^$cur.*"
 85	    elif [[ "$cur" == [0-9]* ]]; then
 86		# Digits followed by no dot - search for digits followed
 87		# by a dot
 88		cur="^$cur.*\."
 89	    elif [ -z "$cur" ]; then
 90		# A blank - search for a dot or an alpha character
 91		cur="[a-z.]"
 92	    else
 93		cur="^$cur"
 94	    fi
 95
 96	    if [ ${#kh[@]} -gt 0 ]; then
 97
 98		# FS needs to look for a comma separated list
 99		COMPREPLY=( $( awk 'BEGIN {FS=","}
100				/^[^|]/ {for (i=1; i<=2; ++i) { \
101				       gsub(" .*$", "", $i); \
102				       if ($i ~ /'$cur'/) {print $i} \
103				}}' "${kh[@]}" 2>/dev/null ) )
104	    fi
105	    if [ ${#khd[@]} -gt 0 ]; then
106		# Needs to look for files called
107		# .../.ssh2/key_22_<hostname>.pub
108		# dont fork any processes, because in a cluster environment,
109		# there can be hundreds of hostkeys
110		for i in "${khd[@]}" ; do
111		    if [[ "$i" == *key_22_$curd*.pub ]] && [ -r "$i" ] ; then
112			host=${i/#*key_22_/}
113			host=${host/%.pub/}
114			COMPREPLY=( "${COMPREPLY[@]}" $host )
115		    fi
116		done
117	    fi
118	    # append any available aliases from config files
119	    if [ ${#config[@]} -gt 0 ] && [ -n "$aliases" ]; then
120	    local host_aliases=$( sed -ne 's/^[ \t]*[Hh][Oo][Ss][Tt]\([Nn][Aa][Mm][Ee]\)\?['"$'\t '"']\+\([^#*?]*\)\(#.*\)\?$/\2/p' "${config[@]}" )
121	    hosts=$( compgen -W "$host_aliases" -- $ocur )
122		COMPREPLY=( "${COMPREPLY[@]}" $hosts )
123	    fi
124	    
125	    # Now add results of normal hostname completion
126	    COMPREPLY=( "${COMPREPLY[@]}" $( compgen -A hostname -- $ocur ) )
127
128	    # apply suffix
129	    for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do
130		COMPREPLY[i]=$user${COMPREPLY[i]}$suffix
131	    done
132	elif [ -z "$configfile" ]; then
133	    # Just do normal hostname completion
134	    COMPREPLY=( $( compgen -A hostname -S "$suffix" -- $cur ) )
135	fi
136
137	return 0
138} # _known_hosts()