Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

UNIX Pipes problem

11 views
Skip to first unread message

Barry Margolin

unread,
Sep 5, 1997, 3:00:00 AM9/5/97
to

In article <01bcb902$505a7570$c1f14998@nne_hld>, hli <h...@nexcom.dk> wrote:
>Various (book) examples shows how to communicate between parent/child
>processes using one pipe. I need to create an FTP wrapper which requires I
>create two pipes, one for read and one for write. Furthermore I need to
>capture stderr as well as stdout from the FTP child process using dup2.
>
>I CANT GET THIS TO WORK I can get only stderr or stdout not both, and
>sometimes my parent process read hangs up!!. Can anyone send my som sample
>code or explain this. It wouldbe highly appreciated..

You should probably consider using Expect to write this; it's designed for
writing wrappers around interactive programs like ftp.

The reason your reads may be hanging is because output to pipes is usually
buffered, so you won't be able to read until the child process fills its
output buffer.

"Advanced Programming in the Unix Environment", by W. Richard Stevens, has
good examples of using pipes, but I don't recall if it discusses issues
like this. "Unix Network Programming" also has good examples of
communicating between processes.

--
Barry Margolin, bar...@bbnplanet.com
GTE Internetworking, Powered by BBN, Cambridge, MA
Support the anti-spam movement; see <http://www.cauce.org/>
Please don't send technical questions directly to me, post them to newsgroups.

Wakeley Purple

unread,
Sep 11, 1997, 3:00:00 AM9/11/97
to

Barry Margolin wrote:
>
> "Advanced Programming in the Unix Environment", by W. Richard Stevens, has

> good examples of using pipes, but I don't recall if it discusses issues
> like this. "Unix Network Programming" also has good examples of
> communicating between processes.
>

Yes it does, and it refers to Expect as a good example of using
pseudo-terminals (ptys) to handle normally interactive processes.

Wake.

Wayne Throop

unread,
Sep 12, 1997, 3:00:00 AM9/12/97
to

: "hli" <h...@nexcom.dk>
: Various (book) examples shows how to communicate between parent/child

: processes using one pipe. I need to create an FTP wrapper which
: requires I create two pipes, one for read and one for write.
: Furthermore I need to capture stderr as well as stdout from the FTP
: child process using dup2.
:
: I CANT GET THIS TO WORK I can get only stderr or stdout not both, and
: sometimes my parent process read hangs up!!. Can anyone send my som
: sample code or explain this. It wouldbe highly appreciated..

I'll give some more examples, and in describing them, describe some
of the common problems that can make them hang. This may be of some use.

In terms of unix system calls and such (no error checking, no exec, etc),

#include <string.h>
main() {
int in, out; /* file descriptors for comm with child stdin/stdout */
int pin[2], pout[2]; /* anoymous pipes */
char *msg = "Now is the time for all good men...\n";
char buf[256];
int len;
pipe(pin);
pipe(pout);
if( fork() ){
/* parent process... */
in = pin[1]; out = pout[0];
close( pin[0] ); close( pout[1] );
write(in, msg, strlen(msg)
close(in);
while( len = read(out,buf,256) )
write( 1, buf, len );
} else {
/* child process */
close(0); close(1); close(2);
dup(pin[0]); dup(pout[1]); dup(1);
close(pin[0]); close(pin[1]);
close(pout[0]); close(pout[1]);
while( len = read(0,buf,256) )
write( 1, buf, len );
}
return 0;
}

Note that if the close(in) after the parent writes isn't there,
this little program will pend forever, the child waiting for
more commands on in (because the pipe is still open, so somebody
might still write on it), and the parent waiting for more
output on out (because the child has it open until it terminates).

The close unravels the nest of waiting, and lets the two processes
terminate, child first.

Note that you must also be careful to flush writes onto pipes before
reading (and hence pending) for input. For example if you used
fprint or fwrite to output to the parent-to-child command pipeline,
it might not be on the actual pipe when you do a read of the child.

Further caution: if you don't drain your client pipes often enough,
you may also hang, so beware of extensive output from the child
(there are several ways of dealing with this, which I'll leave as
an excersize for the student).

Another way to do this (which can be done in shell scripts)
is to create named pipe nodes, and then simply create server processes
that have their IO redirected as needed.

The following shell script demonstrates the idea crudly
(with "sleep" instead of waiting for returning text; an expect script
would work better, of course).

It also demonstrates a workaround for
another problem: the problem that ftp clients expect to be connected
to tty devices. If done with pipes directly to ftp, most ftp clients
will hang. When done on an rlogin-ed pseudo-tty, it works properly.
It would also work if ftp were spawned directly from expect, since
expect uses ptys for IO to children.

All in all, I'd recommend using expect (or expectk) for this purpose,
or perhaps a module from perl's CPAN supporting bidirectional pipes.

mknod in p
mknod out p
rlogin sheol <in >out 2>&1 &
( sleep 4
echo "ftp sheol"
sleep 4
echo throopw
sleep 4
echo watfar
sleep 4
echo dir
while read x
do echo "$x" 1>&2
done
) >in <out

( Note: the above shell example is incomplete in that it
hangs at end end waiting for more ftp output )

--
Wayne Throop thr...@sheol.org http://sheol.org/throopw

Roger Shimada

unread,
Sep 14, 1997, 3:00:00 AM9/14/97
to

hli <h...@nexcom.dk> wrote:
:... I need to create an FTP wrapper ...

My experience has been that ftp actually uses /dev/tty, not
just stdin/stdout/stderr. (It uses /dev/tty for getting the
password.)

We worked around it by using a .netrc file.

If your ftp does use /dev/tty, the you will need use pseudo-ttys -
one of the most OS dependant things I've run into on Unix.

--
Roger M. Shimada
Internet: r...@primenet.com

0 new messages