604 lines
20 KiB
Bash
Executable file
604 lines
20 KiB
Bash
Executable file
#!/bin/sh
|
|
# Clawdie Shell — System Configuration Module
|
|
# Purpose: System-level config (rc.conf, hostname, services, environment)
|
|
# Author: Clawdie Project
|
|
# POSIX-compliant (no bash-isms)
|
|
|
|
set -eu
|
|
# FreeBSD /bin/sh doesn't support trap ERR
|
|
|
|
# Configuration (can be overridden for testing)
|
|
RC_CONF="${RC_CONF:-/etc/rc.conf}"
|
|
LOADER_CONF="${LOADER_CONF:-/boot/loader.conf}"
|
|
SYSCTL_CONF="${SYSCTL_CONF:-/etc/sysctl.conf}"
|
|
HOSTNAME_FILE="${HOSTNAME_FILE:-/etc/hostname}"
|
|
PROFILE_DIR="${PROFILE_DIR:-/etc/profile.d}"
|
|
LOG_FILE="${LOG_FILE:-/var/log/clawdie-firstboot.log}"
|
|
PROGRESS_FILE="${PROGRESS_FILE:-/var/log/clawdie-firstboot.progress}"
|
|
|
|
# Derived from wizard inputs (caller sets these)
|
|
# TZ - Timezone (e.g., "Europe/Ljubljana")
|
|
# AGENT_DOMAIN - FQDN (e.g., "clawdie.home.arpa" for local, or public domain)
|
|
# DETECTED_GPU - GPU vendor from gpu module (intel, amd, nvidia, vmware, vesa)
|
|
|
|
# ============================================================================
|
|
# MAIN ENTRY POINT
|
|
# ============================================================================
|
|
|
|
clawdie_shell_system_config() {
|
|
# Main orchestrator
|
|
|
|
log_msg "[system] Starting system configuration"
|
|
|
|
if [ -z "${TZ:-}" ]; then
|
|
log_msg "[system] ERROR: TZ not set"
|
|
return 1
|
|
fi
|
|
|
|
if [ -z "${AGENT_DOMAIN:-}" ]; then
|
|
log_msg "[system] ERROR: AGENT_DOMAIN not set"
|
|
return 1
|
|
fi
|
|
|
|
if [ -z "${SYSTEM_LOCALE:-}" ]; then
|
|
log_msg "[system] ERROR: SYSTEM_LOCALE not set"
|
|
return 1
|
|
fi
|
|
|
|
# Write rc.conf with timezone and services
|
|
clawdie_shell_system_write_rcconf
|
|
log_msg "[system] Updated rc.conf"
|
|
|
|
# Set hostname
|
|
clawdie_shell_system_set_hostname
|
|
log_msg "[system] Set hostname"
|
|
|
|
# Setup environment
|
|
clawdie_shell_system_setup_env
|
|
log_msg "[system] Setup environment"
|
|
|
|
# Setup locale + keymap
|
|
clawdie_shell_system_setup_locale
|
|
log_msg "[system] Setup locale"
|
|
|
|
# Enable FreeBSD mac_do framework with no credential grants yet
|
|
clawdie_shell_system_setup_mac_do
|
|
log_msg "[system] Setup mac_do framework"
|
|
|
|
# Enable evdev input routing for Xorg/libinput touchpads and mice
|
|
clawdie_shell_system_setup_evdev
|
|
log_msg "[system] Setup evdev input routing"
|
|
|
|
# Enable Linux compatibility at boot and best-effort for the current boot
|
|
clawdie_shell_system_setup_linuxulator
|
|
log_msg "[system] Setup Linux compatibility"
|
|
|
|
# Enable a baseline bhyve host configuration on the target
|
|
clawdie_shell_system_setup_bhyve
|
|
log_msg "[system] Setup bhyve host baseline"
|
|
|
|
# Enable services
|
|
clawdie_shell_system_enable_services
|
|
log_msg "[system] Enabled services"
|
|
|
|
echo "[SYSTEM] COMPLETE" >> "$PROGRESS_FILE"
|
|
log_msg "[system] System configuration complete"
|
|
}
|
|
|
|
# ============================================================================
|
|
# RC.CONF CONFIGURATION
|
|
# ============================================================================
|
|
|
|
clawdie_shell_system_write_rcconf() {
|
|
# Update /etc/rc.conf with:
|
|
# - timezone
|
|
# - service configurations (dbus, sddm)
|
|
# - desktop settings
|
|
|
|
if [ ! -f "$RC_CONF" ]; then
|
|
log_msg "[system] Creating $RC_CONF"
|
|
touch "$RC_CONF"
|
|
fi
|
|
|
|
# Helper to set or update rc.conf variable
|
|
clawdie_shell_system_sysrc "timezone=$TZ"
|
|
if [ -n "${KEYMAP:-}" ]; then
|
|
clawdie_shell_system_sysrc "keymap=$KEYMAP"
|
|
fi
|
|
clawdie_shell_system_sysrc "dbus_enable=YES"
|
|
clawdie_shell_system_sysrc "display_manager=sddm"
|
|
clawdie_shell_system_sysrc "sddm_enable=YES"
|
|
clawdie_shell_system_sysrc "linux_enable=YES"
|
|
clawdie_shell_system_sysrc "zfs_enable=YES"
|
|
clawdie_shell_system_sysrc "vm_enable=YES"
|
|
clawdie_shell_system_append_rc_list kld_list linux linux64 zfs vmm nmdm if_tap if_bridge
|
|
|
|
log_msg "[system] Wrote rc.conf configuration"
|
|
}
|
|
|
|
clawdie_shell_system_sysrc() {
|
|
# Add or update a variable in rc.conf
|
|
# Input: VAR=VALUE
|
|
|
|
clawdie_shell_system_set_config_line "$RC_CONF" "$1"
|
|
}
|
|
|
|
clawdie_shell_system_set_config_line() {
|
|
# Add or update KEY=VALUE in a config file.
|
|
# Input: FILE KEY=VALUE
|
|
|
|
local config_file="$1"
|
|
local var_assignment="$2"
|
|
local var_name
|
|
|
|
var_name=$(echo "$var_assignment" | cut -d= -f1)
|
|
|
|
if [ ! -f "$config_file" ]; then
|
|
mkdir -p "$(dirname "$config_file")"
|
|
touch "$config_file"
|
|
fi
|
|
|
|
if grep -q "^${var_name}=" "$config_file" 2>/dev/null; then
|
|
sed -i '' "s|^${var_name}=.*|${var_assignment}|" "$config_file"
|
|
else
|
|
echo "$var_assignment" >> "$config_file"
|
|
fi
|
|
}
|
|
|
|
clawdie_shell_system_append_rc_list() {
|
|
# Append values to a quoted rc.conf list variable without duplicating entries.
|
|
# Input: VAR VALUE [VALUE...]
|
|
|
|
local var_name="$1"
|
|
shift
|
|
local current merged value
|
|
|
|
current=$(sed -n "s/^${var_name}=\"\\(.*\\)\"/\\1/p" "$RC_CONF" 2>/dev/null | head -1)
|
|
merged="$current"
|
|
|
|
for value in "$@"; do
|
|
if [ -z "$merged" ]; then
|
|
merged="$value"
|
|
continue
|
|
fi
|
|
case " ${merged} " in
|
|
*" ${value} "*) ;;
|
|
*)
|
|
merged="${merged} ${value}"
|
|
;;
|
|
esac
|
|
done
|
|
|
|
clawdie_shell_system_set_config_line "$RC_CONF" "${var_name}=\"${merged}\""
|
|
}
|
|
|
|
# ============================================================================
|
|
# MAC_DO FRAMEWORK
|
|
# ============================================================================
|
|
|
|
clawdie_shell_system_setup_mac_do() {
|
|
# Load FreeBSD mac_do at boot, but grant no credential transitions yet.
|
|
# FreeBSD 15 accepts an empty rule list as no-op policy: security.mac.do.rules=
|
|
|
|
clawdie_shell_system_set_config_line "$LOADER_CONF" 'mac_do_load="YES"'
|
|
clawdie_shell_system_set_config_line "$SYSCTL_CONF" 'security.mac.do.rules='
|
|
|
|
# Best-effort live activation for the firstboot session. The persistent
|
|
# loader/sysctl files above are the source of truth after reboot.
|
|
if command -v kldload >/dev/null 2>&1; then
|
|
kldload mac_do 2>/dev/null || true
|
|
elif [ -x /sbin/kldload ]; then
|
|
/sbin/kldload mac_do 2>/dev/null || true
|
|
fi
|
|
|
|
if command -v sysctl >/dev/null 2>&1; then
|
|
sysctl security.mac.do.rules= >/dev/null 2>&1 || true
|
|
elif [ -x /sbin/sysctl ]; then
|
|
/sbin/sysctl security.mac.do.rules= >/dev/null 2>&1 || true
|
|
fi
|
|
}
|
|
|
|
# ============================================================================
|
|
# EVDEV INPUT ROUTING
|
|
# ============================================================================
|
|
|
|
clawdie_shell_system_setup_evdev() {
|
|
# FreeBSD's xorg/libinput stack recommends routing native evdev events for
|
|
# ums(4)/psm(4). This improves touchpad and mouse support and avoids PS/2
|
|
# detection issues when moused is disabled.
|
|
clawdie_shell_system_set_config_line "$SYSCTL_CONF" 'kern.evdev.rcpt_mask=6'
|
|
|
|
if command -v sysctl >/dev/null 2>&1; then
|
|
sysctl kern.evdev.rcpt_mask=6 >/dev/null 2>&1 || true
|
|
elif [ -x /sbin/sysctl ]; then
|
|
/sbin/sysctl kern.evdev.rcpt_mask=6 >/dev/null 2>&1 || true
|
|
fi
|
|
}
|
|
|
|
# ============================================================================
|
|
# LINUX COMPATIBILITY
|
|
# ============================================================================
|
|
|
|
clawdie_shell_system_setup_linuxulator() {
|
|
# Persist Linux compatibility in rc.conf and try to activate it immediately.
|
|
# This runs on the target system during firstboot, not on the ISO build host.
|
|
|
|
local module
|
|
|
|
for module in linux64 linux; do
|
|
if command -v kldload >/dev/null 2>&1; then
|
|
kldload "$module" >/dev/null 2>&1 || true
|
|
elif [ -x /sbin/kldload ]; then
|
|
/sbin/kldload "$module" >/dev/null 2>&1 || true
|
|
fi
|
|
done
|
|
|
|
if command -v service >/dev/null 2>&1; then
|
|
service linux onestart >/dev/null 2>&1 || true
|
|
elif [ -x /usr/sbin/service ]; then
|
|
/usr/sbin/service linux onestart >/dev/null 2>&1 || true
|
|
fi
|
|
}
|
|
|
|
# ============================================================================
|
|
# BHYVE HOST BASELINE
|
|
# ============================================================================
|
|
|
|
clawdie_shell_system_setup_bhyve() {
|
|
# Persist core bhyve modules and tap behavior. Leave bridge/vm_dir creation
|
|
# to later host-specific setup because the correct NIC and storage dataset are
|
|
# machine-dependent.
|
|
|
|
local module
|
|
|
|
clawdie_shell_system_set_config_line "$SYSCTL_CONF" 'net.link.tap.up_on_open=1'
|
|
|
|
if command -v sysctl >/dev/null 2>&1; then
|
|
sysctl net.link.tap.up_on_open=1 >/dev/null 2>&1 || true
|
|
elif [ -x /sbin/sysctl ]; then
|
|
/sbin/sysctl net.link.tap.up_on_open=1 >/dev/null 2>&1 || true
|
|
fi
|
|
|
|
for module in vmm nmdm if_tap if_bridge; do
|
|
if command -v kldload >/dev/null 2>&1; then
|
|
kldload "$module" >/dev/null 2>&1 || true
|
|
elif [ -x /sbin/kldload ]; then
|
|
/sbin/kldload "$module" >/dev/null 2>&1 || true
|
|
fi
|
|
done
|
|
}
|
|
|
|
# ============================================================================
|
|
# HOSTNAME CONFIGURATION
|
|
# ============================================================================
|
|
|
|
clawdie_shell_system_set_hostname() {
|
|
# Set /etc/hostname and apply live
|
|
|
|
if [ ! -f "$HOSTNAME_FILE" ]; then
|
|
touch "$HOSTNAME_FILE"
|
|
fi
|
|
|
|
# Write to file
|
|
echo "$AGENT_DOMAIN" > "$HOSTNAME_FILE"
|
|
|
|
# Apply live (if not in chroot)
|
|
if command -v hostname >/dev/null 2>&1; then
|
|
hostname "$AGENT_DOMAIN" 2>/dev/null || true
|
|
fi
|
|
|
|
log_msg "[system] Set hostname to $AGENT_DOMAIN"
|
|
}
|
|
|
|
# ============================================================================
|
|
# ENVIRONMENT SETUP
|
|
# ============================================================================
|
|
|
|
clawdie_shell_system_setup_env() {
|
|
# Create /etc/profile.d/clawdie.sh for environment variables
|
|
# Sets up npm global paths and other Clawdie-specific variables
|
|
|
|
if [ ! -d "$PROFILE_DIR" ]; then
|
|
mkdir -p "$PROFILE_DIR"
|
|
fi
|
|
|
|
local clawdie_profile="$PROFILE_DIR/clawdie.sh"
|
|
local normalized_locale
|
|
normalized_locale=$(clawdie_shell_system_normalize_locale "$SYSTEM_LOCALE")
|
|
|
|
cat > "$clawdie_profile" <<EOF
|
|
# Clawdie-AI environment setup
|
|
# Adds npm global bin directory to PATH
|
|
|
|
_clawdie_npm_prefix="/opt/clawdie/npm-global"
|
|
_clawdie_base_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
|
_clawdie_path_has() {
|
|
case ":\${PATH:-}:" in
|
|
*:"\$1":*) return 0 ;;
|
|
*) return 1 ;;
|
|
esac
|
|
}
|
|
export npm_config_prefix="\${_clawdie_npm_prefix}"
|
|
export NPM_CONFIG_PREFIX="\${_clawdie_npm_prefix}"
|
|
export NPM_CONFIG_UPDATE_NOTIFIER=false
|
|
export NO_UPDATE_NOTIFIER=1
|
|
if [ -z "\${PATH:-}" ]; then
|
|
PATH="\${_clawdie_base_path}"
|
|
else
|
|
for _clawdie_dir in /usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin; do
|
|
_clawdie_path_has "\${_clawdie_dir}" || PATH="\${PATH}:\${_clawdie_dir}"
|
|
done
|
|
fi
|
|
_clawdie_path_has "\${_clawdie_npm_prefix}/bin" || PATH="\${_clawdie_npm_prefix}/bin:\${PATH}"
|
|
export PATH
|
|
unset _clawdie_npm_prefix
|
|
unset _clawdie_base_path
|
|
unset -f _clawdie_path_has 2>/dev/null || true
|
|
export LANG="${normalized_locale}"
|
|
export LC_ALL="${normalized_locale}"
|
|
EOF
|
|
|
|
chmod 644 "$clawdie_profile"
|
|
|
|
if id clawdie >/dev/null 2>&1; then
|
|
if [ -x /usr/local/bin/bash ]; then
|
|
if ! grep -qx '/usr/local/bin/bash' /etc/shells 2>/dev/null; then
|
|
echo '/usr/local/bin/bash' >> /etc/shells 2>/dev/null || true
|
|
fi
|
|
pw usermod clawdie -s /usr/local/bin/bash 2>/dev/null || true
|
|
fi
|
|
if [ -x /usr/local/bin/zsh ] && ! grep -qx '/usr/local/bin/zsh' /etc/shells 2>/dev/null; then
|
|
echo '/usr/local/bin/zsh' >> /etc/shells 2>/dev/null || true
|
|
fi
|
|
|
|
cat > /home/clawdie/.profile <<'EOF'
|
|
# Clawdie operator POSIX shell profile.
|
|
[ -r /etc/profile.d/clawdie.sh ] && . /etc/profile.d/clawdie.sh
|
|
|
|
# Start SSH agent on login (FreeBSD: no systemd, no X11 agent launcher).
|
|
# Non-login shells (tmux windows) use ~/.bashrc fallback instead.
|
|
if [ -z "$SSH_AUTH_SOCK" ]; then
|
|
eval $(ssh-agent -s) > /dev/null 2>&1
|
|
fi
|
|
EOF
|
|
cat > /home/clawdie/.bash_profile <<'EOF'
|
|
# Clawdie operator bash login profile.
|
|
[ -r /etc/profile ] && . /etc/profile
|
|
[ -L "${HOME}/.cache" ] && {
|
|
mkdir -p /tmp/clawdie/cache 2>/dev/null || true
|
|
chown "$(id -u):$(id -g)" /tmp/clawdie /tmp/clawdie/cache 2>/dev/null || true
|
|
chmod 0700 /tmp/clawdie /tmp/clawdie/cache 2>/dev/null || true
|
|
}
|
|
[ -r "${HOME}/.bashrc" ] && . "${HOME}/.bashrc"
|
|
EOF
|
|
cat > /home/clawdie/.bashrc <<'BASHRC'
|
|
# Clawdie operator interactive bash shell.
|
|
# Non-interactive shells stop here.
|
|
case $- in *i*) ;; *) return ;; esac
|
|
|
|
# ── PATH (FreeBSD: /usr/local first) ──────────────────────────
|
|
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
|
[ -r /etc/profile.d/clawdie.sh ] && . /etc/profile.d/clawdie.sh
|
|
|
|
# ── Privilege escalation ──────────────────────────────────────
|
|
# Clawdie ISO: no sudo pkg. Use FreeBSD mac_do instead.
|
|
# mac_do rules (gid=0>uid=0) allow wheel→root transitions.
|
|
# ZFS auto-snapshot provides safety net — no confirmation prompts.
|
|
sudo() {
|
|
local pool
|
|
pool=$(zpool list -H -o name 2>/dev/null | head -1)
|
|
if [ -n "$pool" ]; then
|
|
(zfs snapshot "${pool}@cli-$(date +%s)" 2>/dev/null &)
|
|
fi
|
|
mdo -u root "$@"
|
|
}
|
|
|
|
# ── SSH agent (fallback for non-login shells) ─────────────────
|
|
# .profile starts the agent for login shells; tmux windows
|
|
# (non-login) inherit via SSH_AUTH_SOCK if the parent had one,
|
|
# but if not, try a stored env file from a prior login.
|
|
if [ -z "$SSH_AUTH_SOCK" ] && [ -f ~/.ssh-agent-env ]; then
|
|
. ~/.ssh-agent-env 2>/dev/null || true
|
|
fi
|
|
|
|
# ── Prompt ────────────────────────────────────────────────────
|
|
PS1='\h:\w\$ '
|
|
|
|
# ── History ───────────────────────────────────────────────────
|
|
export HISTFILE="${HISTFILE:-/tmp/clawdie/bash_history}"
|
|
export HISTSIZE=5000
|
|
export HISTFILESIZE=10000
|
|
mkdir -p /tmp/clawdie 2>/dev/null || true
|
|
|
|
# ── Aliases ───────────────────────────────────────────────────
|
|
alias ll='ls -lah'
|
|
alias la='ls -A'
|
|
alias lt='ls -laht'
|
|
BASHRC
|
|
cat > /home/clawdie/.zprofile <<'EOF'
|
|
# Clawdie operator zsh login profile.
|
|
[ -r /etc/profile ] && . /etc/profile
|
|
[ -L "${HOME}/.cache" ] && {
|
|
mkdir -p /tmp/clawdie/cache 2>/dev/null || true
|
|
chown "$(id -u):$(id -g)" /tmp/clawdie /tmp/clawdie/cache 2>/dev/null || true
|
|
chmod 0700 /tmp/clawdie /tmp/clawdie/cache 2>/dev/null || true
|
|
}
|
|
[ -r /etc/profile.d/clawdie.sh ] && . /etc/profile.d/clawdie.sh
|
|
[ -r "${HOME}/.zshrc" ] && . "${HOME}/.zshrc"
|
|
EOF
|
|
cat > /home/clawdie/.zshrc <<'EOF'
|
|
# Clawdie operator interactive zsh profile.
|
|
[ -r /etc/profile.d/clawdie.sh ] && . /etc/profile.d/clawdie.sh
|
|
export HISTFILE="${HISTFILE:-/tmp/clawdie/zsh_history}"
|
|
mkdir -p /tmp/clawdie 2>/dev/null || true
|
|
|
|
# Keep zsh optional, but ready: use packaged oh-my-zsh when present.
|
|
if [ -d /usr/local/share/ohmyzsh ]; then
|
|
export ZSH="/usr/local/share/ohmyzsh"
|
|
elif [ -d /usr/local/share/oh-my-zsh ]; then
|
|
export ZSH="/usr/local/share/oh-my-zsh"
|
|
fi
|
|
if [ -n "${ZSH:-}" ] && [ -r "${ZSH}/oh-my-zsh.sh" ]; then
|
|
ZSH_THEME="${ZSH_THEME:-robbyrussell}"
|
|
plugins=(git)
|
|
source "${ZSH}/oh-my-zsh.sh"
|
|
fi
|
|
EOF
|
|
if [ -f /usr/local/etc/xdg/tumbler/tumbler.rc ]; then
|
|
mkdir -p /home/clawdie/.config/tumbler
|
|
cp /usr/local/etc/xdg/tumbler/tumbler.rc /home/clawdie/.config/tumbler/tumbler.rc
|
|
fi
|
|
chown -R clawdie:clawdie /home/clawdie/.config/tumbler 2>/dev/null || true
|
|
chown clawdie:clawdie /home/clawdie/.profile /home/clawdie/.bash_profile /home/clawdie/.bashrc /home/clawdie/.zprofile /home/clawdie/.zshrc 2>/dev/null || true
|
|
chmod 644 /home/clawdie/.profile /home/clawdie/.bash_profile /home/clawdie/.bashrc /home/clawdie/.zprofile /home/clawdie/.zshrc 2>/dev/null || true
|
|
chmod 644 /home/clawdie/.config/tumbler/tumbler.rc 2>/dev/null || true
|
|
fi
|
|
|
|
log_msg "[system] Created $clawdie_profile"
|
|
}
|
|
|
|
# ============================================================================
|
|
# SERVICE ENABLEMENT
|
|
# ============================================================================
|
|
|
|
clawdie_shell_system_enable_services() {
|
|
# Enable and start required services
|
|
# Safe to fail if running in chroot (first boot)
|
|
|
|
local services="dbus sddm"
|
|
|
|
for service in $services; do
|
|
if command -v service >/dev/null 2>&1; then
|
|
# Try to start service
|
|
service "$service" onestart 2>/dev/null || {
|
|
log_msg "[system] Could not start $service (expected in chroot)"
|
|
}
|
|
fi
|
|
done
|
|
|
|
log_msg "[system] Service enablement complete"
|
|
}
|
|
|
|
# ============================================================================
|
|
# LOCALE + KEYMAP SETUP
|
|
# ============================================================================
|
|
|
|
clawdie_shell_system_setup_locale() {
|
|
local normalized_locale
|
|
normalized_locale=$(clawdie_shell_system_normalize_locale "$SYSTEM_LOCALE")
|
|
|
|
# Write per-user login_conf (must be UTF-8).
|
|
if id clawdie >/dev/null 2>&1; then
|
|
local login_conf="/home/clawdie/.login_conf"
|
|
cat > "$login_conf" <<EOF
|
|
me:\\
|
|
:charset=UTF-8:\\
|
|
:lang=${normalized_locale}:
|
|
EOF
|
|
chown clawdie:clawdie "$login_conf" 2>/dev/null || true
|
|
chmod 644 "$login_conf" 2>/dev/null || true
|
|
if command -v cap_mkdb >/dev/null 2>&1; then
|
|
cap_mkdb "$login_conf" 2>/dev/null || true
|
|
fi
|
|
fi
|
|
}
|
|
|
|
clawdie_shell_system_normalize_locale() {
|
|
local raw="$1"
|
|
raw=$(echo "$raw" | tr '-' '_')
|
|
raw=${raw%%.*}
|
|
raw=${raw%%@*}
|
|
if [ -z "$raw" ]; then
|
|
raw="C"
|
|
fi
|
|
echo "${raw}.UTF-8"
|
|
}
|
|
|
|
# ============================================================================
|
|
# VALIDATION
|
|
# ============================================================================
|
|
|
|
clawdie_shell_system_validate() {
|
|
# Verify system configuration completed
|
|
|
|
if [ ! -f "$RC_CONF" ]; then
|
|
echo "ERROR: rc.conf not found" >&2
|
|
return 1
|
|
fi
|
|
|
|
# Check timezone is set
|
|
if ! grep -q "^timezone=" "$RC_CONF"; then
|
|
echo "ERROR: timezone not set in rc.conf" >&2
|
|
return 1
|
|
fi
|
|
|
|
# Check hostname file exists
|
|
if [ ! -f "$HOSTNAME_FILE" ]; then
|
|
echo "ERROR: $HOSTNAME_FILE not created" >&2
|
|
return 1
|
|
fi
|
|
|
|
# Check mac_do framework config exists. Empty rules intentionally grant no
|
|
# credential transitions.
|
|
if ! grep -q '^mac_do_load="YES"' "$LOADER_CONF" 2>/dev/null; then
|
|
echo "ERROR: mac_do_load not set in $LOADER_CONF" >&2
|
|
return 1
|
|
fi
|
|
if ! grep -q '^security.mac.do.rules=' "$SYSCTL_CONF" 2>/dev/null; then
|
|
echo "ERROR: security.mac.do.rules not set in $SYSCTL_CONF" >&2
|
|
return 1
|
|
fi
|
|
|
|
if ! grep -q '^net.link.tap.up_on_open=1$' "$SYSCTL_CONF" 2>/dev/null; then
|
|
echo "ERROR: net.link.tap.up_on_open not set in $SYSCTL_CONF" >&2
|
|
return 1
|
|
fi
|
|
|
|
# Check environment profile exists
|
|
if [ ! -f "$PROFILE_DIR/clawdie.sh" ]; then
|
|
echo "ERROR: $PROFILE_DIR/clawdie.sh not created" >&2
|
|
return 1
|
|
fi
|
|
|
|
if ! grep -q '^linux_enable=YES$' "$RC_CONF" 2>/dev/null; then
|
|
echo "ERROR: linux_enable not set in $RC_CONF" >&2
|
|
return 1
|
|
fi
|
|
|
|
if ! grep -q '^vm_enable=YES$' "$RC_CONF" 2>/dev/null; then
|
|
echo "ERROR: vm_enable not set in $RC_CONF" >&2
|
|
return 1
|
|
fi
|
|
|
|
if ! grep -q '^kld_list=' "$RC_CONF" 2>/dev/null; then
|
|
echo "ERROR: kld_list not set in $RC_CONF" >&2
|
|
return 1
|
|
fi
|
|
|
|
log_msg "[system] Validation passed"
|
|
return 0
|
|
}
|
|
|
|
# ============================================================================
|
|
# UTILITY: Logging
|
|
# ============================================================================
|
|
|
|
log_msg() {
|
|
local msg="$1"
|
|
echo "$msg" >> "$LOG_FILE" 2>/dev/null || true
|
|
}
|
|
|
|
# ============================================================================
|
|
# Export for use by firstboot.sh
|
|
# ============================================================================
|
|
|
|
case "${0##*/}" in
|
|
clawdie-shell-system.sh)
|
|
# Direct execution (for testing)
|
|
clawdie_shell_system_config
|
|
clawdie_shell_system_validate
|
|
;;
|
|
*)
|
|
# Sourced from another script — functions available
|
|
;;
|
|
esac
|