[net.unix] 2 shell questions before the new year

Jeff Damens <US.JD%CU20B@COLUMBIA.ARPA> (12/29/84)

>   1. What is the difference between
>
>		   sh < file
>   and
>		   sh file

With the "sh file" form, standard input can still be redirected
(that is, standard input for any programs that are invoked by
the shell; obviously the shell takes its input from file); the
"sh < file" form doesn't allow input redirection.

>   2. Why begin a shell script with
>
>		   #!/bin/sh
>   or
>		   #!/bin/csh

This tells the C shell which shell is supposed to interpret the
shell script.  It's necessary because the syntax of shell
commands is different in the two shells; I think /bin/sh is used
by default.  However, if the script starts with a # and doesn't
have the !  construct, the C shell is used

Jeff Damens, Systems Integration Group, Columbia U.

-------

chris@umcp-cs.UUCP (Chris Torek) (12/29/84)

> What is the difference between "sh < file" and "sh file"

The first way keeps the script from reading anything else from its
input.  Consider the script

	while read word
	do
		echo $word | sed s/foo/bar/
	done

If run as ``sh zip'', it will read from your terminal, replacing ``foo''
with ``bar''.  If run as ``sh < zip'', it will exit right away, since
after reading the script, there's no input left.

> Why begin a shell script with "#!/bin/sh" or "#!/bin/csh"

Under 4BSD, at least, this makes the program exec()able (assuming that
you have execute permission for that file).  That is, the kernel can
start this program, even though it's not machine code; the kernel will
invoke the named program after fiddling arguments a bit.

In fact, the script

	#! /bin/mv

will rename itself!  Place it in a file called ``zap'', and type
``zap zup'', and now you have a shell script called ``zup''.  Your
shell tried to exec() the program with the argument "zup".  This
succeeded, but actually ran /bin/mv with the arguments "zip" "zup".

You can make self-removing scripts:

	#! /bin/rm

Or self-printing scripts:

	#! /bin/awk NR > 1 { print }
	text...

This last one works because the kernel is willing to do more than
insert the filename in the argument list: it will insert one (and only
one) optional argument.  Normally, this is used for things like the
``-f'' option to the C shell (``fast'', don't read .cshrc's), but it
works well enough for awk too.

#! is described (though not completely) in man 2 execve in 4.2BSD.
-- 
(This line accidently left nonblank.)

In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (301) 454-7690
UUCP:	{seismo,allegra,brl-bmd}!umcp-cs!chris
CSNet:	chris@umcp-cs		ARPA:	chris@maryland

gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) (12/29/84)

> >   2. Why begin a shell script with
> >
> >		   #!/bin/sh
> >   or
> >		   #!/bin/csh
> 
> This tells the C shell which shell is supposed to interpret the
> shell script.  It's necessary because the syntax of shell
> commands is different in the two shells; I think /bin/sh is used
> by default.  However, if the script starts with a # and doesn't
> have the !  construct, the C shell is used

Let's get this right, please.  Recent BSD kernels understand the
"#!" as a "magic number" and exec() succeeds in executing such a
file, feeding it to the specified interpeter (which need not be one
of the "shells").  Only if an attempt to exec() fails will the shell
decide that it's a shell script and interpret it directly.  It is
extremely unfortunate that the Cshell thinks that # is not found in
Bourne shell scripts; apart from the #! line, practically all of
my Bourne shell scripts start with a # comment describing the function.

The full story of which shell will run your script was discussed
several months ago and is too gross to repeat.  Suffice it to say,
indicate with #!<shellpath> which shell you want and persuade your
Cshell to interpret #! lines if your kernel doesn't.

david@ukma.UUCP (David Herron, NPR Lover) (12/31/84)

The "#!" form has other uses as well.  Please peruse our phones command.

	#! /bin/grep ^[^#]
	The phone numbers to dial to reach the VAX-11/750 are:
	   
		ttyh8	257-1474
		ttyh9	257-5627
		ttyha	257-1361
		tty02	257-1353
		tty04	257-1232
	   
	The number for room 907 is:  257-4244

(Sorry, should this be in net.sources?)

One day I happened to notice in the kernal where this was being
interpreted, and noticed that it was capable of handling ONE argument.
So.........

	David Herron

jerryp@tektools.UUCP (Jerry Peek) (01/06/85)

In article <450@ukma.UUCP> david@ukma.UUCP (David Herron, NPR Lover) writes:
>The "#!" form has other uses as well.  Please peruse our phones command.
>
>	#! /bin/grep ^[^#]
>	The phone numbers to dial to reach the VAX-11/750 are:
>	   
>		ttyh8	257-1474
		    .
		    .

