Computer :(

/home/rrix:blog:tags:cgit:rss

Automatically Re-set Emacs Environment

I use gpg-agent as an ssh agent as a means to use a Yubikey Neo PGP smartcard as physical login tokens. Without a pair of Yubikeys and their passphrases you can't log in to any of my assets or as me to any of my work assets. It's pretty great, but it relies on magic environment variables being propagated to the right location.

Thankfully, and crucially, gpg-agent has an option to write out a file containing these environment variables, designed to be sourced in to any Bourne shell. Using rrix/re-agent you can parse that file and push it in to your Emacs environment. I run it every minute, it's cheap and keeps things working if gpg-agent dies and respawns.

(defun rrix/re-agent ()
  "Load your gpg-agent.env file in to the environment

This is extra useful if you use gpg-agent with --enable-ssh-support"
  (let ((home (getenv "HOME"))
        (old-buffer (current-buffer)))
    (with-temp-buffer
      (insert-file-contents (concat home "/.gnupg/gpg-agent.env"))
      (goto-char (point-min))
      (setq case-replace nil)
      (replace-regexp "\\(.*\\)=\\(.*\\)" "(setenv \"\\1\" \"\\2\")")
      (eval-buffer)))
  (getenv "GPG_AGENT_INFO"))

(run-with-idle-timer 60 t 'rrix/re-agent)

I have a nice .zshrc snippet that aides in this process, as well, every time I open a ZSH prompt, it'll check if it's running. If it is running, it'll source the env file, otherwise it'll start a new one:

envfile="$HOME/.gnupg/gpg-agent.env"
if [[ -e "$envfile" ]] && kill -0 $(grep GPG_AGENT_INFO "$envfile" | cut -d: -f 2) 2>/dev/null; then
    eval "$(cat "$envfile")"
else
    eval "$(gpg-agent --daemon --enable-ssh-support --write-env-file "$envfile")"
fi
export GPG_AGENT_INFO
export SSH_AUTH_SOCK