Files
appsandbox/tools/agent_mac/firstboot.sh
James Stringer b10c3de086 Add guest accessibility support to macOS VM viewers
Expose guest accessibility trees through a host AppKit helper and forward attributes, actions, text operations, and input through shared transport.

Package macOS and Windows guest collectors and integrate viewer lifecycle, refresh scheduling, and geometry handling.
2026-09-16 18:13:23 -04:00

94 lines
3.8 KiB
Bash

#!/bin/sh
# Runs once on first guest boot as root, installs the agent LaunchDaemon
# into /Library/LaunchDaemons with correct ownership, then deletes itself.
# This is the macOS analog of Windows' SetupComplete.cmd invoking
# `appsandbox-agent.exe --install`.
set -e
LOG=/var/log/appsandbox-firstboot.log
echo "=== firstboot.sh started $(date) ===" >> "$LOG"
SRC=/Library/AppSandbox/com.appsandbox.agent.plist
DST=/Library/LaunchDaemons/com.appsandbox.agent.plist
if [ ! -f "$SRC" ]; then
echo "Missing $SRC, aborting." >> "$LOG"
exit 1
fi
chown root:wheel /Library/AppSandbox/appsandbox-agent
chmod 755 /Library/AppSandbox/appsandbox-agent
cp "$SRC" "$DST"
chown root:wheel "$DST"
chmod 644 "$DST"
launchctl bootstrap system "$DST" >> "$LOG" 2>&1 || true
# Clipboard sync helper — user-context LaunchAgent. Place the plist in
# /Library/LaunchAgents/ so every user login gets its own instance in
# that user's GUI session (needed for NSPasteboard access).
if [ -f /Library/AppSandbox/com.appsandbox.clipboard.plist ]; then
CLIP_SRC=/Library/AppSandbox/com.appsandbox.clipboard.plist
CLIP_DST=/Library/LaunchAgents/com.appsandbox.clipboard.plist
cp "$CLIP_SRC" "$CLIP_DST"
chown root:wheel "$CLIP_DST"
chmod 644 "$CLIP_DST"
chown root:wheel /Library/AppSandbox/appsandbox-clipboard 2>/dev/null || true
chmod 755 /Library/AppSandbox/appsandbox-clipboard 2>/dev/null || true
fi
if [ -d /Library/AppSandbox/AppSandboxAccessibility.app ] &&
[ -f /Library/AppSandbox/com.appsandbox.accessibility.plist ]; then
AX_APP=/Library/AppSandbox/AppSandboxAccessibility.app
AX_SRC=/Library/AppSandbox/com.appsandbox.accessibility.plist
AX_DST=/Library/LaunchAgents/com.appsandbox.accessibility.plist
mkdir -p /Library/LaunchAgents
chown -R root:wheel "$AX_APP"
chmod -R u=rwX,go=rX "$AX_APP"
chmod 755 "$AX_APP/Contents/MacOS/AppSandboxAccessibility"
cp "$AX_SRC" "$AX_DST"
chown root:wheel "$AX_DST"
chmod 644 "$AX_DST"
AX_UID=$(/usr/bin/stat -f %u /dev/console 2>/dev/null || true)
if [ -n "$AX_UID" ] && [ "$AX_UID" -ne 0 ]; then
/bin/launchctl bootstrap "gui/$AX_UID" "$AX_DST" >> "$LOG" 2>&1 || true
fi
fi
# SSH: primary enablement is the launchd override DB flip the host does
# during stage. As belt-and-braces, also run the in-guest enable path,
# which works without Full Disk Access (unlike systemsetup -setremotelogin).
/bin/launchctl load -w /System/Library/LaunchDaemons/ssh.plist >> "$LOG" 2>&1 || true
# Disable all sleep modes so the VM display/CPU never power down — a
# sandbox VM is expected to be driven by the host, not idle the way a
# laptop does. pmset persists in /Library/Preferences/com.apple.PowerManagement.plist.
/usr/bin/pmset -a displaysleep 0 sleep 0 disksleep 0 >> "$LOG" 2>&1 || true
# Computer name. The host drops /Library/AppSandbox/computer-name with the
# user's chosen VM name; scutil is the canonical way to set these (wraps
# SCDynamicStoreSetComputerName / SCPreferencesSetLocalHostName). The
# validator constrains input to [A-Za-z0-9-], so all three names can be
# identical and DNS-safe.
NAME_FILE=/Library/AppSandbox/computer-name
if [ -f "$NAME_FILE" ]; then
NAME=$(tr -d '\r\n' < "$NAME_FILE")
if [ -n "$NAME" ]; then
/usr/sbin/scutil --set ComputerName "$NAME" >> "$LOG" 2>&1 || true
/usr/sbin/scutil --set HostName "$NAME" >> "$LOG" 2>&1 || true
/usr/sbin/scutil --set LocalHostName "$NAME" >> "$LOG" 2>&1 || true
echo "Set computer name to $NAME" >> "$LOG"
fi
rm -f "$NAME_FILE"
fi
# Remove ourselves so we only run once.
rm -f /Library/LaunchDaemons/com.appsandbox.firstboot.plist
launchctl bootout system/com.appsandbox.firstboot >> "$LOG" 2>&1 || true
rm -f /Library/AppSandbox/firstboot.sh
echo "=== firstboot.sh finished $(date) ===" >> "$LOG"
exit 0