[comp.unix.questions] portability of non-shell scripts

phil@ux1.cso.uiuc.edu (Phil Howard KA9WGN) (01/16/91)

When I write a program in some interpretive language like a shell script,
the full path name of the interpreter is used on the beginning "#!" line.
However I am finding that different systems put these interpreters in
different directories.

Is there no consitency to this?  Has anyone worked a general way to make
these script programs more portable so that they will run w/o having to
have the user do editing on them?

Examples of the interpreters include perl and various flavors of awk.
The sh/csh/ksh shell interpreters so far always seem to be in /bin.
-- 

--Phil Howard, KA9WGN-- | Individual CHOICE is fundamental to a free society
<phil@ux1.cso.uiuc.edu> | no matter what the particular issue is all about.

gwyn@smoke.brl.mil (Doug Gwyn) (01/16/91)

In article <1991Jan15.233523.18150@ux1.cso.uiuc.edu> phil@ux1.cso.uiuc.edu (Phil Howard KA9WGN) writes:
>Is there no consitency to this?  Has anyone worked a general way to make
>these script programs more portable so that they will run w/o having to
>have the user do editing on them?

About the best I know of is to ALWAYS use #!/bin/sh and tell that shell
what command to run, with what arguments.  If you set $PATH to a nice,
fairly inclusive set of possible directories then the command should be
found no matter which of the directories it resides in.

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (01/17/91)

In article <14869@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
: In article <1991Jan15.233523.18150@ux1.cso.uiuc.edu> phil@ux1.cso.uiuc.edu (Phil Howard KA9WGN) writes:
: >Is there no consitency to this?  Has anyone worked a general way to make
: >these script programs more portable so that they will run w/o having to
: >have the user do editing on them?
: 
: About the best I know of is to ALWAYS use #!/bin/sh and tell that shell
: what command to run, with what arguments.  If you set $PATH to a nice,
: fairly inclusive set of possible directories then the command should be
: found no matter which of the directories it resides in.

"Nice" and "fairly inclusive" are fairly incompatible in this context.  Any
fairly inclusive PATH is not going to be very nice.  Your only hope is to
avoid setting PATH at all and use the user's imported PATH.  (You might add
a few directories to the user's PATH, but they're likely to be useless.)

Now, another minor quibble.  On some systems, putting #!/bin/sh will force
it to run under csh rather than sh!  So you need to be really careful to
speak only "shell pidgin".  Yes, it's ghastly, but we were talking about
maximum portability, not some idyllic ideal.  And how are you going to
pass any arguments to the subprogram?  You can use $*, but then filenames
containing spaces won't be handled right.  csh and sh have incompatible ways
of quoting arguments.

Another problem with the #!/bin/sh approach is that it may be difficult
to specify the text of the other program without using a second file or
installing a here-document in the script, either of which can be a pain.
Of course, if your language is designed (like awk) such that you can avoid
single quotes and specify the program as one of the arguments, you can
pass the program as a single-quoted string--but not all languages are
amenable to this.  And it still forces sh to process the whole program
before execution.

Perl can do the single-quote trick, but the maximally portable shell bootstrap
makes use of a three-language hack, in sh, csh and perl.  It avoids making
the shell read the whole file, and goes like this:

    eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
    & eval 'exec perl -S $0 $argv:q'
	if 0;

Even this won't work on those (thankfully few) machines with a csh that mixes
up the meaning of && and || (shudder).  I gave up trying to be portable at
that point.  Human nature being what it is, most people will simply continue
to post scripts with first lines like:

	#!/users/calc101/freddie/.hidden/prog/bin/perl

Personally, I'd rather doctor the #! lines and avoid starting up the extra
shell process on every invocation.  Simplicity lurks in strange places.

Larry Wall
lwall@jpl-devvax.jpl.nasa.gov

dave@galaxia.Newport.RI.US (David H. Brierley) (01/18/91)

In article <1991Jan15.233523.18150@ux1.cso.uiuc.edu> phil@ux1.cso.uiuc.edu (Phil Howard KA9WGN) writes:
[ talks about problems when using #! construct ]
...
>... Has anyone worked a general way to make
>these script programs more portable so that they will run w/o having to
>have the user do editing on them?

How do you plan on having this work "portably" on systems that don't
support the #! mechanism?  The only thing I know of that is even close
to being portable is to assume that your script will be run by one of
the shell interpreters and have the first line of the file exec the
program that you really want run.  Make sure that you dont have anything
on this first line that is sh/ksh/csh specific because I can't gaurantee
what shell will be used to run your script.

This is one of those problems that has no real solution short of forcing
everyone to upgrade to a version of the kernel that supports the #!
mechanism (yes, the #! mechanism is implemented *inside the kernel*!!).
Since you can make a pretty good guess as to what the odds of this happening
are you can apply those same odds to coming up with a solution.
-- 
David H. Brierley
Home: dave@galaxia.Newport.RI.US    Work: dhb@quahog.ssd.ray.com
Can I be excused, my brain is full.

koerberm@nixsin.UUCP (Mathias Koerber) (01/22/91)

In article <1136@galaxia.Newport.RI.US> dave@galaxia.Newport.RI.US (David H. Brierley) writes:
>This is one of those problems that has no real solution short of forcing
>everyone to upgrade to a version of the kernel that supports the #!
>mechanism (yes, the #! mechanism is implemented *inside the kernel*!!).
>Since you can make a pretty good guess as to what the odds of this happening
>are you can apply those same odds to coming up with a solution.

I haven't been following this discussion and just happened to read it here,
so I might ask something already discussed:
My system doesn't support #!, so I can't test it.
Does #! use the PATH, when finding only the name of the executable, or do I 
have to provide the full path/filename for the shell. I mean, my perl is
likely to sit somewhere else than Larry's (in fact it does). So I'd provide
a PATH on my login shell, which points to my local/bin, export it and
exec() then can search the shell to find it. I only would have to provide

	#!perl
	#

as the first line of the script. And anyone could create a file (maybe also in
local/bin, that looks like

	# where does perl reside on this machine ?
	PERL=/usr/local/bin
	# where does csh reside ?
	CSH=/bin
	# where does xxx reside ?
	XXX=/usr/local/xxx/bin
	#
	PATH=$PATH:$PERL:$CSH:$XXX
	export PATH
	# maybe export PERL CSH XXX

another solution (something to agree upon across systems):

	agree upon an exported SHELL-VAR for every shell like:

	# where does perl reside?
	PERL=/usr/local/bin/perl
	export PERL

run this at login time to set the VARS,

and use

	#!$PERL

in the scripts (would that work ?)

Just asking,

Mathias


-- 
Mathias Koerber  | S iemens             | EUnet: koerber.sin@nixdorf.de
2 Kallang Sector | N ixdorf             | USA:   koerber.sin@nixdorf.com 
S'pore 1344      | I nformation Systems | Tel: +65/7402852 | Fax: +65/7402834
* Packed with Power, SNIckers really satisfy  (or do they? Ask them gals :-) )*