From: Chris on
Anyone have any experience using Net::FTP going against IBM TSO? As
usual, IBM (just like Microsloth) have their own way of doing things,
unfortunately. It would *appear* from using debug in a real FTP client
and turning on Net::Cmd debugging that the real FTP client sends an
'EPSV' command just before each 'get' on a TSO dataset. Trying to
simulate this behavior using Net::FTP doesn't seem to do the job.
Sending or not sending EPSV results in the same thing using Net::FTP --
a download timeout. So now I'm faced with the possibility of doing an
external 'ftp -s' hack... :-(

Here is the main part of the script with all the Net::FTP commands I am
using, the XML file I am using, and the debug output from each
(Net::FTP and real ftp client running on Linux). The hostname,
username, password and the gets I want to do are defined in an XML
file. So don't worry about those details in the script too much. It's
irrelevant. All the information from the XML file (handled by
XML::Simple) is fine -- I've verified the data I need to drive this is
being picked up and used just fine. It's the actual $ftp->get() that
isn't working with or without the $ftp->quot( 'EPSV' ) command:

__PERL__

## Get hostname, username, and password, decrypt password if encrypted,
and login to
## host via FTP.

my $dlConfig = $config->{Download};
my $lnConfig = $dlConfig->{Login};
$lnConfig->{Password} = decrypt( $lnConfig->{Password} )
if $lnConfig->{PasswordEncrypted};
my $ftp = Net::FTP->new( $lnConfig->{Host}, Debug => $lnConfig->{Debug}
|| 0 ) ||
error( "Can't open session to host /$lnConfig->{Host}/!" );
$ftp->login( $lnConfig->{Username}, $lnConfig->{Password} ) ||
error( "Can't log in to host /$lnConfig->{Host}/ as username
/$lnConfig->{Username}/!" );

## Get all files designated in get section of download section.

my $gets = getCollection( $dlConfig->{Gets}->{Get} );
for my $get (@{$gets}) {
puts( " Getting: Remote( $get->{Remote} ) -> Local( $get->{Local}
)" );
$ftp->quot( 'EPSV' ); # Doesn't seem to matter if I use this or
not...
$ftp->get( $get->{Remote}, $get->{Local} ); # Line 69 in Perl debug
session below
}
$ftp->quit(); # Line 71 in Perl debug session below

sub puts { for (@_) { print "$_\n" } }
sub getCollection { ref $_[0] eq 'ARRAY' ? $_[0] : [ $_[0] ] }

__END__

__XML__

<?xml version="1.0" encoding="utf-8"?>
<config>
<Download>
<Login>
<Host>ftphost.some.private.net</Host>
<Username>foouser</Username>
<Password>foo.password</Password>
<PasswordEncrypted>0</PasswordEncrypted>
<Debug>1</Debug>
</Login>
<Gets>
<Get Remote="'FOO.SOX.COBOL(GEN1)'" Local="/tmp/foouser.cob"
/>
<Get Remote="'FOO.SOX.COBOL(GEN1)'" Local="/tmp/a.cob" />
<Get Remote="'FOO.SOX.COBOL(GEN1)'" Local="/tmp/b.cob" />
</Gets>
</Download>
</config>

__END__

Real ftp client debug session:

chris(a)mylinux:~/work/foo> ftp ftphost.some.private.net
Connected to ftphost.some.private.net.
220-FTPHOST IBM FTP CS V1R6 at FTPHOST.SOME.PRIVATE.NET, 21:52:49 on
2006-03-14.
220 Connection will close if idle for more than 5 minutes.
Name (ftphost.some.private.net:chris): foouser
331 Send password please.
Password:
230 FOOUSER is logged on. Working directory is "FOOUSER.".
Remote system type is MVS.
ftp> debug
Debugging on (debug=1).
ftp> get 'FOO.SOX.COBOL(GEN1)' x.cob
local: x.cob remote: 'FOO.SOX.COBOL(GEN1)'
ftp: setsockopt (ignored): Permission denied
---> EPSV
229 Entering Extended Passive Mode (|||1874|)
---> RETR 'FOO.SOX.COBOL(GEN1)'
125 Sending data set FOO.SOX.COBOL(GEN1) FIXrecfm 80
250 Transfer completed successfully.
114308 bytes received in 00:00 (281.03 KB/s)
ftp> quit
---> QUIT
221 Quit command received. Goodbye.


Net::FTP debug session:

colive(a)mylinux:~/work/foo> ./download-dbload-foo.pl -i
download-dbload-foo.xml download-dbload-foo.pl (v1.00-000) - Download &
DB Load Foo Feed
(c) Copyright 2006, My Big Company - All rights reserved

Net::FTP>>> Net::FTP(2.75)
Net::FTP>>> Exporter(5.58)
Net::FTP>>> Net::Cmd(2.26)
Net::FTP>>> IO::Socket::INET(1.28)
Net::FTP>>> IO::Socket(1.28)
Net::FTP>>> IO::Handle(1.24)
Net::FTP=GLOB(0x87846d0)<<< 220-FTPHOST IBM FTP CS V1R6 at
FTPHOST.SOME.PRIVATE.NET, 21:57:41 on 2006-03-14.
Net::FTP=GLOB(0x87846d0)<<< 220 Connection will close if idle for more
than 5 minutes.
Net::FTP=GLOB(0x87846d0)>>> user foouser
Net::FTP=GLOB(0x87846d0)<<< 331 Send password please.
Net::FTP=GLOB(0x87846d0)>>> PASS ....
Net::FTP=GLOB(0x87846d0)<<< 230 FOOUSER is logged on. Working
directory is "FOOUSER.".
Getting: Remote( 'FOO.SOX.COBOL(GEN1)' ) -> Local( /tmp/foouser.cob
)
Net::FTP=GLOB(0x87846d0)>>> EPSV
Net::FTP=GLOB(0x87846d0)<<< 229 Entering Extended Passive Mode
(|||1875|)
Net::FTP=GLOB(0x87846d0)>>> PORT 172,17,4,47,4,80
Net::FTP=GLOB(0x87846d0)<<< 200 Port request OK.
Net::FTP=GLOB(0x87846d0)>>> RETR 'FOO.SOX.COBOL(GEN1)'
Net::FTP=GLOB(0x87846d0): Timeout at ./download-dbload-foo.pl line 69
Net::FTP=GLOB(0x87846d0)>>> QUIT
Net::FTP=GLOB(0x87846d0): Timeout at ./download-dbload-foo.pl line 71


The "get" on a.cob and b.cob in the XML file above is never done
because I took them out for the debug session above. I left them in
the XML file above to demonstrate the intent of the getCollection() and
for loop for the gets.

If I take the $ftp->quot( 'EPSV' ) line out, I get the exact same
results as the above Net::FTP session save for seeing EPSV sent to the
host, of course.

If anyone has any ideas, I've love to hear about them. I grow weary of
IBM and Microsoft and their "implementation" of TCP/IP standards. :-/
Sorry if anyone here works for them, but those are my candid
sentiments.

-ceo

From: usenet on
Chris wrote:
> Anyone have any experience using Net::FTP going against IBM TSO?

Yeah, I've got a nightly cron script at work that uses Net::FTP from an
AIX box to an MVS TSO big-iron host, but it does a put(), not a get().
It's a very old script, but I don't remember having any problems with
it - pretty straightforward. But, like I say, I put, not get.

Have you tried a put as a test?

I can post a bit of relevant code when I get in the office tomorrow.

--
http://DavidFilmer.com

From: Chris on
usenet(a)DavidFilmer.com wrote:
> Chris wrote:
> > Anyone have any experience using Net::FTP going against IBM TSO?
>
> Yeah, I've got a nightly cron script at work that uses Net::FTP from an
> AIX box to an MVS TSO big-iron host, but it does a put(), not a get().
> It's a very old script, but I don't remember having any problems with
> it - pretty straightforward. But, like I say, I put, not get.
>
> Have you tried a put as a test?

No, I suppose I could try this. Maybe it would shed some light on the
situation.

> I can post a bit of relevant code when I get in the office tomorrow.

Thanks. I'll look forward to it.

Meanwhile, I'm digging out and updating a Net::PsuedoFTP I wrote
somewhere in 2000 that mimics most of the regular Net::FTP commands,
but on $ftp->quit() executes an ftp script. It's a dropin replacement
practically for Net::FTP. If there is any interest in it, I can see
about posting it to CPAN.

-ceo

From: usenet on
Chris wrote:
> usenet(a)DavidFilmer.com wrote:
> > I can post a bit of relevant code when I get in the office tomorrow.
>
> Thanks. I'll look forward to it.

I did one better - I created a simple script (adapted from my nightly
cron script) to get() the file that I usually put() to the host in my
nightly cron. This works perfectly from my AIX workstation connecting
to my MVS TSO host:

#!/usr/bin/perl

use Net::FTP;
my %ftp = qw{ host 123.456.78.90
userid MYUSER
password MYPASS
remote_dir DEPT.TFOO.BAR
remote_file INDEX
local_file foo.txt };

$ftp = Net::FTP->new($ftp{'host'}) || die $!;
$ftp->login ($ftp{'userid'}, $ftp{'password'}) || die $!;
$ftp->cwd ("..") || die $!;
$ftp->cwd ($ftp{'remote_dir'}) || die $!;
$ftp->ascii () || die $!;
$ftp->get ($ftp{'remote_file'}, $ftp{'local_file'}) || die $!;
$ftp->quit ();

__END__

--
http://DavidFilmer.com

From: Chris on
use...(a)DavidFilmer.com wrote:
> Chris wrote:
> > usenet(a)DavidFilmer.com wrote:
> > > I can post a bit of relevant code when I get in the office tomorrow.
> >
> > Thanks. I'll look forward to it.
>
> I did one better - I created a simple script (adapted from my nightly
> cron script) to get() the file that I usually put() to the host in my
> nightly cron. This works perfectly from my AIX workstation connecting
> to my MVS TSO host:
>
> #!/usr/bin/perl
>
> use Net::FTP;
> my %ftp = qw{ host 123.456.78.90
> userid MYUSER
> password MYPASS
> remote_dir DEPT.TFOO.BAR
> remote_file INDEX
> local_file foo.txt };
>
> $ftp = Net::FTP->new($ftp{'host'}) || die $!;
> $ftp->login ($ftp{'userid'}, $ftp{'password'}) || die $!;
> $ftp->cwd ("..") || die $!;
> $ftp->cwd ($ftp{'remote_dir'}) || die $!;
> $ftp->ascii () || die $!;
> $ftp->get ($ftp{'remote_file'}, $ftp{'local_file'}) || die $!;
> $ftp->quit ();
>
> __END__

Hmmm, I see you are doing some cwd's and maybe positioning yourself
better than I am before doing the get. My get requires the tick marks
(') around the dataset name, but it's only because I'm getting it
"fully qualified" for lack of any other term I know to use because I
know precious little about TSO (and I'd like to keep it that way).

I'm beginning to wonder if I can finagle this using something closer to
your approach. I'll get a hold of one of our TSO guys and learn enough
TSO to get this to work, hopefully. This obviously is not the place to
get TSO help...! :-)

Thanks much!
-ceo