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