[comp.unix.wizards] weird sh

meulenbr@cstw01.UUCP (Frans Meulenbroeks) (08/01/88)

[I posted this before to comp.unix.questions but got no reply;
 hopefully some wizard can help me]

I noticed a peculiarity in sh which causes me a lot of trouble.
The commands:
sh file
and
sh <file
are NOT equivalent.
If you do think so, create a file which contains the command 
rm core
Try both versions in a dir without a file named core.
sh file will give you an error message "No such file...", while
sh <file won't.
The same holds when sh is used in a pipe.

I've played with the options of sh, but to no avail.
Can somebody explain this behaviour to me, and tell me how I can 
communicate through popen with the (a) shell, without losing my error
messages.

B.t.w. The problem is at least present in SunOS 3.4 and Ultrix 2.0

Many thanks!

-- 
Frans Meulenbroeks
	Centre for Software Technology
	...!mcvax!philmds!prle!cst!meulenbr   or   ...!uunet!prlb2!cst!meulenbr
        or perhaps   meulenbr@cst.prl.philips.nl

guy@gorodish.Sun.COM (Guy Harris) (08/03/88)

> I noticed a peculiarity in sh which causes me a lot of trouble.

No, you've noticed a peculiarity in "rm" that causes you trouble.

> If you do think so, create a file which contains the command 
> rm core
> Try both versions in a dir without a file named core.
> sh file will give you an error message "No such file...", while
> sh <file won't.
> The same holds when sh is used in a pipe.

"sh file" causes the shell to run all commands in "file" with the shell's
standard input as their standard input.  So does "sh <file".  The difference is
that the shell's standard input is probably your terminal in the first case,
and certainly not the terminal in the second case.

If you run the 4BSD "rm" from something other than a terminal, it acts as if
you gave it the "-f" flag.  This flag appears to suppress most error messages.

> I've played with the options of sh, but to no avail.
> Can somebody explain this behaviour to me, and tell me how I can 
> communicate through popen with the (a) shell, without losing my error
> messages.

See above for the explanation.  As for getting this to work via "popen", you
may be out of luck.

ok@quintus.uucp (Richard A. O'Keefe) (08/03/88)

In article <163@cstw01.UUCP> meulenbr@cst.UUCP () writes:
>I noticed a peculiarity in sh which causes me a lot of trouble.
>The commands:
>	sh file
>and
>	sh <file
>are NOT equivalent.
>If you do think so, create a file which contains the command 
>	rm core

It isn't the shell's fault.  The sensitive command is 'rm'.
rm(1) will print an error message iff >>its<< standard input
is a terminal.  To verify this, in a directory having no 'core' file, do
	</dev/tty  rm core	# produces an error message
	</dev/null rm core	# is silent

If your script contains the line
	</dev/tty rm core
then both "sh script" and "sh <script" will produce the error message.

This is known and intended behaviour of the BSD /bin/rm; it doesn't
happen under V.3.  However, doing
	</dev/null rm file...
is harmless in V.3

hd@mh_co2.mh.nl (Theo Hardendood) (08/03/88)

From article <163@cstw01.UUCP>, by meulenbr@cstw01.UUCP (Frans Meulenbroeks):
> I noticed a peculiarity in sh which causes me a lot of trouble.
> The commands:
> sh file
> and
> sh <file
> are NOT equivalent.
> If you do think so, create a file which contains the command 
> rm core
> Try both versions in a dir without a file named core.
> sh file will give you an error message "No such file...", while
> sh <file won't.
> The same holds when sh is used in a pipe.

Not sh but rm does his job this way. If the standard input is not a
terminal, then no diagnostics are produced. This is certainly NOT a
bug and makes it possible, for example, to use rm in a crontab entry
without extensive checking.

The difference between 'sh file' and 'sh <file' is that 'sh file'
executes with your terminal as standard input and 'sh <file' doesn't.
To show you the problems that can occur, try the following script.
I think it works on most BSD systems but I didn't check (sorry).

-------------------------- Cut here ---------------------------------
read xx
echo -n 'Did you expect this '
echo $xx
exit 0
This is a dirty way to read input.
------------ End of script (do not include this line) --------------

A way to avoid this problem is to include a line:
	exec </dev/tty
before the first read is done.

Note: The following code is invalid:
	read xx </dev/tty

Theo Hardendood                  hd@mh.nl via european backbone (mcvax)
Multihouse NV, Gouda - The Netherlands          uucp: ..!mcvax!mh.nl!hd
"A conclusion is simply the place where someone got tired of thinking."

gwyn@smoke.ARPA (Doug Gwyn ) (08/03/88)

In article <163@cstw01.UUCP> meulenbr@cst.UUCP () writes:
>sh file
>and
>sh <file
>are NOT equivalent.

That's for sure.  I had a heck of a time getting both these
invocations to not source the user's $ENV file while still
having the normal interactive sh do so, in our extended sh.

merlyn@intelob (Randal L. Schwartz @ Stonehenge) (08/03/88)

In article <163@cstw01.UUCP>, meulenbr@cstw01 (Frans Meulenbroeks) writes:
| [I posted this before to comp.unix.questions but got no reply;
|  hopefully some wizard can help me]
| 
| I noticed a peculiarity in sh which causes me a lot of trouble.
| The commands:
| sh file
| and
| sh <file
| are NOT equivalent.
| If you do think so, create a file which contains the command 
| rm core
| Try both versions in a dir without a file named core.
| sh file will give you an error message "No such file...", while
| sh <file won't.
| The same holds when sh is used in a pipe.
| 
| I've played with the options of sh, but to no avail.
| Can somebody explain this behaviour to me, and tell me how I can 
| communicate through popen with the (a) shell, without losing my error
| messages.

The problem is not sh(1), but rm(1).  Try:

  rm core

vs.

  rm core </dev/null

to see the difference.  rm(1) is checking stdin to see if it needs to
bitch.  This is true of a few other commands as well, but the exact
list escapes me.  sh doesn't really care (well, almost :-).  Another
difference between your two invocations is the matter of additional
parameters.  Notice the difference between:

  sh file arg1 arg2 arg3

and

  sh <file arg1 arg2 arg3

The first sets $1 to arg1, $2 to arg2, and so on.  The second
(attempts to) execute arg1 as a shell script, with $1 set to arg2, $2
set to arg3, and stdin set to file!
-- 
Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095
on contract to BiiN Technical Publications (for now :-), Hillsboro, Oregon
<merlyn@intelob.intel.com> or ...!tektronix!ogcvax!omepd!intelob!merlyn
Standard disclaimer: I *am* my employer!