* add support for systemd, OpenRC, SysVinit, and Dinit * add automatic init-system detection through CMake * make libsystemd optional for non-systemd builds * add native service definitions for all supported init systems * add Gentoo ebuild and Alpine APKBUILD packaging support * publish the official BastionGuard source repository * update the README with supported distributions, init systems, repository information, and build documentation
1041 lines
31 KiB
Bash
Executable file
1041 lines
31 KiB
Bash
Executable file
#!/bin/sh
|
|
# BastionGuard service-manager compatibility layer.
|
|
# Supports systemd, OpenRC, SysVinit and Dinit, plus per-user services when
|
|
# no native user service manager is available.
|
|
|
|
set -u
|
|
|
|
SELF=/usr/libexec/bastionguard/bastionguard-service
|
|
CONFIG=/usr/libexec/bastionguard/bastionguard-init-config
|
|
BG_DINIT_SYSTEM_DIR=/etc/dinit.d
|
|
BG_DINIT_USER_DIR=/usr/lib/dinit.d/user
|
|
BG_DINIT_ENABLE_DIR=/etc/dinit.d/bastionguard.d
|
|
if [ -r "$CONFIG" ]; then
|
|
# Generated by CMake and installed as root-owned package data.
|
|
. "$CONFIG"
|
|
fi
|
|
scope=system
|
|
|
|
usage() {
|
|
cat >&2 <<USAGE
|
|
usage: bastionguard-service [--system|--user] ACTION [OPTIONS] [UNIT]
|
|
|
|
Actions:
|
|
backend, daemon-reload, exists, is-active, is-enabled, status
|
|
start, stop, restart, reload, try-restart, try-reload-or-restart
|
|
enable [--now], disable [--now], logs [LINES]
|
|
start-enabled (user scope only)
|
|
USAGE
|
|
exit 64
|
|
}
|
|
|
|
case "${1-}" in
|
|
--system) scope=system; shift ;;
|
|
--user) scope=user; shift ;;
|
|
esac
|
|
|
|
[ "$#" -gt 0 ] || usage
|
|
action=$1
|
|
shift
|
|
|
|
valid_unit() {
|
|
case "$1" in
|
|
""|*[!A-Za-z0-9_.@:-]*) return 1 ;;
|
|
*) return 0 ;;
|
|
esac
|
|
}
|
|
|
|
strip_unit_suffix() {
|
|
value=$1
|
|
case "$value" in
|
|
*.timer) value=${value%.timer}-timer ;;
|
|
*.service) value=${value%.service} ;;
|
|
esac
|
|
printf '%s\n' "$value"
|
|
}
|
|
|
|
detect_backend() {
|
|
if [ -d /run/openrc ] && command -v rc-service >/dev/null 2>&1; then
|
|
printf '%s\n' openrc
|
|
return
|
|
fi
|
|
if [ -d /run/systemd/system ] && command -v systemctl >/dev/null 2>&1; then
|
|
printf '%s\n' systemd
|
|
return
|
|
fi
|
|
if { [ -S /dev/dinitctl ] || [ -S /run/dinitctl ]; } && command -v dinitctl >/dev/null 2>&1; then
|
|
printf '%s\n' dinit
|
|
return
|
|
fi
|
|
|
|
init_real=$(readlink -f /sbin/init 2>/dev/null || readlink -f /usr/sbin/init 2>/dev/null || true)
|
|
case "$init_real" in
|
|
*openrc*) printf '%s\n' openrc; return ;;
|
|
*systemd*) printf '%s\n' systemd; return ;;
|
|
*/dinit|*/dinit-*) printf '%s\n' dinit; return ;;
|
|
*sysvinit*) printf '%s\n' sysvinit; return ;;
|
|
esac
|
|
|
|
if command -v rc-service >/dev/null 2>&1 && command -v openrc-run >/dev/null 2>&1; then
|
|
printf '%s\n' openrc
|
|
elif command -v dinitctl >/dev/null 2>&1 && ! command -v systemctl >/dev/null 2>&1; then
|
|
printf '%s\n' dinit
|
|
elif command -v systemctl >/dev/null 2>&1; then
|
|
printf '%s\n' systemd
|
|
elif [ -d /etc/init.d ]; then
|
|
printf '%s\n' sysvinit
|
|
else
|
|
printf '%s\n' unknown
|
|
fi
|
|
}
|
|
|
|
backend=$(detect_backend)
|
|
|
|
systemd_user_available() {
|
|
[ "$backend" = systemd ] || return 1
|
|
command -v systemctl >/dev/null 2>&1 || return 1
|
|
user_dirs >/dev/null 2>&1 || true
|
|
systemctl --user show-environment >/dev/null 2>&1
|
|
}
|
|
|
|
dinit_user_available() {
|
|
[ "$backend" = dinit ] || return 1
|
|
command -v dinitctl >/dev/null 2>&1 || return 1
|
|
user_dirs >/dev/null 2>&1 || true
|
|
dinitctl --user list >/dev/null 2>&1
|
|
}
|
|
|
|
service_candidates() {
|
|
original=$1
|
|
base=$(strip_unit_suffix "$original")
|
|
printf '%s\n' "$base"
|
|
|
|
case "$base" in
|
|
clamd@scan|clamd.scan)
|
|
printf '%s\n' clamd
|
|
printf '%s\n' clamav-daemon
|
|
;;
|
|
clamd)
|
|
printf '%s\n' clamav-daemon
|
|
;;
|
|
clamav-daemon)
|
|
printf '%s\n' clamd
|
|
;;
|
|
clamav-freshclam)
|
|
printf '%s\n' freshclam
|
|
;;
|
|
clamav-clamonacc)
|
|
printf '%s\n' clamonacc
|
|
;;
|
|
esac
|
|
}
|
|
|
|
dinit_system_service_dirs() {
|
|
printf '%s\n' \
|
|
"$BG_DINIT_SYSTEM_DIR" \
|
|
/etc/dinit.d \
|
|
/run/dinit.d \
|
|
/usr/local/lib/dinit.d \
|
|
/usr/lib/dinit.d \
|
|
/lib/dinit.d
|
|
}
|
|
|
|
dinit_user_service_dirs() {
|
|
config_home=${XDG_CONFIG_HOME:-${HOME:-/tmp}/.config}
|
|
printf '%s\n' \
|
|
"$config_home/dinit.d" \
|
|
"${HOME:-/tmp}/.config/dinit.d" \
|
|
"$BG_DINIT_USER_DIR" \
|
|
/etc/dinit.d/user \
|
|
/usr/lib/dinit.d/user \
|
|
/usr/local/lib/dinit.d/user
|
|
}
|
|
|
|
dinit_service_file_exists() {
|
|
service_name=$1
|
|
for service_dir in $(dinit_system_service_dirs); do
|
|
[ -f "$service_dir/$service_name" ] && return 0
|
|
done
|
|
return 1
|
|
}
|
|
|
|
dinit_user_service_file_exists() {
|
|
service_name=$1
|
|
for service_dir in $(dinit_user_service_dirs); do
|
|
[ -f "$service_dir/$service_name" ] && return 0
|
|
done
|
|
return 1
|
|
}
|
|
|
|
dinit_system_enable_dir() {
|
|
printf '%s\n' "$BG_DINIT_ENABLE_DIR"
|
|
}
|
|
|
|
dinit_system_managed_services() {
|
|
printf '%s\n' \
|
|
bastionguard \
|
|
BastionGuard-phishing-scanner \
|
|
BastionGuard-phishing-updater \
|
|
BastionGuard-phishing-updater-timer \
|
|
BastionGuard-ransomware-realtime \
|
|
bastionguard-sanesecurity \
|
|
bastionguard-sanesecurity-timer \
|
|
BastionGuard-usbd \
|
|
clamav-clamonacc \
|
|
bsc-daemon
|
|
}
|
|
|
|
dinit_user_managed_services() {
|
|
printf '%s\n' \
|
|
BastionGuard-useragent \
|
|
BastionGuard-privacyd \
|
|
BastionGuard-ransomware-alert \
|
|
BastionGuard-ransomware-realtime-alert \
|
|
BastionGuard-ransomware-scanner \
|
|
BastionGuard-pacd \
|
|
BastionGuard-mailproxy \
|
|
BastionGuard-user-session-watch \
|
|
BastionGuard-cef
|
|
}
|
|
|
|
find_native_service() {
|
|
unit=$1
|
|
for candidate in $(service_candidates "$unit"); do
|
|
case "$backend" in
|
|
openrc|sysvinit)
|
|
if [ -x "/etc/init.d/$candidate" ]; then
|
|
printf '%s\n' "$candidate"
|
|
return 0
|
|
fi
|
|
;;
|
|
dinit)
|
|
if dinit_service_file_exists "$candidate" ||
|
|
dinitctl status "$candidate" >/dev/null 2>&1; then
|
|
printf '%s\n' "$candidate"
|
|
return 0
|
|
fi
|
|
;;
|
|
systemd)
|
|
printf '%s\n' "$unit"
|
|
return 0
|
|
;;
|
|
esac
|
|
done
|
|
return 1
|
|
}
|
|
|
|
system_exists() {
|
|
unit=$1
|
|
case "$backend" in
|
|
systemd)
|
|
systemctl cat "$unit" >/dev/null 2>&1
|
|
;;
|
|
openrc|sysvinit|dinit)
|
|
find_native_service "$unit" >/dev/null 2>&1
|
|
;;
|
|
*) return 1 ;;
|
|
esac
|
|
}
|
|
|
|
system_active() {
|
|
unit=$1
|
|
case "$backend" in
|
|
systemd)
|
|
systemctl is-active --quiet "$unit"
|
|
;;
|
|
openrc)
|
|
native=$(find_native_service "$unit") || return 3
|
|
rc-service "$native" status >/dev/null 2>&1
|
|
;;
|
|
dinit)
|
|
native=$(find_native_service "$unit") || return 3
|
|
dinitctl is-started "$native" >/dev/null 2>&1
|
|
;;
|
|
sysvinit)
|
|
native=$(find_native_service "$unit") || return 3
|
|
if command -v service >/dev/null 2>&1; then
|
|
service "$native" status >/dev/null 2>&1
|
|
else
|
|
"/etc/init.d/$native" status >/dev/null 2>&1
|
|
fi
|
|
;;
|
|
*) return 3 ;;
|
|
esac
|
|
}
|
|
|
|
system_enabled() {
|
|
unit=$1
|
|
case "$backend" in
|
|
systemd)
|
|
systemctl is-enabled --quiet "$unit"
|
|
;;
|
|
openrc)
|
|
native=$(find_native_service "$unit") || return 1
|
|
rc-update show 2>/dev/null | awk -v svc="$native" '
|
|
$1 == svc { found=1 }
|
|
END { exit(found ? 0 : 1) }
|
|
'
|
|
;;
|
|
dinit)
|
|
native=$(find_native_service "$unit") || return 1
|
|
enable_dir=$(dinit_system_enable_dir)
|
|
if [ -e "$enable_dir/$native" ] || [ -L "$enable_dir/$native" ]; then
|
|
return 0
|
|
fi
|
|
for service_dir in $(dinit_system_service_dirs); do
|
|
find "$service_dir" -mindepth 2 -maxdepth 2 -type l \
|
|
-name "$native" -print -quit 2>/dev/null | grep -q . &&
|
|
return 0
|
|
done
|
|
return 1
|
|
;;
|
|
sysvinit)
|
|
native=$(find_native_service "$unit") || return 1
|
|
if command -v chkconfig >/dev/null 2>&1; then
|
|
chkconfig --list "$native" 2>/dev/null | grep -Eq '(^|[[:space:]])[2-5]:on([[:space:]]|$)'
|
|
else
|
|
find /etc/rc?.d -maxdepth 1 -type l -name "S??$native" -print -quit 2>/dev/null | grep -q .
|
|
fi
|
|
;;
|
|
*) return 1 ;;
|
|
esac
|
|
}
|
|
|
|
system_call() {
|
|
op=$1
|
|
unit=$2
|
|
|
|
case "$backend" in
|
|
systemd)
|
|
systemctl "$op" "$unit"
|
|
;;
|
|
openrc)
|
|
native=$(find_native_service "$unit") || return 5
|
|
rc-service "$native" "$op"
|
|
;;
|
|
dinit)
|
|
native=$(find_native_service "$unit") || return 5
|
|
case "$op" in
|
|
reload)
|
|
case "$native" in
|
|
bsc-daemon) return 3 ;;
|
|
BastionGuard-phishing-updater|bastionguard-sanesecurity)
|
|
return 3
|
|
;;
|
|
esac
|
|
dinitctl signal HUP "$native"
|
|
;;
|
|
*) dinitctl "$op" "$native" ;;
|
|
esac
|
|
;;
|
|
sysvinit)
|
|
native=$(find_native_service "$unit") || return 5
|
|
if command -v service >/dev/null 2>&1; then
|
|
service "$native" "$op"
|
|
else
|
|
"/etc/init.d/$native" "$op"
|
|
fi
|
|
;;
|
|
*) return 5 ;;
|
|
esac
|
|
}
|
|
|
|
system_enable() {
|
|
unit=$1
|
|
native=$(find_native_service "$unit" 2>/dev/null || true)
|
|
case "$backend" in
|
|
systemd) systemctl enable "$unit" ;;
|
|
openrc)
|
|
[ -n "$native" ] || return 5
|
|
rc-update add "$native" default
|
|
;;
|
|
dinit)
|
|
[ -n "$native" ] || return 5
|
|
mkdir -p "$(dinit_system_enable_dir)" || return 73
|
|
if dinit_service_file_exists bastionguard; then
|
|
if ! dinitctl enable bastionguard >/dev/null 2>&1; then
|
|
system_enabled bastionguard || return 5
|
|
fi
|
|
fi
|
|
dinitctl enable "$native"
|
|
;;
|
|
sysvinit)
|
|
[ -n "$native" ] || return 5
|
|
if command -v update-rc.d >/dev/null 2>&1; then
|
|
update-rc.d "$native" defaults >/dev/null
|
|
update-rc.d "$native" enable >/dev/null 2>&1 || true
|
|
elif command -v chkconfig >/dev/null 2>&1; then
|
|
chkconfig --add "$native" >/dev/null 2>&1 || true
|
|
chkconfig "$native" on
|
|
else
|
|
return 5
|
|
fi
|
|
;;
|
|
*) return 5 ;;
|
|
esac
|
|
}
|
|
|
|
system_disable() {
|
|
unit=$1
|
|
native=$(find_native_service "$unit" 2>/dev/null || true)
|
|
case "$backend" in
|
|
systemd) systemctl disable "$unit" ;;
|
|
openrc)
|
|
[ -n "$native" ] || return 5
|
|
rc-update del "$native" default
|
|
;;
|
|
dinit)
|
|
[ -n "$native" ] || return 5
|
|
dinitctl disable "$native"
|
|
;;
|
|
sysvinit)
|
|
[ -n "$native" ] || return 5
|
|
if command -v update-rc.d >/dev/null 2>&1; then
|
|
update-rc.d "$native" disable >/dev/null 2>&1 || \
|
|
update-rc.d -f "$native" remove >/dev/null
|
|
elif command -v chkconfig >/dev/null 2>&1; then
|
|
chkconfig "$native" off
|
|
else
|
|
return 5
|
|
fi
|
|
;;
|
|
*) return 5 ;;
|
|
esac
|
|
}
|
|
|
|
system_logs() {
|
|
unit=$1
|
|
lines=${2:-100}
|
|
case "$lines" in *[!0-9]*|"") lines=100 ;; esac
|
|
|
|
if [ "$backend" = systemd ] && command -v journalctl >/dev/null 2>&1; then
|
|
exec journalctl -u "$unit" -n "$lines" --no-pager
|
|
fi
|
|
if [ "$backend" = dinit ] && command -v dinitctl >/dev/null 2>&1; then
|
|
native=$(find_native_service "$unit") || return 1
|
|
dinitctl catlog "$native" 2>/dev/null | tail -n "$lines"
|
|
return 0
|
|
fi
|
|
|
|
base=$(strip_unit_suffix "$unit")
|
|
for logfile in \
|
|
"/var/log/BastionGuard/$base.log" \
|
|
"/var/log/bastionguard-secure-connectiond.log" \
|
|
"/var/log/clamav/clamonacc.log" \
|
|
"/var/log/clamav/clamav.log" \
|
|
"/var/log/clamav/clamd.log" \
|
|
"/var/log/clamav/freshclam.log" \
|
|
/var/log/messages /var/log/syslog; do
|
|
if [ -r "$logfile" ]; then
|
|
tail -n "$lines" "$logfile"
|
|
return $?
|
|
fi
|
|
done
|
|
return 1
|
|
}
|
|
|
|
user_dirs() {
|
|
uid=$(id -u)
|
|
runtime=${XDG_RUNTIME_DIR:-/run/user/$uid}
|
|
if [ ! -d "$runtime" ] || [ ! -w "$runtime" ]; then
|
|
runtime=${TMPDIR:-/tmp}/bastionguard-runtime-$uid
|
|
mkdir -p "$runtime" 2>/dev/null || return 73
|
|
chmod 0700 "$runtime" 2>/dev/null || true
|
|
fi
|
|
|
|
XDG_RUNTIME_DIR=$runtime
|
|
export XDG_RUNTIME_DIR
|
|
if [ -S "$runtime/bus" ] && [ -z "${DBUS_SESSION_BUS_ADDRESS:-}" ]; then
|
|
DBUS_SESSION_BUS_ADDRESS=unix:path=$runtime/bus
|
|
export DBUS_SESSION_BUS_ADDRESS
|
|
fi
|
|
|
|
config_home=${XDG_CONFIG_HOME:-${HOME:-/tmp}/.config}
|
|
state_home=${XDG_STATE_HOME:-${HOME:-/tmp}/.local/state}
|
|
user_enable_dir=$config_home/BastionGuard/services
|
|
user_state_dir=$state_home/BastionGuard/services
|
|
user_runtime_dir=$runtime/BastionGuard/services
|
|
mkdir -p "$user_enable_dir" "$user_state_dir" "$user_runtime_dir" 2>/dev/null || return 73
|
|
}
|
|
|
|
user_name() {
|
|
strip_unit_suffix "$1"
|
|
}
|
|
|
|
user_command() {
|
|
name=$(user_name "$1")
|
|
USER_WORKDIR=${HOME:-/}
|
|
USER_RESTART=always
|
|
USER_RESTART_DELAY=3
|
|
|
|
case "$name" in
|
|
BastionGuard-useragent)
|
|
set -- /usr/bin/BastionGuard-ransomware-alert
|
|
;;
|
|
BastionGuard-ransomware-alert)
|
|
USER_RESTART=on-failure
|
|
set -- /usr/bin/BastionGuard-ransomware-alert
|
|
;;
|
|
BastionGuard-privacyd)
|
|
set -- /usr/bin/BastionGuard-privacyd
|
|
;;
|
|
BastionGuard-ransomware-realtime-alert)
|
|
set -- /usr/bin/BastionGuard-ransomware-realtime-alert
|
|
;;
|
|
BastionGuard-ransomware-scanner)
|
|
USER_WORKDIR=${HOME:-/tmp}/.local/share/BastionGuard
|
|
set -- /usr/bin/BastionGuard-ransomware-scanner \
|
|
--0day-protection \
|
|
/usr/share/BastionGuard/data/0day_ransomware_protection/ZeroDay.yara
|
|
;;
|
|
BastionGuard-pacd|bastionguard-pacd)
|
|
set -- /usr/bin/bastionguard-pacd \
|
|
--listen 127.0.0.1 --port 8765 \
|
|
--stub-host 127.0.0.1 --stub-port 3129 \
|
|
--backend-host 127.0.0.1 --backend-port 3130 \
|
|
--trigger-cmd "$SELF --user start BastionGuard-cef.service" \
|
|
--backend-wait-ms 4000
|
|
;;
|
|
BastionGuard-mailproxy)
|
|
set -- /usr/bin/BastionGuard-mailproxy
|
|
;;
|
|
BastionGuard-user-session-watch)
|
|
set -- /usr/share/BastionGuard/data/scripts/BastionGuard-user-session-watch.sh
|
|
;;
|
|
BastionGuard-cef)
|
|
set -- /usr/bin/bastionguard-cef --listen 127.0.0.1 --port 3130
|
|
;;
|
|
*) return 5 ;;
|
|
esac
|
|
|
|
[ -x "$1" ] || return 5
|
|
USER_DAEMON=$1
|
|
shift
|
|
# Store the positional parameters as quoted shell text used only inside this
|
|
# process. Values above are constants, not user-provided strings.
|
|
USER_ARGS=""
|
|
for arg in "$@"; do
|
|
escaped=$(printf '%s' "$arg" | sed "s/'/'\\\\''/g")
|
|
USER_ARGS="$USER_ARGS '$escaped'"
|
|
done
|
|
return 0
|
|
}
|
|
|
|
user_pidfile() {
|
|
user_dirs || return $?
|
|
name=$(user_name "$1")
|
|
printf '%s/%s.pid\n' "$user_runtime_dir" "$name"
|
|
}
|
|
|
|
user_logfile() {
|
|
user_dirs || return $?
|
|
name=$(user_name "$1")
|
|
printf '%s/%s.log\n' "$user_state_dir" "$name"
|
|
}
|
|
|
|
user_fallback_active() {
|
|
pidfile=$(user_pidfile "$1")
|
|
[ -r "$pidfile" ] || return 3
|
|
pid=$(cat "$pidfile" 2>/dev/null || true)
|
|
case "$pid" in *[!0-9]*|"") return 3 ;; esac
|
|
kill -0 "$pid" 2>/dev/null
|
|
}
|
|
|
|
user_fallback_start() {
|
|
unit=$1
|
|
user_fallback_active "$unit" && return 0
|
|
user_command "$unit" || return $?
|
|
|
|
pidfile=$(user_pidfile "$unit") || return $?
|
|
logfile=$(user_logfile "$unit") || return $?
|
|
rm -f "$pidfile"
|
|
|
|
# USER_ARGS is assembled exclusively from the constant command table.
|
|
eval "set -- '$USER_DAEMON' $USER_ARGS"
|
|
mkdir -p "$USER_WORKDIR" 2>/dev/null || return 73
|
|
nohup /usr/libexec/bastionguard/bastionguard-supervise \
|
|
--restart "$USER_RESTART" \
|
|
--delay "$USER_RESTART_DELAY" \
|
|
--chdir "$USER_WORKDIR" -- "$@" >>"$logfile" 2>&1 &
|
|
pid=$!
|
|
printf '%s\n' "$pid" > "$pidfile"
|
|
sleep 1
|
|
if kill -0 "$pid" 2>/dev/null; then
|
|
return 0
|
|
fi
|
|
rm -f "$pidfile"
|
|
return 1
|
|
}
|
|
|
|
user_fallback_stop() {
|
|
unit=$1
|
|
pidfile=$(user_pidfile "$unit") || return $?
|
|
[ -r "$pidfile" ] || return 0
|
|
pid=$(cat "$pidfile" 2>/dev/null || true)
|
|
case "$pid" in *[!0-9]*|"") rm -f "$pidfile"; return 0 ;; esac
|
|
|
|
kill "$pid" 2>/dev/null || true
|
|
count=0
|
|
while kill -0 "$pid" 2>/dev/null && [ "$count" -lt 50 ]; do
|
|
sleep 0.1
|
|
count=$((count + 1))
|
|
done
|
|
if kill -0 "$pid" 2>/dev/null; then
|
|
kill -KILL "$pid" 2>/dev/null || true
|
|
fi
|
|
rm -f "$pidfile"
|
|
return 0
|
|
}
|
|
|
|
user_fallback_enabled() {
|
|
user_dirs || return $?
|
|
name=$(user_name "$1")
|
|
[ -f "$user_enable_dir/$name.enabled" ]
|
|
}
|
|
|
|
user_fallback_enable() {
|
|
user_dirs || return $?
|
|
name=$(user_name "$1")
|
|
user_command "$1" || return $?
|
|
: > "$user_enable_dir/$name.enabled"
|
|
}
|
|
|
|
user_fallback_disable() {
|
|
user_dirs || return $?
|
|
name=$(user_name "$1")
|
|
rm -f "$user_enable_dir/$name.enabled"
|
|
}
|
|
|
|
user_fallback_start_enabled() {
|
|
user_dirs || return $?
|
|
found=0
|
|
for marker in "$user_enable_dir"/*.enabled; do
|
|
[ -e "$marker" ] || continue
|
|
found=1
|
|
name=$(basename "$marker" .enabled)
|
|
user_fallback_start "$name.service" || true
|
|
done
|
|
[ "$found" -eq 1 ] || return 0
|
|
}
|
|
|
|
user_fallback_logs() {
|
|
logfile=$(user_logfile "$1") || return $?
|
|
lines=${2:-100}
|
|
case "$lines" in *[!0-9]*|"") lines=100 ;; esac
|
|
[ -r "$logfile" ] || return 1
|
|
tail -n "$lines" "$logfile"
|
|
}
|
|
|
|
user_dinit_enabled() {
|
|
user_dirs || return $?
|
|
name=$(user_name "$1")
|
|
[ -f "$user_enable_dir/$name.dinit-enabled" ]
|
|
}
|
|
|
|
user_dinit_enable() {
|
|
user_dirs || return $?
|
|
name=$(user_name "$1")
|
|
dinit_user_service_file_exists "$name" || return 5
|
|
# Use Dinit's native boot dependency when the user manager provides one.
|
|
# The marker remains as a portable fallback started by XDG Autostart.
|
|
dinitctl --user enable "$name" >/dev/null 2>&1 || true
|
|
: > "$user_enable_dir/$name.dinit-enabled"
|
|
}
|
|
|
|
user_dinit_disable() {
|
|
user_dirs || return $?
|
|
name=$(user_name "$1")
|
|
dinitctl --user disable "$name" >/dev/null 2>&1 || true
|
|
rm -f "$user_enable_dir/$name.dinit-enabled"
|
|
}
|
|
|
|
user_dinit_start_enabled() {
|
|
user_dirs || return $?
|
|
for marker in "$user_enable_dir"/*.dinit-enabled; do
|
|
[ -e "$marker" ] || continue
|
|
name=$(basename "$marker" .dinit-enabled)
|
|
dinitctl --user start "$name" >/dev/null 2>&1 || true
|
|
done
|
|
}
|
|
|
|
user_systemd() {
|
|
exec systemctl --user "$@"
|
|
}
|
|
|
|
if [ "$action" = backend ]; then
|
|
if [ "$scope" = user ]; then
|
|
if systemd_user_available; then
|
|
printf '%s\n' systemd
|
|
elif dinit_user_available; then
|
|
printf '%s\n' dinit
|
|
else
|
|
printf '%s\n' user-supervisor
|
|
fi
|
|
else
|
|
printf '%s\n' "$backend"
|
|
fi
|
|
exit 0
|
|
fi
|
|
|
|
if [ "$scope" = user ]; then
|
|
if systemd_user_available; then
|
|
case "$action" in
|
|
start-enabled)
|
|
# Enabled systemd user units are started by the user manager.
|
|
exit 0
|
|
;;
|
|
logs)
|
|
[ "$#" -ge 1 ] || usage
|
|
unit=$1; lines=${2:-100}
|
|
valid_unit "$unit" || exit 64
|
|
exec journalctl --user -u "$unit" -n "$lines" --no-pager
|
|
;;
|
|
exists)
|
|
[ "$#" -eq 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
systemctl --user cat "$1" >/dev/null 2>&1
|
|
exit $?
|
|
;;
|
|
daemon-reload)
|
|
user_systemd daemon-reload
|
|
;;
|
|
enable|disable)
|
|
now=0
|
|
if [ "${1-}" = --now ]; then now=1; shift; fi
|
|
[ "$#" -eq 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
if [ "$now" -eq 1 ]; then
|
|
user_systemd "$action" --now "$1"
|
|
else
|
|
user_systemd "$action" "$1"
|
|
fi
|
|
;;
|
|
is-active)
|
|
[ "$#" -eq 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
if systemctl --user is-active --quiet "$1"; then
|
|
printf '%s\n' active
|
|
exit 0
|
|
else
|
|
rc=$?
|
|
printf '%s\n' inactive
|
|
exit "$rc"
|
|
fi
|
|
;;
|
|
is-enabled)
|
|
[ "$#" -eq 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
if systemctl --user is-enabled --quiet "$1"; then
|
|
printf '%s\n' enabled
|
|
exit 0
|
|
else
|
|
rc=$?
|
|
printf '%s\n' disabled
|
|
exit "$rc"
|
|
fi
|
|
;;
|
|
try-restart)
|
|
[ "$#" -eq 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
systemctl --user try-restart "$1"
|
|
exit $?
|
|
;;
|
|
try-reload-or-restart)
|
|
[ "$#" -eq 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
systemctl --user try-reload-or-restart "$1"
|
|
exit $?
|
|
;;
|
|
start|stop|restart|reload|status)
|
|
[ "$#" -eq 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
user_systemd "$action" "$1"
|
|
;;
|
|
*) usage ;;
|
|
esac
|
|
fi
|
|
|
|
if dinit_user_available; then
|
|
case "$action" in
|
|
start-enabled)
|
|
[ "$#" -eq 0 ] || usage
|
|
user_dinit_start_enabled
|
|
;;
|
|
logs)
|
|
[ "$#" -ge 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
name=$(user_name "$1")
|
|
lines=${2:-100}
|
|
case "$lines" in *[!0-9]*|"") lines=100 ;; esac
|
|
dinitctl --user catlog "$name" 2>/dev/null | tail -n "$lines"
|
|
;;
|
|
exists)
|
|
[ "$#" -eq 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
name=$(user_name "$1")
|
|
dinit_user_service_file_exists "$name"
|
|
;;
|
|
daemon-reload)
|
|
for name in $(dinit_user_managed_services); do
|
|
dinit_user_service_file_exists "$name" || continue
|
|
dinitctl --user reload "$name" >/dev/null 2>&1 || true
|
|
done
|
|
exit 0
|
|
;;
|
|
enable|disable)
|
|
now=0
|
|
if [ "${1-}" = --now ]; then now=1; shift; fi
|
|
[ "$#" -eq 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
name=$(user_name "$1")
|
|
if [ "$action" = enable ]; then
|
|
user_dinit_enable "$1" || exit $?
|
|
[ "$now" -eq 0 ] || dinitctl --user start "$name"
|
|
else
|
|
[ "$now" -eq 0 ] || dinitctl --user stop --ignore-unstarted "$name" || true
|
|
user_dinit_disable "$1"
|
|
fi
|
|
;;
|
|
is-active|status)
|
|
[ "$#" -eq 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
name=$(user_name "$1")
|
|
if dinitctl --user is-started "$name" >/dev/null 2>&1; then
|
|
printf '%s\n' active
|
|
exit 0
|
|
else
|
|
rc=$?
|
|
printf '%s\n' inactive
|
|
exit "$rc"
|
|
fi
|
|
;;
|
|
is-enabled)
|
|
[ "$#" -eq 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
if user_dinit_enabled "$1"; then
|
|
printf '%s\n' enabled
|
|
exit 0
|
|
else
|
|
rc=$?
|
|
printf '%s\n' disabled
|
|
exit "$rc"
|
|
fi
|
|
;;
|
|
start|stop|restart)
|
|
[ "$#" -eq 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
name=$(user_name "$1")
|
|
dinitctl --user "$action" "$name"
|
|
;;
|
|
reload)
|
|
[ "$#" -eq 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
name=$(user_name "$1")
|
|
dinitctl --user signal HUP "$name"
|
|
;;
|
|
try-restart)
|
|
[ "$#" -eq 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
name=$(user_name "$1")
|
|
if dinitctl --user is-started "$name" >/dev/null 2>&1; then
|
|
dinitctl --user restart "$name"
|
|
fi
|
|
;;
|
|
try-reload-or-restart)
|
|
[ "$#" -eq 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
name=$(user_name "$1")
|
|
if dinitctl --user is-started "$name" >/dev/null 2>&1; then
|
|
dinitctl --user signal HUP "$name" 2>/dev/null ||
|
|
dinitctl --user restart "$name"
|
|
fi
|
|
;;
|
|
*) usage ;;
|
|
esac
|
|
exit $?
|
|
fi
|
|
|
|
case "$action" in
|
|
start-enabled)
|
|
[ "$#" -eq 0 ] || usage
|
|
user_fallback_start_enabled
|
|
;;
|
|
daemon-reload)
|
|
exit 0
|
|
;;
|
|
exists)
|
|
[ "$#" -eq 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
user_command "$1" >/dev/null 2>&1
|
|
;;
|
|
is-active|status)
|
|
[ "$#" -eq 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
if user_fallback_active "$1"; then
|
|
printf '%s\n' active
|
|
exit 0
|
|
else
|
|
rc=$?
|
|
printf '%s\n' inactive
|
|
exit "$rc"
|
|
fi
|
|
;;
|
|
is-enabled)
|
|
[ "$#" -eq 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
if user_fallback_enabled "$1"; then
|
|
printf '%s\n' enabled
|
|
exit 0
|
|
else
|
|
rc=$?
|
|
printf '%s\n' disabled
|
|
exit "$rc"
|
|
fi
|
|
;;
|
|
start)
|
|
[ "$#" -eq 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
user_fallback_start "$1"
|
|
;;
|
|
stop)
|
|
[ "$#" -eq 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
user_fallback_stop "$1"
|
|
;;
|
|
restart)
|
|
[ "$#" -eq 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
user_fallback_stop "$1"
|
|
user_fallback_start "$1"
|
|
;;
|
|
reload)
|
|
[ "$#" -eq 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
pidfile=$(user_pidfile "$1") || exit $?
|
|
pid=$(cat "$pidfile" 2>/dev/null || true)
|
|
case "$pid" in *[!0-9]*|"") exit 3 ;; esac
|
|
kill -HUP "$pid"
|
|
;;
|
|
try-restart)
|
|
[ "$#" -eq 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
if user_fallback_active "$1"; then
|
|
user_fallback_stop "$1"
|
|
user_fallback_start "$1"
|
|
fi
|
|
;;
|
|
try-reload-or-restart)
|
|
[ "$#" -eq 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
if user_fallback_active "$1"; then
|
|
pidfile=$(user_pidfile "$1") || exit $?
|
|
pid=$(cat "$pidfile")
|
|
kill -HUP "$pid" 2>/dev/null || {
|
|
user_fallback_stop "$1"
|
|
user_fallback_start "$1"
|
|
}
|
|
fi
|
|
;;
|
|
enable|disable)
|
|
now=0
|
|
if [ "${1-}" = --now ]; then now=1; shift; fi
|
|
[ "$#" -eq 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
if [ "$action" = enable ]; then
|
|
user_fallback_enable "$1" || exit $?
|
|
[ "$now" -eq 0 ] || user_fallback_start "$1"
|
|
else
|
|
[ "$now" -eq 0 ] || user_fallback_stop "$1"
|
|
user_fallback_disable "$1"
|
|
fi
|
|
;;
|
|
logs)
|
|
[ "$#" -ge 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
user_fallback_logs "$1" "${2:-100}"
|
|
;;
|
|
*) usage ;;
|
|
esac
|
|
exit $?
|
|
fi
|
|
|
|
# System scope.
|
|
case "$action" in
|
|
daemon-reload)
|
|
if [ "$backend" = systemd ]; then
|
|
exec systemctl daemon-reload
|
|
fi
|
|
if [ "$backend" = dinit ]; then
|
|
for name in $(dinit_system_managed_services); do
|
|
dinit_service_file_exists "$name" || continue
|
|
dinitctl reload "$name" >/dev/null 2>&1 || true
|
|
done
|
|
fi
|
|
exit 0
|
|
;;
|
|
exists)
|
|
[ "$#" -eq 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
system_exists "$1"
|
|
;;
|
|
is-active|status)
|
|
[ "$#" -eq 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
if system_active "$1"; then
|
|
printf '%s\n' active
|
|
exit 0
|
|
else
|
|
rc=$?
|
|
printf '%s\n' inactive
|
|
exit "$rc"
|
|
fi
|
|
;;
|
|
is-enabled)
|
|
[ "$#" -eq 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
if system_enabled "$1"; then
|
|
printf '%s\n' enabled
|
|
exit 0
|
|
else
|
|
rc=$?
|
|
printf '%s\n' disabled
|
|
exit "$rc"
|
|
fi
|
|
;;
|
|
start|stop|restart|reload)
|
|
[ "$#" -eq 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
system_call "$action" "$1"
|
|
;;
|
|
try-restart)
|
|
[ "$#" -eq 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
if system_active "$1"; then system_call restart "$1"; fi
|
|
;;
|
|
try-reload-or-restart)
|
|
[ "$#" -eq 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
if system_active "$1"; then
|
|
system_call reload "$1" 2>/dev/null || system_call restart "$1"
|
|
fi
|
|
;;
|
|
enable|disable)
|
|
now=0
|
|
if [ "${1-}" = --now ]; then now=1; shift; fi
|
|
[ "$#" -eq 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
if [ "$action" = enable ]; then
|
|
system_enable "$1" || exit $?
|
|
[ "$now" -eq 0 ] || system_call start "$1"
|
|
else
|
|
[ "$now" -eq 0 ] || system_call stop "$1" || true
|
|
system_disable "$1"
|
|
fi
|
|
;;
|
|
logs)
|
|
[ "$#" -ge 1 ] || usage
|
|
valid_unit "$1" || exit 64
|
|
system_logs "$1" "${2:-100}"
|
|
;;
|
|
*) usage ;;
|
|
esac
|