#!/usr/bin/perl

use Socket;
use Net::FTP;


my $MAXPIDS=250;

my $HELP=q
{Usage: ftpcheck [-h | --help] host
};

my @hosts;

for $_ (@ARGV){
    if(/^--(.*)/){
	$_=$1;
	if(/help/){
	    print $HELP;
	    exit(0);
	}
    }
    elsif(/^-(.*)/){
	$_=$1;
	if(/^h/ or /^?/){
	    print $HELP;
	    exit(0);
	}
    }else{
	push @hosts,$_;
    }
}

if(!$hosts[0]){
    print $HELP;
    exit(-1);
}

my $host;

print "ftpcheck v0.2 by dave weekly <dew\@cs.stanford.edu>\n\n";

# bury dead children
$SIG{CHLD}= sub{wait()};

# go through all of the hosts, replacing subnets with all contained IPs.
for $host (@hosts){
    $_=shift(@hosts);

    # scan a class C
    if(/^([^.]+)\.([^.]+)\.([^.]+)$/){
	my $i;
	print "Expanding class C $_\n";
	for($i=1;$i<255;$i++){
	    my $thost="$_.$i";
	    push @hosts,$thost;
	}
    }
    else{
	push @hosts,$_;
    }
}

my @pids;
my $npids=0;

for $host (@hosts){
    my $pid;
    $pid=fork();
    if($pid>0){
	$npids++;
	if($npids>$MAXPIDS){
	    for(1..($MAXPIDS/2)){
		if(wait()>0){
		    $npids--;
		}
	    }
	}
	next;
    }elsif($pid==-1){
	print "fork error\n";
	exit(0);
    }else{
	$ARGV0="(checking $host)";
	my($proto,$port,$sin,$ip);
	$proto=getprotobyname('tcp');
	$port=21;
	$ip=inet_aton($host);
	if(!$ip){
	    print "couldn't find host $host\n";
	    exit(0);
	}
	$sin=sockaddr_in($port,$ip);
	socket(Sock, PF_INET, SOCK_STREAM, $proto);
	if(!connect(Sock,$sin)){
	    exit(0);
	}
	my $iaddr=(unpack_sockaddr_in(getpeername(Sock)))[1];
	close(Sock);
	
	# SOMETHING is listening on the FTP port...really ftp server?

	$hostname=gethostbyaddr($iaddr,AF_INET);

	$ftp = Net::FTP->new($host);
	if(!$ftp){
	    print "      <$host ($hostname) denied you>\n";
	    exit(0);
	}
	if(!$ftp->login("anonymous","just\@checking.com")){
	    print "   FTP on $host [$hostname]\n";
	    exit(0);
	}

	print "Anon FTP on $host [$hostname]\n";

	$ftp->quit;
	exit(0);
    }
}

print "done spawning, $npids children remain\n";
# wait for my children
$|=1;
for(1..$npids){
    my $wt=wait();
    if($wt==-1){
	print "hey $!\n";
	redo;
    }else{
#	print "$wt\n";
    }
}

print "Done\n";
