Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
*~
.*.sw?
ssh-identc
*.pyc
.tox
ssh_ident.egg-info/
build
dist
93 changes: 93 additions & 0 deletions scripts/ssh-ident-completion.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
_SSH_COMPLETION_FILE=${SSH_IDENT_SSH_COMPLETION:-/usr/share/bash-completion/completions/ssh}
source $_SSH_COMPLETION_FILE

# Save function named in $1 as name in $2
save_function() {
local ORIG_FUNC=$(declare -f $1)
local NEWNAME_FUNC="$2${ORIG_FUNC#$1}"
eval "$NEWNAME_FUNC"
}

save_function _ssh_configfile __ssh_configfile_orig

_ssh_ident_configfile_override()
{
if [ ! -z ${__ssh_ident_config+x} ]; then
configfile=$__ssh_ident_config
fi

set -- "${words[@]}"
while [[ $# -gt 0 ]]; do
if [[ $1 == -F* ]]; then
if [[ ${#1} -gt 2 ]]; then
configfile="$(dequote "${1:2}")"
else
shift
[[ $1 ]] && configfile="$(dequote "$1")"
fi
break
fi
shift
done
}

_ssh_ident_ssh()
{
# Set the ssh config path if available
if [[ "${SSH_IDENT_CONFIG}" != "" ]]; then
__ssh_ident_config=${SSH_IDENT_CONFIG}
fi

# Override function _ssh_configfile in _SSH_COMPLETION_FILE
save_function _ssh_ident_configfile_override _ssh_configfile
_ssh $@
# Restore _ssh_configfile function
save_function __ssh_configfile_orig _ssh_configfile

unset __ssh_ident_config

return 0
} && shopt -u hostcomplete && complete -F _ssh_ident_ssh ssh slogin autossh


_ssh_ident_scp()
{
# Set the ssh config path if available
if [[ "${SSH_IDENT_CONFIG}" != "" ]]; then
__ssh_ident_config=${SSH_IDENT_CONFIG}
fi

# Override function _ssh_configfile in _SSH_COMPLETION_FILE
save_function _ssh_ident_configfile_override _ssh_configfile
_scp $@
# Restore _ssh_configfile function
save_function __ssh_configfile_orig _ssh_configfile

unset __ssh_ident_config

return 0
} && complete -F _ssh_ident_scp scp


# scp completion with _ssh_ident_scp doesn't work properly due to the extra call
# 'set -- "${words[@]}"' in function _scp() in
# /usr/share/bash-completion/completions/ssh

#_ssh_ident_scp()
#{
# # Set the ssh config path if available
# if [[ "${SSH_IDENT_CONFIG}" != "" ]]; then
# conf="-F$SSH_IDENT_CONFIG"
# conf_len=${#conf}
# set -- "${@:1:1}" "$conf" "${@:2}"
# COMP_WORDS=("$@")
# COMP_CWORD=$((COMP_CWORD+1))
# COMP_LINE=$(printf " %s" "$@")
# COMP_LINE=${COMP_LINE:1}
# COMP_POINT=$((COMP_POINT+$conf_len+1))
# fi
#
# _scp $@
#
# return 0
#} && complete -F _ssh_ident_scp scp
180 changes: 180 additions & 0 deletions scripts/ssh_ident.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
# Bash functions for ssh-ident

#Flag values returned from ssh_ident_cli
__ssh_ident_cli_flag_set_shell_env=1
__ssh_ident_cli_flag_unset_shell_env=2
__ssh_ident_cli_flag_ssh_identity=4
__ssh_ident_cli_flag_ssh_config=8
__ssh_ident_cli_flag_enable_prompt=16
__ssh_ident_cli_flag_disable_prompt=32
__ssh_ident_cli_flag_define_bash_functions=64
__ssh_ident_cli_flag_undefine_bash_functions=128
__ssh_ident_cli_flag_print_output=256
__ssh_ident_cli_flag_verbose=512
__ssh_ident_cli_flag_disable_shell_agent=1024
__ssh_ident_cli_flag_enable_shell_agent=2048


define_ssh_ident_bash_funcs () {
# SSH_IDENT_EXEC_SCRIPT must be global to be available when the functions are executed
SSH_IDENT_EXEC_SCRIPT=`which ssh_ident_exec`
export GIT_SSH=$SSH_IDENT_EXEC_SCRIPT
rsync() { BINARY_SSH=ssh command rsync -e $SSH_IDENT_EXEC_SCRIPT "$@"; }
sftp() { BINARY_SSH=ssh command sftp -S $SSH_IDENT_EXEC_SCRIPT "$@"; }
scp() { BINARY_SSH=ssh command scp -S $SSH_IDENT_EXEC_SCRIPT "$@"; }
ssh() { BINARY_SSH=ssh command $SSH_IDENT_EXEC_SCRIPT "$@"; }
}

undefine_ssh_ident_bash_funcs () {
unset -f rsync
unset -f sftp
unset -f scp
unset -f ssh
unset GIT_SSH
}

__ssh_ident_split_output() {
local cli_action_str
read -d '' -r cli_action_str cli_stdout <<< "$1"
# Convert to int
cli_action=$((cli_action_str + 0))
# Remove trailing newline
cli_stdout="${cli_stdout%"${cli_stdout##*[![:space:]]}"}"
}

# Called using PROMPT_COMMAND variable
__ssh_ident_update_ssh_config_var() {
local cli_action
local cli_output
local cli_stdout
cli_output=`ssh_ident_cli --action-code --config $__SSH_IDENT_PROMPT_ID`
__ssh_ident_split_output "$cli_output"

if [[ $(($cli_action & $__ssh_ident_cli_flag_ssh_config)) -gt 0 ]] ; then
SSH_IDENT_CONFIG=$cli_stdout
fi
}

# Called using PROMPT_COMMAND variable
__ssh_ident_update_prompt_id() {
# If SSH_IDENT is set for the shell
if [[ -n "$SSH_IDENT" ]]; then
if [[ "$SSH_IDENT" != "$__SSH_IDENT_PROMPT_ID" ]]; then
__SSH_IDENT_PROMPT_ID=$SSH_IDENT
__ssh_ident_update_ssh_config_var
unset __SSH_IDENT_PWD
fi
return
fi

# Only update __SSH_IDENT_PROMPT_ID if PWD has changed
if [[ "$__SSH_IDENT_PWD" != "$PWD" ]]; then
__SSH_IDENT_PWD=$PWD
local cli_result
cli_result=`ssh_ident_cli -iq`
__SSH_IDENT_PROMPT_ID=$cli_result
__ssh_ident_update_ssh_config_var
fi
}

# Activate the ssh-ident shell prompt
ssh_ident_activate() {
ssh_ident -a $1
}

# Activate the ssh-ident shell prompt
ssh_ident_dectivate() {
ssh_ident -d
}

# Main entry point to ssh-ident. Calls ssh_ident_cli and acts according to the response
ssh_ident() {
local cli_output
local cli_action
local cli_stdout
local cli_verbose=0
cli_output=`ssh_ident_cli --action-code $@`
__ssh_ident_split_output "$cli_output"

if [[ $(($cli_action & $__ssh_ident_cli_flag_verbose)) -gt 0 ]] ; then
cli_verbose=1
echo "Shell action flags: $cli_action"
fi

# Set/Unset shell identity env variable
if [[ $(($cli_action & $__ssh_ident_cli_flag_set_shell_env)) -gt 0 ]] ; then
export SSH_IDENT=$cli_stdout
elif [[ $(($cli_action & $__ssh_ident_cli_flag_unset_shell_env)) -gt 0 ]] ; then
unset SSH_IDENT
fi

if [[ $(($cli_action & $__ssh_ident_cli_flag_ssh_identity)) -gt 0 ]] ; then
if [[ $cli_verbose -eq 1 ]] ; then
echo "Setting shell identity: $SSH_IDENT"
fi
fi

# Enable/Disable ssh-ident shell prompt
if [[ $(($cli_action & $__ssh_ident_cli_flag_enable_prompt)) -gt 0 ]] ; then
# If prompt already contains __SSH_IDENT_PROMPT_ID, ignore
if [[ ! "$PS1" == *__SSH_IDENT_PROMPT_ID* ]]; then
__SSH_IDENT_OLD_PROMPT=$PS1
PS1="(ssh:\${__SSH_IDENT_PROMPT_ID}) $PS1"
SSH_IDENT_PROMPT_COMMAND=__ssh_ident_update_prompt_id
# Add to PROMPT_COMMAND only if not already added
if [[ ! "$PROMPT_COMMAND" == *SSH_IDENT_PROMPT_COMMAND* ]]; then
PROMPT_COMMAND=${PROMPT_COMMAND:+$PROMPT_COMMAND; }'$SSH_IDENT_PROMPT_COMMAND'
fi
fi
elif [[ $(($cli_action & $__ssh_ident_cli_flag_disable_prompt)) -gt 0 ]] ; then
unset SSH_IDENT_PROMPT_COMMAND
unset __SSH_IDENT_PROMPT_ID
unset __SSH_IDENT_PWD
unset -f rsync
if [ ! -z "${__SSH_IDENT_OLD_PROMPT}" ] ; then
PS1=$__SSH_IDENT_OLD_PROMPT
unset __SSH_IDENT_OLD_PROMPT
fi
fi

# Define/Undefine bash function overrides for ssh/scp/sftp/rsync
if [[ $(($cli_action & $__ssh_ident_cli_flag_define_bash_functions)) -gt 0 ]] ; then
define_ssh_ident_bash_funcs
elif [[ $(($cli_action & $__ssh_ident_cli_flag_undefine_bash_functions)) -gt 0 ]] ; then
undefine_ssh_ident_bash_funcs
fi

if [[ $(($cli_action & $__ssh_ident_cli_flag_disable_shell_agent)) -gt 0 ]] ; then
echo "ssh-agent disabled for shell"
export SSH_IDENT_SHELL_AGENT_DISABLED=1
fi

if [[ $(($cli_action & $__ssh_ident_cli_flag_enable_shell_agent)) -gt 0 ]] ; then
echo "ssh-agent enabled for shell"
unset SSH_IDENT_SHELL_AGENT_DISABLED
fi

if [[ $(($cli_action & $__ssh_ident_cli_flag_print_output)) -gt 0 ]] ; then
echo "$cli_stdout"
fi
}

# Source the ssh-ident bash completion
source_bash_completion() {
local ssh_ident_bash_completion_script=ssh-ident-completion.bash
local script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
local bash_completion_script_path=`which $ssh_ident_bash_completion_script`

# If not found, check the dir containing this script
if [[ -z "$bash_completion_script_path" ]]; then
bash_completion_script_path=$script_dir/$ssh_ident_bash_completion_script
fi

if [[ -f $bash_completion_script_path ]]; then
source $bash_completion_script_path
else
echo "Bash completion script $ssh_ident_bash_completion_script not found!"
fi
}

source_bash_completion
8 changes: 8 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[isort]
known_standard_library = future_builtins
known_third_party = jinja2,requests,nose
#known_first_party = system
order_by_type = true
line_length = 100
not_skip = __init__.py
skip = .tox,vendor,build
68 changes: 68 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function

import os

from setuptools import find_packages, setup
from setuptools.command.develop import develop

# Importing __version__ from ssh_ident fails for some reason, so import directly
from ssh_ident.ssh_ident import VERSION


class SshIdentDevelop(develop):

user_options = develop.user_options + [
("symlinks", "s", "Create script symlinks"),
]
boolean_options = develop.boolean_options + ['symlinks']

def initialize_options(self):
self.symlinks = False
develop.initialize_options(self)

def run(self):
develop.run(self)

if not self.symlinks:
return

print("Creating symlinks for scripts")
for script in self.distribution.scripts or []:
fname = os.path.basename(script)
script_abs_path = os.path.abspath(script)
dest_file = os.path.join(self.script_dir, fname)
if os.path.isfile(dest_file):
os.remove(dest_file)
print("%s -> %s" % (dest_file, script_abs_path))
os.symlink(script_abs_path, dest_file)


setup(name='ssh-ident',
version=VERSION,
description="Start and use ssh-agent and load identities as necessary.",
long_description="Start and use ssh-agent and load identities as necessary.",
url='https://github.com/ccontavalli/ssh-ident',
license="BSD",
packages=find_packages(),
namespace_packages=['ssh_ident'],
entry_points={'console_scripts':
['ssh_ident_exec = ssh_ident.ssh_ident:main',
'ssh_ident_cli = ssh_ident.ssh_ident_cli:main'
]
},
scripts=[
'scripts/ssh-ident-completion.bash',
'scripts/ssh_ident.sh',
],
cmdclass={'develop': SshIdentDevelop},
zip_safe=False,
classifiers=[
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Development Status :: 4 - Beta',
'License :: OSI Approved :: BSD License',
'Natural Language :: English',
'Operating System :: POSIX'
])
7 changes: 7 additions & 0 deletions ssh_ident/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# this is a namespace package
import pkg_resources
from ssh_ident import VERSION

pkg_resources.declare_namespace(__name__)

__version__ = VERSION
Loading