[comp.unix.questions] csh reading from stdin

glenn@wacsvax.uwa.oz (Glenn Huxtable) (08/23/90)

While modifying a csh script (hey, I dont write them, I just fix them) I came 
across the following odd behaviour in csh. Can anyone expalin why it does this?
More to the point, is it correct and standard? (I have only tried this on a
SunOS 4.0.3 host).

I wanted to look a the first line of a file (on stdin) and decide which filter
to pass it to, depending on the first few characters. I thought this would be
quite straight forward, use $< to read the first line, decide which filter to
use then echo the line just read and cat the remaining file to the filter.
Something like ...

	set line=$<
	# decide which filter
	(echo $line ; cat) | $FILTER

this resulted in two copies of the first line.
now, the csh manual says that $< can be used to read values from the
keyboard, it doesnt say anything about reading from a file, however you would
expect ...

a simpler test is the following

	set first=$<
	set second=$<
	echo $first
	echo $second
	cat

running this with stdin taken from the keyboard (ie. no redirect) does what
you would expect, reads two lines, echos them then cats the rest back at you.

running this with input redirected from a file prints the first two lines
of the file, then the entire file INCLUDING the first two line.

Just to make life more interesting, taking input from a pipe does the expected 
(ie no duplication of lines). It looks very much like csh is looking to see
if stdin is a file and maintaining duplicate file pointers for itself and
subsequent commands.

As it turns out, this is exactly what I want, since I thought that having read
the first line (in my example above) that I would have to mess around with
the (echo $line; cat)  subshell to get the line back intothe subsequent input
stream of the filter. The question is, can I trust this is normal? If it is,
someone should probably be shot!

glenn
ACSnet   - glenn@wacsvax.uwa.oz				         glenn huxtable
Internet - glenn@wacsvax.cs.uwa.oz.au                  dept of computer science
phone 	 - +61 09 380 2878			university of western australia
fax      - +61 09 382 1688

maart@cs.vu.nl (Maarten Litmaath) (08/23/90)

In article <glenn.651406891@bilby>,
	glenn@wacsvax.uwa.oz (Glenn Huxtable) writes:
)...
)[SunOS 4.0.3]
)
)	set line=$<
)	# decide which filter
)	(echo $line ; cat) | $FILTER
)
)this resulted in two copies of the first line.

1) The bug is in `cat': it reads the file using mmap(2), blindly assuming
   you want to start reading at byte offset 0.  :-(
   Probably fixed in SunOS 4.1.
   You can't mmap() a pipe, so things work correctly if stdin is a pipe,
   as cat must use read(2) in that case.

2) Your scheme depends on csh reading the line 1 byte at a time (normally
   file IO is _block-buffered_); though your implicit assumption appears
   to be correct indeed, the manual doesn't guarantee it.  :-(
--
        "[Your C code] seems about as portable as the Rock of Gibraltar."
                                 (Wayne Throop)