|
Posted by harryfmudd [AT] comcast [DOT] on January 10, 2006, 9:16 am
Please log in for more thread options
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
|