X-Git-Url: https://git.sev.monster/~sev/dotfiles.git/blobdiff_plain/1ef46e010e2dc017f60cddfabf6e669a0469ef3f..c9ab0b12d4183935113856f0c9c5575c8e149208:/base/.zshenv diff --git a/base/.zshenv b/base/.zshenv index 11cded7..45ea339 100644 --- a/base/.zshenv +++ b/base/.zshenv @@ -1,227 +1,32 @@ -# WARN: not used in this repo, but gpgconf --list-dirs does not read -# gpg-agent.conf to get socket path, see dev.gnupg.org/T3108 - -### unset unwanted options that could be set in /etc/zshenv -unsetopt SH_WORD_SPLIT KSH_ARRAYS - -### check if su -if [[ -v _sev_olduser && $_sev_olduser != $USERNAME ]] _sev_reset_shell= -export _sev_olduser=$USERNAME - -### exports for all new shells -if [[ -v _sev_reset_shell || $SHLVL == 1 ]] { - ## lang - export CHARSET=UTF-8 - export LANG=en_US.UTF-8 - export LC_CTYPE=$LANG - - ## path - # path and fpath should already be linked to PATH and FPATH - # we don't want duplicates so turn on unique mode if it isn't already - typeset -U path fpath - # do not run more than once per session, even if resetting shell - if [[ $SHLVL == 1 ]] { - # take a backup before any customizations - export _sev_sys_PATH=$PATH - export _sev_sys_FPATH=$FPATH - } - # /usr/{pkg,local,games} are unix/bsdisms - path=({~/,/,/usr/}sbin {~/,/,/usr/}bin /usr/pkg/{s,}bin /usr/X11R{7,6}/bin - /usr/local/{s,}bin /usr/games) - PATH=$PATH:$_sev_sys_PATH - fpath=(${ZDOTDIR:-$HOME/.zsh}/functions/{*,Completions/*}(N)) - # fpath is not exported by default - export FPATH=$FPATH:$_sev_sys_FPATH - # take another backup, explained in .zprofile - typeset -U _backup_path - _backup_path=("${path[@]}") - - ## xdg - # TODO: check for and merge existing XDG env vars - export XDG_CONFIG_HOME=~/etc - export XDG_CONFIG_DIRS=~/.config:/usr/pkg/etc/xdg:/usr/local/etc/xdg:/etc/xdg - export XDG_DATA_HOME=~/share - export XDG_DATA_DIRS=~/.local/share:/usr/pkg/share:/usr/local/share:/usr/share - export XDG_CACHE_HOME=~/tmp - export XDG_RUNTIME_DIR=~/tmp - if [[ -e $XDG_CONFIG_HOME/user-dirs.dirs ]] { - source $XDG_CONFIG_HOME/user-dirs.dirs - } - - ## create tmp link - t=${TMPDIR:-/tmp}/.home-$LOGNAME - if [[ ! -e $t ]] { - mkdir -m 700 $t 2>/dev/null - if [[ ! -d $t ]] { - [[ -o interactive ]] && - print -P "%F{red}!!! Can't create temp folder $t%f" - [[ -h $XDG_RUNTIME_DIR ]] && unlink $XDG_RUNTIME_DIR 2>/dev/null - [[ ! -e $XDG_RUNTIME_DIR ]] && mkdir $XDG_RUNTIME_DIR 2>/dev/null - } - } - # allow opaque entries to override link creation - [[ ! -e $XDG_RUNTIME_DIR ]] && ln -sf $t $XDG_RUNTIME_DIR 2>/dev/null - unset t - - ## gpg forwarding - # NOTE: while ssh automatically sets SSH_AUTH_SOCK with the ForwardSsh - # directive, GPG must be forwarded manually. to support this, we - # forward the restricted gpg-agent extra socket to the remote host - # with a RemoteForward rule in ~/.ssh/config that uses the - # _GNUPG_SOCK_* env vars. - # to avoid conflicts with other ssh sessions where the same user is - # connecting to the same host from different machines, gpg in each - # environment should utilize its own forwarded socket, rather than - # replace the sockets in GNUPGHOME which will be overridden on the - # next connection. previously, you could provide a path to the agent - # socket in GPG_AGENT_INFO, but that was deprecated in GPG v2.1. - # instead, we must clone GNUPGHOME and replace the agent sockets - # there with the forwarded one. - # HACK: without SendEnv, which is disabled by default in most sshd configs, - # there is no foolproof way to prevent race conditions or filename - # collisions, pass the forward path to the remote host environment, - # or even know if the forward path exists and is writable. we just - # have to guess this path is good on the desination host, and assume - # the newest matching socket is the correct one after connecting. in - # theory we could occlude the ssh binary on PATH with an alias or - # script that communicates with the remote host before opening a - # shell, but that would open up too many edge cases where it wouldn't - # work to make it worth the effort and extra overhead. - # do not run more than once per session, even if resetting shell - if [[ $SHLVL == 1 && -v commands[gpg] ]] { - export _GNUPG_SOCK_DEST_BASE=/tmp/.gpg-agent-forward - export _GNUPG_SOCK_DEST_EXT=$(date +%s).$RANDOM - export _GNUPG_SOCK_DEST=$_GNUPG_SOCK_DEST_BASE.$_GNUPG_SOCK_DEST_EXT - _sev_gpg_forward_dir=${GNUPGHOME:-~/.gnupg}/.ssh_forward - s=($_GNUPG_SOCK_DEST_BASE*(N=oc[1])) - # clean up forwards if its session is dead or we ask for it - if [[ -d $_sev_gpg_forward_dir ]] { - find $_sev_gpg_forward_dir -type d -mindepth 1 -maxdepth 1 | - while read -r x; do - # NOTE: the only way we can get here is if we are SHLVL 1. if - # our own pid already has a dir, it is most likely stale, - # or something is very broken—assume the former. - p=$(basename $x) - if [[ -v _sev_gpg_forward_clean || $$ == $p ]] || - ! kill -0 $p 2>/dev/null; then - find $x -mindepth 1 -maxdepth 1 | while read -r y; do - unlink $y - done - rmdir $x - fi - done - unset x p y - } - # create new forward dir - if [[ -n $s && -v SSH_CLIENT ]] { - export _sev_gpg_forwarded= - mkdir -pm700 $_sev_gpg_forward_dir - h=$_sev_gpg_forward_dir/$$ - mkdir -pm700 $h - # XXX: is it safe to link scdaemon socket? can its name be changed? - for x in S.scdaemon gpg.conf gpg-agent.conf sshcontrol \ - pubring.kbx trustdb.gpg private-keys-v1.d crls.d; do - ln -s ${GNUPGHOME:-~/.gnupg}/$x $h - done - export GNUPGHOME=$h - unset h - for x in $(gpgconf --list-dirs | grep 'agent-.*-\?socket:'); do - # dirs are prefixed and percent-encoded—strip and decode - # https://stackoverflow.com/a/64312099 - x=${${x/#agent-*socket:/}//(#b)%([[:xdigit:]](#c2))/${(#):-0x$match[1]}} - if [[ ! -v orig ]] { - mv $s $x - orig=$x - } else { - ln -s $orig $x - } - done - unset x orig - } - unset s - - # what we will forward if we start a new ssh connection - # NOTE: do this after setting up GNUPGHOME to pick up new socket path; - # if already connected over SSH, extra should be the remote one - export _GNUPG_SOCK_SRC=$(gpgconf --list-dirs agent-extra-socket) - } else { - # required for RemoteForward to not error out if the vars are unset - export _GNUPG_SOCK_SRC=/nonexistent - export _GNUPG_SOCK_DEST=/nonexistent - } - - ## gpg agent - # always try to start agent during setup - if [[ SHLVL == 1 ]] { - gpg-connect-agent /bye >/dev/null 2>&1 - [[ $? -ne 0 && -o interactive ]] && - print -P "%F{red}!!! Can't communicate with GPG agent%f" - } - # set up tty if it isn't, and we're interactive or in xorg & not forwarded - # do not run more than once per session, even if resetting shell - if [[ -v commands[gpg-connect-agent] && - ! -v _sev_gpg_forward && ! -v GPG_TTY && - ( -o interactive || -v DISPLAY ) ]] { - export GPG_TTY=$(tty) - export PINENTRY_USER_DATA=USE_TTY=$((!${+DISPLAY})) - gpg-connect-agent UPDATESTARTUPTTY /bye >/dev/null 2>&1 - } - - ## ssh agents - # NOTE: preferred order of agents to check: okcagent, gnupg, openssh - # first block takes care of okcagent and openssh, second gnupg - [[ -o interactive ]] && print -nP "%F{blue}>>>%f SSH: %F{green}" - if [[ ! -v SSH_AUTH_SOCK && ( -v commands[okc-ssh-agent] || - ( -v commands[ssh-agent] && ! -v commands[gpg] ) ) ]] { - okc=${commands[okc-ssh-agent]:+okc-} - agentfile=~/tmp/${okc}ssh-agent-exports - typeset sock= - typeset -i pid= - if [[ -f $agentfile ]] { - IFS=$'\0' read -r sock pid <$agentfile - } - if [[ -S $sock && $pid > 0 ]] && kill -0 $pid; then - [[ -o interactive ]] && echo "Reusing agent PID $pid" - export SSH_AUTH_SOCK=$sock - export SSH_AGENT_PID=$pid - else - # TODO: ensure ssh-agent path looks legit - # to avoid unsafe eval? - # NOTE: no way around doing redirection like this I think - e=${okc}ssh-agent - if [[ -o interactive ]] { - eval `$e` - } else { - eval `$e` >/dev/null 2>&1 - } - echo -n $SSH_AUTH_SOCK$'\0'$SSH_AGENT_PID >!$agentfile - fi - unset okc agentfile sock pid - } elif [[ ! -v SSH_AUTH_SOCK && -v commands[gpg] ]] { - # since gpg agent was started above, we just have to export and notify - if [[ -o interactive ]] { - if [[ -v _sev_gpg_forwarded ]] { - echo 'Remote GPG agent' - } else { - gpg-connect-agent /subst /serverpid \ - '/echo GPG agent PID ${get serverpid}' /bye - } - } - export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket) - } elif [[ -v SSH_AUTH_SOCK ]] { - [[ -o interactive ]] && echo "Preconfigured agent" - } else { - [[ -o interactive ]] && print -P "%F{red}No agent available" - } -} +[[ -v _sev_home ]] || export _sev_home=$HOME +export ZDOTDIR=${XDG_CONFIG_HOME:-~/.config}/zsh ### load site-specific -if [[ -f ~/.zshenv.local ]] { source ~/.zshenv.local } +[[ -f ${ZDOTDIR:-~}/.zshenv.local ]] && source ${ZDOTDIR:-~}/.zshenv.local -### source .zprofile -# if we used su, without --login, let's run zprofile ourselves -# XXX: system zprofile is not run -if [[ -v _sev_reset_shell || $SHLVL == 1 ]] source ~/.zprofile +### fix broken term +if [[ ! -v TERM ]] { + TERM=xterm-256color >/dev/null 2>&1 +} +if [[ -o interactive && $#terminfo -eq 0 ]] { + _oldterm=$TERM + export TERM=xterm >/dev/null 2>&1 + print -P "%F{red}!!! Can't find terminfo for $_oldterm, using $TERM%f" + unset _oldterm +} -# vim: set et sts=4 sw=4 ts=8 tw=79 : +# NOTE: see .zprofile comment for rationale on sourcing +if [[ ! -v _sev_first_display && ( -v DISPLAY || -v WAYLAND_DISPLAY ) ]] { + ### update gpgagent to use graphical pinentry + # XXX: will be sourced by every new child shell if zsh is not used to + # start the graphical session and the _sev_first_display var isn't + # exported; for example, this previously happened with sway without a + # display manager or launcher in front of it + export _sev_first_display= + _sev_refresh_gpgagent= + [[ ! -o login ]] && source ${ZDOTDIR:-~}/.zprofile +} elif [[ ! -o login && $SHLVL -eq 1 && ${+TERMUX_VERSION} -eq 0 ]] { + ### early zprofile sourcing for first shell even if not a login shell + source ${ZDOTDIR:-~}/.zprofile +}