Path: utzoo!mnetor!uunet!steinmetz!mercutio!lanzo
From: lanzo@mercutio.steinmetz (Mark Lanzo)
Newsgroups: comp.unix.questions
Subject: Another attempt at getting help with process communications
Message-ID: <8214@steinmetz.steinmetz.UUCP>
Date: 14 Dec 87 22:16:44 GMT
Sender: root@steinmetz.steinmetz.UUCP
Reply-To: lanzo@.UUCP (Mark Lanzo)
Organization: General Electric CRD, Schenectady, NY
Lines: 113
Keywords: LONG!


Once, again, I appeal to the net for help with process communications.
In a recent article, I described a program whereby I opened up a pair
of pipes for communications between two processes, then used fork/exec
to spawn a subprocess, with communications being maintained between the
two processes via the pipes.  Well, I've given up on that idea since 
there seems to be absolutely no way to defeat the buffering mechanism
for pipes.  So, now I'm trying similar stunts with pseudoterminals.

I realize that I probably can't totally defeat the buffering mechanisms
with pseudoterminals, but at least then I might get line buffering, which
in most circumstances is all I'm really after anyways.
What I'd like to be able to do is open up a pseudoterminal slave end
as "stdin" and "stdout" (with "stderr" connected to "stdout" usually) 
for a subprocess, and have the pseudoterminal master end opened up 
in the master process to maintain communications.  My previous posting
included a algorithm description which went something like:

     call "pipe" to open a pipe which is for writing from parent-to-child
     call "pipe" to open a pipe for writing from child-to-parent
     fork process:

	child				 
        -------                          
	disconnect unused ends of pipes:
	    close parent-to-child write end
	    close child-to-parent read	end
	use close/dup etc to make pipe ends be stdin & stdout.
	set unbuffered I/O mode on stdin, stdout, stderr (I know, this 
	    doesn't do anything useful, I realize now that only the file
	    descriptor table is inherited and that the level 2 I/O 
	    buffers are just part of the overlayed (-ing) program.)
	exec subprocess...

    
        parent                            
	----------			   
	disconnect unused ends of pipes:
	    close child-to-parent write end 
	    close parent-to-child read end
	sit in loop waiting for I/O activity (using "select(2)")

This works, except for the aforementioned buffering problems.
Is there some way I can use a similar process with pseudoterminals?

I tried replacing the "pipe" calls with "open(pty_name,mode,prot)" type
calls, but this didn't seem to do the trick, even when I successfully
opened the pty.

The thing which confuses me most is that I don't know how to handle the
bidirectional communications with a pseudoterminal, especially with the
master end of the pseudoterminal, which can only be opened once (ie., I
can't do an "open("/dev/ptyp0",O_RDONLY,0)" followed by 
"open("/dev/ptyp0",O_WRONLY,0)" to open up two file descriptors in the master
process, one for input and one for output to the subprocess.
If I do "fd = open("/dev/ptyp0",O_RDWR,0)" and then do a "write(fd...)"
followed by a "read(fd...)" will I read what I just wrote?  I would assume
not, but it looked like that was what was happening to me; especially if
the child process exited so that the slave end of the pty wasn't really
connected to anything.

From the master process, I really don't care too much whether the 
channel to the subprocess is via 1 or 2 descriptors; but I definitely need
2 (or 3) descriptors in the subprocess, since these are supposed to be
stdin, stdout, and stderr.

A second question:
    How do I locate an unused pty/tty pair; and how do I ensure that nothing
else tries to access the pty while my job is using it?  Do I just loop
trying to open /dev/ptyp0 then /dev/ttyp0; on failure try /dev/ptyp1 and
/dev/ttyp1, then ptyp2, p3 ... etc, or is there a more clever mechanism
here?  What if there is NO currently unused pty? (as when a bunch of 
people have rlogin'ed (?)).


Miscellaneous:
    I'm using Ultrix 1.2 (going to 2.0 soon), but I'm interesting in solutions
which are as portable as possible between various flavors of Unix.
[Same disclaimer as last time!]

	    Once again, thanks in advance,

		    Mark Lanzo
                    mercutio!lanzo



P.S.
Thanks to those people who did reply to my last article.  I'd reply
directly, but that never seems to work around here.  I definitely 
appreciate the person who pointed out the "select" call to me.

A miscellaneous question regarding "select":

    I did a "select" call something like:

    rd_fds = (1<