[net.unix] read and write given single file descriptor

shore@adobe.UUCP (Andrew Shore) (08/06/85)

Both the 4.2BSD and System V line printer spoolers invoke a
printer-specific interface program with one file descriptor
already open to "the device" (the printer).  On both systems the
fd is open for writing, but the documentation states that the
device can be opened for reading also under certain
circumstances (specifying "rw" in the BSD printcap entry, or
having the file (device) readable on SysV); however, you still
only get one fd when you get called.  You do NOT get passed the
name of the device (so you can't do your own open(2)).

The days of printers-as-stupid-data-sinks are long gone.  More
and more printers are sophisticated devices which may want to
carry on detailed dialogs with a host -- passing status
information, requesting certain operations, etc.  Some may
generate asynchronous messages (e.g., "out of paper").

I am implementing spooler interfaces for such printers, and have
to be able to read from and write to the printer independently.
My spooler interface starts off by doing a fork with the parent
continuing as "sender" and the child as "listener".  Each of
these needs a stream to (from) the device respectively.  If I
try to read and write from the single fd I got started with,
things mess up (the fd has only one buffer and file pointer
which gets confused if you try to share arbitrary reads and
writes to it).  I find that I have to have 2 fd's to the same
device.

The way I currently accomplish this is:
	/* Before the fork (stdout is the device) ... */
	fdsend = fileno(stdout);	/* the printer (write) */
	fdlisten = dup(fdsend);		/* the printer (read) */
	/* Do the fork */
	/* parent can write to fdsend (stdout) */
	/* child does the following ... */

	psin = fdopen(fdlisten,"r");	/* make a FILE out of an fd */
	/* child now has fdlisten (psin) to read from */

This seems to work fine on both 4.2BSD and SysV, but it is not at
all obvious that this is correct or that it should work at all.

I've been warned that this technique will NOT work for 
non-character (non-terminal?) devices.  If the device is really
a socket (like a PUP connection to an ethertip) this supposedly
fails.  Will this work for block devices, FIFOs, etc?

Is there a better, cleaner, more general solution?
Or am I really doing things OK and just beening paranoid?

I can't change the way I get invoked -- the spoolers just
do it that way.

Thanks in advance,
--Andy Shore
  Adobe Systems Incorporated	(415)852-0271
  
  {decwrl,glacier,sun}!adobe!shore

chris@umcp-cs.UUCP (Chris Torek) (08/07/85)

Why not simply avoid stdio within the despoolers?  It tends to
create more problems than it's worth when you need exact control
over what happens when.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 4251)
UUCP:	seismo!umcp-cs!chris
CSNet:	chris@umcp-cs		ARPA:	chris@maryland