This also works well with "more +2"... to make a self-contained help program
that paginates itself (don't even bother flaming about "more", please):

      #! /usr/ucb/more +2
      For help with UNIX, call the Tek UNIXhelp hotlines: 627-5245 or 629-1630.
      UNIX classes are available at Tek: Call 627-1602 for information.

      The "sysinfo" command will give you a menu of tektools system information.

      The commands:
	      apropos topic		lists commands relevant to the topic
	      man command		shows the manual for a command
		.
		.
		.
		.

--Jerry Peek, UNIX Training Instructor, Tektronix, Inc.
US Mail:    MS 76-036, P.O. Box 500, Beaverton, OR 97077
uucp:       {allegra,decvax,hplabs,ihnp4,ucbvax}!tektronix!tektools!jerryp
CS,ARPAnet: jerryp%tektools@tektronix.csnet
Phone:      503/627-1603

ed@mtxinu.UUCP (Ed Gould) (01/07/85)

> >   2. Why begin a shell script with
> >
> >	 #!/bin/sh
> >   or
> >      #!/bin/csh
>
> This tells the C shell which shell is supposed to interpret the
> shell script.  It's necessary because the syntax of shell
> commands is different in the two shells; I think /bin/sh is used
> by default.  However, if the script starts with a # and doesn't
> have the ! construct, the C shell is used

On recent 4bsd systems (certainly 4.2, I believe 4.1 and don't remember
before) this construct also allows the file to be handled by the
kernel's exec() routine.  The documented syntax is

	#! pathname arg

where the space after the ! (exactly one space character, or perhaps
either one space or one tab) is required, and there may be no more than
one argument.  (In reality, the space has never to my knowledge been
required.)

The advantages of directly-execable scripts are two-fold.  First,
it allows *any* interpreter to be specified for the rest of the
file, not just a shell.  Second, the set-uid and set-gid bits
are honored.  Voila!  Set-uid shell scripts!

-- 
Ed Gould		    mt Xinu, 739 Allston Way, Berkeley, CA  94710  USA
{ucbvax,decvax}!mtxinu!ed   +1 415 644 0146
			    (I'd rather not be parochial.)

henry@utzoo.UUCP (Henry Spencer) (01/09/85)

> The advantages of directly-execable scripts are two-fold.  ...
> ...  Second, the set-uid and set-gid bits
> are honored.  Voila!  Set-uid shell scripts!

Of course, as we all (should) know, setuid shell scripts are terminally
insecure.  The shell is just too complex, and there are too many ways
to subvert it into doing things that the author of a (setuid) shell
script did not intend.  There are things that will help, like being
careful to standardize PATH and having your shell refuse to import a
non-standard value of IFS, but those aren't the only problems.
-- 
				Henry Spencer @ U of Toronto Zoology
				{allegra,ihnp4,linus,decvax}!utzoo!henry

jim@mcvax.UUCP (Jim McKie) (01/10/85)

In article <240@mtxinu.UUCP> ed@mtxinu.UUCP (Ed Gould) writes:
	>The advantages of directly-execable scripts are two-fold.  First,
	>it allows *any* interpreter to be specified for the rest of the
	>file, not just a shell.  Second, the set-uid and set-gid bits
	>are honored.  Voila!  Set-uid shell scripts!

Unless you've fixed your kernel, if you have setuid shell scripts you
have a security hole. Don't send me mail asking what it is.

Jim McKie
mcvax!jim

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

> Unless you've fixed your kernel, if you have setuid shell scripts you
> have a security hole. Don't send me mail asking what it is.

One should be careful for ANY security-related code to check for
loopholes.  This means, in C code, argc == 0, PATH=funny_places,
signals in critical places, fd 0, 1, and/or 2 not opened, etc.
For shell scripts, one should ALWAYS set PATH=wherever and if
security-critical set IFS=standard_whitespace and catch traps.

hans@log-hb.UUCP (Hans Albertsson) (01/13/85)

In article <7173@brl-tgr.ARPA> gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) writes:
>> Unless you've fixed your kernel, if you have setuid shell scripts you
>> have a security hole. Don't send me mail asking what it is.
>
>One should be careful for ANY security-related code to check for
>loopholes.  This means, in C code, argc == 0, PATH=funny_places,
>signals in critical places, fd 0, 1, and/or 2 not opened, etc.
>For shell scripts, one should ALWAYS set PATH=wherever and if
>security-critical set IFS=standard_whitespace and catch traps.


Well, do all of that, and still do NOT use any set-uid shell scripts.
I had the bug demonstrated privately, and believe me, you should NOT
permit setuid shell scripts. Ever. Period.
No amount of defensive programming helps.

A fix may or may not be available at a later date, they tell me.
I have NO idea how that will be distributed, if ever.
Or by whom.
I've got it, I think ( hope? ), but won't spill.
-- 
Hans Albertsson, USENET/uucp: {decvax,philabs}!mcvax!enea!log-hb!hans
Real World:  TeleLOGIC AB, Box 1001, S-14901 Nynashamn,SWEDEN