commit 29eaef3e6b7c71bf57aa93df34250bbcf1b6e37e
parent b729952bf6f969fdf4c38afd0562b24245dd43b5
Author: Jan Pobrislo <ccx@webprojekty.cz>
Date: Wed, 29 May 2019 20:00:13 +0200
split out containerized X11 sessions on tty[234]
Diffstat:
3 files changed, 143 insertions(+), 4 deletions(-)
diff --git a/bin/zshaskpass_lock b/bin/zshaskpass_lock
@@ -0,0 +1,131 @@
+#!/bin/zsh
+if [[ $+ZSHASKPASS_PROMPTFD -eq 0 || -z $ZSHASKPASS_PROMPTFD ]]; then
+ echo >&2 'ZSHASKPASS_PROMPTFD not set'
+ exit 2
+fi
+
+if [[ $+ZSHASKPASS_PASSFD -eq 0 || -z $ZSHASKPASS_PASSFD ]]; then
+ echo >&2 'ZSHASKPASS_PASSFD not set'
+ exit 2
+fi
+
+setopt no_unset warn_create_global
+zmodload zsh/zselect
+
+typeset -g COPROC_OUT fd newfd prompt_end keep_running
+typeset -a coproc_args
+typeset -gA fds
+
+#if [[ $ZSHASKPASS_PROMPTFD -gt $ZSHASKPASS_PASSFD ]]; then
+# COPROC_OUT=$[ $ZSHASKPASS_PROMPTFD + 1 ]
+#else
+# COPROC_OUT=$[ $ZSHASKPASS_PASSFD + 1 ]
+#fi
+
+prompt_end=%f
+coproc_args=(
+ fdmove -c 2 1
+ unexport ZSHASKPASS_PROMPTFD
+ unexport ZSHASKPASS_PASSFD
+ unexport SSH_ASKPASS
+ "$@"
+)
+if (($+LOGINCAP_READFD)); then
+ coproc_args=( fdclose $LOGINCAP_READFD unexport LOGINCAP_FD "$coproc_args[@]" )
+fi
+if (($+LOGINCAP_WRITEFD)); then
+ coproc_args=( fdclose $LOGINCAP_WRITEFD unexport LOGINCAP_FD "$coproc_args[@]" )
+fi
+
+logincap() {
+ if ! (( $+LOGINCAP_READFD & $+LOGINCAP_WRITEFD )); then
+ echo "logincap FDs not defined"
+ return
+ fi
+ printf >&$LOGINCAP_WRITEFD '%s\n' "$*"
+ local line result_color
+ read -u $LOGINCAP_READFD line
+ result_color=%F{cyan}
+ printf '%s\n' ${(%)result_color}$line${(%)prompt_end}
+}
+
+cmd() {
+ case $1 in
+ ('') ;;
+ ('c '*)
+ logincap ${1#c };;
+ (off|poweroff)
+ logincap o;;
+ (reboot)
+ logincap b;;
+ (root)
+ logincap "terminal rxvt-unicode importas -i PTY_FD PTY_FD s6-envdir /run/user/ccx/X$[ ${TTY#/dev/tty} + 4 ]/env urxvt -pty-fd \$PTY_FD" ;;
+ (exit)
+ true >/run/user/ccx/X$[ ${TTY#/dev/tty} + 4 ]/fifo
+ keep_running=0;;
+ (shell)
+ zsh -i; printf "shell exited with %d\n" $?;;
+ (*) printf '%s: unknown command\n' ${(qqq)REPLY};;
+ esac
+}
+
+# typeset -f -t cmd
+
+coproc "$coproc_args[@]"
+trap 'kill %1' EXIT
+trap 'kill %1; ssh-add -D; exit' INT HUP TERM QUIT
+trap 'printf "\nALRM!\n"' ALRM
+(($+TMOUT)) && printf 'TMOUT=%s\n' ${(qqq)TMOUT}
+#coproc "$@"
+exec {COPROC_OUT}<& p
+select_fds=( $ZSHASKPASS_PROMPTFD $COPROC_OUT )
+
+keep_running=1
+while (($keep_running)) && zselect -A fds -r 0 $select_fds; do
+ if ! (($#jobstates)); then
+ echo >&2 "Session exited."
+ exit 0
+ fi
+ for fd in ${(k)fds}; do
+ if [[ $fds[$fd] != r ]]; then
+ echo >&2 "Error on filedescriptor $fd"
+ exit 1
+ fi
+ if [[ $fd == $ZSHASKPASS_PROMPTFD ]]; then
+ # zshaskpass
+ if IFS= read -u $fd; then
+ if [[ $REPLY == *': ' ]]; then
+ printf '%s' "$REPLY${(%)prompt_end}"
+ read -s
+ RET=$?
+ echo
+ if (($RET)); then
+ REPLY=$'\0'
+ fi
+ cat <<<$REPLY >& $ZSHASKPASS_PASSFD
+ else
+ printf '%s\n' "$REPLY${(%)prompt_end}"
+ fi
+ else
+ echo >&2 "Read from askpass failed"
+ fi
+ elif [[ $fd == $COPROC_OUT ]]; then
+ # coprocess
+ if IFS= read -u $COPROC_OUT -t; then
+ if [[ $REPLY == "XFIFO: "* ]]; then
+ printf '< opening: %s\n' ${REPLY#*: }
+ exec {newfd}>>${REPLY#*: }
+ else
+ printf '> %s\n' $REPLY
+ fi
+ fi
+ else
+ # stdin
+ if IFS= read -u $fd -s; then
+ cmd "$REPLY"
+ else
+ echo >&2 "Read from filedescriptor $fd failed"
+ fi
+ fi
+ done
+done
diff --git a/bin/zshaskpass_mux b/bin/zshaskpass_mux
@@ -12,7 +12,7 @@ fi
setopt no_unset warn_create_global
zmodload zsh/zselect
-typeset -g COPROC_OUT fd newfd prompt_end
+typeset -g COPROC_OUT fd newfd prompt_end keep_running
typeset -a coproc_args
typeset -gA fds
@@ -61,7 +61,8 @@ cmd() {
(root)
logincap "terminal rxvt-unicode importas -i PTY_FD PTY_FD s6-envdir /run/user/ccx/X$[ ${TTY#/dev/tty} + 4 ]/env urxvt -pty-fd \$PTY_FD" ;;
(exit)
- printf '\n' >/run/user/ccx/X$[ ${TTY#/dev/tty} + 4 ]/fifo;;
+ true >/run/user/ccx/X$[ ${TTY#/dev/tty} + 4 ]/fifo
+ keep_running=0;;
(shell)
zsh -i; printf "shell exited with %d\n" $?;;
(*) printf '%s: unknown command\n' ${(qqq)REPLY};;
@@ -79,7 +80,8 @@ trap 'printf "\nALRM!\n"' ALRM
exec {COPROC_OUT}<& p
select_fds=( $ZSHASKPASS_PROMPTFD $COPROC_OUT )
-while zselect -A fds -r 0 $select_fds; do
+keep_running=1
+while (($keep_running)) && zselect -A fds -r 0 $select_fds; do
if ! (($#jobstates)); then
echo >&2 "Session exited."
exit 0
diff --git a/home/loginexec b/home/loginexec
@@ -1,8 +1,14 @@
#!/bin/zsh -l
set -x
+mkdir -p /run/user/$USER/ssh-master && chmod 700 /run/user/$USER/ssh-master
if [[ $TTY = /dev/tty[1-4] ]]; then
+ [[ -S /run/user/$USER/ssh_agent.${${TTY#/dev/}//\//.} ]] && rm /run/user/$USER/ssh_agent.${${TTY#/dev/}//\//.}
X=$[ ${TTY#/dev/tty} + 4 ]
- exec startsshagent.passfd /run/user/$USER/ssh_agent.${${TTY#/dev/}//\//.} =zshaskpass_mux xinit -- :$X tty$X -quiet
+ if [[ $X == 5 ]]; then
+ exec startsshagent.passfd /run/user/$USER/ssh_agent.${${TTY#/dev/}//\//.} =zshaskpass_mux xinit -- :$X tty$X -quiet -nolisten local -nolisten tcp -retro
+ else
+ exec startsshagent.passfd /run/user/$USER/ssh_agent.${${TTY#/dev/}//\//.} =zshaskpass_lock
+ fi
else
exec ssh-agent -a /run/user/$USER/ssh_agent.${${TTY#/dev/}//\//.} /bin/execlineb -c \
'if { redirfd -r 0 /dev/null env DISPLAY=pipe SSH_ASKPASS=/home/ccx/bin/cat_pass_fd ssh-add } zsh -l'