#autoload # Returns 0 on success export GPG_AGENT_PID= export GPG_AGENT_SOCK= echo "Recalculating gpg-agent info ..." local pids pids=( `pgrep -u $USER gpg-agent` ) if (( $#pids > 1 )); then echo "$#pids pids found ($pids); aborting." echo "Please ensure only one agent is running." return 1 fi GPG_AGENT_PID=$pids[0] if [[ "$GPG_AGENT_PID" != *[0-9]* ]]; then # If interactive, prompt whether to start a new one. # # UPDATE: don't prompt; I always answer yes. # if false && [[ -t 1 ]]; then if [[ -t 1 ]]; then echo -n "gpg-agent process not found; start a new one [y/N] ? " if read -q; then eval `gpg-agent --daemon` || return 1 write_gpg_agent_cache return 0 else echo "Unable to determine gpg-agent info; aborting." return 1 fi else eval `gpg-agent --daemon` || return 1 write_gpg_agent_cache return 0 fi fi echo "Found a single owned gpg-agent, pid $GPG_AGENT_PID" _sockets=( /tmp/gpg-*/*(=UN) ) if (( $#_sockets == 0 )); then echo "No sockets found; aborting." return 1 fi local -a _dead_sockets _matched_sockets _orphan_sockets guessed_parent_pid socket echo "$#_sockets socket(s) found: $_sockets[*]" if ! agentbin="`which gpg-agent`"; then echo "Error: couldn't find gpg-agent! Aborting." return 1 else : echo "Found agent $agentbin" fi agent_parent_pid=$( awk '{print $4}' /proc/$GPG_AGENT_PID/stat ) if [[ "$agent_parent_pid" == 1 ]]; then guessed_agent_parent_pid=$(( GPG_AGENT_PID - 1 )) echo "Agent with pid $GPG_AGENT_PID has been adopted by init; guessing parent pid $agent_parent_pid" else echo "Agent with pid $GPG_AGENT_PID has parent pid $agent_parent_pid" fi # Now we look for a socket corresponding to the gpg-agent we found running. for socket in "${_sockets[@]}"; do echo "Examining $socket ..." _lsof="`lsof $socket`" if [[ -n "$_lsof" ]]; then if [[ "$_lsof" == *gpg-agent* ]]; then _socket_status=matched # The following code indents "$_lsof", i.e. does the same as: # echo "$_lsof" | sed -e 's/^/ /' # by splitting at \n into an array (f), substituting start # of each element (#s) for ' ' and rejoining with \n (F). echo "${(F@)${(f)_lsof}//(#s)/ }" else echo "BUG? weird lsof output:\n$_lsof" >&2 return 1 fi else # gpg-agent is secure, so without useful info from lsof or fuser, # we have to do it the hard way :-( socket_parent_pid="${socket##*agent.}" _socket_status= if [[ "$agent_parent_pid" == "$socket_parent_pid" ]]; then # We just matched the only running gpg-agent's pid with its socket, # since the parent pids match. (OK, so the same parent could # have started two agents with two sockets having the same # prefix, and then one of them died leaving a socket, and the # other is still running without a socket, but that's very unlikely!) _socket_status=matched echo " \$GPG_AGENT_PID's parent is $agent_parent_pid, matches socket filename $socket" elif [[ "$guessed_agent_parent_pid" == "$socket_parent_pid" ]]; then _socket_status=matched echo " ppid from socket $socket matches guessed agent parent pid $guessed_agent_parent_pid" else _socket_status=unknown echo " \$GPG_AGENT_PID's parent is $agent_parent_pid, doesn't match socket filename $socket" fi fi case "$_socket_status" in unknown) echo " $socket of unknown origin" _unknown_sockets=( "${_unknown_sockets[@]}" "$socket" ) ;; matched) echo " $socket matched agent pid $GPG_AGENT_PID" _matched_sockets=( "${_matched_sockets[@]}" "$socket" ) ;; dead) echo " $socket appears dead" _dead_sockets=( "${_dead_sockets[@]}" "$socket" ) ;; *) echo BUG >&2 ; return 1 ;; esac done if (( $#_dead_sockets > 0 )); then echo "Could remove dead sockets:\n rm $_dead_sockets" #rm "$_dead_sockets[@]" fi if (( $#_matched_sockets != 1 )); then if (( $#_unknown_sockets == 1 && $#_dead_sockets == 0 )); then echo "Only one unknowned socket $_unknown_sockets[0] and none dead; assuming it's matched." : ${GPG_AGENT_SOCK:=$_unknown_sockets[0]} else echo "BUG? Didn't find a unique matched socket" >&2 return 1 fi else : ${GPG_AGENT_SOCK:=$_matched_sockets[0]} fi export GPG_AGENT_INFO="${GPG_AGENT_SOCK}:${GPG_AGENT_PID}:1" write_gpg_agent_cache return 0