#!/usr/bin/env zsh # Usage: _call_sshagent [ -l | -r ] # -l: try to use an existing ssh-agent and change SSH_AUTH_SOCK # accordingly. This is useful for some non-login shells (no # possible clean-up by the .zlogout). # -r: remove the socket associated with the current process and # kill ssh-agent if there are no sockets any longer. # # Note: You should execute _call_sshagent from your .zlogin and have # the following code (or similar) in your .zlogout so that after you # exit the last login shell, the authentication agent is killed. # # if [[ -n $SSH_AUTH_SOCK ]] then # if [[ `whence -w _call_sshagent` == '_call_sshagent: function' ]] then # _call_sshagent -r # elif [[ -n $SSH_AGENT_PID ]] then # eval `ssh-agent -k` # fi # fi # # Also, if you use the "screen" utility and do SSH connections from # it, the shells started by screen should be login shells (thanks to # a line "shell -zsh" in your .screenrc) to make sure that ssh-agent # will still be running after you exit all the other shells. emulate -LR zsh local link=/tmp/ssh-agent-$USER local i=0 until (ln -s /dev/null $link.lock 2> /dev/null) do [[ $i -eq 0 ]] && echo "$0: waiting for lock" >&2 if [[ $((++i)) -eq 4 ]] then echo "$0: can't lock $link" >&2 return fi sleep 2 done local dir=`readlink $link` if [[ $1 == -r ]] then if [[ -O $link && -d $dir && -O $dir && $SSH_AUTH_SOCK == $link/* ]] then local others rm -f $SSH_AUTH_SOCK unset SSH_AUTH_SOCK others=($dir/agent.*(N=)) if [[ -z $others ]] then local pid=$(<$dir/ssh-agent.pid) rm -f $link $dir/ssh-agent.pid kill -TERM $pid kill_sshmasters fi else # Inconsistent data, try to kill ssh-agent in the standard way eval `ssh-agent -k` fi elif [[ $1 == -l ]] then if [[ -O $link && -d $dir && -O $dir ]] then local old old=($link/agent.*(N=[1])) if [[ -S $old ]] then SSH_AUTH_SOCK=$old ssh-add -l >& /dev/null if [[ $? -ne 2 ]] then export SSH_AUTH_SOCK=$old unset SSH_AGENT_PID fi else echo "$0: $old isn't a socket" >&2 fi fi else if [[ -O $link && -d $dir && -O $dir ]] then local old old=($link/agent.*(N=[1])) if [[ -S $old ]] then SSH_AUTH_SOCK=$old ssh-add -l >& /dev/null if [[ $? -eq 2 ]] then # The agent could not be contacted, assume that it has died rm -f $dir/agent.*(N) $dir/ssh-agent.pid && rmdir $dir rm -f $link rm -f $link.lock $0 return fi local new=$link/agent.$$ if [[ $new == $old ]] || ln -f $old $new; then export SSH_AUTH_SOCK=$new unset SSH_AGENT_PID else echo "$0: can't link $new -> $old" >&2 fi else echo "$0: $old isn't a socket" >&2 fi elif eval `ssh-agent`; then if ln -fs $SSH_AUTH_SOCK:h $link; then local old=$SSH_AUTH_SOCK echo $SSH_AGENT_PID > $link/ssh-agent.pid rm -f $link.lock $0 && rm -f $old return else echo "$0: can't symlink $dir -> $SSH_AUTH_SOCK:h" >&2 fi else echo "$0: can't call ssh-agent" >&2 fi fi rm -f $link.lock # $Id: _call_sshagent 14529 2006-10-22 10:13:13Z lefevre $