Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 23 additions & 4 deletions mtproxymax.sh
Original file line number Diff line number Diff line change
Expand Up @@ -525,9 +525,21 @@ detect_os() {
fi
}

# True only when systemd is actually running as PID 1. Testing for the `systemctl`
# binary alone is not enough: a chroot, a container that pulled systemd in as a
# dependency, and a half-booted host all have the binary while every systemctl call
# fails. `systemctl --version` is no better — it exits 0 with no bus at all.
_systemd_is_running() {
[ -d /run/systemd/system ] || return 1
local _state
_state=$(systemctl is-system-running 2>/dev/null) || true
# "degraded" still means booted, so this compares the value rather than the status.
[ -n "$_state" ] && [ "$_state" != "offline" ]
}

# Detect the host init system: systemd | openrc | none
detect_init_system() {
if command -v systemctl &>/dev/null; then
if _systemd_is_running; then
echo "systemd"
elif [ -x /sbin/openrc-run ] || command -v rc-service &>/dev/null; then
echo "openrc"
Expand Down Expand Up @@ -13560,9 +13572,16 @@ ExecStop=/usr/local/bin/mtproxymax stop
WantedBy=multi-user.target
AUTOSTART_EOF

systemctl daemon-reload
systemctl enable mtproxymax.service 2>/dev/null
log_success "Auto-start enabled (systemd)"
systemctl daemon-reload >/dev/null 2>&1 || true
# Check the result instead of discarding it. `systemctl enable` exits non-zero when
# there is no systemd to talk to (the not-booted case), so the old unconditional
# log_success told users autostart was on when nothing had been enabled.
if systemctl enable mtproxymax.service >/dev/null 2>&1; then
log_success "Auto-start enabled (systemd)"
else
log_warn "Could not enable auto-start — run: systemctl enable mtproxymax"
return 1
fi
;;
openrc)
# Type=oneshot + RemainAfterExit=yes wraps the manager's own start/stop,
Expand Down
147 changes: 147 additions & 0 deletions tests/test_init_detection.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
#!/bin/bash
# Regression tests for init-system detection and autostart reporting.
#
# detect_init_system() tested for the presence of the `systemctl` *binary*, not for systemd
# actually running as PID 1. In a chroot, in a container that pulled systemd in as a
# dependency, or on a half-booted host, it reported "systemd" — and the systemd branch of
# setup_autostart() then ran `systemctl daemon-reload` and `systemctl enable` with no
# status check and printed "Auto-start enabled (systemd)" regardless. The user was told
# autostart was enabled when nothing had been enabled.
#
# The OpenRC branch directly below it already verifies (openrc_enable_service checks that
# the runlevel symlink landed) and returns 1 with a warning. These tests assert the
# systemd branch behaves the same way.
set -o pipefail

if [ "${BASH_VERSINFO[0]:-0}" -lt 4 ]; then
echo "SKIP: bash 4+ required (got ${BASH_VERSION:-unknown})" >&2
exit 0
fi

TEST_TMPDIR=$(mktemp -d 2>/dev/null || mktemp -d -t 'mtp_init_XXXXXX')

# A systemctl whose behaviour is driven by the environment, so both "not booted" and
# "booted but enable fails" can be reproduced without a real init system.
FAKEBIN="$TEST_TMPDIR/bin"
mkdir -p "$FAKEBIN"
cat >"$FAKEBIN/systemctl" <<'SYSTEMCTL_EOF'
#!/bin/bash
case "${1:-}" in
is-system-running)
echo "${FAKE_SYSTEMD_STATE:-offline}"
[ "${FAKE_SYSTEMD_STATE:-offline}" = "offline" ] && exit 1
exit 0
;;
is-enabled)
echo "${FAKE_IS_ENABLED:-disabled}"
[ "${FAKE_IS_ENABLED:-disabled}" = "enabled" ] && exit 0
exit 1
;;
enable) exit "${FAKE_ENABLE_RC:-0}" ;;
*) exit 0 ;;
esac
SYSTEMCTL_EOF
chmod +x "$FAKEBIN/systemctl"
PATH="$FAKEBIN:$PATH"
export PATH

