#!/afs/athena/contrib/perl/perl

$#ARGV == 0 || die "Usage: $0 <regexp>\n";

$expression = $ARGV[0];

$hostfile = "/afs/net.mit.edu/admin/hosts/hstath.txt";

# Read hosts file.

$| = 1;

print "Reading hosts file...";

$| = 0;

open (HOSTS, $hostfile) || die "Error opening host file $hostfile: $!";

while (<HOSTS>) {
    next if /^;/;
    next if /^\s*$/;
    $name = (split (' : ', $_))[2];
    @names = split (',', $name);			       
    push (@hostlist, @names);
}

close (HOSTS);

print "done.\n";

eval '@matchhosts = grep (/$expression/i, @hostlist);';

$port = (getservbyname ("telnet","tcp"))[2];
$proto = (getprotobyname ("tcp"))[2];
$sockaddr = "S n a4 x8";

chop ($thishost = `hostname`);
$thisaddr = ((gethostbyname($thishost))[4])[0];

require "sys/socket.ph";
require "sys/wait.ph";

foreach $host (@matchhosts) {
    $hostaddr = ((gethostbyname($host))[4])[0];
    if (! $hostaddr) {
	print "No such host '$host'.\n";
	next;
    }
    socket (S, &AF_INET, &SOCK_STREAM, $proto) || die "$!";
    bind (S, pack ($sockaddr, &AF_INET, 0, $thisaddr)) || die "$!";

    FORK: {
	if ($pid = fork) {
	    $diepid = wait;
	    if ($diepid == -1) {
		print STDERR "No child\n";
		next;
	    }
	    if ($? == 14) {
		print STDERR "Timed out connecting to $host\n";
		next;
	    }
	    if ($? == 0) {
		print "$host\n";
	    } 
	} elsif (defined $pid) {
	    alarm 5;
	    if (connect (S, pack ($sockaddr, &AF_INET, $port, $hostaddr))) 
		{
		    shutdown (S, 2);
		    exit 0;
		}
	    shutdown (S, 2);
	    exit 1;
	} elsif ($! =~ /No more process/) {
	    # EAGAIN
	    sleep 5;
	    redo FORK;
	} else {
	    # weird fork error
	    die "Can't fork: $!\n";
	}
    }
}
