Download raw body.
rc.subr: hoist OPTIND reset out of service scripts
See bugs@ "etc/rc.d/unbound assumes defaults in rc_pre()"
and the last rc.d/{unbound,spamlogd} commit for context.
In base only those two use getopts, ports I did not check.
Either way, the common "problem" is rc.subr(8)'s getopts;
code flow looks like this:
* '/etc/rc.d/unbound [-dqf] start'
1) dot-sources rc.subr
2) rc.subr runs getopts; iff flags are used, OPTIND is >1
3) runs rc_*() which may use getopts; if OPTIND is >1,
daemon_flags is parsed improperly.
* 'rcctl start unbound'
rcctl(8) has its own getopts, but runs rc.subr as separate
process and thus does not effect it.
* netstart
dot-sources rc.subr, but with FUNCS_ONLY=1, i.e. rc.subr
exits after function definitions and before getopts usage
and thus does not effect it.
We can simply reset getopts in in 2) instead of 3) such that
any service script will work properly.
Feedback? OK?
Test:
# mv /var/unbound/etc/{unbound,foo}.conf
# rcctl enable unbound
# rcctl set unbound flags -c /var/unbound/etc/foo.conf -p
yesterday's -current, i.e. no OPTIND=1 anywhere:
# /etc/rc.d/unbound -f restart; pgrep unbound; echo $?
unbound(failed)
1
-current or the diff below (no difference):
# /etc/rc.d/unbound -f restart; pgrep -fl unbound
unbound(ok)
84833 /usr/sbin/unbound -c /var/unbound/etc/foo.conf -p
Index: rc.subr
===================================================================
RCS file: /cvs/src/etc/rc.d/rc.subr,v
diff -u -p -r1.166 rc.subr
--- rc.subr 16 Aug 2025 10:23:45 -0000 1.166
+++ rc.subr 29 Nov 2025 17:59:19 -0000
@@ -347,6 +347,7 @@ while getopts "dfq" c; do
esac
done
shift $((OPTIND-1))
+OPTIND=1
[[ -n ${_RC_DEBUG} && -n ${_RC_QUIET} ]] && _rc_usage
_RC_RUNDIR=/var/run/rc.d
Index: spamlogd
===================================================================
RCS file: /cvs/src/etc/rc.d/spamlogd,v
diff -u -p -r1.8 spamlogd
--- spamlogd 29 Nov 2025 10:44:46 -0000 1.8
+++ spamlogd 29 Nov 2025 18:11:37 -0000
@@ -9,7 +9,7 @@ daemon="/usr/libexec/spamlogd"
rc_reload=NO
rc_pre() {
- local _opt pflog=pflog0 OPTIND=1
+ local _opt pflog=pflog0
while getopts :l: _opt $daemon_flags; do
[[ $_opt == l ]] && pflog=$OPTARG
Index: unbound
===================================================================
RCS file: /cvs/src/etc/rc.d/unbound,v
diff -u -p -r1.11 unbound
--- unbound 29 Nov 2025 10:44:46 -0000 1.11
+++ unbound 29 Nov 2025 17:59:35 -0000
@@ -8,7 +8,7 @@ daemon_flags="-c /var/unbound/etc/unboun
. /etc/rc.d/rc.subr
rc_pre() {
- local _anchor _config _opt OPTIND=1
+ local _anchor _config _opt
while getopts :c: _opt $daemon_flags; do
[[ $_opt == c ]] && _config=$OPTARG
rc.subr: hoist OPTIND reset out of service scripts