MTPROXYMAX_SOURCE_ONLY=true source "$(dirname "${BASH_SOURCE[0]}")/../mtproxymax.sh"
set +e

# setup_autostart writes to ${SYSTEMD_DIR}; keep it inside the sandbox.
SYSTEMD_DIR="$TEST_TMPDIR/systemd"
mkdir -p "$SYSTEMD_DIR"

# Real systemd installs have this directory; its absence is how a not-booted host looks.
RUNDIR=/run/systemd/system
RUNDIR_PREEXISTED=0
[ -d "$RUNDIR" ] && RUNDIR_PREEXISTED=1

cleanup() {
[ "$RUNDIR_PREEXISTED" -eq 0 ] && rmdir "$RUNDIR" 2>/dev/null
rmdir /run/systemd 2>/dev/null
rm -rf "$TEST_TMPDIR"
}
trap cleanup EXIT

TESTS_RUN=0
TESTS_FAILED=0

assert_eq() {
local name="$1" want="$2" got="$3"
TESTS_RUN=$((TESTS_RUN + 1))
if [ "$got" = "$want" ]; then
printf ' PASS %s\n' "$name"
else
printf ' FAIL %s (got=%q want=%q)\n' "$name" "$got" "$want"
TESTS_FAILED=$((TESTS_FAILED + 1))
fi
}

assert_ne() {
local name="$1" unwanted="$2" got="$3"
TESTS_RUN=$((TESTS_RUN + 1))
if [ "$got" != "$unwanted" ]; then
printf ' PASS %s\n' "$name"
else
printf ' FAIL %s (unexpectedly %q)\n' "$name" "$got"
TESTS_FAILED=$((TESTS_FAILED + 1))
fi
}

LOG_SUCCESS=""
LOG_WARN=""
log_success() { LOG_SUCCESS="$*"; }
log_warn() { LOG_WARN="$*"; }
log_info() { :; }
log_error() { :; }

echo "init detection tests"

# The stub must be the systemctl that resolves, or none of this proves anything.
assert_eq "stub systemctl is on PATH" "$FAKEBIN/systemctl" "$(command -v systemctl)"
assert_eq "no OpenRC present to fall back to" "absent" \
"$([ -x /sbin/openrc-run ] || command -v rc-service >/dev/null 2>&1 && echo present || echo absent)"

# --- systemctl exists but systemd is not running ---------------------------------
# This is the chroot / container / half-booted case.
rm -rf "$RUNDIR"
export FAKE_SYSTEMD_STATE=offline

assert_ne "binary present but not booted is not detected as systemd" "systemd" "$(detect_init_system)"

LOG_SUCCESS=""
LOG_WARN=""
setup_autostart >/dev/null 2>&1
assert_ne "setup_autostart does not report success" "0" "$?"
assert_eq "no success message is printed" "" "$LOG_SUCCESS"
assert_ne "a warning is printed instead" "" "$LOG_WARN"

# --- systemd running, but enabling the unit fails ---------------------------------
# The unit file is still written; what must not happen is reporting success.
mkdir -p "$RUNDIR"
export FAKE_SYSTEMD_STATE=running
export FAKE_ENABLE_RC=1
export FAKE_IS_ENABLED=disabled

assert_eq "booted systemd is detected" "systemd" "$(detect_init_system)"

LOG_SUCCESS=""
LOG_WARN=""
setup_autostart >/dev/null 2>&1
assert_ne "a failed enable does not report success" "0" "$?"
assert_eq "no success message on a failed enable" "" "$LOG_SUCCESS"

# --- and the happy path must still work -------------------------------------------
FAKE_ENABLE_RC=0
FAKE_IS_ENABLED=enabled
export FAKE_ENABLE_RC FAKE_IS_ENABLED

LOG_SUCCESS=""
LOG_WARN=""
setup_autostart >/dev/null 2>&1
assert_eq "a working enable reports success" "0" "$?"
assert_ne "success message is printed when it really succeeded" "" "$LOG_SUCCESS"

printf '\n%d tests, %d failures\n' "$TESTS_RUN" "$TESTS_FAILED"
[ "$TESTS_FAILED" -eq 0 ]