commit b14f9dec7919b95c5a1b8192ee6189a6e5b7cd15
parent d3def3fd568cf6b41fa32396191fdf443a03405b
Author: Jan Pobrislo <ccx@webprojekty.cz>
Date: Tue, 15 Dec 2020 01:19:14 +0100
Plumber interface over FIFO for the X11 container; enable boot/poweroff caps; add chvt capability
Diffstat:
2 files changed, 69 insertions(+), 12 deletions(-)
diff --git a/bin/zshaskpass_lock b/bin/zshaskpass_lock
@@ -12,7 +12,7 @@ fi
setopt no_unset warn_create_global
zmodload zsh/zselect
-typeset -g COPROC_OUT fd newfd prompt_end keep_running X die_color
+typeset -g COPROC_OUT fd newfd prompt_end keep_running X die_color plumb_r plumb_w
typeset -a coproc_args
typeset -gA fds
@@ -43,6 +43,8 @@ coproc_args=(
)
if [[ -n $X ]]; then
coproc_args+=( tail -F /run/containers/xsession.$X.ccx/run/uncaught-logs/current )
+ typeset -g plumber_fifo
+ plumber_fifo=/run/containers/xsession.$X.ccx/run/plumber_fifo
else
coproc_args+=( tail -F /run/user/ccx.logs/current )
fi
@@ -69,10 +71,28 @@ lock() {
ssh-add -D || die "Error removing identities"
s6-svc -o -wu -T 3000 /run/containers/xsession.$X.ccx/run/service/screen-locker/ || "Failed to bring up screen locker"
s6-svstat /run/containers/xsession.$X.ccx/run/service/screen-locker/
- s6-svlisten1 -d /run/containers/xsession.$X.ccx/run/service/screen-locker/ zsh -c "read -sk 1 $'?Session locked, press enter to unlock.\n' || exit 98; until ssh-add -c; do sleep 2; read -sk 1 $'?\nUnlock failed, press enter to try again.\n' || exit 98; done; if ssh-add -l >/dev/null; then printf '%s\n' 'Success, stopping screen locker'; s6-svc -d '/run/containers/xsession.$X.ccx/run/service/screen-locker/'; fi"
+ s6-svlisten1 -d /run/containers/xsession.$X.ccx/run/service/screen-locker/ zsh -c "read -sk 1 $'?Session locked, press enter to unlock.\n' || exit 98; until ssh-add -c; do sleep 2; read -sk 1 $'?\nUnlock failed, press enter to try again.\n' || exit 98; done; if ssh-add -l >/dev/null; then printf '%s\n' 'Success, stopping screen locker'; s6-svc -d '/run/containers/xsession.$X.ccx/run/service/screen-locker/'; fi"
ssh-add -l >/dev/null || die "Failed to load SSH agent identities (screen locker died?), exiting."
}
+setup-plumber-listener() {
+ local temp_r # keep plumb_r in temp variable and set it at the end to indicate success
+ [[ -n $plumb_r ]] && return 0
+
+ if [[ ! -p $plumber_fifo ]]; then
+ mkfifo $plumber_fifo || return $?
+ fi
+
+ true >$plumber_fifo &! # background disowned task to keep the fifo's writing side open until it's opened below
+ sysopen -o cloexec -u temp_r -r $plumber_fifo || return $?
+ if ! sysopen -o cloexec -f plumber_w -w $plumber_fifo; then
+ exec {temp_r}>&- # close fd
+ return 1
+ fi
+ plumb_r=$temp_r
+ fds+=( $plumb_r )
+}
+
cmd() {
case $1 in
('') ;;
@@ -86,6 +106,7 @@ cmd() {
logincap X\ $X
s6-svc -wu -o /run/service/container.xsession.$X.ccx
s6-svstat /run/service/container.xsession.$X.ccx
+ setup-plumber-listener
;;
(off|poweroff)
logincap o;;
@@ -104,9 +125,32 @@ cmd() {
esac
}
+read-plumber-message() {
+ local plumb_dst plumb_wdir plumb_type plumb_attr plumb_ndata plumb_data
+
+ IFS= read -ru $plumb_r plumb_src || return $?
+ IFS= read -ru $plumb_r plumb_dst || return $?
+ IFS= read -ru $plumb_r plumb_wdir || return $?
+ IFS= read -ru $plumb_r plumb_type || return $?
+ IFS= read -ru $plumb_r plumb_attr || return $?
+ IFS= read -ru $plumb_r plumb_ndata || return $?
+ [[ $plumb_ndata =~ [0-9]+ ]] || return $?
+ IFS= read -ru $plumb_r -k $plumb_ndata plumb_data || return $?
+ printf >&2 '%s=%s\n' src ${(qqq)plumb_src} dst ${(qqq)plumb_dst} wdir ${(qqq)plumb_wdir} type ${(qqq)plumb_type} attr ${(qqq)plumb_attr} data ${(qqq)plumb_data}
+ case $plumb_data in
+ (poweroff) logincap o;;
+ (reboot) logincap b;;
+ (lock)
+ logincap chvt tty
+ lock
+ logincap chvt X
+ ;;
+ esac
+}
+
# typeset -f -t cmd
-coproc "$coproc_args[@]" | s6-tai64nlocal
+coproc "$coproc_args[@]" | s6-tai64nlocal
trap 'kill %1' EXIT
trap 'kill %1; ssh-add -D; exit' INT HUP TERM QUIT
trap 'printf "\nALRM!\n"' ALRM
@@ -154,6 +198,8 @@ while (($keep_running)) && zselect -A fds -r 0 $select_fds; do
printf '> %s\n' $REPLY
# fi
fi
+ elif [[ $fd == $plumb_r ]]; then
+ read-plumber-message
else
# stdin
if IFS= read -u $fd -s; then
diff --git a/sbin/logincaps b/sbin/logincaps
@@ -64,17 +64,23 @@ run_x() {
}
typeset -f -t run_x
+cap_cmd() {
+ if "$@"; then
+ printf 'OK\n'
+ else
+ printf 'EX%d\n' $?
+ fi
+}
+
main() {
local line term_cmd REPLY
while read line; do
case $line in
(o) printf >&2 "%s\n" "Would power-off."
- pretendrun s6-poweroff
- printf 'OK\n'
+ cap_cmd s6-poweroff
;;
(b) printf >&2 "%s\n" "Would reboot."
- pretendrun s6-reboot
- printf 'OK\n'
+ cap_cmd s6-reboot
;;
(terminal *)
term_cmd=( "${(Q@)${(z)${line#terminal }}}" )
@@ -85,13 +91,18 @@ main() {
printf 'OK\n'
;;
+ (chvt tty)
+ cap_cmd chvt ${LOGIN_TTY#/dev/tty}
+ ;;
+
+ (chvt [Xx])
+ cap_cmd chvt $X
+ ;;
+
(X [5678]*)
- if run_x "${(Q@)${(z)${line#X }}}"; then
- printf 'OK\n'
- else
- printf 'EX%d\n' $?
- fi
+ cap_cmd run_x "${(Q@)${(z)${line#X }}}"
;;
+
(*) printf 'ECMD\n';;
esac
done