#!/usr/local/bin/perl
# Version 0.3 with a minor patches....
#----Stuff here must be customized for your machine----
$myName = "hell.micro.umn.edu";   	#host full domain name
$myPort = "7997";			#port at which inetd is listening
$ftp = "/usr/ucb/ftp";			#whereever on your box this lives
$logFile = "/tmp/gftplog";		#Leave this empty "" for no logging
#----end local customizations-------
#Hmm.  I'm really not sure how to catch signals...
$SIG{'INT'} = 'CLEANUP';
$SIG{'HUP'} = 'CLEANUP';
$SIG{'QUIT'} = 'CLEANUP';
$SIG{'PIPE'} = 'CLEANUP';
$SIG{'ALRM'} = 'CLEANUP';
$tmp = "/tmp/gf$$";			#I'll clean up; Promise!
$tmpData = "/tmp/gfd$$";		#This one's for spooling
$separator = "@";			#For encoding selector with hostname
$host = "";
$getBinary = "";
$query = <STDIN>;
chop($query);
chop($query);
if ($logFile ne "") {
        $remoteHost = &getRemoteHost;
        open(LOG, ">>$logFile");
        print LOG "$$\t$remoteHost \t- $query\n";
        close(LOG);
}
if ($query eq "") {
	print "3 Incorrectly specified request for FTP (No hostname)\r\n.\r\n";
	exit; 
}
($host, $thing) = split(/@/, $query, 2);
$thing = "/" if ($thing eq "");
open(FTP, "| $ftp -n $host >$tmp") || die "3 Error. Couldn't connect to server\r\n.\r\n";
print FTP "user anonymous gopher@$myName\n";
$thing2 = $thing;
$dir = chop($thing2);
if ($dir eq "/") {		#asking for a dir
	print FTP "cd $thing2\n" if ($thing2 ne "");
	print FTP "ls -F\n";
	$tmpData = "";
} else  {			#asking for a file 
	$thing = $thing2 if ($dir eq "*") || ($dir eq "@");
	$getBinary = $thing =~ /\.(ZIP)|(ZOO)|(ARJ)|(ARC)|(LZH)|(HYP)|(PAK)|(EXE)|(TAR)|Z$/i;	#ick ick ick
	print FTP "binary\n" if $getBinary ne "";
	print FTP "get $thing $tmpData\n"; 
}
print FTP "quit\n";
close(FTP);		#re-use the fileHandle
if ($tmpData eq "") {	#maybe use an exists instead?
	open(FTP, "$tmp") || die "3 Error. Could not return list.\r\n.\r\n";
	while (<FTP>) {
		chop;
		s/\*$//;			#Hack out stars
		s&\@$&/&;			#Hack out ats
		if  (s%/$%%) {			#It's a directory
			print "1$_\t$host$separator$thing$_/";
		} elsif (/\.HQX$/i) {	#binhex file
			print "4$_\t$host$separator$thing$_";
		} elsif (/\.(ZIP)|(ZOO)|(ARJ)|(ARC)|(LZH)|(HYP)|(PAK)|(EXE)$/i) {	#DOS scrap
			print "5$_\t$host$separator$thing$_";
		} elsif (/\.(TAR)|Z$/i) {	#we'll let these thru as 9
			print "9$_\t$host$separator$thing$_";
		} else {			#Regular text file
			print "0$_\t$host$separator$thing$_";
		}
		print "\t$myName\t$myPort\r\n";
	}
	print ".\r\n";
} elsif ($getBinary) {
	open(FTP, "$tmpData") || die "3 Error.  Could not transfer file.\r\n.\r\n";
	while (read(FTP, $buf, 16384)) {
		print $buf;
	}
} elsif (-T $tmpData) { 
	open(FTP, "$tmpData") || die "3 Error. Could not transfer file.\r\n.\r\n";
	while (<FTP>) {
		chop;
		print "$_\r\n";
	}
	print".\r\n";
} else {
	print "3 Sorry.  Requested file did not appear to contain text.\r\n.\r\n";
}
close(FTP);
unlink("$tmp");
unlink("$tmpData") if ($tmpData ne "");
exit;

sub CLEANUP {
	print "3 Error in FTP transaction.\r\n.\r\n";
	unlink("$tmp");
	unlink("$tmpData") if ($tmpData ne "");
}

sub AF_INET {2;}

sub getRemoteHost {
	$srcHost = shift(@ARGV);
	$srcHost =~ s/\..*//;
	@ans = gethostbyaddr(&str2inet($srcHost), &AF_INET);
	if (!defined @ans) {
		$ans = "$srcHost : unknown address";
	} else {
		$ans = $ans[0];
	}
}

sub str2inet {
	$dec = hex($_[0]);
	pack('L', $dec);
}

