On Thu, Jul 22, 2010 at 9:11 PM, Ted Unangst <[email protected]> wrote: > On Thu, Jul 22, 2010 at 6:52 PM, Daniel Dickman <[email protected]> wrote: >> sure. let me try. the problem is that right now i think env on OpenBSD >> can return 4 ambiguous values: 0, 1, 126, 127. if any of these values >> are returned i don't think it's possible to know if the value was >> returned from env itself or from the underlying utility. (and in fact > > The only thing close to ambiguous is running env with a bad command > line, in which case you get usage and exit 1. Don't do that.
Sorry Ted, but there are many more ambiguous cases. If you run a command that smells kinda posixy and you get back a status of 127, that _probably_ means that *somewhere* in the chain of processes that was involved in the execution of that command, something tried to execute a command and got an ENOENT error from the kernel. It doesn't mean that the 'outermost' command got an ENOENT error from execve. It doesn't mean that the child process tried to invoked execve() at all. It doesn't guarantee that *any* command got that error. Ditto for the similar rules for a status of 126. All you know is that the command you invoked returned 127 or 126...which may be the result of it passing through that status from a command that _it_ invoked! So what does the rule about env return 127 or 126 after execve fails get you? It helps rule *out* failure cases: if you _don't_ get that, then any failure wasn't because a posixy command couldn't find something to exec. > If you get back a 0 it means, tada, it worked! (Well, it means the command that env invoked returned zero, which hopefully means "success" ) > If you get back 127, it means env didn't find the command. Unless you > did something retarded like run env env env env diddly, and then it's > not env returning 127 but the inner inner inner env. I really hope > this is not the kind of problem you are facing when writing a shell > script. I know legitimate cases where 'env' will end up invoking 'env', albeit via an indirection. Others may consider more legit situations that mix env and other commands (xargs, find, nice, nohup, etc...). The thing is that "a command" is an abstraction. A process forks, and at some point it gets an exit status from that child. It can't directly tell whether the child process successfully invoked execve(), zero times, once, twice, or a thousand times before exiting. All the kernel tells it is "child returned status N". That's true whether N is 0, 1, 126, 127, or 42. All a status of 126 tells you is "someone probably screwed up permissions on a program"; all 127 tells you is "someone probably misspelled a program". >> the second problem, is that according to (my reading of posix) >> something that uses env will expect a return value in the range of >> 1-125 to mean "something went wrong in env" and 126 to mean "something >> went wrong with invoking utility". but at the moment there are 2 >> places in the code where 126 is returned where something went wrong in >> env. > > You are clearly reading this exactly backwards. I actually agree with the original poster on his original patch to env.c: env shouldn't return 126 on a non-execve() error, because the user expectation on getting that status is that execve() was called, but it failed with errno!=ENOENT, and they'll look in the wrong place to fix the problem. env can directly return any status from 0 to 127. IMO, it should only return 0 'directly' (without successfully invoking execve) in the case where it is invoked without a command, and it should only directly return the 126 and 127 exit statuses if execve was invoked but failed. (And yes, execve() can fail 'late': at some point, the process of execing a program crosses a "can't roll back" point after which if something goes wrong, the process will die instead of the execve() call returning. The status the parent gets depends on the implementation and the exact point at which it died. The system is imperfect; get over it.) Philip Guenther
