+### cleanup
+# XXX: only call after relevant vars have been set up, defined early so that
+# below code can utilize it after they do so
+function _sev_zcleanup {
+ ## gpg forwarding
+ if [[ -d $_sev_gpg_forward_dir && ( -z $1 || $1 == 'gpg-forward' ) ]] {
+ # clean up forward dirs if its session is dead or we ask for it
+ find $_sev_gpg_forward_dir -mindepth 1 -maxdepth 1 -type d |
+ while {read -r x} {
+ # NOTE: the only way we can get here is if we have not been
+ # forwarded before, if the user asks for it, or during
+ # logout. if our own pid already has a dir, it is most likely
+ # stale, the user wants it removed, or something is very
+ # broken—in all 3 of these cases the best choice is remove it.
+ p=$(basename $x)
+ if {[[ -v _sev_gpg_forward_clean || $$ == $p ]] ||
+ ! kill -0 $p 2>/dev/null} {
+ find $x -mindepth 1 -maxdepth 1 | while {read -r y} {
+ # XXX: real dirs will stop unlink, consider it a feature
+ unlink $y
+ }
+ # don't force in case something important is still there
+ rmdir $x
+ }
+ }
+ # reset GNUPGHOME if we removed our own dir
+ if [[ $GNUPGHOME =~ '/.ssh_forward/\d+/*$' && ! -e $GNUPGHOME ]] {
+ x=$GNUPGHOME
+ [[ -o GLOB_ASSIGN ]]; y=$?
+ setopt GLOB_ASSIGN
+ GNUPGHOME=$GNUPGHOME/../..(:a)
+ (( y != 0 )) && unsetopt GLOB_ASSIGN
+ }
+ }
+
+ ## tmp
+ # NOTE: _sev_tmp is not unset so session dirs will not be recreated
+ # NOTE: XDG dirs that use our tmp are not unset here, they are in zlogout
+ if [[ -d $_sev_tmp && ( -z $1 || $1 == 'tmp' ) ]] {
+ # clean up tmp dirs if its session is dead or we ask for it
+ find $_sev_tmp -mindepth 1 -maxdepth 1 -name '.session.*' -type d |
+ while {read -r x} {
+ # NOTE: same rationale as above
+ p=${$(basename $x)#.session.}
+ if {[[ -v _sev_tmp_clean || $$ == $p ]] ||
+ ! kill -0 $p 2>/dev/null} {
+ rm -rf $x
+ }
+ }
+ }
+
+ unset x p y
+}
+