about summary refs log tree commit
diff options
context:
space:
mode:
authorGraham Barr <gbarr@pobox.com>1996-01-02 08:46:21 -0600
committerGraham Barr <gbarr@pobox.com>2009-01-24 15:13:57 -0600
commitfd77ae996c2072b825071bc09b82558c9210c4ba (patch)
tree217e388b50dd0585d12911927cb80ee25e223841
parent80b46cb092321cdd20f394eb666b6b722aa86dcf (diff)
downloadperl-libnet-fd77ae996c2072b825071bc09b82558c9210c4ba.tar.gz
Net-FTP-1.18_1
-rw-r--r--ftp/ChangeLog26
-rw-r--r--ftp/MANIFEST8
-rw-r--r--ftp/Makefile.PL185
-rw-r--r--ftp/README56
-rw-r--r--ftp/README.CPAN76
-rw-r--r--ftp/README.DEBUG13
-rw-r--r--ftp/lib/Net/FTP.pm333
-rw-r--r--ftp/lib/Net/Netrc.pm123
-rw-r--r--ftp/lib/Net/Socket.pm (renamed from ftp/lib/IO/Socket.pm)51
-rw-r--r--ftp/t/require.t11
10 files changed, 612 insertions, 270 deletions
diff --git a/ftp/ChangeLog b/ftp/ChangeLog
index 9f1bb51..dd8eea4 100644
--- a/ftp/ChangeLog
+++ b/ftp/ChangeLog
@@ -1,3 +1,29 @@
+Thu Apr 25 1996  Graham Barr <bodg@tiuk.ti.com>
+
+        o Fixed a bug in A::read when a line ended in "\r\n". Replaced regexp
+          with explicit substr and chop
+
+Mon Mar 18 1996  Graham Barr <bodg@tiuk.ti.com>
+
+        o Removed parse_dir and file_mode as there is now a File::Listing
+          package avaliable with libwww which can do directory listings
+
+Tue Mar  5 1996  Graham Barr <bodg@tiuk.ti.com>
+
+        o Changes to Net::FTP::A::read for files which have very long
+          lines and do not fit into a single buffer
+        o Changes to responce for knackered FTP servers which send
+          a Transfer Complete response before they send the data ?? :-(
+
+Wed Jan  3 1996  Graham Barr <bodg@tiuk.ti.com>
+
+        o Moved netrc stuff into Net::Netrc
+
+Tue Dec 19 1995  Graham Barr <bodg@tiuk.ti.com>
+
+        o Fixed a problem with Net::FTP::A:read which caused the last line
+          of a transfer to be dropped if it did not end in a \n
+
 Mon Dec 11 1995  Graham Barr <bodg@tiuk.ti.com>
 
         o Introduced IO::Socket which eventually will be released
diff --git a/ftp/MANIFEST b/ftp/MANIFEST
index 9bd1df5..436e029 100644
--- a/ftp/MANIFEST
+++ b/ftp/MANIFEST
@@ -2,6 +2,10 @@ ChangeLog
 MANIFEST                        This file
 Makefile.PL                        Makemaker makefile
 README                                Copyright
-lib/IO/Socket.pm                (v1.01) Generic socket package
-lib/Net/FTP.pm                        (v1.08) FTP package
+README.CPAN
+README.DEBUG
+lib/Net/Socket.pm                TEMP replacement for IO::Socket
+lib/Net/FTP.pm                        (v1.17) FTP package
+lib/Net/Netrc.pm                (v0)
 t/dummy.t
+t/require.t
diff --git a/ftp/Makefile.PL b/ftp/Makefile.PL
index a399259..baffa1d 100644
--- a/ftp/Makefile.PL
+++ b/ftp/Makefile.PL
@@ -1,69 +1,172 @@
 # This -*- perl -*- script makes the Makefile
-# $Id: Makefile.PL,v 1.4 1995/12/11 13:16:04 gbarr Exp gbarr $
+# $Id: Makefile.PL,v 1.8 1996/03/28 08:03:48 gbarr Exp $
+
+#--- Configuration section ---
+
+%install_pgm = ();
+
+#--- End User Configuration - You should not have to change anything below this line
+
+$NAME     = 'Net::FTP';
+
+$lib_only = 0;
+
+#--- End Configuration
 
 use ExtUtils::MakeMaker;
 use ExtUtils::Manifest qw(maniread);
-use lib qw(./lib);
+use FileHandle;
 
-sub initialize {
- local($_);
+#--- MY package
 
- my $manifest = maniread();
+sub MY::libscan
+{
+ my($self,$path) = @_;
+
+ return ''
+        if($path =~ m:/(RCS|CVS|SCCS)/: ||
+           $path =~ m:[~%]$: ||
+           $path =~ m:\.(orig|rej)$:
+          );
+
+ $path;
+}
 
- $Version = eval { require "./lib/Net/FTP.pm"; Net::FTP->Version . "b"; } || "0.00";
+#--- End MY package
 
- my %pl_files = ();
- my @exe_files = ();
+sub doIt
+{
+ my $manifest = maniread();
+
+ my %PL_FILES = ();
+ my %EXE_FILES = ();
+ my %macro = ();
 
+ #--- Install what ?
+
  foreach (keys %$manifest) {
-  $pl_files{$_} = $1 if(/(.*)\.PL\Z/ && !/^Makefile.PL$/);
-  push(@exe_files,$_) if(m#\bbin/# && !m#demo#);
+  $PL_FILES{$_} = $1 if(/(.*)\.PL\Z/ && !/^Makefile.PL$/);
+
+  if(m#\bbin/# && !m#demo#) {
+   my $f = $_;
+
+   $f =~ s#\.PL$##;
+
+   if(defined $install_pgm{$f} && $install_pgm{$f}) {
+    $EXE_FILES{$f} = 1 if(-x $f || -f "$f.PL");
+   }
+  }
  }
-
- my $hash = {
-        VERSION   => $Version,
-        NAME      => 'Net::FTP',
-        SKIP      => [qw(static dynamic)],
-        PL_FILES  => \%pl_files,
-        EXE_FILES => \@exe_files,
-
+
+ %EXE_FILES = () if($lib_only);
+
+ #--- Dist. VERSION
+
+ unless(defined $VERSION)
+  {
+   my($pm,$rcs);
+   my $fh = new FileHandle;
+  
+   ($pm = $NAME . ".pm") =~ s,.*::,,;
+   ($pm = $NAME . ".pm") =~ s,::,/,g unless(-f $pm);
+   $pm = "lib/" . $pm unless(-f $pm);
+  
+   if($fh->open($pm))
+    {
+     while (<$fh>)
+      {
+       chomp;
+       next unless /\$([\w:]*\bVERSION)\b.*=/;
+       my $module_version_variable = $1;
+       my($eval) = "$_;";
+       eval $eval;
+       die "Could not eval '$eval': $@" if $@;
+       $VERSION = $ {$module_version_variable};
+       last;
+      }
+     close $fh;
+    }
+  
+   ($rcs = $pm) =~ s:([^/]+\.pm):RCS/$1,v:;
+  
+   # update VERSION when checked in
+   $macro{CONFIGDEP} = $rcs
+     if(-f $rcs);
+  }
+
+ $VERSION .= $RELTYPE
+         if(defined $RELTYPE);
+
+ #--- Write the Makefile
+
+ %hash = (
+        VERSION   => $VERSION,
+        NAME      => $NAME,
+        PL_FILES  => \%PL_FILES,
+        EXE_FILES => [ keys %EXE_FILES ],
+
+        'linkext' => {LINKTYPE => '' },
         'dist'    => {COMPRESS => 'gzip -9f',
                       SUFFIX   => 'gz',
                       POSTOP   => 'mv $(DISTNAME)-$(VERSION).tar.gz ../',
                       DIST_DEFAULT => 'all tardist',
                       CI => 'ci -l'
                      },
+
+        'clean'   => {FILES => join(" ", qw(*% *.html *.bak *.old lib/*% lib/*/*%),values %PL_FILES)},
+ );
+
+ $hash{macro} = \%macro
+         if(%macro);
+
+ $hash{DISTNAME} = $DISTNAME
+         if(defined $DISTNAME);
+
+ WriteMakefile( %hash ) ;
+
+}
 
-        'linkext' => {LINKTYPE => '' },
-        'clean'   => {FILES => '*% *.html *.bak *.old lib/*% lib/*/*% $(EXE_FILES)'},
- };
+#--- UNIVERSAL package
 
- $hash;
-}
+sub UNIVERSAL::require_version
+{
+ my($self, $wanted) = @_;
+ my $pkg = ref $self || $self;
+ my $version = ${"${pkg}::VERSION"} || "(undef)";
 
-if ($ExtUtils::MakeMaker::Version < 4.17) {
- my $hash = initialize();
- WriteMakefile( %$hash ) ;
-}
-else {
- WriteMakefile( CONFIGURE => \&initialize ) ;
+ die("$pkg $wanted required--this is only version $version")
+                if $version < $wanted;
+
+ $version;
 }
 
+#--- End UNIVERSAL package
+#--- Installation check
 
-sub MY::test {
-    q{
-TEST_VERBOSE=0
+sub require_version
+{
+ my($pkg,$version,$msg) = @_;
 
-test:
-        $(FULLPERL) -I$(INST_LIB) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -e 'use Test::Harness qw(&runtests $$verbose); $$verbose=$(TEST_VERBOSE); runtests @ARGV;' t/*.t
+ $| = 1;
+ print "Checking for $pkg...";
 
-};
-}
+ eval " require $pkg; $pkg->require_version('$version') ";
 
-sub MY::libscan {
-    return '' if m:/(RCS|CVS)/:;
-    return '' if m/[~%]$/;
-    return '' if m/\.(orig|rej)$/;
-    $_;
+ print $@ ? "failed\n" . $msg  : "ok\n";
 }
 
+#--- Check for Socket
+
+require_version(
+'Socket',
+'1.30',
+"
+For Net::FTP to work you require the Socket distribution
+version 1.30 or later.
+"
+);
+
+#--- Write the Makefile
+
+doIt();
+
diff --git a/ftp/README b/ftp/README
index cf9c75f..bf5f055 100644
--- a/ftp/README
+++ b/ftp/README
@@ -1,6 +1,53 @@
-Copyright (c) 1995 Graham Barr <Graham.Barr@tiuk.ti.com>. All rights
-reserved. This program is free software; you can redistribute it and/or
-modify it under the same terms as Perl itself.
+This distribution 1.18_1 is identical to 1.18 except that IO::Socket has been
+renamed as Net::Socket. This is because the IO::* modules are having a serious
+re-fit.
+
+This is the README file for Net::FTP
+
+Net::FTP is a perl5 package which implements the client side of
+a FTP connection as per RFC959
+
+In order to use this package you will need Perl version 5.001m or
+better. The File::Listing package can be found in the libwww distribution.
+To use the complete libwww distribution you require 5.002, If you
+do not have 5.002 File::Listing can be extracted from libwww and will work
+with 5.001
+
+See lib/Net/FTP.pm for details of the library. See ChangeLog for recent
+changes. POD style documentation is included in all/most modules and scripts.
+You should be able to use the 'perldoc' utility to extract documentation
+from these files.
+
+Before building this extension you will require the following modules. The
+building of the Makefile will abort if you do not have the required versions.
+All of these modules should be avaliable from CPAN (see README.CPAN for
+more information)
+
+   Socket v1.03
+
+You install the library by running these commands:
+
+   perl Makefile.PL
+   make
+   make test
+   make install
+
+You can edit the configuration section of Makefile.PL to select which
+programs to install in addition to the library itself.  If you don't
+want to install any programs at all then make the initial Makefile with:
+
+   perl Makefile.PL -l
+
+
+Please report any bugs/suggestions to <Graham.Barr@tiuk.ti.com>
+
+When reporting bugs/problems please, if possible, include a transcript of
+a run with the Debug option turned on.
+
+Copyright 1996 Graham Barr. All rights reserved.
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
 
 This release has got a significant number of changes sine the last release
 so is probably prone to a few bugs.
@@ -15,5 +62,6 @@ future releases will be 100% compatable.
 
 *** NOTE *** NOTE *** NOTE *** NOTE *** NOTE *** NOTE *** NOTE *** NOTE ***
 
-Please report any bugs/suggestions to <Graham.Barr@tiuk.ti.com>.
+Share and Enjoy!
+Graham <Graham.Barr@tiuk.ti.com>
 
diff --git a/ftp/README.CPAN b/ftp/README.CPAN
new file mode 100644
index 0000000..e15683e
--- /dev/null
+++ b/ftp/README.CPAN
@@ -0,0 +1,76 @@
+
+Welcome to the CPAN, the Comprehensive Perl Archive Network.
+
+This document describes the CPAN itself, the Network.
+
+---
+
+Network
+
+The master CPAN site is at ftp://ftp.funet.fi/
+(Finland, Europe).
+
+The list of the registered CPAN sites follows.
+Please note that the sorting order is alphabetical on fields:
+
+
+        continent - country/state - ftp-url
+
+
+and thus the North American servers happen to be listed last (for the
+moment, anyway, no Oceanian or South American sites volunteered, yet).
+
+
+Registered CPAN sites
+
+
+  Africa
+
+    South Africa    ftp://ftp.is.co.za/programming/perl/CPAN/
+
+  Asia
+
+    Japan           ftp://ftp.lab.kdd.co.jp/lang/perl/CPAN/
+    Taiwan          ftp://dongpo.math.ncu.edu.tw/perl/CPAN/
+
+  Australasia
+
+    Australia       ftp://coombs.anu.edu.au/pub/perl/
+                    ftp://ftp.mame.mu.oz.au/pub/perl/CPAN/
+    New Zealand     ftp://ftp.tekotago.ac.nz/pub/perl/CPAN/
+
+  Europe
+
+    Finland         ftp://ftp.funet.fi/pub/languages/perl/CPAN/
+    France          ftp://ftp.ibp.fr/pub/perl/CPAN/
+                    ftp://ftp.pasteur.fr/pub/computing/unix/perl/CPAN/
+    Germany         ftp://ftp.leo.org/pub/comp/programming/languages/perl/CPAN/
+                    ftp://ftp.rz.ruhr-uni-bochum.de/pub/CPAN/
+    the Netherlands ftp://ftp.cs.ruu.nl/pub/PERL/CPAN/
+    Portugal        ftp://ftp.ci.uminho.pt/pub/lang/perl/
+    Slovenia        ftp://ftp.arnes.si/software/perl/CPAN/
+    Sweden          ftp://ftp.sunet.se/pub/lang/perl/CPAN/
+    Switzerland     ftp://ftp.switch.ch/mirror/CPAN/
+    UK              ftp://ftp.demon.co.uk/pub/mirrors/perl/CPAN/
+                    ftp://unix.hensa.ac.uk/mirrors/perl-CPAN/
+
+  North America
+
+    Florida         ftp://ftp.cis.ufl.edu/pub/perl/CPAN/
+    Illinois        ftp://uiarchive.cso.uiuc.edu/pub/lang/perl/CPAN/
+    Massachusetts   ftp://ftp.delphi.com/pub/mirrors/packages/perl/CPAN/
+    Oklahoma        ftp://ftp.uoknor.edu/mirrors/CPAN/
+    Texas           ftp://ftp.sedl.org/pub/mirrors/CPAN/
+                    ftp://ftp.sterling.com/programming/languages/perl/
+
+
+
+We apologise for the diversity of the CPAN path names but
+having identical and hopefully as short as possible path names
+across several separate ftp sites is well nigh impossible.
+
+Feedback
+
+You can send email
+to the CPAN administrators, cpan-adm@ftp.funet.fi.
+
diff --git a/ftp/README.DEBUG b/ftp/README.DEBUG
new file mode 100644
index 0000000..0783569
--- /dev/null
+++ b/ftp/README.DEBUG
@@ -0,0 +1,13 @@
+When debugging a script which uses Net::FTP please try the following
+
+  Ensure you have the most upto date version of the Net-FTP distribution
+  from CPAN
+
+  Try adding 'Debug => 1' to the Net::FTP->new line and see if there is
+  anything obvious in the transcript
+
+  Failing that, and you belive it is a real Net::FTP problem then mail the
+  transcript to <bodg@tiuk.ti.com>. I run a mail filter here so I would
+  appreciate the text Net::FTP to be in the subject.
+
+
diff --git a/ftp/lib/Net/FTP.pm b/ftp/lib/Net/FTP.pm
index a10c483..c98652b 100644
--- a/ftp/lib/Net/FTP.pm
+++ b/ftp/lib/Net/FTP.pm
@@ -30,7 +30,8 @@ Net::FTP - FTP Client class
 
 =head1 DESCRIPTION
 
-C<Net::FTP> is a class implementing a simple FTP client in Perl.
+C<Net::FTP> is a class implementing a simple FTP client in Perl as described
+in RFC959
 
 =head2 TO BE CONTINUED ...
 
@@ -39,11 +40,11 @@ C<Net::FTP> is a class implementing a simple FTP client in Perl.
 require 5.001;
 use Socket 1.3;
 use Carp;
-use IO::Socket;
+use Net::Socket;
 
-@ISA = qw(IO::Socket);
+@ISA = qw(Net::Socket);
 
-$VERSION = sprintf("%d.%02d", q$Revision: 1.8 $ =~ /(\d+)\.(\d+)/);
+$VERSION = sprintf("%d.%02d", q$Revision: 1.18 $ =~ /(\d+)\.(\d+)/);
 sub Version { $VERSION }
 
 use strict;
@@ -63,19 +64,20 @@ remote host. Possible options are:
 
 =cut
 
-sub FTP_READY    { 0 }
-sub FTP_RESPONSE { 1 }
-sub FTP_XFER     { 2 }
+sub FTP_READY    { 0 } # Ready
+sub FTP_RESPONSE { 1 } # Waiting for a response
+sub FTP_XFER     { 2 } # Doing data xfer
 
 sub new {
  my $pkg  = shift;
  my $host = shift;
  my %arg  = @_;
- my $me = bless IO::Socket->new(Peer        => $host,
+ my $me = bless Net::Socket->new(Peer        => $host,
                                 Service        => 'ftp',
                                 Port        => $arg{Port} || 'ftp'
                                 ), $pkg;
 
+ ${*$me} = "";                                        # partial response text
  @{*$me} = ();                                        # Last response text
 
  %{*$me} = (%{*$me},                                # Copy current values
@@ -95,6 +97,9 @@ sub new {
 
  $me->autoflush(1);
 
+ $me->debug($arg{Debug})
+   if(exists $arg{Debug});
+
  unless(2 == $me->response())
   {
    $me->close();
@@ -120,8 +125,13 @@ sub debug {
  my $me = shift;
  my $debug = ${*$me}{Debug};
 
- ${*$me}{Debug} = 0 + shift
-        if @_;
+ if(@_)
+  {
+   ${*$me}{Debug} = 0 + shift;
+
+   printf STDERR "\n$me VERSION %s\n", $Net::FTP::VERSION
+     if(${*$me}{Debug});
+  }
 
  $debug;
 }
@@ -183,8 +193,14 @@ sub login {
  my $acct = shift if(defined $pass);
  my $ok;
 
- ($user,$pass,$acct) = netrc(${*$me}{FtpHost})
-        unless defined $user;
+ unless(defined $user)
+  {
+   require Net::Netrc;
+   my $rc = Net::Netrc->lookup(${*$me}{FtpHost});
+
+   ($user,$pass,$acct) = $rc->lpa()
+        if $rc;
+  }
 
  $user = "anonymous"
         unless defined $user;
@@ -265,6 +281,7 @@ sub get {
  my $me = shift;
  my $remote = shift;
  my $local  = shift;
+ my $where  = shift || 0;
  my($loc,$len,$buf,$resp,$localfd,$data);
  local *FD;
 
@@ -281,15 +298,21 @@ sub get {
   {
    $loc = \*FD;
 
-   unless(open($loc,">$local"))
+   unless(($where) ? open($loc,">>$local") : open($loc,">$local"))
     {
      carp "Cannot open Local file $local: $!\n";
      return undef;
     }
   }
 
- $data = $me->retr($remote) or
-        return undef;
+ if ($where) {  
+   $data = $me->rest_cmd($where,$remote) or
+        return undef;
+ }
+ else {
+   $data = $me->retr($remote) or
+     return undef;
+ }
 
  $buf = '';
 
@@ -302,9 +325,7 @@ sub get {
  close($loc)
         unless $localfd;
 
- $resp = $data->close();
-
- 200 <= $resp && $resp < 300;
+ $data->close() == 2; # implied $me->response
 }
 
 sub cwd {
@@ -315,6 +336,13 @@ sub cwd {
                      : $me->CWD($dir);
 }
 
+sub pwd {
+ my $me = shift;
+
+ $me->PWD() ? ($me->message =~ /\"([^\"]+)/)[0]
+            : undef;
+}
+
 sub put               { shift->send("stor",@_) }
 sub put_unique { shift->send("stou",@_) }
 sub append     { shift->send("appe",@_) }
@@ -399,7 +427,7 @@ sub port {
 
    # create a Listen socket at same address as the command socket
 
-   $listen = IO::Socket->new(Listen  => 5,
+   $listen = Net::Socket->new(Listen  => 5,
                              Service => 'ftp',
                              Addr    => $me->sockhost,
                             );
@@ -448,7 +476,7 @@ sub timeout {
 
 sub accept {
  my $me = shift;
-
+
  return undef unless defined ${*$me}{LISTEN};
 
  my $data = ${*$me}{LISTEN}->accept;
@@ -487,25 +515,30 @@ sub list_cmd {
  my $cmd = lc shift;
  my $data = $me->$cmd(@_);
 
- die "undef" unless(defined $data);
+ return undef
+        unless(defined $data);
 
  bless $data, "Net::FTP::A"; # Force ASCII mode
 
  my $databuf = '';
- my $list = [];
+ my $buf = '';
 
  while($data->read($databuf,1024)) {
-   push(@{$list}, split(/\n/,$databuf)); ## break into lines
+   $buf .= $databuf;
  }
 
+ my $list = [ split(/\n/,$buf) ];
+
+ $data->close();
+
  wantarray ? @{$list} : $list;
 }
 
 sub data_cmd {
  my $me = shift;
+ my $cmd = uc shift;
  my $ok = 1;
  my $pasv = defined ${*$me}{Pasv} ? 1 : 0;
- my $cmd = uc shift;
 
  $ok = $me->port
         unless $pasv || defined ${*$me}{Port};
@@ -518,6 +551,27 @@ sub data_cmd {
                     : undef;
 }
 
+sub rest_cmd {
+ my $me = shift;
+ my $ok = 1;
+ my $pasv = defined ${*$me}{Pasv} ? 1 : 0;
+ my $where = shift;
+ my $file = shift;
+
+ $ok = $me->port
+        unless $pasv || defined ${*$me}{Port};
+
+ $ok = $me->REST($where)
+        if $ok;
+
+ $ok = $me->RETR($file)
+        if $ok;
+
+ return $pasv ? $ok
+              : $ok ? $me->accept()
+                    : undef;
+}
+
 sub cmd {
  my $me = shift;
 
@@ -538,7 +592,7 @@ sub send_cmd {
 
   ${*$me}{State} = FTP_RESPONSE;
 
-  printf STDERR "$me>> %s\n", $cmd=~/^(pass|resp)/i ? "$1 ...." : $cmd
+  printf STDERR "\n$me>> %s", $cmd=~/^(pass|resp)/i ? "$1 ....\n" : $cmd
         if $me->debug;
  }
 
@@ -575,14 +629,16 @@ sub response {
  my($code,$more,$rin,$rout,$partial,$buf) = (undef,0,'','','','');
 
  @{*$me} = (); # the responce
+ $buf = ${*$me};
+ my @buf = ();
 
  vec($rin,fileno($me),1) = 1;
 
  do
   {
-   if(($timeout==0) || select($rout=$rin, undef, undef, $timeout))
+   if(length($buf) || ($timeout==0) || select($rout=$rin, undef, undef, $timeout))
     {
-     unless(sysread($me, $buf, 1024))
+     unless(length($buf) || sysread($me, $buf, 1024))
       {
        carp "Unexpected EOF on command channel";
        return undef;
@@ -590,21 +646,25 @@ sub response {
 
      substr($buf,0,0) = $partial;    ## prepend from last sysread
 
-     my @buf = split(/\r?\n/, $buf);  ## break into lines
+     @buf = split(/\r?\n/, $buf);  ## break into lines
 
      $partial = (substr($buf, -1, 1) eq "\n") ? ''
                                               : pop(@buf);
 
-     my $cmd;
-     foreach $cmd (@buf)
+     $buf = "";
+
+     while (@buf)
       {
+       my $cmd = shift @buf;
        print STDERR "$me<< $cmd\n"
          if $me->debug;
 
        ($code,$more) = ($1,$2)
         if $cmd =~ /^(\d\d\d)(.)/;
-
+
        push(@{*$me},$');
+
+       last unless(defined $more && $more eq "-");
       }
     }
    else
@@ -613,7 +673,10 @@ sub response {
      return undef;
     }
   }
- while(length($partial) || (defined $more && $more eq "-"));
+ while((scalar(@{*$me}) == 0) || (defined $more && $more eq "-"));
+
+ ${*$me} = @buf ? join("\n",@buf,"") : "";
+ ${*$me} .= $partial;
 
  ${*$me}{Code} = $code;
  ${*$me}{State} = FTP_READY;
@@ -621,138 +684,6 @@ sub response {
  substr($code,0,1);
 }
 
-sub netrc {
- my $host = shift;
- my $file = (getpwuid($>))[7] . "/.netrc";
- my($login,$pass,$acct) = (undef,undef,undef);
- local *NETRC;
- local $_;
-
- my @stat = stat($file);
-
- if(@stat)
-  {
-   if($stat[2] & 077)
-    {
-     carp "Bad permissions: $file";
-     return ();
-    }
-   if($stat[4] != $<)
-    {
-     carp "Not owner: $file";
-     return ();
-    }
-  }
-
- if(open(NETRC,$file))
-  {
-   my($mach,$macdef,$tok,@tok) = (0,0);
-
-LINE_LOOP:
-   while(<NETRC>)
-    {
-     $macdef = 0 if /\A\n\Z/;
-
-     next if $macdef;
-
-     push(@tok, split(/[\s\n]+/, $_));
-
-TOKEN_LOOP:
-     while(@tok)
-      {
-       if($tok[0] eq "default")
-        {
-         last LINE_LOOP if $mach;
-
-         shift(@tok);
-         $mach = 1;
-         ($login,$pass,$acct) = (undef,undef,undef);
-
-         next TOKEN_LOOP;
-        }
-
-       last TOKEN_LOOP unless @tok > 1;
-       $tok = shift(@tok);
-
-       if($tok eq "machine")
-        {
-         last LINE_LOOP if $mach;
-         $mach = 1 if $host eq shift(@tok);
-         ($login,$pass,$acct) = (undef,undef,undef);
-        }
-       elsif($tok eq "login")
-        {
-         $login = shift(@tok);
-        }
-       elsif($tok eq "password")
-        {
-         $pass = shift(@tok);
-        }
-       elsif($tok eq "account")
-        {
-         $acct = shift(@tok);
-        }
-       elsif($tok eq "macdef")
-        {
-         $macdef = 1;
-        }
-      }
-    }
-   close(NETRC);
-
-   return ($login,$pass,$acct)
-        if $mach;
-  }
-
- return ();
-}
-
-sub file_mode {
- local $_ = shift;
- my $mode = 0;
- my($type,$ch);
-
- s/^(.)// and $type = $1;
-
- foreach $ch (split(//,$_))
-  {
-   $mode <<= 1;
-   $mode |= 1 unless $ch eq "-";
-  }
-
- $type eq "d" and $mode |= 0040000 or        # Directory
-   $type eq "l" and $mode |= 0120000 or        # Symbolic Link
-   $mode |= 0100000;                        # Regular File
-
- $mode |= 0004000 if /^...s....../i;
- $mode |= 0002000 if /^......s.../i;
- $mode |= 0001000 if /^.........t/i;
-
- $mode;
-}
-
-sub parse_dir
-{
- my $me = shift;
- my $dir = shift;
- my @files = ();
-
- local $_;
-
- foreach (@$dir)
-  {
-   if(/^([\-FlrwxsStTdD]{10}).*(\w+)\s+(\w*\D)\s*(\d+)\s+(\w{3}\s+\d+\s*(\d+:\d+|\d{4}))\s+(\S+)(\s+->\s+(\S+))?/ )
-    {
-     my($mode,$owner,$group,$size,$date,$file,$link) = ($1,$2,$3,$4,$5,$7,$9);
-
-     $mode = file_mode($mode);
-     push(@files, [$mode, $owner, $group, $size, $date, $file, $link]);
-    }
-  }
- wantarray ? @files : \@files;
-}
-
-
 ;########################################
 ;#
 ;# RFC959 commands
@@ -782,6 +713,7 @@ sub RNFR { shift->send_cmd("RNFR",@_)->response() == 3}
 sub RNTO { shift->send_cmd("RNTO",@_)->response() == 2}
 sub ACCT { shift->send_cmd("ACCT",@_)->response() == 2}
 sub RESP { shift->send_cmd("RESP",@_)->response() == 2}
+sub REST { shift->send_cmd("REST",@_)->response() == 3}
 sub USER { my $ok = shift->send_cmd("USER",@_)->response();($ok == 2 || $ok == 3) ? $ok : 0;}
 sub PASS { my $ok = shift->send_cmd("PASS",@_)->response();($ok == 2 || $ok == 3) ? $ok : 0;}
 sub AUTH { my $ok = shift->send_cmd("AUTH",@_)->response();($ok == 2 || $ok == 3) ? $ok : 0;}
@@ -795,10 +727,10 @@ sub SYST { no_imp; }
 sub STAT { no_imp; }
 sub STRU { no_imp; }
 sub REIN { no_imp; }
-sub REST { no_imp; }
 
 package Net::FTP::dataconn;
 use Carp;
+no strict 'vars';
 
 sub abort {
  my $fd = shift;
@@ -812,15 +744,24 @@ sub close {
  my $fd = shift;
  my $ftp = ${*$fd}{Cmd};
 
- $fd->IO::Socket::close();
+ $fd->Net::Socket::close();
  delete ${*$ftp}{DATA};
 
  $ftp->response();
 }
 
+sub timeout {
+ my $me = shift;
+ my $timeout = ${*$me}{Timeout};
+
+ ${*$me}{Timeout} = 0 + shift if(@_);
+
+ $timeout;
+}
+
 sub _select {
  my $fd = shift;
- my $timeout = shift;
+ local *timeout = \$_[0]; shift;
  my $rw = shift;
  my($rin,$win);
 
@@ -842,14 +783,14 @@ sub _select {
 
 sub can_read {
  my $fd = shift;
- my $timeout = shift;
+ local *timeout = \$_[0];
 
  $fd->_select($timeout,1);
 }
 
 sub can_write {
  my $fd = shift;
- my $timeout = shift;
+ local *timeout = \$_[0];
 
  $fd->_select($timeout,0);
 }
@@ -860,8 +801,6 @@ sub cmd {
  ${*$me}{Cmd};
 }
 
-# should I have a close sub which calls response ??
-
 
 @Net::FTP::L::ISA = qw(Net::FTP::I);
 @Net::FTP::E::ISA = qw(Net::FTP::I);
@@ -875,29 +814,51 @@ no strict 'vars';
 sub read {
  my $fd = shift;
  local *buf = \$_[0]; shift;
- my $size = shift || croak 'read($buf,$size,[$timeout])';
- my $timeout = @_ ? shift : ${*$fd}{Timeout};
+ my $size = shift || croak 'read($buf,$size,[$offset])';
+ my $offset = shift || 0;
+ my $timeout = ${*$fd}{Timeout};
+ my $l;
 
- $fd->can_read($timeout) or
+ croak "Bad offset"
+        if($offset < 0);
+
+ $offset = length $buf
+        if($offset > length $buf);
+
+ $l = 0;
+ READ:
+  {
+   $fd->can_read($timeout) or
         croak "Timeout";
 
- # this needs a bit more thought so I return the correct number of bytes !!
+   my $n = sysread($fd, ${*$fd}, $size, length ${*$fd});
 
- $buf = '';
+   return $n
+        unless($n >= 0);
 
- my $n = sysread($fd, $buf, $size);
+   my $lf = substr(${*$fd},-1,1) eq "\r" ? chop(${*$fd})
+                                         : "";
 
- if($n >= 0)
-  {
-   substr($buf,0,0) = ${*$fd};
-   $buf =~ s/\r\n/\n/g;
-   $buf =~ s/([^\n]*)\Z//so;
-   ${*$fd} = $1;
+   ${*$fd} =~ s/\r\n/\n/go;
+
+   substr($buf,$offset) = ${*$fd};
+
+   $l += length(${*$fd});
+   $offset += length(${*$fd});
+
+   ${*$fd} = $lf;
+  
+   redo READ
+     if($l == 0 && $n > 0);
 
-   $n = length $buf;
+   if($n == 0 && $l == 0)
+    {
+     substr($buf,$offset) = ${*$fd};
+     ${*$fd} = "";
+    }
   }
 
- $n;
+ return $l;
 }
 
 sub write {
@@ -964,7 +925,7 @@ Graham Barr <Graham.Barr@tiuk.ti.com>
 
 =head2 REVISION
 
-$Revision: 1.8 $
+$Revision: 1.17 $
 
 =head2 COPYRIGHT
 
diff --git a/ftp/lib/Net/Netrc.pm b/ftp/lib/Net/Netrc.pm
new file mode 100644
index 0000000..58f0663
--- /dev/null
+++ b/ftp/lib/Net/Netrc.pm
@@ -0,0 +1,123 @@
+package Net::Netrc;
+
+use Carp;
+use strict;
+
+my %netrc = ();
+
+sub _readrc {
+ my $host = shift;
+ my $file = (getpwuid($>))[7] . "/.netrc";
+ my($login,$pass,$acct) = (undef,undef,undef);
+ local *NETRC;
+ local $_;
+
+ $netrc{default} = undef;
+
+ my @stat = stat($file);
+
+ if(@stat)
+  {
+   if($stat[2] & 077)
+    {
+     carp "Bad permissions: $file";
+     return ();
+    }
+   if($stat[4] != $<)
+    {
+     carp "Not owner: $file";
+     return ();
+    }
+  }
+
+ if(open(NETRC,$file))
+  {
+   my($mach,$macdef,$tok,@tok) = (0,0);
+
+   while(<NETRC>)
+    {
+     undef $macdef if /\A\n\Z/;
+
+     if($macdef)
+      {
+       push(@$macdef,$_);
+       next;
+      }
+
+     push(@tok, split(/[\s\n]+/, $_));
+
+TOKEN:
+     while(@tok)
+      {
+       if($tok[0] eq "default")
+        {
+         shift(@tok);
+         $mach = $netrc{default} = {};
+
+         next TOKEN;
+        }
+
+       last TOKEN unless @tok > 1;
+       $tok = shift(@tok);
+
+       if($tok eq "machine")
+        {
+         my $host = shift @tok;
+         $mach = $netrc{$host} = {};
+        }
+       elsif($tok =~ /^(login|password|account)$/)
+        {
+         next TOKEN unless $mach;
+         my $value = shift @tok;
+         $mach->{$1} = $value;
+        }
+       elsif($tok eq "macdef")
+        {
+         next TOKEN unless $mach;
+         my $value = shift @tok;
+         $mach->{macdef} = {} unless exists $mach->{macdef};
+         $macdef = $mach->{machdef}{$value} = [];
+        }
+      }
+    }
+   close(NETRC);
+  }
+}
+
+sub lookup {
+ my $pkg = shift;
+ my $mach = shift;
+
+ _readrc() unless exists $netrc{default};
+
+ return bless \$mach if exists $netrc{$mach};
+
+ return bless \("default") if defined $netrc{default};
+
+ return undef;
+}
+
+sub login {
+ my $me = shift;
+ $me = $netrc{$$me};
+ exists $me->{login} ? $me->{login} : undef;
+}
+
+sub account {
+ my $me = shift;
+ $me = $netrc{$$me};
+ exists $me->{account} ? $me->{account} : undef;
+}
+
+sub password {
+ my $me = shift;
+ $me = $netrc{$$me};
+ exists $me->{password} ? $me->{password} : undef;
+}
+
+sub lpa {
+ my $me = shift;
+ ($me->login, $me->password, $me->account);
+}
+
+1;
diff --git a/ftp/lib/IO/Socket.pm b/ftp/lib/Net/Socket.pm
index a0f77a0..d24e625 100644
--- a/ftp/lib/IO/Socket.pm
+++ b/ftp/lib/Net/Socket.pm
@@ -1,42 +1,13 @@
-package IO::Socket;
+package Net::Socket;
 
 =head1 NAME
 
-IO::Socket - Socket filedescriptor class
-
-=head1 SYNOPSIS
-
- use IO::Socket;
-
- $sock = IO::Socket->new(Peer         => $host,
-                          Service => 'ftp',
-                         );
-
- $sock = IO::Socket->new(Listen  => 5,
-                          Proto   => 'tcp'
-                         );
-
+Net::Socket - TEMPORARY Socket filedescriptor class, so Net::FTP still
+works while IO::Socket is having a re-fit <GBARR>
 
 =head1 DESCRIPTION
 
-C<IO::Socket> is a class which simplifies the creating of a socket. With
-one function call it will do all the required lookups and system calls
-to create the required socket.
-
-To create a socket connection to a foreign host C<ftp.uu.net> using
-the C<ftp> service
-
- $sock = IO::Socket->new(Peer         => $host,
-                          Service => 'ftp',
-                         );
-
-If you want to use the same protocal as the C<ftp> service but provide
-your own port number to connect to
-
- $sock = IO::Socket->new(Peer         => $host,
-                          Service => 'ftp',
-                          Port    => 2001,
-                         );
+NO TEXT --- THIS MODULE IS TEMPORARY
 
 =cut
 
@@ -48,7 +19,7 @@ require Exporter;
 @ISA = qw(Exporter);
 @EXPORT_OK = @Socket::EXPORT;
 
-$VERSION = sprintf("%d.%02d", q$Revision: 1.1 $ =~ /(\d+)\.(\d+)/);
+$VERSION = sprintf("%d.%02d", q$Revision: 1.2 $ =~ /(\d+)\.(\d+)/);
 sub Version { $VERSION }
 
 ##
@@ -161,7 +132,7 @@ sub new {
                                     : undef;
   
   
-   if($type == SOCK_STREAM)
+   if($type == SOCK_STREAM || $destaddr)
     {
      croak "bad peer address"
         unless defined $destaddr;
@@ -197,7 +168,7 @@ sub autoflush {
 
 =head2 accept
 
-perform the system call C<accept> on the socket and return a new IO::Soscket
+perform the system call C<accept> on the socket and return a new Net::Socket
 object. This object can be used to communicate with the client that was trying
 to connect.
 
@@ -211,6 +182,12 @@ sub accept {
  accept($new,$sock) or
         croak "accept: $!";
 
+ ${*$new}{Peername} = getpeername($new) or
+        croak "getpeername: $!";
+
+ ${*$new}{Sockname} = getsockname($new) or
+        croak "getsockname: $!";
+
  $new;
 }
 
@@ -340,7 +317,7 @@ Graham Barr <Graham.Barr@tiuk.ti.com>
 
 =head1 REVISION
 
-$Revision: 1.1 $
+$Revision: 1.2 $
 
 =head1 COPYRIGHT
 
diff --git a/ftp/t/require.t b/ftp/t/require.t
new file mode 100644
index 0000000..5f37e74
--- /dev/null
+++ b/ftp/t/require.t
@@ -0,0 +1,11 @@
+#
+# Dummy test file
+#
+
+
+print "1..1\n";
+
+require IO::Socket;
+require Net::FTP;
+
+print "ok 1\n";