Dissimilar Program Interaction? (sorry, long)

jon at msunix.UUCP jon at msunix.UUCP
Sun Oct 5 07:04:48 AEST 1986


In article <5263 at cbneb.UUCP>, adm at cbneb.UUCP writes:
> 	pipe (fildes);
> 
> 	if( (pid = fork()) == 0 )
> 	{
> 	/* CHILD */
> 	    close(0);
>     	    dup (fildes[0]);		/* Redirect stdin of child from parent*/
> 	    close(1);
>     	    dup (fildes[1]);		/* Redirect stdout of child to parent */
> 	    close (fildes[0]);		/* Don't need these anymore */
> 	    close (fildes[1]);
> 	    exec_ (the_child);
> 	    /* 
> 	     * Now when the child writes to its file descriptor 1, it is 
> 	     * actually going down the pipe's write end. Likewise its read
> 	     * on file descriptor 0 is actually reading from the read end of
> 	     * the pipe.
> 	     */
> 	}


Wait a minute.  Does this mean I've been doing pipes wrong all my life?
I thought if you wanted to have bidirectional communication with a pipe,
you needed two pipe system calls.  The example looks like the child could
write down the pipe, and both the child and parent could then read the
data, causing mass confusion.  The way I always did it for bidirectional
pipes was to first call pipe to make a channel for the parent to talk to
the child.  Then I would close the read end of the parent and the write
end of the child so EOF can be detected.  Then I would call pipe again for
a channel for the child to talk to the parent, and close the write end
of the parent and the read end of the child, again so EOF could be detected.
The code would look something like (well, maybe not this bad):

	int pid, p2c_fd[2], c2p_fd[2], newfd;


	if (pipe(p2c_fd) == -1)  {	/* parent talks to child */
		perror("pipe");
		exit(1);
	}
	if (pipe(c2p_fd) == -1)  {	/* child talks to parent */
		perror("pipe");
		exit(1);
	}
	if ((pid = fork()) == -1)  {
		perror("fork");
		exit(1)
	}
	if (!pid)  {
/*
 * fix up child's fd and exec new program
 */
		close(p2c_fd[1]);	/* child doesn't write on this one */
		close(c2p_fd[0]);	/* child doesn't read on this one */
/*
 * If you have dup2() available, you don't have to do the close first
 */
		close(0);		/* close child stdin fd */
		close(1);		/* close child stdout fd */
/*
 * should get duped onto fd 0
 */
		if (newfd = dup(p2c_fd[0]))  {
			fprintf(stderr, "Huh? Duped onto %d instead of 0\n", newfd);
/*
 * should get duped onto fd 1
 */
		if ((newfd = dup(c2p_fd[1])) != 1)  {
			fprintf(stderr, "Huh? Duped onto %d instead of 1\n", newfd);
		close(p2c_fd[0]);	/* not needed anymore, */
		close(c2p_fd[1]);	/* close so EOF works  */
/*
 * Confuse people running ps
 */
		execl("program_filename", "Gobot Death Squad", "first_arg", 0);
		perror("execl");
		fputs("What the heck?  I'm dead\n");
		_exit();
	}
/*
 * parent
 */
	else  {
		close(p2c_fd[0]);	/* parent doesn't read on this one */
		close(c2p_fd[1]);	/* parent doesn't write on this one */
	}
/* 
 * Now, write to child's stdin on p2c_fd[1] and read from child's stdout on
 * c2p_fd[0].
 */


Am I way off?  I could swear this is how I read it out of the UNIX manual
a few years ago.  Wouldn't using only one pipe with both parent and child
reading out of it reference only a single open file, and reads by one would
advance the pointer in the file for both parent and child?  In fact, I could
swear I've seen that behavior when trying to use just one pipe for
bidirectional communication.



"If we did it like everyone else,	  Jonathan Hue
what would distinguish us from		  Via Visuals Inc.
every other company in Silicon Valley?"	  sun!sunncal\
						      >!leadsv!msunix!jon
"A profit?"				amdcad!cae780/



More information about the Comp.unix mailing list