>>    o   OPTIND is saved/reset and restored on entry and exit from the
>>        function so getopts can be used properly both inside and outside the
>>        function (Bourne-style functions leave OPTIND untouched, so using
>>        getopts inside a function interferes with using getopts outside the
>>        function).
>
>> I did some testing to see what OPTIND was set to when rc_pre is called.
>> When I run "rcctl start unbound" then OPTIND is 1 when rc_pre starts.
>> but if I run "rcctl -q start unbound" then OPTIND is 2 when rc_pre starts.
>
>Is something not working correctly?
>
>> Just appending OPTIND to local doesn't clear its' value (I still get 2)
>> 
>> Since everything uses bourne-style functions it is probably better
>> to append OPTIND=1 to the local definitions line to reset it.
>
>Your text does not explain the diff.
>
>What does it fix?
>What's the problem here?

Getopts uses OPTIND to keep track of its' position within the args.
So in the example of "rcctl -q start unbound", OPTIND would be 2
when unbound's rc_pre is called (I verified by temp adding a line
to echo the value of OPTIND before the getopts line).  This would
cause getopts to start the search for c (or l for spamlogs) at the
second option in daemon_options, for unbound there is only 1 option
normally.

It is rare that we would specify options to rcctl (rc doesn't) so
we are unlikely to see this issue in normal use.  The man page for
ksh took the time to point out that getopts inside and outside of
functions could potentially interfere with each other.  I was just
illustrating an example of how it could with rcctl unbound/spamlogd.
(Run rcctl with -q and unbound would not see its' config filename)
By adding OPTIND=1 to local allows getopts to always work correctly
and see all options within daemon_options, and restores OPTIND for
the calling environment if it still needs it for its' own getopts.
Functions defined using the function keyword this happens automatically,
functions defined the bourne-style way (which is everything in rc,
rcctl, rc.subr) it is not automatic and that's what my diff tries to fix.

> /etc/rc.d$ diff -u unbound unbound
> --- unbound     Sun Nov 16 13:27:50 2025     1.10
> +++ unbound     Mon Nov 24 22:21:24 2025
> @@ -8,7 +8,7 @@
>  . /etc/rc.d/rc.subr
>  
>  rc_pre() {
> -     local _anchor _config _opt
> +     local _anchor _config _opt OPTIND=1
>  
>       while getopts :c: _opt $daemon_flags; do
>               [[ $_opt == c ]] && _config=$OPTARG
> 
> /etc/rc.d$ diff -u spamlogd spamlogd
> --- spamlogd     Sun Nov 16 13:29:02 2025     1.7
> +++ spamlogd     Mon Nov 24 22:21:37 2025
> @@ -9,7 +9,7 @@
>  rc_reload=NO
>  
>  rc_pre() {
> -     local _opt pflog=pflog0
> +     local _opt pflog=pflog0 OPTIND=1
>  
>       while getopts :l: _opt $daemon_flags; do
>               [[ $_opt == l ]] && pflog=$OPTARG

Reply via email to