Page MenuHomeFreeBSD

man: reset OPTIND after parsing args

Authored by kevans on Sep 22 2021, 8:31 PM.



From jilles: POSIX requires that a script set OPTIND=1 before using
different sets of parameters with getopts, or the results will be

The specific problem observed here is that we would execute man -f or
man -k without cleaning up state from man_parse_args()' getopts
loop. FreeBSD's /bin/sh seems to reset OPTIND to 1 after we hit the
second getopts loop, rendering the following shift harmless; other
/bin/sh implementations will leave it at what we came into the loop at
(e.g., bash as /bin/sh), shifting off any keywords that we had.

Diff Detail

rG FreeBSD src repository
Lint Not Applicable
Tests Not Applicable

Event Timeline

I agree that OPTIND=1 is needed, but I have another reason for it. POSIX requires that a script set OPTIND=1 between using different sets of parameters with getopts; otherwise, the results are unspecified.

An assignment OPTIND=1 resets the getopts state, even if OPTIND was already 1.

In FreeBSD sh, the whole getopts state is local to functions (along with the positional parameters). This is more useful (so that functions can use getopts from within a caller's getopts loop) but is not strictly compliant (wrapping getopts with a function will not work).

From this point of view, the assignment in man_parse_args suffices, since that is the only place where two getopts loops run in the same script execution. Alternatively, OPTIND=1 could be added before each getopts loop within a function.

Go ahead and reset getopts state before each, to be safe/correct.

This revision is now accepted and ready to land.Sep 23 2021, 10:10 AM
This revision was automatically updated to reflect the committed changes.