blob: ccc2bc97dfb88684d33194034fb89ab1858c2c98 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
#!/bin/sh
# This file is a part of RSPlayer
# Licensed under the GPL-3.0 License
# Copyright (C) 2026 Salmonik @ salmonik@tuta.io
# https://codeberg.org/salmonik/RSPlayer
#
# FreeBSD rc.d service for RSPlayer.
#
# Add the following to /etc/rc.conf to enable the service:
#
# rsplayer_enable="YES"
# rsplayer_user="salmon" # user to run the daemon as (NOT root)
# rsplayer_group="wheel" # group of that user
#
# rsplayer_user must be a regular user: the daemon socket and PID file live
# in that user's XDG state directory (~/.local/state/rsplayer) and the `rsp`
# CLI connects to that socket, so the daemon and the CLI must run as the
# same user. This also means the socket path no longer depends on the
# environment (XDG_RUNTIME_DIR), so the service and manual runs agree.
# PROVIDE: rsplayer
# REQUIRE: LOGIN dbus
# KEYWORD: shutdown
. /etc/rc.subr
name="rsplayer"
rcvar=rsplayer_enable
load_rc_config $name
: ${rsplayer_user:="root"}
: ${rsplayer_group:="wheel"}
# daemon(8) does not set HOME when dropping privileges, and rsp derives its
# config and runtime paths from it, so resolve the user's home explicitly.
rsplayer_home=$(pw usershow "${rsplayer_user}" 2>/dev/null | awk -F: '{print $9}')
if [ -z "${rsplayer_home}" ]; then
echo "Cannot determine home directory for user '${rsplayer_user}'."
echo "Set rsplayer_user in /etc/rc.conf."
exit 1
fi
command="/usr/local/bin/rsp"
procname="${command}"
state_dir="${rsplayer_home}/.local/state/rsplayer"
pidfile="${state_dir}/rsplayer.pid"
socket="${state_dir}/daemon.sock"
start_cmd="rsplayer_start"
stop_cmd="rsplayer_stop"
rsplayer_start()
{
if [ -s "${pidfile}" ] && kill -0 "$(cat "${pidfile}")" 2>/dev/null; then
echo "rsplayer is already running (PID $(cat "${pidfile}"))."
return 0
fi
if [ "${rsplayer_user}" = "root" ]; then
echo "WARNING: rsplayer_user is \"root\"; the rsp CLI will not be able to"
echo " connect to the daemon socket. Set rsplayer_user in rc.conf."
fi
# daemon(8) opens the log file (-o) before exec'ing rsp and before
# dropping privileges, but the state dir is only created by rsp itself —
# create both up front so the log can open and stays user-owned/readable.
install -d -o "${rsplayer_user}" -g "${rsplayer_group}" -m 700 "${state_dir}"
if [ ! -e "${state_dir}/rsplayer.log" ]; then
install -o "${rsplayer_user}" -g "${rsplayer_group}" -m 600 /dev/null "${state_dir}/rsplayer.log"
fi
echo "Starting rsplayer as ${rsplayer_user} (HOME=${rsplayer_home})."
/usr/bin/env HOME="${rsplayer_home}" \
/usr/sbin/daemon -u "${rsplayer_user}" -o "${state_dir}/rsplayer.log" \
"${command}" start-daemon
}
rsplayer_stop()
{
echo "Stopping rsplayer."
if ! su -m "${rsplayer_user}" -c "env HOME='${rsplayer_home}' ${command} stop-daemon"; then
# stop-daemon could not reach the daemon (stale/missing PID file or
# socket, e.g. a daemon started under an older runtime dir): kill any
# leftover rsp start-daemon processes for this user.
echo "Graceful stop failed; killing leftover daemons."
pkill -u "${rsplayer_user}" -f "${command} start-daemon" 2>/dev/null || true
fi
rm -f "${pidfile}" "${socket}"
}
run_rc_command "$1"
|