[net.unix] #! /bin/sh

chris@umcp-cs.UUCP (Chris Torek) (08/14/86)

In article <1361@ulysses.UUCP> dgk@ulysses.UUCP (David Korn) writes:
>The #! /bin/sh on the first line is interpretted by the kernel in BSD 4.2.

>This has two unfortunate consequences.  First of all it execs a new copy
>of the shell to run the shell procedure even if you are already running
>the Bourne shell.  This is a lot slower than just letting the exec
>fail and letting the shell read the procedure directly.

This is the second time I have seen this assertion.  I did not
believe it earlier, so this time I set out to test it.  The base
form of my test scripts are appended below.  I ran the commands

	time sh doit.sh

and

	time csh doit.csh

and edited doit.sh and doit.csh to run `x1.sh' or `x2.sh' as
appropriate.  Results (on a Vax 8600 running 4.3BSD-beta-plus):

		  doit.sh	doit.csh
		--------------------------
	#!	| 1.4u 4.7s	1.6u 5.6s
	direct	| 1.1u 4.0s	1.4u 5.9s

In both cases, using `#!' is somewhat less efficient: .01 seconds
per script invocation when using `sh', and .001 seconds per invocation
when using `csh'.  (The csh results look a bit anomalous, but I am
ready to believe almost anything regarding efficiency, or lack
thereof, within the C shell.)

I imagine that most shell scripts are rather more complex than
`x1.sh' and `x2.sh' (both of which do nothing), and that the
hundredth-second difference gets lost quite quickly in practise.
In any case the extra time is, in my opinion, more than offset by
the ability to run the scripts via the various `exec' calls.  In
addition, `#!' can run things other than sh and csh:

	#! /bin/awk NR > 2 { print }
	# this file prints the rest of itself to stdout
	try it and
	see.

>Secondly, this allows for a very insecure implementation of setuid shell
>procedures.

Setuid shell scripts are quite dangerous.  I believe it is possible
to write a `secure' setuid script, but there are enough bugs with
setuid and shells that I recommend against such scripts purely on
priciple.  However, that #! allows this is not necessarily a point
against it.

---test scripts:

: Run this shell script with "sh" not "csh"
PATH=/bin:/usr/bin:/usr/ucb:/etc:$PATH
export PATH
echo Extracting doit.csh
sed 's/^X//' <<'//go.sysin dd *' >doit.csh
foreach i (0 1 2 3 4 5 6 7 8 9)
foreach j (0 1 2 3 4 5 6 7 8 9)
x1.sh
end
end
//go.sysin dd *
chmod 644 doit.csh
echo -n '	'; ls -ld doit.csh
echo Extracting doit.sh
sed 's/^X//' <<'//go.sysin dd *' >doit.sh
for i in 0 1 2 3 4 5 6 7 8 9; do
for j in 0 1 2 3 4 5 6 7 8 9; do
x1.sh
done
done
//go.sysin dd *
chmod 644 doit.sh
echo -n '	'; ls -ld doit.sh
echo Extracting x1.sh
sed 's/^X//' <<'//go.sysin dd *' >x1.sh
: sh file
: does nothing
#! /bin/sh
//go.sysin dd *
chmod 755 x1.sh
echo -n '	'; ls -ld x1.sh
echo Extracting x2.sh
sed 's/^X//' <<'//go.sysin dd *' >x2.sh
#! /bin/sh
: sh file
: does nothing
//go.sysin dd *
chmod 755 x2.sh
echo -n '	'; ls -ld x2.sh
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1516)
UUCP:	seismo!umcp-cs!chris
CSNet:	chris@umcp-cs		ARPA:	chris@mimsy.umd.edu