[comp.unix.wizards] Taking Control of stdin/stdout of a slave process

rduff@evax.arl.utexas.edu (Robert Duff) (03/14/91)

I am interested in starting a UNIX process from a program and having the
slave process' stdin and stdout piped through FILE*'s in the master process.

I have worked with popen(), but that only allows one-way piping.
How can I get both directions piped to my controller process?

Thanks In Advance

-------------------------------------------------------------------------------
Remeber the immortal words of Socrates       |  Robert Duff
who said:                                    |  Automation & Robotics Research
          "I Drank WHAT!?"                   |  Institute - (817) 794-5957
                              Chris Knight   |  rduff@evax.uta.edu

jik@athena.mit.edu (Jonathan I. Kamens) (03/14/91)

In article <1991Mar13.163756.26785@evax.arl.utexas.edu>, rduff@evax.arl.utexas.edu (Robert Duff) writes:
|> I am interested in starting a UNIX process from a program and having the
|> slave process' stdin and stdout piped through FILE*'s in the master process.
|> 
|> I have worked with popen(), but that only allows one-way piping.
|> How can I get both directions piped to my controller process?

  This is not a comp.unix.wizards question.

  Not only is it not a wizards question, but it's answered in the monthly
Frequently Asked Questions posting in comp.unix.questions (which is where this
question should have been posted in the first place).  Question number 26.

  If the comp.unix.questions FAQ has expired at your site, you can either wait
until it is posted again, or send me E-mail and I'll send it to you.

  And rather than just reading the one question in the FAQ that answers this
particular question it would probably be a good idea for you to scan the whole
thing briefly before posting any additional questions to the net.

-- 
Jonathan Kamens			              USnail:
MIT Project Athena				11 Ashford Terrace
jik@Athena.MIT.EDU				Allston, MA  02134
Office: 617-253-8085			      Home: 617-782-0710

subbarao@phoenix.Princeton.EDU (Kartik Subbarao) (03/14/91)

> I am interested in starting a UNIX process from a program and having the
> slave process' stdin and stdout piped through FILE*'s in the master process.
> 
> I have worked with popen(), but that only allows one-way piping.
> How can I get both directions piped to my controller process?

  This is not a comp.unix.wizards question.
>
>  Not only is it not a wizards question, but it's answered in the monthly
>Frequently Asked Questions posting in comp.unix.questions (which is where this
>question should have been posted in the first place).  Question number 26.

Why does every other question posted to this newsgroup that can be answered
in the FAQ deals with pipes and popen()? Is this just a coincidence, or
something else?.....






--
internet# find . -name core -exec cat {} \; |& tee /dev/tty*
subbarao@phoenix.Princeton.EDU -| Internet
kartik@silvertone.Princeton.EDU (NeXT mail)  
SUBBARAO@PUCC.BITNET			          - Bitnet

bharat@cf-cm.computing-maths.cardiff.ac.uk (Bharat Mediratta) (03/14/91)

In article <1991Mar13.163756.26785@evax.arl.utexas.edu> rduff@evax.arl.utexas.edu (Robert Duff) writes:
>
>I am interested in starting a UNIX process from a program and having the
>slave process' stdin and stdout piped through FILE*'s in the master process.
>
>I have worked with popen(), but that only allows one-way piping.
>How can I get both directions piped to my controller process?

Try using pipe(3), and dup2(3):

#define READ 0
#define WRITE 1

main()
{
	int master[2], slave[2];
	int slave_out, slave_in;

	if ((pipe(local) < 0) || (pipe(remote) < 0)) {
	    fprintf(stderr, "Pipes failed!\n");
	    exit(1);
	}

	if (fork() == 0) {
		dup2(master[READ], 0);
		dup2(slave[WRITE], 1);
		dup2(slave[WRITE], 2);

		/* execl the job */
	} else {
		char ch;
		to_slave = slave[WRITE];
		from_slave = slave[READ];	
		while (read(from_slave,&ch,1)==1)
			printf("%c", ch);
	}
}	

This ought to do the trick.  Writing to 'to_slave' will
send bytes to the slave process, and reading from 'from_slave'
will read the output from the slave process.  

