Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: [PATCH] return status 126 for execution failures other than 'not found'



Martijn Dekker wrote on Fri, 08 May 2020 21:36 +0100:
> When the argument list to an external command is too long (exceeds 
> ARG_MAX), zsh returns exit status 127. This is incorrect because status 
> 127 means the command was not found.
> 
> POSIX says in "2.8.2 Exit Status for Commands":
> https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_08_02
> | If a command is not found, the exit status shall be 127. If the
> | command name is found, but it is not an executable utility, the exit
> | status shall be 126.
> 

In the test case you added, I think the answers to "Was «env» found?"
and "Is «env» an executable utility?" are both "yes".  Thus, neither of
the sentence quoted from §2.8.2 applies: the exit status in that case is
neither required to be 127 nor required to be 126.

That would appear to be a lacuna: the standard does not specify what the
exit status shall be when the command _is_ found and _is_ an "executable
utility", but execution fails for some other reason, such as an argument
being too long.

Furthermore, the standard doesn't _forbid_ the exit status of the test
you added from being either 126 or 127.  (That's the plain meaning of
quoted sentences: they say "if A then B", not "A iff B".)

It _would_ be useful for error codes to only be caused by specific
failure modes, in order to enable scripts to handle error codes
selectively.  However, the incumbent code has this property too:
status 126 has only two specific causes.

We could still make the change you propose, of course, but it's not
a black and white case of the incumbent behaviour being "incorrect".
Therefore, in particular, we should consider not only whether we'd be
compatible with other shells, but also whether the proposed change might
constitute a regression for people upgrading from older zsh to newer
zsh.  For example, might some zsh users be relying on the incumbent
"status 126 can only be caused by EACCES and ENOEXEC" semantics?

To be clear, I'm not objecting to the change; I'm only trying to ensure
all viewpoints are taken into account.

Thanks, Martijn.

Daniel

> Now, the phrasing "it is not an executable utility" is a little vague, 
> but the current versions of all other shells return 126 upon any failure 
> to execute a utility that was found, so they seem to interpret that 
> phrase as meaning "it could not be executed for whatever reason (other 
> than 'not found')". In any case, 126 is better than any alternative, as 
> all other exit codes potentially conflict with other meanings.
> 
> Currently, the execute() function in Src/exec.c only returns status 126 
> if the error code is EACCES (permission denied) or ENOEXEC (exec format 
> error). In all other cases, 127 is returned.
> 
> That logic is not right, because 127 is the specific case: it is only to 
> be used if the command was not found. Any failure to execute after the 
> command is found should yield status 126.
> 
> The attached patch changes that logic to return status 127 if there is 
> no error number (which happens if a PATH search does not find a command) 
> or if the error number is ENOENT (no such file or directory). In all 
> other cases it now returns 126.
> 
> I've also added a test for the "argument list too long" case.



Messages sorted by: Reverse Date, Date, Thread, Author