[comp.lang.perl] even better chat2.pl, and a useful

merlyn@iwarp.intel.com (Randal L. Schwartz) (05/01/91)

Here's an improved version of the chat2.pl script that supports
opening a TCP socket awaiting a connection (giving you enough info to
tell the other end what to do).  And, as if that wasn't enough, I've
also enclosed ftp-ls-R, which acts as a rudimentary ftp client by
connecting to an ftp server then performing an "ls -Ra" equivalent.
Usage is something like:

	ftp-ls-R host [topdir]

so an invocation of

	ftp-ls-R prep.ai.mit.edu pub/gnu

gives you all the GNU stuff.

Enjoy.  I'm still hacking away.  I hope to expand this ftp client to
maintain ftp-shadow directories with minimal fuss (have all the RFCs
online here, for example).  If someone else does something with this,
let me know, so I can coordinate.

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  chat2.pl ftp-ls-R
# Wrapped by merlyn@iwarpse on Tue Apr 30 13:28:42 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'chat2.pl' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'chat2.pl'\"
else
echo shar: Extracting \"'chat2.pl'\" \(7365 characters\)
sed "s/^X//" >'chat2.pl' <<'END_OF_FILE'
X## chat.pl: chat with a server
X## V2.01.alpha.3 91/04/30
X## Randal L. Schwartz
X
Xpackage chat;
X
X$sockaddr = 'S n a4 x8';
Xchop($thishost = `hostname`); $thisaddr = (gethostbyname($thishost))[4];
X$thisproc = pack($sockaddr, 2, 0, $thisaddr);
X
X# *S = symbol for current I/O, gets assigned *chatsymbol....
X$next = "chatsymbol000000"; # next one
X$nextpat = "^chatsymbol"; # patterns that match next++, ++, ++, ++
X
X
X## $handle = &chat'open_port("server.address",$port_number);
X## opens a named or numbered TCP server
X
Xsub open_port { ## public
X	local($server, $port) = @_;
X
X	local($serveraddr,$serverproc);
X
X	*S = ++$next;
X	if ($server =~ /^(\d+)+\.(\d+)\.(\d+)\.(\d+)$/) {
X		$serveraddr = pack('C4', $1, $2, $3, $4);
X	} else {
X		local(@x) = gethostbyname($server);
X		return undef unless @x;
X		$serveraddr = $x[4];
X	}
X	$serverproc = pack($sockaddr, 2, $port, $serveraddr);
X	unless (socket(S, 2, 1, 6)) {
X		# XXX hardwired $AF_SOCKET, $SOCK_STREAM, 'tcp'
X		# but who the heck would change these anyway? (:-)
X		($!) = ($!, close(S)); # close S while saving $!
X		return undef;
X	}
X	unless (bind(S, $thisproc)) {
X		($!) = ($!, close(S)); # close S while saving $!
X		return undef;
X	}
X	unless (connect(S, $serverproc)) {
X		($!) = ($!, close(S)); # close S while saving $!
X		return undef;
X	}
X	select((select(S), $| = 1)[0]);
X	$next; # return symbol for switcharound
X}
X
X## ($host, $port, $handle) = &chat'open_listen();
X## opens a TCP port on the current machine, ready to be listened to
X
Xsub open_listen { ## public
X
X	*S = ++$next;
X	local(*NS) = "__" . time;
X	unless (socket(NS, 2, 1, 6)) {
X		# XXX hardwired $AF_SOCKET, $SOCK_STREAM, 'tcp'
X		# but who the heck would change these anyway? (:-)
X		($!) = ($!, close(NS));
X		return undef;
X	}
X	unless (bind(NS, $thisproc)) {
X		($!) = ($!, close(NS));
X		return undef;
X	}
X	unless (listen(NS, 1)) {
X		($!) = ($!, close(NS));
X		return undef;
X	}
X	select((select(NS), $| = 1)[0]);
X	local($family, $port, @myaddr) =
X		unpack("S n C C C C x8", getsockname(NS));
X	$S{"needs_accept"} = *NS; # so expect will open it
X	(@myaddr, $port, $next); # returning this
X}
X
X## $handle = &chat'open_proc("command","arg1","arg2",...);
X## opens a /bin/sh on a pseudo-tty
X
Xsub open_proc { ## public
X	local(@cmd) = @_;
X
X	*S = ++$next;
X	local(*TTY) = "__TTY" . time;
X	local($pty,$tty) = &_getpty(S,TTY);
X	die "Cannot find a new pty" unless defined $pty;
X	local($pid) = fork;
X	die "Cannot fork: $!" unless defined $pid;
X	unless ($pid) {
X		close STDIN; close STDOUT; close STDERR;
X		setpgrp(0,$$);
X		if (open(DEVTTY, "/dev/tty")) {
X		    ioctl(DEVTTY,0x20007471,0);		# XXX s/b &TIOCNOTTY
X		    close DEVTTY;
X		}
X		open(STDIN,"<&TTY");
X		open(STDOUT,">&TTY");
X		open(STDERR,">&STDOUT");
X		die "Oops" unless fileno(STDERR) == 2;	# sanity
X		close(S);
X		exec @cmd;
X		die "Cannot exec @cmd: $!";
X	}
X	close(TTY);
X	$next; # return symbol for switcharound
X}
X
X# $S is the read-ahead buffer
X
X## $return = &chat'expect([$handle,] $timeout_time,
X## 	$pat1, $body1, $pat2, $body2, ... )
X## $handle is from previous &chat'open_*().
X## $timeout_time is the time (either relative to the current time, or
X## absolute, ala time(2)) at which a timeout event occurs.
X## $pat1, $pat2, and so on are regexs which are matched against the input
X## stream.  If a match is found, the entire matched string is consumed,
X## and the corresponding body eval string is evaled.
X##
X## Each pat is a regular-expression (probably enclosed in single-quotes
X## in the invocation).  ^ and $ will work, respecting the current value of $*.
X## If pat is 'TIMEOUT', the body is executed if the timeout is exceeded.
X## If pat is 'EOF', the body is executed if the process exits before
X## the other patterns are seen.
X##
X## Pats are scanned in the order given, so later pats can contain
X## general defaults that won't be examined unless the earlier pats
X## have failed.
X##
X## The result of eval'ing body is returned as the result of
X## the invocation.  Recursive invocations are not thought
X## through, and may work only accidentally. :-)
X##
X## undef is returned if either a timeout or an eof occurs and no
X## corresponding body has been defined.
X## I/O errors of any sort are treated as eof.
X
Xsub expect { ## public
X	if ($_[0] =~ /$nextpat/) {
X		*S = shift;
X	}
X	local($endtime) = shift;
X
X	$endtime += time if $endtime < 600_000_000;
X	local($rmask, $nfound, $timeleft, $thisbuf);
X	local($timeout,$eof) = (1,1);
X	local($cases,$pattern,$action);
X	local($caller) = caller;
X	local($return,@return);
X	local($returnvar) = wantarray ? '@return' : '$return';
X
X	if (defined $S{"needs_accept"}) { # is it a listen socket?
X		local(*NS) = $S{"needs_accept"};
X		delete $S{"needs_accept"};
X		$S{"needs_close"} = *NS;
X		unless(accept(S,NS)) {
X			($!) = ($!, close(S), close(NS));
X			return undef;
X		}
X		select((select(S), $| = 1)[0]);
X	}
X
X	## strategy: create a giant block inside $cases
X	$cases .= <<'ESQ';
X	LOOP: {
XESQ
X	while (@_) {
X		($pattern,$action) = splice(@_,0,2);
X		if ($pattern =~ /^eof$/i) {
X			$cases .= <<"EDQ";
X		if (\$eof) {
X			$returnvar = do { package $caller; $action; };
X			last LOOP;
X		}
XEDQ
X			$eof = 0;
X		} elsif ($pattern =~ /^timeout$/i) {
X			$cases .= <<"EDQ";
X		if (\$timeout) {
X			$returnvar = do { package $caller; $action; };
X			last LOOP;
X		}
XEDQ
X			$timeout = 0;
X		} else {
X			$pattern =~ s#/#\\/#g;
X			$cases .= <<"EDQ";
X		if (\$S =~ /$pattern/) {
X			\$S = \$';
X			$returnvar = do { package $caller; $action; };
X			last LOOP;
X		}
XEDQ
X		}
X	}
X	$cases .= <<"EDQ" if $eof;
X		if (\$eof) {
X			$returnvar = undef;
X			last LOOP;
X		}
XEDQ
X	$cases .= <<"EDQ" if $timeout;
X		if (\$timeout) {
X			$returnvar = undef;
X			last LOOP;
X		}
XEDQ
X	$eof = $timeout = 0;
X	$cases .= <<'ESQ';
X		$rmask = "";
X		vec($rmask,fileno(S),1) = 1;
X		($nfound, $rmask) =
X		 	select($rmask, undef, undef, $endtime - time);
X		if ($nfound) {
X			"<nfound = $nfound>";
X			$nread = sysread(S, $thisbuf, 1024);
X			if ($nread > 0) {
X				$S .= $thisbuf;
X			} else {
X				$eof++, redo LOOP; # any error is also eof
X			}
X		} else {
X			$timeout++, redo LOOP; # timeout
X		}
X		redo LOOP;
X	}
XESQ
X	eval $cases; die "$cases:\n$@" if $@;
X	if (wantarray) {
X		return @return;
X	} else {
X		return $return;
X	}
X}
X
X## &chat'print([$handle,] @data)
X## $handle is from previous &chat'open().
X## like print $handle @data
X
Xsub print { ## public
X	if ($_[0] =~ /$nextpat/) {
X		*S = shift;
X	}
X	print S @_;
X}
X
X## &chat'close([$handle,])
X## $handle is from previous &chat'open().
X## like close $handle
X
Xsub close { ## public
X	if ($_[0] =~ /$nextpat/) {
X	 	*S = shift;
X	}
X	close(S);
X	if (defined $S{"needs_close"}) { # is it a listen socket?
X		local(*NS) = $S{"needs_close"};
X		delete $S{"needs_close"};
X		close(NS);
X	}
X}
X
X# ($pty,$tty) = $chat'_getpty(PTY,TTY):
X# internal procedure to get the next available pty.
X# opens pty on handle PTY, and matching tty on handle TTY.
X# returns undef if can't find a pty.
X
Xsub _getpty { ## private
X	local($_PTY,$_TTY) = @_;
X	$_PTY =~ s/^([^']+)$/(caller)[$[]."'".$1/e;
X	$_TTY =~ s/^([^']+)$/(caller)[$[]."'".$1/e;
X	local($pty,$tty);
X	for $bank (112..127) {
X		next unless -e sprintf("/dev/pty%c0", $bank);
X		for $unit (48..57) {
X			$pty = sprintf("/dev/pty%c%c", $bank, $unit);
X			open($_PTY,"+>$pty") || next;
X			select((select($_PTY), $| = 1)[0]);
X			($tty = $pty) =~ s/pty/tty/;
X			open($_TTY,"+>$tty") || next;
X			select((select($_TTY), $| = 1)[0]);
X			system "stty nl>$tty";
X			return ($pty,$tty);
X		}
X	}
X	undef;
X}
X
X1;
END_OF_FILE
if test 7365 -ne `wc -c <'chat2.pl'`; then
    echo shar: \"'chat2.pl'\" unpacked with wrong size!
fi
# end of 'chat2.pl'
fi
if test -f 'ftp-ls-R' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'ftp-ls-R'\"
else
echo shar: Extracting \"'ftp-ls-R'\" \(2658 characters\)
sed "s/^X//" >'ftp-ls-R' <<'END_OF_FILE'
X#!/usr/bin/perl
X
Xpush(@INC, '/local/merlyn/lib/perl');
X
Xrequire 'chat2.pl';
X
X$| = $trace = 1, shift if $ARGV[0] =~ /^-d/; # debug mode
X
X$host = shift || "localhost";
X$topdir = shift || ".";
X$user = "anonymous";
X$pass = "merlyn\@iwarp.intel.com";
X
X($Control = &chat'open_port($host,21)) || die "open control: $!";
Xdie "expected 2, got $_"
X	unless ($_ = &clisten(10)) =~ /^2/;
X&ctalk("user $user\n");
Xdie "expected 3, got $_"
X	unless ($_ = &clisten(10)) =~ /^3/;
X&ctalk("pass $pass\n");
Xdie "expected 2, got $_"
X	unless ($_ = &clisten(10)) =~ /^2/;
X## all set up for a conversation
X
X@list = ($topdir);
Xwhile ($dir = shift list) {
X	next if $all{$dir}++;
X	print "=== $dir ===\n";
X	for (&list($dir)) {
X		print "$_\n";
X		push(@list, "$dir/$1")
X			if /^d.*\s(\S+)\s*$/;
X	}
X}
X
X## shutdown
X&ctalk("quit\n");
X&clisten(5); # for trace
X&chat'close($Control);
Xexit(0);
X
Xsub ctalk {
X	local($text) = @_;
X	print "{$text}" if $trace;
X	&chat'print($Control,$text);
X}
X
Xsub clisten {
X	local($secs) = @_;
X	local($return,$tmp);
X	while (1) {
X		$tmp = &chat'expect($Control, $secs, '(.*)\r?\n', '"$1\n"');
X		print $tmp if $trace;
X		$return .= $tmp;
X		return $return if !length($tmp) || $tmp =~ /^\d\d\d /;
X	}
X}
X
Xsub dopen {
X	local($_);
X
X	local(@ret) = &chat'open_listen();
X	&ctalk("port " .
X		join(",", @ret[0,1,2,3], int($ret[4]/256), $ret[4]%256) .
X		"\n");
X	die "expected 2, got $_"
X		unless ($_ = &clisten(5)) =~ /^2/;
X	$Data = $ret[5];
X}
X
Xsub dtalk {
X	local($text) = @_;
X	print "{D:$text}" if $trace;
X	&chat'print($Data,$text);
X}
X
Xsub dlisten {
X	local($secs) = @_;
X	local($return,$tmp);
X	while (1) {
X		$tmp = &chat'expect($Data, $secs,
X			'(.|\n)+', '$&',
X			TIMEOUT, '""',
X			EOF, 'undef');
X		if (defined $tmp) {
X			print "[D:$tmp]" if $trace;
X			$return .= $tmp;
X			return $return unless length $tmp;
X				# if timeout, return what you have
X		} else { # eof
X			return $return;
X				# maybe undef
X		}
X	}
X}
X
Xsub dclose {
X	&chat'close($Data);
X}
X
Xsub nlst {
X	local($dir) = @_;
X	local(@files);
X	local($_);
X
X	&dopen();
X	&ctalk("nlst -a $dir/.\n");
X	die "expected 1, got $_"
X		unless ($_ = &clisten(10)) =~ /^1/;
X	$_ = &dlisten(30);
X	@files = sort grep(!/^\.\.?$/, split(/\r?\n/))
X		unless /^ls: /;
X	die "expected 2, got $_"
X		unless ($_ = &clisten(10)) =~ /^2/;
X	&dclose();
X	@files;
X}
X
Xsub list {
X	local($dir) = @_;
X	local(@files);
X	local($_,$tmp);
X
X	&dopen();
X	&ctalk("list -A $dir/.\n");
X	die "expected 1, got $_"
X		unless ($_ = &clisten(10)) =~ /^(.*\n)*1/;
X	while (1) {
X		$tmp = &dlisten(30);
X		last unless defined $tmp;
X		$_ .= $tmp;
X	}
X	@files = sort grep(/^\S[rwx\-]{8}/, split(/\r?\n/));
X	die "expected 2, got $_"
X		unless ($_ = &clisten(10)) =~ /^2/;
X	&dclose();
X	@files;
X}
END_OF_FILE
if test 2658 -ne `wc -c <'ftp-ls-R'`; then
    echo shar: \"'ftp-ls-R'\" unpacked with wrong size!
fi
chmod +x 'ftp-ls-R'
# end of 'ftp-ls-R'
fi
echo shar: End of shell archive.
exit 0

print "Just another Perl hacker,"
-- 
/=Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 ==========\
| on contract to Intel's iWarp project, Beaverton, Oregon, USA, Sol III      |
| merlyn@iwarp.intel.com ...!any-MX-mailer-like-uunet!iwarp.intel.com!merlyn |
\=Cute Quote: "Intel: putting the 'backward' in 'backward compatible'..."====/

rbj@uunet.UU.NET (Root Boy Jim) (05/08/91)

merlyn@iwarp.intel.com (Randal L. Schwartz) writes:
>
>so an invocation of
>
>	ftp-ls-R prep.ai.mit.edu pub/gnu
>
>gives you all the GNU stuff.

I suppose I should have seen where this was going ...

Why do you think "rget" isn't in the ftp client?
The answer isn't technical, it's political.

People, PLEASE BE CAREFUL about where and when you point this thing.
If you point it at us, please do so during the daytime.
Everyone wants their mail delivered at night, so we're busy then.

5:39pm /home/rbj [rbj@uunet 7] df /ftp
Filesystem            kbytes    used   avail capacity  Mounted on
/dev/ds2             1142364  923731  104396    90%    /usr/spool/ftp

Yes, that's right, almost a gigabyte. Some others even have more.
-- 
		[rbj@uunet 1] stty sane
		unknown mode: sane

emv@ox.com (Ed Vielmetti) (05/08/91)

In article <132095@uunet.UU.NET> rbj@uunet.UU.NET (Root Boy Jim) writes:

   Why do you think "rget" isn't in the ftp client?
   The answer isn't technical, it's political.

It's always a problem when political considerations work their way
into technical developments.  Certainly there are risks involved in
commands which have the potential of transferring large amounts of
data without too much effort; links clog up, computers get busy,
paying customers get unhappy that their machines don't work so hot.
But don't interfere with my ability to work efficiently.

   People, PLEASE BE CAREFUL about where and when you point this thing.
   If you point it at us, please do so during the daytime.

I would think that uunet would welcome the deveopment of better ftp
client tools, especially those which would facilitate the development
of efficient and effective shadow archives.  Since much of UUNET's
gigabyte worth of stuff is shadows of stuff which is originally
available on other sites, it would seem reasonable to build tools to
periodically tap the original sites on the shoulder and note whether
anything new has happened there in the past month.  (or be tapped on
the shoulder by something which watches for new developments, like
comp.archives.)  Good things to do intelligent recursive ftp's should
be welcomed.

-- 
Edward Vielmetti, MSEN Inc. 	moderator, comp.archives 	emv@msen.com

"often those with the power to appoint will be on one side of a
controversial issue and find it convenient to use their opponent's
momentary stridency as a pretext to squelch them"

allbery@NCoast.ORG (Brandon S. Allbery KB8JRR/AA) (05/09/91)

As quoted from <132095@uunet.UU.NET> by rbj@uunet.UU.NET (Root Boy Jim):
+---------------
| merlyn@iwarp.intel.com (Randal L. Schwartz) writes:
| >
| >so an invocation of
| >
| >	ftp-ls-R prep.ai.mit.edu pub/gnu
| >
| >gives you all the GNU stuff.
| 
| I suppose I should have seen where this was going ...
| 
| Why do you think "rget" isn't in the ftp client?
| The answer isn't technical, it's political.
+---------------

I had a feeling someone would say that.  Read the code (and the rest of his
message) --- it sends an ls -lR listing of all the GNU stuff, not the actual
GNU archives.

++Brandon
-- 
Me: Brandon S. Allbery			  Ham: KB8JRR/AA  10m,6m,2m,220,440,1.2
Internet: allbery@NCoast.ORG		       (restricted HF at present)
Delphi: ALLBERY				 AMPR: kb8jrr.AmPR.ORG [44.70.4.88]
uunet!usenet.ins.cwru.edu!ncoast!allbery       KB8JRR @ WA8BXN.OH

rbj@uunet.uu.net (Root Boy Jim) (05/16/91)

allbery@ncoast.ORG (Brandon S. Allbery KB8JRR/AA) writes:
>As quoted from <132095@uunet.UU.NET> by rbj@uunet.UU.NET (Root Boy Jim):
>| 
>| Why do you think "rget" isn't in the ftp client?
>| The answer isn't technical, it's political.
>+---------------
>
>I had a feeling someone would say that.  Read the code (and the rest of his
>message) --- it sends an ls -lR listing of all the GNU stuff, not the actual
>GNU archives.

Even so, consider the size of our ls-lR.Z:

376 -rw-r--r--  1 rick     371745 May 15 03:39 /usr/spool/ftp/ls-lR.Z

The file is probably a megabyte of so uncompressed.

and also: [rbj@uunet 29] zcat ~ftp/ls-lR.Z |wc
   39816  227715 1711169

We don't need people stat'ing 4000 files several times a day,
or worse yet, at night. As I said, please be careful.
-- 
		[rbj@uunet 1] stty sane
		unknown mode: sane

emv@ox.com (Ed Vielmetti) (05/16/91)

In article <1991May15.235542.3938@uunet.uu.net> rbj@uunet.uu.net (Root Boy Jim) writes:

  >I had a feeling someone would say that.  Read the code (and the rest of his
  >message) --- it sends an ls -lR listing of all the GNU stuff, not the actual
  >GNU archives.

  Even so, consider the size of our ls-lR.Z:
  376 -rw-r--r--  1 rick     371745 May 15 03:39 /usr/spool/ftp/ls-lR.Z

What fraction of this is

-rw-r--r--  1 16       21           5624 Sep 19  1989 part02.Z
-rw-r--r--  1 16       21           5504 Sep 19  1989 part03.Z
-rw-r--r--  1 16       21           4531 Sep 19  1989 part04.Z
-rw-r--r--  1 16       21           5045 Sep 19  1989 part05.Z
-rw-r--r--  1 16       21           3046 Sep 19  1989 part06.Z

nonsense with close to zero information content?  You want us to ftp
back a third of a megabyte full of that?  (not to mention all of the
old outdated versions of software that uunet has long after new
versions are announced.) no way.  esp. not over this person's 19.2kb
line.

  and also: [rbj@uunet 29] zcat ~ftp/ls-lR.Z |wc
      39816  227715 1711169

  We don't need people stat'ing 4000 files several times a day,
  or worse yet, at night. As I said, please be careful.

you have control over your ftp server, turn it off it you don't like
it; reject recursive directory descents at the top level or two of
your hierarchy.  if it's that bad, it's within your power to solve it
by administrative policy rather than jawboning us poor coders into not
writing code.

uunet is very different from the ordinary anonymous ftp system;
many of the other 1000 or so sites have adequate CPU to handle a
well-aimed request.  if the net as a whole is beating up on your
machines so bad, why don't you drop a few grand on a nice scsi disk
and a cheap risc machine, call it "ftp.uu.net", and let the world know
that it's out there.  should extend the life of your existing gear,
and since it'll be non-paying customers who are stat'ing files left
and right they will have no right to complain if things are too slow.
block non-paying customers from the revenue system.

obperl: (not quite even) it's worth your while to pick up the
log_archie script just posted to comp.sources.misc; nice way of
keeping a tidy account of archie search sessions.  (but it's in awk.
so use a2pl first if you feel obligated)

-- 
Edward Vielmetti, vice president for research, MSEN Inc. emv@msen.com

"(6) The Plan shall identify how agencies and departments can
collaborate to ... expand efforts to improve, document, and evaluate
unclassified public-domain software developed by federally-funded
researchers and other software, including federally-funded educational
and training software; "
			"High-Performance Computing Act of 1991, S. 272"

rbj@uunet.uu.net (Root Boy Jim) (05/17/91)

In article <EMV.91May16030640@poe.aa.ox.com> emv@ox.com (Ed Vielmetti) writes:
?In <1991May15.235542.3938@uunet.uu.net> rbj@uunet.uu.net (Root Boy Jim) writes:
?
?  Even so, consider the size of our ls-lR.Z:
?  376 -rw-r--r--  1 rick     371745 May 15 03:39 /usr/spool/ftp/ls-lR.Z
?
?What fraction of this is
?
?-rw-r--r--  1 16       21           5624 Sep 19  1989 part02.Z
?-rw-r--r--  1 16       21           5504 Sep 19  1989 part03.Z
?-rw-r--r--  1 16       21           4531 Sep 19  1989 part04.Z
?-rw-r--r--  1 16       21           5045 Sep 19  1989 part05.Z
?-rw-r--r--  1 16       21           3046 Sep 19  1989 part06.Z

[rbj@uunet 38] zcat ~ftp/ls-lR.Z | grep 'part[0-9]*.Z$' | wc
    5274   42192  284667

from the line below: [rbj@uunet 42] expr 284667 / 17111 = 16%

?nonsense with close to zero information content?  You want us to ftp
?back a third of a megabyte full of that?  (not to mention all of the
?old outdated versions of software that uunet has long after new
?versions are announced.) no way.  esp. not over this person's 19.2kb
?line.

I wonder how much could be saved by deleting old versions.
And sometimes the old versions are better (but rarely).

Perhaps we should include a ls-sR.Z as well.

I'd rather have you retrieve this list as a text file
than to generate it on the fly.

?  and also: [rbj@uunet 29] zcat ~ftp/ls-lR.Z |wc
?      39816  227715 1711169
?
?  We don't need people stat'ing 4000 files several times a day,
?  or worse yet, at night. As I said, please be careful.
?
?you have control over your ftp server, turn it off it you don't like it.

When you snarf something from another machine via anonymous FTP
you are a guest in their house. Please act politely.

?it; reject recursive directory descents at the top level or two of
?your hierarchy.

A good point. However, some people feel that it isn't really
worth writing code to do this, especially since that puts the
power into anyone's hands, including novices and pinheads alike.

?if it's that bad, it's within your power to solve it
?by administrative policy rather than jawboning us poor coders into not
?writing code.

Yes, it appears that such attempts are fruitless.

?uunet is very different from the ordinary anonymous ftp system;

There are bigger sites than us, better organized.
Reorganization is on our to do list.

?many of the other 1000 or so sites have adequate CPU to handle a
?well-aimed request.

That's all I was asking. Please aim well. We aim to please.

?if the net as a whole is beating up on your
?machines so bad, why don't you drop a few grand on a nice scsi disk
?and a cheap risc machine, call it "ftp.uu.net", and let the world know
?that it's out there.

ftp.uu.net is a cname for uunet.uu.net, and we do ask people to use
it.  We may actually make it a separate machine someday.  I suppose the
real reason is that ~uucp == ~ftp. I suppose we could mount it via NFS tho.

In another letter you mentioned better ftp client/servers. Well it just
so happens that Rick is in charge of BSD ftp and has made several
enhancements. They include restarting in the middle of transfers,
sending the modification time, only transferring newer versions, etc.

The world would be a better place if more people ran it.
-- 
		[rbj@uunet 1] stty sane
		unknown mode: sane