[net.unix-wizards] Please do NOT use "/bin/test" as a command name

ian@utcs.uucp (Ian F. Darwin) (12/09/85)

In article <1016@sdcsla.UUCP> west@sdcsla.UUCP (Larry West) writes:
>However, I would like to point out that users have a habit
>of naming programs "test", and of having "/bin" occur late
>in their paths.   This tends to cause confusion because the
>problem (as usual) doesn't come up until that brief "test"
>program has been forgotten.
>
>So, my suggestion is to always use "/bin/test" instead
>of simply "test", or else use "[ ]".   I know, fixing 
>the particular pathname of a program is a bad idea, but this
>seems a fairly safe case (unless you plan to provide an
>improved user interface to "test":-).

No, no, no. Do not use absolute paths for test, mv, cp, or
anything else. Least of all in shell files.

Sure, once in a while a new user will make a program called `test'
and get confused. Some people even do it twice (I did). Most
people don't do it a third time.

Note that the problem only comes up if you have your `test' 
program in your $HOME/bin (what you call your private bin directory)
OR if you are in the same directory where you made that long-forgotten
test program.

On the other hand, if you post even a single shell file with /bin/test
in it, your `error' will be repeated hundreds of times all over the world.
Why is it an error? I call it an error because it violates the 
portability principle: UNIX uses the PATH environment variable
to find programs, rather than making the user specify full path names
for programs. This allows you to write your own. Why would anybody
want to mv test out of /bin? Well, what if somebody decides that
test is used so often that it belongs in the shell? Then you have
to keep two versions of test around -- a fast one inside the shell,
and a slow one for `erroneuos' shell files. Oh, you say that they already
did this in some release of System V? My, what a surprise.

