From: Klemens Nanni Subject: rc.subr: hoist OPTIND reset out of service scripts To: OpenBSD tech Cc: Antoine Jacoutot , obsd@mulh.net Date: Sat, 29 Nov 2025 19:03:07 +0000 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