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