#!/bin/zsh setopt no_unset extended_glob warn_create_global typeset -g DSTROOT DISPLAYNUM REPO_ROOT set -x DSTROOT=$1 DISPLAYNUM=$2 REPO_ROOT=${0:P:h:h} # helpers die() { printf >&2 '%s\n' "$@" exit 1 } ensure-container-started() { [[ $1 == */* ]] && die "Invalid container name: ${(qqq)1}" s6-svc -wU -T 4000 -o /run/service/container.$1 } to-current-inbox() { local from_container=$1 shift ensure-container-started $from_container link-to-container-inbox $from_container ${DSTROOT:t} "$@" || exit $? } # Copy over the versioned filesystem image copy-skel() { local skel dst s6-hiercopy $REPO_ROOT/xsession-skel/homedir $DSTROOT/home/$USER || exit $? for skel in $REPO_ROOT/xsession-skel/*/*(DN); do [[ ${skel:h:t} == homedir ]] && continue dst=$DSTROOT/${skel:h:t}/${skel:t} s6-hiercopy $skel $dst || exit $? done } # make files that can't be easily version-controlled setup-special() { # FIFO for plumber local fifo=/run/user/$UID/plumber_fifo.X$DISPLAYNUM if ! [[ -p $fifo ]]; then mkfifo $fifo || exit $? fi ln -f $fifo $DSTROOT/run/plumber_fifo || exit $? # init symplink for container startup ln -sf /home/$USER/run $DSTROOT/run/user-run || exit $? ln -sf user-run/init $DSTROOT/run/init || exit $? } # make X server available to the xsession container setup-x11() { s6-svwait /run/service/container.X$DISPLAYNUM || exit $? #ls -lhA --full-time /run /run/containers /run/containers/X$DISPLAYNUM.xorg/tmp /run/containers/X$DISPLAYNUM.xorg/tmp/.X11-unix $DSTROOT $DSTROOT/run cp -v /run/Xauthority.$DISPLAYNUM $DSTROOT/run/Xauthority.$DISPLAYNUM || exit $? #ln -f /run/Xauthority.$DISPLAYNUM $DSTROOT/run/Xauthority.$DISPLAYNUM || exit $? printf '%s' >$DSTROOT/home/$USER/run/env/XAUTHORITY /run/Xauthority.$DISPLAYNUM || exit $? ln -f /run/containers/X$DISPLAYNUM.xorg/tmp/.X11-unix/X$DISPLAYNUM $DSTROOT/tmp/.X11-unix/X$DISPLAYNUM || exit $? printf '%s' >$DSTROOT/home/$USER/run/env/DISPLAY :$DISPLAYNUM || exit $? } # launch container for xpra and make X server available to it setup-xpra() { to-current-inbox xpra.$USER run/exec/x11 run/exec/exec || exit $? return # TODO: the rest is probably unnecessary, delete if not needed local svstat xpra_svc xpra_dir xpra_svc=/run/service/container.xpra.$USER xpra_dir=/run/containers/xpra.$USER svstat=$(s6-svstat -ur $xpra_svc) if (($!)); then echo >&2 "Warning: could not read status of service: $xpra_svc" return fi if [[ $svstat != 'true true' ]]; then echo >&2 "Warning: service not up and running: $xpra_svc" return fi cp -v /run/Xauthority.$DISPLAYNUM $xpra_dir/run/Xauthority.$DISPLAYNUM || exit $? #printf '%s' >$DSTROOT/home/$USER/run/env/XAUTHORITY /run/Xauthority.$DISPLAYNUM || exit $? ln -f /run/containers/X$DISPLAYNUM.xorg/tmp/.X11-unix/X$DISPLAYNUM $xpra_dir/tmp/.X11-unix/X$DISPLAYNUM || exit $? } # launch container for handling passwords setup-pass() { to-current-inbox pass.$USER run/pass/list run/exec/exec || exit $? } # link sockets for uncontainerized helpers setup-helper-sockets() { local sock s6-rc -l /run/user/$USER/s6-rc -u change xsession-all || exit $? for sock in /run/user/$USER/xsession/*(=); do ln -f $sock $DSTROOT/run/${sock:t}.s || exit $? done } main() { if ! [[ -d $DSTROOT ]]; then echo >&2 "Destination root not a directory: $DSTROOT" exit 2 fi if [[ $DISPLAYNUM != [0-9] ]]; then echo >&2 "Invalid display number: $DISPLAYNUM" exit 3 fi copy-skel || exit $? setup-special || exit $? setup-x11 || exit $? setup-xpra || exit $? setup-pass || exit $? setup-helper-sockets || exit $? } main