utils/vmbox/guest/vmbox-x11.sh
Krzysztof kuhy Rudnicki 00bb6706fd
Some checks are pending
dependency freshness / dependencies on newest stable (push) Waiting to run
file length / file-length (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
palette drift / palette (push) Waiting to run
shared gate tests / gate unit tests (push) Waiting to run
vmbox: vm lightdm and vm shim — the host's login topology and fake hardware
The golden image logs in with agetty+startx and has no RGB controllers,
no NVIDIA card and no sound card, so the night-lockdown scripts — which
mask/stop lightdm.service and getty@.service and shell out to openrgb,
nvidia-smi and amixer — had nothing real to act on in a sandbox and
were being "verified" on the host instead.

- `vm lightdm <name>`: installs lightdm + lightdm-gtk-greeter into the
  live overlay (pacman -Syu, not -S: the overlay's package database is
  the image's and mirrors have rotated those versions out), configures
  autologin -> i3 exactly like the host, turns tty1 back into a plain
  getty, reboots the guest and proves lightdm.service is active with an
  Xorg it owns. Never rebuilds the base: `vm build --force` re-seals a
  new checksum while every existing sandbox still backs onto the old
  file's name, which is silent qcow2 corruption.
- `vm shim <name> <tool> [exit[:N]|hang|sleep:S]`: a fake tool ahead of
  the real one on PATH, every call logged with an epoch to
  /var/log/vmbox-shim/<tool>.log so the host can assert what ran and in
  what order. `hang` is the openrgb 1.0-2 that never returned on
  2026-09-12 and defeated the curfew.
- The DISPLAY/XAUTHORITY resolver `vm run` sources becomes its own file,
  guest/vmbox-x11.sh, installed by the image build and re-installed by
  the lightdm switch; it now tests readability, not existence, and tries
  ~/.Xauthority before the startx serverauth glob, because lightdm's
  Xorg -auth file is root-only.
- README: the worked example uses MIDNIGHT_SHUTDOWN_CONFIRM=y (the
  installer refuses to run unattended now; `echo y |` no longer works),
  and the "i2c RGB stays on the host" line is gone.
- bats: four host-side tests for shim.sh (exit, exit:N, hang, refusals).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015mLnUeoJ3mUwGRTowTUH6d
2026-09-13 10:51:10 +02:00

60 lines
2.7 KiB
Bash

#!/bin/sh
# Installed to /etc/profile.d/vmbox-x11.sh by provision-desktop.sh (golden
# image) and re-installed by desktop-lightdm.sh (per-sandbox lightdm switch).
# Sourced by `vm run`; POSIX sh, because /etc/profile.d may be read by dash.
#
# Point non-login shells at the guest's X session, if one is running.
# Sourced by vmbox's `vm run`; harmless when no X session exists.
if [ -z "${DISPLAY:-}" ]; then
# Wait briefly for the X session rather than reporting "no X".
#
# vmbox now returns control as soon as sshd answers (~11s), which is
# EARLIER than getty@tty1 autologin has run .bash_profile and started
# Xorg. Without this wait the first `vm run` after a boot silently gets
# no DISPLAY and every X tool fails as if the sandbox had no X server --
# the exact failure this file exists to prevent, reintroduced by making
# the rest of the tool faster. Bounded, and skipped entirely once Xorg
# is up, so a guest with no graphical session costs at most this wait.
# Default 0: a plain `vm run` must not pay for a graphical session it is
# not using. Set VMBOX_X_WAIT=<seconds> for X11/i3/locker work.
_vmbox_x_wait="${VMBOX_X_WAIT:-0}"
while [ "$_vmbox_x_wait" -gt 0 ]; do
pgrep -x Xorg >/dev/null 2>&1 && break
sleep 1
_vmbox_x_wait=$((_vmbox_x_wait - 1))
done
unset _vmbox_x_wait
if pgrep -x Xorg >/dev/null 2>&1; then
DISPLAY=":0"
export DISPLAY
fi
fi
if [ -n "${DISPLAY:-}" ] && [ -z "${XAUTHORITY:-}" ]; then
# Prefer the auth file the running Xorg was actually started with. Test
# READABILITY, not existence: under lightdm that is /run/lightdm/root/:0,
# root-only, and the user's cookie is ~/.Xauthority instead. The startx
# serverauth glob is the last resort for the golden image's tty1 session.
_vmbox_xauth="$(tr '\0' '\n' < /proc/"$(pgrep -x Xorg | head -1)"/cmdline 2>/dev/null \
| grep -A1 -x -- -auth | tail -1)"
if [ ! -r "${_vmbox_xauth:-}" ]; then
_vmbox_xauth="$HOME/.Xauthority"
fi
if [ ! -r "${_vmbox_xauth:-}" ]; then
for _vmbox_cand in /tmp/serverauth.*; do
[ -r "$_vmbox_cand" ] && _vmbox_xauth="$_vmbox_cand"
done
unset _vmbox_cand
fi
if [ -r "${_vmbox_xauth:-}" ]; then
XAUTHORITY="$_vmbox_xauth"
export XAUTHORITY
fi
unset _vmbox_xauth
fi
# i3 tools look here when I3SOCK is unset; setting it explicitly avoids a
# second round of X round-trips in tests that shell out repeatedly.
if [ -n "${DISPLAY:-}" ] && [ -z "${I3SOCK:-}" ] && command -v i3 >/dev/null 2>&1; then
I3SOCK="$(i3 --get-socketpath 2>/dev/null || true)"
if [ -n "$I3SOCK" ]; then export I3SOCK; else unset I3SOCK; fi
fi