mrrl-logincaps

MRRL version of logincaps
git clone https://ccx.te2000.cz/git/mrrl-logincaps
Log | Files | Refs

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:
Abin/zshaskpass_lock | 131+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mbin/zshaskpass_mux | 8+++++---
Mhome/loginexec | 8+++++++-
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'