#!/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