I'm equally against the practice of putting /bin/rm, /bin/mv, etc
into shell files. Please use rm, mv, etc, rather than the full paths.
You don't know what might motivate me to have my own version of rm
(indeed, you probably don't want to know what motivates me :=!). Please use 
the facilities that UNIX provides. Don't negate UNIX's wonderful generality 
for the benefit of a few nanoseconds.

Ian Darwin
Toronto, Canada

davel@dciem.UUCP (Dave Legg) (12/09/85)

> = Ian Darwin
>> = Larry West

In article <1019@utcs.uucp> ian@utcs.UUCP (Ian F. Darwin) writes:
>In article <1016@sdcsla.UUCP> west@sdcsla.UUCP (Larry West) writes:
>>However, I would like to point out that users have a habit
>>of naming programs "test", and of having "/bin" occur late
>>in their paths.   ...
>>
>>So, my suggestion is to always use "/bin/test" instead
>>of simply "test", or else use "[ ]".   ...
>
>No, no, no. Do not use absolute paths for test, mv, cp, or
>anything else. Least of all in shell files.
>

I can see both sides of this, I have run  up against a user reporting a
strange failure of a shell script that is installed for general use, and
which usually works with no problem.   The problem is that the user that
finds such a problem is usually new and inexperienced, and it can take
signifigant amounts of time to find that the whole problem is simply a
name collision.  

One point not mentioned in the article I saw was that of the collision
with a users program that had undesirable side effects.  For example,
if a user writes a program to delete files, and calls it some common system
program name, then runs a script (which he might not even know is a script)
which calls on that name.

I have a  suggestion.
Set a shell variable to the absolute path of the program, i.e.
TEST=/bin/test (or equivelent for other shells)
and use $TEST in the shell program.  This isolates the dependencies at
the top of the script, making for easy changes.  As for portability,
if the changes are obvious and at the top, then any body getting a script
from the net should be able to see what is necessary.  
Anybody recieving a script will normally at least scan it briefly to see
what it does, especially if it fails.  

Although I can see that it is generally
desirable to be as portable as possible,  in shell scripts, I now normally
fully qualify all proram names via  the above convention.  This is purely
on the basis of experience with problems caused by unqualified program
names in scripts. 

-- 
Dave Legg, DCIEM, Toronto, Ont. Canada.    (416) 635-2065
{linus,ihnp4,uw-beaver,floyd}!utcsri!dciem!davel
{allegra,ihnp4,linus,decvax}!utzoo!dciem!davel

geoff@utcs.uucp (Geoff Collyer) (12/09/85)

In article <1747@dciem.UUCP>, Dave Legg writes about Ian Darwin's
suggestion that absolute path names not be burned in to shell scripts,
and suggests that they be burned in at the top, in definitions like
TEST=/bin/test.  (This is a particularly bad example since, as Ian
pointed out, test is a shell built-in in modern shells, but /bin/test is
not.)

Ian didn't mention our standard practice here: set PATH at the top of
the shell script (e.g. PATH=/bin:/usr/bin; export PATH). This is really
essential since otherwise an oddball PATH may result in a shell file
executing commands with the same name as standard commands but with
completely different effects.  The author of a shell file usually
intends that the standard commands be used.

Yes, it does mean that your private versions of the standard commands
will not be found in shell files which set PATH to the standard
directories, but this is often just as well. Rather than rehash this
whole issue, I refer the interested reader to The UNIX* Programming
Environment by Brian Kernighan and Rob Pike, in which I believe this
topic is fairly thoroughly covered.

___
* According to p. 8 of the November 1985 issue of "$ echo", an
overpriced AT&T Marketing & Legal rag, I must, being a foreigner, utter
the magic mantra "Trademark of AT&T in the USA and other countries."

cc-06@ucbcory.BERKELEY.EDU (Ilya Goldberg) (12/10/85)

In article <1019@utcs.uucp> ian@utcs.UUCP (Ian F. Darwin) writes:
>I'm equally against the practice of putting /bin/rm, /bin/mv, etc
>into shell files. Please use rm, mv, etc, rather than the full paths.
>You don't know what might motivate me to have my own version of rm
>(indeed, you probably don't want to know what motivates me :=!). Please use 
>the facilities that UNIX provides. Don't negate UNIX's wonderful generality 
>for the benefit of a few nanoseconds.
>
>Ian Darwin
>Toronto, Canada

	Ian, no one is trying to save cpu time by doing what they are doing.
Just think of what would happen if the user doesn't have the right things
in his/her path variable or no path at all!

	Also, I would love to try to break into a system kept secure by your
shell scripts which do not contain absolute path names.  I would do exactly
what you suggest - substitute my own versions of rm, mv, etc so that when
a set-u-id root shell script tries to execute one of those, UNIX will take
the version in my directory.  My version will perform whatever I want it to.
including things you might not want me to.

	So, when writing programs/shell scripts which call other programs
do include full path names, preferrably in a place where they are easily
found and can be easily modified (e.g. ".h" files).

						Ilya	(...!ucbvax!ilya)

chris@umcp-cs.UUCP (Chris Torek) (12/10/85)

[PATH=/foo:/bar:/baz; export PATH]

In article <11193@ucbvax.BERKELEY.EDU> cc-06@ucbcory.BERKELEY.EDU
(Ilya Goldberg) writes:

> no one is trying to save cpu time by doing what they are doing.
> Just think of what would happen if the user doesn't have the right
> things in his/her path variable or no path at all!

Then nothing works at all, so why worry about that case?

> Also, I would love to try to break into a system kept secure by
> your shell scripts which do not contain absolute path names.

Who uses setuid shell scripts?  (Actually, I have on one machine
a shell script that is run privileged by a separate setuid C program,
which verifies the user first; and the script is relatively careful.)

> I would do exactly what you suggest - substitute my own versions of
> rm, mv, etc so that when a set-u-id root shell script tries to
> execute one of those, UNIX will take the version in my directory.

Putting in full path names is not the solution---suppose I change $IFS?

> So, when writing programs/shell scripts which call other programs
> do include full path names, preferrably in a place where they are
> easily found and can be easily modified (e.g. ".h" files).

Include *paths*, not full path *names*.  There is a difference.  See
`man execvp' and `man execlp'.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 4251)
UUCP:	seismo!umcp-cs!chris
CSNet:	chris@umcp-cs		ARPA:	chris@mimsy.umd.edu

gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) (12/10/85)

I have to disagree with Ian on this one.
Because you never know what kind of weird $PATH
people will be using, it is essential when
writing shell scripts for use by others to
FORCE the correct commands to be used in
your shell script, in order to guarantee
that the script does what you intended.
The simplest way to do this is to just set
PATH=whatever at the front of the script.
Besides being less trouble than using absolute
pathnames, this also handles problems like:
Is "sort" in /bin or /usr/bin (or /usr/5bin)?

The internals of a utility are subject to change.
You can't even reasonably make the user
responsible for looking inside utilities to see
whether they will work in conjunction with his
$PATH.  As far as a user should be concerned, a
utility should be a "black box" that does its job
reliably and without fuss.  If you're going to
make a utility reliable, its internal operation
should be protected against environmental factors
except when they are a deliberate part of the
interface.  If someone has his own "rm" command
(some of our users do), how do you know that it
is suitable for use in your script to remove a
link?  The answer is, you don't.

mts@ms.UUCP (Martin Stanley) (12/10/85)

And just to add fuel to the fire: 

What about personal aliases conflicting with csh script commands.  For
example, many people around here alias rm to rm -i.  This would break
many csh scripts.  The PATH solution given in geoff's article would not
solve this problem.

Of course, a *very* conscientious programmer could unalias every
potentially conflicting name he uses in a script. :-)
-- 

 Martin Stanley
 Department of Computer Science
 University of Toronto
 Toronto, ON
 M5S 1A4

 USENET:	{decvax,ihnp4,linus,uw-beaver}!utcsri!utai!ms!mts
 CSNET:		mts@toronto
 ARPANET:	mts.toronto@csnet-rela

