IO::Pty - reads/writes fail *only* with system()

Do you have a question? Post it now! No Registration Necessary.  Now with pictures!

Threaded View

Starting from the example in the IO::Pty man page I've now got a
perl script which forks, the child reopens stdin/stdout on the
slave side of the pty, and the parent reopens on the master side.

The child writes to STDOUT using 'print', the parent reads from
STDIN using 'while (<>) ...'. This works fine.

I changed the child to write using 'system("echo ...")' and later
I changed the parent to read using 'sed' or 'cat'. This fails,
and I can't see why.

Using only the child using 'system()' the output simply never
appears on the parent side. Using only the parent using 'system()'
results in:

    sed: read error on stdin: Bad file descriptor

I tried various combinations of the set_raw() and setting the
controlling terminal of the child using the documented methods,
but still no dice. Googling brings up plenty of pre-OO examples
of pty but nothing besides what's in the FAQ and the perlipc
man page.

Judging by the sed error message, I guess somehow my plumbing
of file handles has gone wrong, but I just can't see it, especially
as it works when - as mentioned above - I use 'print' for the
output and 'while (<>) ..." for the input. Has anybody any ideas?

The script is short and reproduced below. As it is it works, but
with either of the current write/read lines replaced by the
system() equivalents, it will fail:


use IO::Pty;
$pty = new IO::Pty;
$slave  = $pty->slave;
(defined($pid = fork)) || die "fork failed";

#  Child
if ($pid == 0) {
    $pty->make_slave_controlling_terminal() || die;

    #  Remap stdin and stdout to slave side of pty
    open(STDOUT, ">&=" . $slave->fileno) || die;
    open(STDIN, "<&=" . $slave->fileno) || die;

    #  -- write options: print works, system doesn't!
    print "To be or not to be, that is the question.\n";
    #system("echo \"To be or not to be, that is the question.\"");

    #  Tidy up

#  Parent
} else {

    #  Remap stdin and stdout to master side of pty
    open(STDOUT, ">&=" . $pty->fileno) || die;
    open(STDIN, "<&=" . $pty->fileno) || die;

    #  -- read options: print (<>), system doesn't!
    while (<>) { chomp; print STDERR "parent read from slave: $_\n"; }
    #system("sed 's/^/parent read from slave: /'");

    #  Tidy up

In case it's relevent:

This is perl, v5.8.4 built for i386-linux-thread-multi, running on
Debian Linux.

(Ultimately what I'm trying to do is rewrite a script I googled called
ssh-ppp, which runs 'ssh <host> pppd' in one half, and 'pppd' in
the other. Yes, I know that pppd has a 'pty' directive, but that just
doesn't cut the mustard for what I want ,which is to do
'su -c "ssh -t <first-hop> ssh -t <second-hop> slogin <third-hop>"'
where my shell on <third-hop> is pppd, and all hops require inputting
password, and avoiding entering passwords by using RSA authentication
is neither possible nor desirable.)

Thanks for reading so far :-) and any advice you can offer; the
results of this labour will be google-able.


Re: IO::Pty - reads/writes fail *only* with system()

Alexis Huxley wrote:
Quoted text here. Click to load it

How about

print `echo "To be or not to be, what was the question?"`;

Quoted text here. Click to load it

How about

open SED, "|sed 's/^parent read from slave: /'" or die;
while (<>) {print SED}

But I'm not sure what sed does for you that Perl won't. My sed is really
rusty, but I suspect your sed is the equivalent of command different from

while (<>) {s/^/parent read from slave: /; print}

and I suspect that anything you wanted to do to the input stream could
be done just as well with Perl.

Quoted text here. Click to load it

The basic problem is that just kicking off a system command doesn't
necessarily magically connect the command's STDIN and STDOUT to yours.

Tom Wyant

Re: IO::Pty - reads/writes fail *only* with system()

Quoted text here. Click to load it

Maybe I wasn't clear enough; the echo and sed commands are not what I
want to do *ultimately*; they will be replaced by calls to ssh and to
pppd respectively. But I want to start simple.

Quoted text here. Click to load it

Yes, as I said, I think my plumbing is somehow wrong. But still, these
handles are generally inherited otherwise the following command would
produce some output, which it doesn't:

    sh -c 'echo hello >&2' 2>/dev/null

and that being so, my the error in my script isn't obvious to me; hence
asking, specifically, what did I do wrong? THanks!


Site Timeline