The current incarnation of execvPe() is a bit messy, and it can be
rather difficult to reason about whether we're actually doing the right
thing with our errors. We have two cases in which we may enter the loop:
1.) We have a name that has no slashes in it, and we enter the loop
normally through our strsep() logic to process $PATH
2.) We have a name with at least one slash, in which case we jump into
the middle of the loop then bail after precisely the one iteration if we failed
Both paths will exit the loop if we failed, either via jumping to the
done label to preserve an errno or into the path that clobbers errno.
Clobbering errno for case #2 above would seem to be wrong, as we did not
actually search -- this would seem to be what POSIX expects, as well,
based on expectations of the conformance test suite.
Simplify reasoning about the two paths by splitting out an execvPe_prog
that does the execve(2) call specifically, and returns based on whether
the error would be fatal in a PATH search or not. For the
relative/absolute case, we can just ignore the return value and keep
errno intact. The search case gets simplified to return early if
we hit a fatal error, or continue until the end and clobber errno if
we did not find a suitable candidate.
Another posix_spawnp() test is added to confirm that we didn't break our
EACCES behavior in the process.
Sponsored by: Klara, Inc.