Subject: Re: cat(1) question: multiple "-"s
To: Johnny Billquist <bqt@update.uu.se>
From: Steven M. Bellovin <smb@cs.columbia.edu>
List: netbsd-users
Date: 04/18/2006 14:26:18
On Tue, 18 Apr 2006 20:07:29 +0200, Johnny Billquist <bqt@update.uu.se>
wrote:

> Steven M. Bellovin wrote:

> > If we had streams, and if pipes were streams, it could be done quite
> > easily -- make sure there's a 0-length record present.  Otherwise, it's
> > not particularly easy.  It would take a kernel multiplexor that you handed
> > several files -- more likely, several file descriptors -- that would read
> > the first until it ended, give EOF, then the next, etc.
> 
> Well, it also needs to signal eof at the end of each file, and then 
> reset the status if another file exists, which to switch over to.

That's what I said, I think.
> 
> But I'm not sure about your thoughs... You need read() to return 0. I 
> don't think a stream have the data stored in records. A stream will 
> return as much data as exists, or until the read buffer is full. If no 
> data exists, it will wait. It will only return 0 on a EOF situation.
> That's what we want to access. I suspect this means that we need some 
> oob data to tell that en EOF should be delivered here, or the 
> implementation behind the read needs to be changed.
> The whole point of a stream is that there isn't any structure to it, 
> which includes the absence of a record concept.
> 
> But I might be wrong. It's been a long time since I was anywhere near 
> that kind of code (back in 4.3BSD...).
> 
> A pipe can be wrapped in a stream, by the way, can it not? A stream is 
> just distinguished by the fact that it have a FILE descriptor. When 
> stdin is redirected to a pipe, it's still a stream?
> Or am I confusing things a lot now?
> 
We may be talking past each other.  I'm speaking of System V Release 4
streams and/or Ritchie streams.  Both were capable of preserving record
boundaries.

Without going into details, streams a form of kernel pipeline.  You had
producers and consumers, but you also had filters.  Thus, a tty device
would simply generate an uinterpreted byte stream; if you wanted tty
semantics such as erase and kill, you pushed a line discipline on top of
the tty fd.  But the same could be done with TCP fds and pipe fds -- no
need for ptys in that model.  (I'm oversimplifying.)

Ritchie streams contained a linear sequence of buffers of some maximum
length.  There were also control records; one was record mark, which (for
example) the tty line discipline would emit when it saw a ^D.  SVR4
streams were more like mbuf chains, in that each stream message could be
the head of a list of buffers.  In this case, a 0-length buffer list
indicated a record mark.

We're getting off-topic, but I think it's clear how either scheme would
let you DTRT for this case.

		--Steven M. Bellovin, http://www.cs.columbia.edu/~smb