[comp.unix.ultrix] Question

chuck@felix.UUCP (12/03/87)

Reply-Path:



Hi,
    I'm working on an application where I need to be able to have bidirectional
communications between two processes, usually a parent & child process.

My first attempt at this involved calling "pipe" twice to open a pair of
channels, and forking off the subprocess with the pipes connected to its
stdin & stdout:
	pipe(parent_to_child)
	pipe(child_to_parent)
	fork()

	parent process closes read end of "parent_to_child" pipe,
	and write end of "child_to_parent" pipe; child process does
	the reverse.
	Child process uses "dup" or "dup2" to attach the pipes as
	stdin (file descriptor 0) and stdout (fd 1).

	exec(subprocess info....)

So far, things seem to work, and there is some sort of communications going
on between the processes.  The problem I run into now is with the buffering
mechanisms.  Each time the child writes to the parent, I want the parent
process to recognize the fact, and fetch the data written.  I do NOT want
data buffered.  This is not a problem to me from the parent end since I 
can call fflush(), but I don't necessarily have access to the child process
source code, so I can't modify its normal activities (such as to insert fflush
after every write(), printf(), etc.).  The parent process here is the
application I'm working on, the child process(es) is any arbitrary executable.

The questions then are:
    Can I determine when the child has written something to the pipe?
    Can I determine exactly how many characters have been written?
    Can I do this both in a synchronous and an asynch. fashion?
    Oh yes, if the answer to any of these is "yes", next comes "How?"  :-)

I did try using "setbuf" to set non-buffered I/O on stdin and stdout; in the
child process, but this didn't seem to have any effect.

I would like to find a solution which will work with different flavors of Unix
too (Ultrix, BSD, SysV), but the only one which I have real familiarity with
is Ultrix, so I'm afraid I don't know what is portable and what isn't.
I am aware of the existence of "sockets", but don't know how to use them,
and what little SysV documentation I could find never mentioned them at all,
so I don't know if these are particularly portable.

It would also be useful to me to communicate between two processes which
aren't directly related (one the  parent of the other); so far, the only 
mechanism I know of which might be useful here (besides sockets) is the
pseudoterminal drivers (pty/tty).

Can anyone out there enlighten me?

    Thanks in advance,
	Mark
	mercutio!lanzo

jpn@genrad.UUCP (John P. Nelson) (12/17/87)

>                This is not a problem to me from the parent end since I 
>can call fflush(), but I don't necessarily have access to the child process
>source code, so I can't modify its normal activities (such as to insert fflush
>after every write(), printf(), etc.).  The parent process here is the
>application I'm working on, the child process(es) is any arbitrary executable.

I'm afraid that you are out of luck.  The stdio package buffers output
to a pipe by default.  There is nothing you can do to change this behavior
in an arbitrary child task.

You should consider setting up a PSUEDO terminal (see 4 pty) for the
child program instead.  The PTY looks just like a regular tty to the
child task, so that normal line-oriented buffering occurs.  (also the
child won't block on read, if it attempts to read an entire buffer,
when a single line of data is available).

The biggest flaw in using PTYs is that there is no equivalent facility
in System V systems.  However, you said that you were most interested
in ULTRIX (BSD) type systems.

To set up a pty connection, you must search through all pty pairs,
attempting to open up (read/write) a master/slave pair.  If either open
fails, go to the next pty.  When a pair has been successfully opened,
you can set up the tty mode on the slave pair (it is just like a tty,
see tty(4)).  You should also set up the master mode (input as either
raw data, or each packet prefixed with a #chars byte).  Then after
fork()ing, in the child task close the master side, dup2 the slave
descriptor into 0 1 and 2.  Then exec.  The child task will function
normally.

Good Luck.  I'd send you some sample code, but it is derived from the
"script" program source, and I don't want to violate my source license.

------- End of Forwarded Message