Home > Archive > PERL Modules > January 2006 > IO::Pty - reads/writes fail *only* with system()
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
IO::Pty - reads/writes fail *only* with system()
|
|
| Alexis Huxley 2006-01-10, 7:55 am |
| 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:
#!/usr/bin/perl
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;
close($pty);
# Remap stdin and stdout to slave side of pty
close(STDOUT);
open(STDOUT, ">&=" . $slave->fileno) || die;
close(STDIN);
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
close($slave);
# Parent
} else {
$pty->close_slave();
# Remap stdin and stdout to master side of pty
close(STDOUT);
open(STDOUT, ">&=" . $pty->fileno) || die;
close(STDIN);
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
close($pty);
}
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.
Alexis
| |
| harryfmudd [AT] comcast [DOT] net 2006-01-10, 9:55 pm |
| Alexis Huxley wrote:
> 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:
>
> #!/usr/bin/perl
>
> 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;
> close($pty);
>
> # Remap stdin and stdout to slave side of pty
> close(STDOUT);
> open(STDOUT, ">&=" . $slave->fileno) || die;
> close(STDIN);
> 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.\"");
How about
print `echo "To be or not to be, what was the question?"`;
>
> # Tidy up
> close($slave);
>
> # Parent
> } else {
> $pty->close_slave();
>
> # Remap stdin and stdout to master side of pty
> close(STDOUT);
> open(STDOUT, ">&=" . $pty->fileno) || die;
> close(STDIN);
> 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: /'");
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.
>
> # Tidy up
> close($pty);
> }
>
> 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.
>
> Alexis
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
| |
| Alexis Huxley 2006-01-10, 9:55 pm |
| >> Starting from the example in the IO::Pty man page I've now got a
>
> print `echo "To be or not to be, what was the question?"`;
>
> How about
>
> open SED, "|sed 's/^parent read from slave: /'" or die;
> while (<> ) {print SED}
>
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.
[color=darkred]
> The basic problem is that just kicking off a system command doesn't
> necessarily magically connect the command's STDIN and STDOUT to yours.
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!
Alexis
|
|
|
|
|