Subject: Re: Shell behaviour regarding PATH
To: NetBSD Userlevel Technical Discussion List <tech-userlevel@netbsd.org>
From: Lucio De Re <lucio@proxima.alt.za>
List: tech-userlevel
Date: 02/10/2000 07:57:16
On Wed, Feb 09, 2000 at 12:27:40PM -0500, Greg A. Woods wrote:
> > > 
> > Do I?  I think that's an artifice, and an ugly one, at that.
> 
> If you don't know that then you haven't read/understood the manual!  ;-)
> 
I didn't know that until I typed bin/build.sh as root and discovered it
worked.  It _surprised_ me, despite 18 years of Unix admninistration.

> The exception is necessary in order to implement a sane way of dealing
> with search paths in the face of allowing relative pathnames at the same
> time.
> 
To me, this extends naturally.  The reverse (currently the norm) makes a
mockery of consistency: foo/bar is the same as ./foo/bar (OK, that makes
sense) but foo is not the same as ./foo (sigh).

> The rule is very simple:  If there's a slash anywhere in argv[0] then
> treat it as a relative pathname and do not apply the $PATH search
> algorithm.  If there is no slash then search in $PATH.  If you allow any
> slash in a $PATH search then you will not be able to specify a program
> in a relative directory that is also in a $PATH directory without
> specifying an absolute (fully qualified) pathname which would make the
> behaviour of such relative pathnames very un-predictable and thus
> dangerous.  It would be better to simply outlaw relative pathnames all
> together (and always force $PATH searches for argv[0]) and I don't think
> anyone will go for that!  :-)
> 
Well, I can prefix it with "./", can't I?  My very complaint is that I
cannot reverse this behaviour.  I want to be able to treat ./foo/bar as
different from foo/bar, the way I can with foo and ./foo.  Current practice
blocks this difference and I lose.  Long live Tom Duff, I see the package
"rc" shell still displays the behaviour I seek :-)

> Sorry, but you're wrong.  Perhaps you don't understand the definition of
> a "relative pathname" in the Unix sense.
> 
I firmly believe the difference is so subtle, there'd be no noticeable
difference in behaviour had the alternative approach been taken.  Yes,
./ and ../ are used to represent relative positions in a directory, but
in practice they define absolute pathnames.  To me, in other words, the
significant difference is whether a _resolved_ pathname starts with a
"/" or not, and ~/foo, ./foo and ../foo do, implicitly rather than
explicitly.  In fact, on the command line, they could be resolved by the
shell (~/foo does, but here I may be getting into hot waters with the
likes of Tom Duff) with no great change in the operation of existing
code (not that I'd advocate such a change, except perhaps in QNX and Plan 9).

> Unless a pathname begins with a '/' it is a relative pathname and the
> search always begins at the current working directory.  From intro(2):
> 
Well, I always believed that ./ is an abbreviation.  I accept it is not,
as pointed out, in foo/./bar - but that's an obvious difference - and
that its meaning changes with the context, but that does not invalidate
my perception (which is why it stayed with me for 18 years :-)

> On Plan-9 someone has to bind(2) /usr/local/netscape to /bin if you
> don't put it in $path.
> 
I can also put netscape in /bin/netscape/netscape and refer to it as
netscape/netscape, providing me with a logical location for netscape's
executables, as well as other options.  What I was hoping for, was to
extend the Plan 9 directory hierarchy into NetBSD by reversing, say,
/usr/local/ssh/{bin,sbin,libexec,etc} which is intolerable for more
than zero "ssh", to /usr/local/{bin,sbin,libexec,etc}/ssh which seems
much more practical.

> Since Plan-9 doesn't have execlp() there is no path searching outside of
> what's done in "rc" itself and thus it may make sense for "rc" to always
> look for "kfs/diskcmd" in the directories specified in $path.  This is
> totally irrelevant though because this is not the way Unix works because
> Unix does have execlp().
> 
Well, execlp() is obviously not used in /usr/pkg/bin/rc as supplied in the
packages collection, and I can cope quite well with that :-)  I should
suggest we add exec?pr(2) to implement a PATH behaviour analogous to rc's.

> I think once you integrate the defined meaning of "relative pathname"
> into your understanding that you'll better understand why execlp() et al
> must not search $PATH when a slash ('/') appears in argv[0].
> 
It is all based on a _consistent_ meaning, without regard for the deeper
philosophy.  In my book, Unix is wrong in this case.  I accept that this
cannot be changed, and I bow to that principle.

I do maintain, though, that the difference is sufficiently subtle as to
fool even a sophisticated user, and that the alternative is more
consistent and more practical without being totally disruptive.  I was
however curious about the origin of the confusion (Stephen Bourne?) and
the ramifications of a possible change.

++L