I'm communicating with another system through its serial port. It's connected to a terminal server, so to me it's a socket connection via Net::Telnet. I opened the socket manually and used Net::Telnet's fhopen, so I have the socket available to me in the main program. My program is running on a Linux box.
What I want to do is send a file via zmodem to the other system. I haven't been able to find any Perl zmodem libraries, so I tried
open2($socket, $socket, ['sz', 'myfile']);
The error I got was:
open2: close(IO::Socket::INET=GLOB(0x940d78c)) failed: Bad file descriptor at ./tryit line 21
Line 21 is the "open2" line.
Does anyone have any suggestions? I'd really rather not re-implement zmodem in Perl if I don't have to.
Thanks.
Ahem, where was I? Ah yes, we're in the year 2006! What the heck are you using zmodem over telnet for?
Here's a few alternatives to consider:
Any of these will probably be easier to implement than trying to jury-rig zmodem to transfer files via Net::Telnet.
-sam
Unless I'm missing something, that pretty much locks me into zmodem over telnet, no matter how retarded it sounds.
Assuming I understand correctly, you want to execute rz on the remote side and sz on the local side. You can do this with something similar to the spawn() routine given in the [cpan://Net::Telnet] docs. Here's something I just cobbled together that is fairly close to what I think should work (completely untested):
# get the remote end ready to receive
$nt->print "rz\r";
use IO::Pty ();
$pty = new IO::Pty or die $!;
## Execute sz in another process.
unless ($pid = fork) { # child process
die "problem spawning program: $!\n" unless defined $pid;
## Disassociate process from existing controlling terminal.
use POSIX ();
POSIX::setsid or die "setsid failed: $!";
## Associate process with a new controlling terminal.
my $tty = $pty->slave;
my $tty_fd = $tty->fileno;
close $pty;
## Make stdio use the new controlling terminal.
open STDIN, "<&$tty_fd" or die $!;
open STDOUT, ">&$tty_fd" or die $!;
open STDERR, ">&STDOUT" or die $!;
close $tty;
exec "sz @filenames" or die "problem executing sz\n";"
}
In any case, that's the gist of how it should work.
[duff]
#!/usr/bin/perl
use warnings;
use strict;
use IO::Socket::INET;
use POSIX;
my $sock = IO::Socket::INET->new(PeerHost => 'gfn.org',
PeerPort => 9999)
or die "Couldn't open socket: $!\n";
my $pid = fork;
if (!defined($pid)) { die "Couldn't fork: $!\n"; }
if (!$pid) {
# child
POSIX::close(0);
POSIX::close(1);
POSIX::dup2(fileno($sock),0);
POSIX::dup2(fileno($sock),1);
print "Running lsz $0...\n";
exec('lsz','-v',$0)
or die "Couldn't run zmodem: $!\n";
}
# Parent
wait
or die "lsz failed: $?\n";
print "lsz exited $?\n";
Note that on my system, sz is called lsz, and this script sends a copy of its own source code.
Also, you'll want to make sure you use the appropriate options to sz and rz to make them telnet-safe; otherwise some of the characters they send could be interpreted as telnet escape sequences, which will cause you no end of grief. I use the -e and -b options for zmodem over ssh, and it usually works.
perlmonks.org content © perlmonks.org and duff, ikegami, samtregar, sgifford, splinky
prlmnks.org © 2006 edmund von der burg (eccles & toad)
v 0.03