The POSIX shell standard says on this site
http://pubs.opengroup.org/onlinepubs/9699919799/
about how shells use PATH
to look for executables:
"The list shall be searched from beginning to end, applying the filename to each prefix, until an executable file with the specified name and appropriate execution permissions is found."
Well, this is not how this appears to work in real POSIX implementation:
man which
says:
"returns the pathnames of the files (or links) which would be executed in the current environment, had its arguments been given as commands in a strictly POSIX-conformant shell. It does this by searching the PATH for executable files matching the names of the arguments. It does not follow symbolic links."
OK, let's look at this situation:
$ pwd
/home/mark
$ echo $PATH
/home/mark/bin:
...
$ ls -l bin/foobar
lrwxrwxrwx 1 mark mark 18 Dec 12 22:51 bin/foobar -> /home/mark/foobar1
$ touch foobar1
$ which foobar
$ chmod a+x foobar1
$ which foobar
/home/mark/bin/foobar
OK, here is a symbolic link in PATH
with the correct name, and it is reported by ls
to be executable.
which
does not look at it at all,
but is only interested in what it points to.
That despite the fact that both man which
explicitly says that it does not follow symbolic links (and indeed we see it doesn't, because which foobar
does not print foobar1
), and also that the POSIX shell documentation quoted above, never ever mentions following symlinks in the PATH
algorithm.
So, is which
and the existing shells wrong, or am I not understanding the documentation?
TO CLARIFY:
I know and can explain the existing behaviour. My question is not "how does this work?". That I know.
My question is about documentation: where is my mistake in following the documentation that I quoted. Or is the documentation wrong?
MOTIVATION: Why do I care?
Well, I am an implementer. Different implementers have different requirements. For me, the requirement is that the word of the current POSIX standard MUST be followed EXACTLY (or, more precisely, the best it can be, because, the standard itself is somewhat buggy). Like as it were the word of God.
Now, the standard wording is pretty clear - following symlinks is not mentioned, where in many other places, it is mentioned where it needs to be done. So in this case, don't.
However, I always double check how dash
and bash
behave, just to make sure. Now of course, there is a little problem here as well, dash
even though it is billed as POSIX, has plenty of small bugs with conformance to POSIX. bash
, I have yet to find any bugs with POSIX, but... bash isn't actually POSIX, it is much more than that.
So there you have it. That is why I care.
$PATH
can contains symlinks. Trywhich sh
.$PATH
does not have any symlinks.lstat(2)
), following them is not usually stated. For instance, the description ofopen(2)
only mentions symlinks when talking about the behavior ofO_CREAT | O_EXCL
. It doesn't need to state that the target file will be opened.