gmp@rayssd.UUCP (Gregory M. Paris) (12/11/85)

> No, no, no. Do not use absolute paths for test, mv, cp, or
> anything else. Least of all in shell files.
> 
> Sure, once in a while a new user will make a program called `test'
> and get confused. Some people even do it twice (I did). Most
> people don't do it a third time.

As you mentioned, this kind of problem crops up not only with
"test" but with many of the oft-used UNIX utilities.  For those of
us that support a user community of hundreds, even one or two "custom"
utility problems per user can become quite a time consuming hassle.
Just about any shell script can be broken with custom utilities, and
I certainly don't expect every user to have the savvy to figure out
which ones his/her new "rm" command is going to break (try rm -i -f).

There's more than a speed advantage to including full pathnames,
and only very minor portability problems associated with the practice.
I'm not saying that you *must* or even *should* include full pathnames,
but I disagree completely with your saying *never*!

As a compromise, how about setting PATH at the beginning of the script?
-- 

++---------------------------------------------------------------------------++
||  Greg Paris             {allegra,linus,raybed2,ccice5,brunix}!rayssd!gmp  ||
++---------------------------------------------------------------------------++

rudy@wang.UUCP (Rudy Bazelmans x72609 ms 1989) (12/11/85)

> 	So, when writing programs/shell scripts which call other programs
> do include full path names, preferrably in a place where they are easily
> found and can be easily modified (e.g. ".h" files).
> 
> 						Ilya	(...!ucbvax!ilya)

Users should NOT use full directory names in their scripts/programs UNLESS:

	1)	They specifically do not want the local version of a program.
	2)	They are writing setuid scripts (actually, this would be alright too if
		the script changed the path variable).

If users use fullly qualified pathnames for programs, then administrators of
systems would have to replace the standard programs with the new ones rather
than allow both to be available.

jpn@teddy.UUCP (12/12/85)

>What about personal aliases conflicting with csh script commands.  For
>example, many people around here alias rm to rm -i.  This would break
>many csh scripts.  The PATH solution given in geoff's article would not
>solve this problem.

Assuming you are talking about csh aliases, this does not come up in
"sh" scripts (which was what the discussion was about).  If you are
writing csh scripts, then I hope your kernel also supports the "#! xxx"
shell hack, or else the csh script startup times may be prohibatively
long.  If your kernel supports this, then use "#! /bin/csh -f" to avoid
loading the user's .cshrc.

>Of course, a *very* conscientious programmer could unalias every
>potentially conflicting name he uses in a script. :-)

How about "unalias *"?

henry@utzoo.UUCP (Henry Spencer) (12/13/85)

> What about personal aliases conflicting with csh script commands...
> 
> Of course, a *very* conscientious programmer could unalias every
> potentially conflicting name he uses in a script. :-)

A conscientious programmer would never use csh to write scripts.

henry@utzoo.UUCP (Henry Spencer) (12/13/85)

> 	Also, I would love to try to break into a system kept secure by your
> shell scripts which do not contain absolute path names.  I would do exactly
> what you suggest - substitute my own versions of rm, mv, etc...

Wouldn't help, since all those shell scripts start with the magic line:

	PATH=/bin:/usr/bin ; export PATH

which solves the problem without requiring hardwired path names everywhere.
Also, it solves the problem for everything invoked by the shell script,
rather than just for the shell script itself.

henry@utzoo.UUCP (Henry Spencer) (12/13/85)

> As a compromise, how about setting PATH at the beginning of the script?

This is not a compromise, it is the correct and complete solution.  Don't
forget to do "export PATH".

tbray@mprvaxa.UUCP (Tim Bray) (12/13/85)

I am NOT a unix-wizard.  But it seems elementary to me that all shell scripts
should be as follows:

#!/bin/sh
PATH=/bin:/usr/bin:/usr/ucb   # 'n maybe some more
if test bletch ....
mv foo
rm bar
etc..

That way you can't get bitten by (maybe intentional) name duplication, you
will preserve the flexibility of path usage, and everything is hunky dory.
This assumes that you can trust the contents of /bin:/usr/bin:/usr/ucb.
If you want to use nonstandard commands as a privileged person, you should
#$&*)$ well have them in a protected place - we use /opr.

We had a secretary who created a little script called 'test' (dunno why) that 
printed out some guy's performance appraisal on her screen, and it turns
out there were a FEW system scripts promiscuously using 'test' without
protecting their paths - she was pretty upset for a while.

wcs@ho95e.UUCP (Bill.Stewart.4K435.x0705) (12/15/85)

In article <6223@utzoo.UUCP> henry@utzoo.UUCP (Henry Spencer) writes:
>> 	Also, I would love to try to break into a system kept secure by your
>> shell scripts which do not contain absolute path names.  I would do exactly
>> what you suggest - substitute my own versions of rm, mv, etc...
>
>Wouldn't help, since all those shell scripts start with the magic line:
>
>	PATH=/bin:/usr/bin ; export PATH
>
>which solves the problem without requiring hardwired path names everywhere.
>Also, it solves the problem for everything invoked by the shell script,
>rather than just for the shell script itself.

Henry and Ian are usually right :-), but ......
Actually, it has the potential for BREAKING almost everything invoked
by the shell script, though not the shell script itself!  If you do

	PATH=/bin:/usr/bin:$PATH: ; export PATH

(perhaps with /usr/ucb/bin or /usr/lbin wedged in there) then the
script can call other scripts that depend on the user's path.  You do
need to protect all the standard-location commands, but you should also
allow the user's path to remain.  (I once saw an in-house shell
tutorial thatt showed a .profile with PATH=:/bin:/usr/bin:/4513/fred/bin: -
the user had tried it out and wondered why lots of useful commands
didn't work any more.)

There are a few other fun commands to have local versions of.  One of
my users wrote a "sort", in Fortran.  After he got it to compile, he
decided to add some features, and "f77 sort.f" died with ugly errors.
Seems the system V f77 compiler used "sort" to help with symbol tables,
and his sort routine didn't take the same arguments as /bin/sort.

-- 
# Bill Stewart, AT&T Bell Labs 2G-202, Holmdel NJ 1-201-949-0705 ihnp4!ho95c!wcs