blob: 232caf4e20e7bce00c919c0bd9698b1ff733623b (
plain)
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
94
95
96
97
98
99
|
#!/usr/bin/env bash
# Canonical max25d start — escalate to root only when hardware needs it.
# Works from source tree (scripts/) and from PREFIX/bin after install.
# Root needed: ttyS / USB serial / ioperm / /dev/port / max25-bcpr SER12 (max25e0).
# Escalation: already root → sudo -n → sudo → su → pkexec.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if [[ -x "${SCRIPT_DIR}/max25d" && ! -d "${SCRIPT_DIR}/../stacks/daemon" ]]; then
DAEMON="${SCRIPT_DIR}/max25d"
TREE=""
else
TREE="$(cd "${SCRIPT_DIR}/.." && pwd)"
DAEMON="${TREE}/stacks/daemon/max25d"
fi
if [[ ! -x "$DAEMON" ]]; then
echo "run-max25d: missing $DAEMON" >&2
exit 1
fi
# Match real daemon only (not agent shells whose argv text mentions max25d).
if pgrep -x max25d >/dev/null 2>&1 \
|| pgrep -f -- '/max25d(\.py)?[[:space:]]+-c[[:space:]]' >/dev/null 2>&1; then
echo "run-max25d: max25d already running" >&2
pgrep -af -- '/max25d(\.py)?[[:space:]]+-c[[:space:]]' | head -5 || true
pgrep -ax max25d | head -5 || true
ls -la /run/max25/modem.sock /var/run/max25/modem.sock 2>/dev/null \
|| echo "run-max25d: WARNING no modem.sock under /run/max25 or /var/run/max25" >&2
exit 0
fi
# Accept path or max25d-style "-c path".
INI="${1:-}"
if [[ "$INI" == "-c" || "$INI" == "--config" ]]; then
INI="${2:-}"
fi
if [[ -z "$INI" ]]; then
if [[ -n "$TREE" && -f "${TREE}/local/max25d.ini" ]]; then
INI="${TREE}/local/max25d.ini"
elif [[ -f "${PWD}/local/max25d.ini" ]]; then
INI="${PWD}/local/max25d.ini"
elif [[ -f /etc/max25/max25d.ini ]]; then
INI=/etc/max25/max25d.ini
elif [[ -f /usr/local/etc/max25/max25d.ini ]]; then
INI=/usr/local/etc/max25/max25d.ini
else
echo "run-max25d: no INI (pass path or create local/max25d.ini / /etc/max25/max25d.ini / /usr/local/etc/max25/max25d.ini)" >&2
exit 1
fi
fi
if [[ ! -f "$INI" ]]; then
echo "run-max25d: INI not found: $INI" >&2
exit 1
fi
needs_root() {
local f="$1"
[[ -f "$f" ]] || return 1
if grep -Eiq '^[[:space:]]*(max25[-_]bcpr|bcpr|baycom|pccom)[[:space:]]*=[[:space:]]*yes' "$f"; then return 0; fi
if grep -Eiq '^[[:space:]]*(max25e0|max25e0:bc[01]|tnc2c|pktnc2|baycom-kiss|pccom-kiss)[[:space:]]*=' "$f"; then return 0; fi
if grep -Eiq '^[[:space:]]*device[[:space:]]*=[[:space:]]*(max25e0|tnc2c|pktnc2)' "$f"; then return 0; fi
if grep -Eqi '/dev/(ttyS|ttyUSB|ttyACM|port)\b' "$f"; then return 0; fi
if grep -Eiq '^[[:space:]]*unix_socket[[:space:]]*=[[:space:]]*/(var/)?run/max25/' "$f"; then return 0; fi
return 1
}
if [[ "$(id -u)" -ne 0 ]]; then
if needs_root "$INI"; then
if command -v sudo >/dev/null 2>&1; then
if sudo -n true 2>/dev/null; then
echo "run-max25d: hardware path — escalating via sudo -n" >&2
exec sudo -n "$0" "$INI"
fi
echo "run-max25d: hardware path — escalating via sudo (password may be required)" >&2
exec sudo "$0" "$INI"
fi
if command -v su >/dev/null 2>&1; then
echo "run-max25d: hardware path — escalating via su" >&2
exec su -c "$(printf '%q ' "$0" "$INI")"
fi
if command -v pkexec >/dev/null 2>&1; then
echo "run-max25d: hardware path — escalating via pkexec" >&2
exec pkexec "$0" "$INI"
fi
echo "run-max25d: PC-COM or serial hardware needs admin — run: sudo $0 $INI" >&2
exit 1
fi
echo "run-max25d: starting unprivileged (uid=$(id -u))" >&2
else
echo "run-max25d: running as root (uid=0)" >&2
fi
if [[ "$(id -u)" -eq 0 ]]; then
mkdir -p /run/max25 /var/run/max25
fi
echo "run-max25d: ini=$INI"
exec "$DAEMON" -c "$INI"
|