Cheers!
-Bharat
--
|  Bharat Mediratta  | JANET: bharat@cm.cf.ac.uk                               |
+--------------------+ UUNET: bharat%cm.cf.ac.uk%cunyvm.cuny.edu@uunet.uucp    |
|On a clear disk...  | uk.co: bharat%cm.cf.ac.uk%cunyvm.cuny.edu%uunet.uucp@ukc|
|you can seek forever| UUCP: ...!uunet!cunym.cuny.edu!cm.cf.ac.uk!bharat       |

gwyn@smoke.brl.mil (Doug Gwyn) (03/18/91)

In article <1991Mar14.140749.24337@cm.cf.ac.uk> bharat@cf-cm.computing-maths.cardiff.ac.uk (Bharat Mediratta) writes:
-In article <1991Mar13.163756.26785@evax.arl.utexas.edu> rduff@evax.arl.utexas.edu (Robert Duff) writes:
->I am interested in starting a UNIX process from a program and having the
->slave process' stdin and stdout piped through FILE*'s in the master process.
->I have worked with popen(), but that only allows one-way piping.
->How can I get both directions piped to my controller process?
-[attempted solution deleted]
-This ought to do the trick.  Writing to 'to_slave' will
-send bytes to the slave process, and reading from 'from_slave'
-will read the output from the slave process.  

The fellow said FILE*s, but in any case there is a fundamental problem
with the request that has no simple solution.  Namely, deadlock can
easily occur in such a scenario.  Only with a carefully-designed
communication protocol can one have confidence that deadlock will not
occur.  That requires support on the slave end as well as the master,
so the slave cannot be an arbitrary process.

I would suggest reconsidering the request to see what it is that is
REALLY wanted, before wasting time on inadequate solutions.

kpv@ulysses.att.com (Phong Vo[drew]) (03/19/91)

In article <15500@smoke.brl.mil>, gwyn@smoke.brl.mil (Doug Gwyn) writes:
: In article <1991Mar14.140749.24337@cm.cf.ac.uk> bharat@cf-cm.computing-maths.cardiff.ac.uk (Bharat Mediratta) writes:
: -In article <1991Mar13.163756.26785@evax.arl.utexas.edu> rduff@evax.arl.utexas.edu (Robert Duff) writes:
: ->I am interested in starting a UNIX process from a program and having the
: ->slave process' stdin and stdout piped through FILE*'s in the master process.
: ->I have worked with popen(), but that only allows one-way piping.
: ->How can I get both directions piped to my controller process?
...
: 
: The fellow said FILE*s, but in any case there is a fundamental problem
: with the request that has no simple solution.  Namely, deadlock can
: easily occur in such a scenario.  Only with a carefully-designed
: communication protocol can one have confidence that deadlock will not
: occur.  That requires support on the slave end as well as the master,
: so the slave cannot be an arbitrary process.
: 
Indeed there is no way to this with the current stdio. However,
a simple way to solve this problem is to introduce the notion of pool
auto-synchronization. A pool is a collection of streams (FILE*'s)
in which only one stream at a time can be done io on. All the other
ones are guaranteed to be synchronized. Now, to put this to work,
we need two things done automatically by the library:
1. popen() (or rather an appropriate extension of it) puts the two
   connecting streams into the same pool.
2. stdin and stdout if not seekable are put into the same pool.
Given these two features, deadlocks because of buffering and
simultaneous read requests can no longer arise. (2) also solves
the famous C-novice problem of what happens to the prompt:
	printf("Please type something: ");
	gets(buf);
I'll discuss the idea of stream pools and a few others this Summer
at Usenix in a joined paper with Dave Korn.

gwyn@smoke.brl.mil (Doug Gwyn) (03/19/91)

In article <5404:Mar1805:47:4991@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
>A carefully designed protocol can ensure that deadlock will not occur,
>but if you don't have control over the slave then the master can still
>eliminate the chance of deadlock all by itself.

Not necessarily; it all depends on what use the master is trying to make
of the slave.  For example, if the master sends some command to the slave
then listens for a response, and if the slave happens to have put the
response into its stdout buffer but hasn't fflush()ed it out, the master
simply cannot proceed, and nothing it can do will make the slave cooperate.