PIPES

Steve Scherf steve at altos86.Altos.COM
Wed Nov 28 10:49:36 AEST 1990


In article <2274 at megadon.UUCP> akrishn at csserv2.ic.sunysb.edu (Arvind Krishnan) writes:
>two pipes for full duplex communications with its child (mailx). 
>     
>     1. stdout of the child is the stdin of the parent and
>     2. stdout of the parent is the stdin of the child
>
>For some unknown reason, '1' works but '2' doesn't. The parent process can 
>read the output of its child, but the child doesn't seem to be reading the
>output of the parent process.

Your pipes seem set up properly, but I do have a few comments about how you
do it. I also have a few questions about your interesting while loop.

>  if (fork() == 0)
>   {
This close() is unnecessary since dup2() closes the descriptor.
>     close(0);
>     dup2(to_child[0], 0);
Ditto.
>     close(1);
>     dup2(to_par[1], 1);
>     close(to_par[1]);
>     close(to_child[0]);
>     close(to_par[0]);
>     close(to_child[1]);
The below if() is unnecessary, since execl() will only return on error.
>     if (execl("/usr/bin/mailx", "mailx", (char *) 0))
>        fprintf(stderr,"Exec Error\n");
An exit() here would be nice.
>   }
...
And here's that while loop:
>  fcntl(0, F_SETFL, O_NDELAY);
>  while (1)
>   {
>     if (flag == 0) 
Just say no to busy-waits. This is bogus on a multiuser system.
>        while ((flag = read(0,buf,1)) == 0);
And just what does ^^ (flag) do here? flag just gets reset below anyway.
>     write(2,buf,1);
What's this read() all about?
>     flag = read(0,buf,1);
Huh?
>     if (flag == 0)
>        write(1, command, 1);
>   }
>} 

Your while loop seems to be written in such a way that you might end up
spinning in that busy-wait forever. It is also possible that you might never
actually write to the child. You are playing around with time-dependent
factors in a bad way. If your system has select(), you might look it up. I
would suggest scanning for the mailx input prompt, but it seems to suppress
printing it when input is not a tty. Also, you seem to throw away every other
byte that you get from the child. Actually, I'm exactly not sure what you're
trying to do.

Below is a version which might do what you want. You would also probably
want to write a signal handler for SIGCLD and SIGPIPE, in addition. It is
rough and untested, but should hopefully give you a hint.

readmail()
{
	char buf[100];
	int p2c[2], c2p[2], c;

	pipe(p2c);
	pipe(c2p);

	if((c = fork()) < 0)
		return -1;

	if(c) {
		/* parent */
		dup2(p2c[1], 1);
		dup2(c2p[0], 0);
	}
	else {
		/* child */
		dup2(c2p[1], 1);
		dup2(p2c[0], 0);
	}

	close(p2c[0]);
	close(p2c[1]);
	close(c2p[0]);
	close(c2p[1]);

	if(!c) {
		execl("/usr/bin/mailx", "mailx", 0);
		exit(1);
	}

	/* talk to child */
	write(1, "1\nx\n", 4);	/* tell it to print mail, then quit */

	/* listen to child */
	for(;;) {
		if((c = read(0, buf, 100)) <= 0)
			return c;
		write(2, buf, c);
	}
}

Hope this helps.
-- 
Steve Scherf
steve at Altos.COM    ...!{sun|sco|pyramid|amdahl|uunet}!altos!steve

These opinions are solely mine, but others may share them if they like.



More information about the Comp.unix mailing list