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

require 'sys/socket.ph';
require 'sys/un.ph';
require 'sys/file.ph';
require 'fcntl.ph';

# global variables

%clients = ();
$clientno = 0;

sub fhbits 
{
    local ($bits);
    
    while (($key, $value) = each (%clients))
    {
	vec ($bits, fileno ($key), 1) = 1;
    }
    $bits;
}

sub check_clients
{
    local ($rin) = '';
    local ($rout) = '';
    local ($win) = '';
    local ($wout) = '';
    local ($buf) = '';
    
    $rin = &fhbits ();
    
    local ($nfound, $timeout) =
	select ($rout=$rin, undef, undef, undef);
    
    while (($client, $number) = each (%clients))
    {
	if (vec ($rout, fileno ($client), 1))
	{
	    local ($nbytes) = read ($client, $buf, 4096);
	    defined ($nbytes) || die "read $!";
	    if ($nbytes == 0)
	    {
		print STDERR "EOF on client $number\n";
		delete $clients{$client};
#		close $client;
	    }
	    else 
	    {
		print "$number: ";
		print $buf;
		print $client "Hello\015\012" || warn $!;
	    }
	}
    }
}

sub sigio_handler
{
    do check_clients ();
}

sub new_connection
{
    ++$fh;
#    print "checking for new connections...\n";
    if (accept ($fh, S))
    {
	$clients{$fh} = ++$clientno;

	print "Connection #$clientno accepted.\n";

	$SIG{'IO'} = 'sigio_handler';
	
	fcntl ($fh, &F_SETOWN, $$)
	    || die "fnctl: $!";
	
	fcntl ($fh, &F_SETFL, &FASYNC)
	    || die "fnctl: $!";
	
    }
    else
    {
	die $! if $! !~ /Interrupted system call/;
    }
}

$port = 2345;

chop ($hostname = `hostname`);

$sockaddr_in = 'S n a4 x8';

$this = pack ($sockaddr_in, &AF_INET, $port, "\0\0\0\0");

select (NS); $! = 1; select (STDOUT);

socket (S, &AF_INET, &SOCK_STREAM, 0) || die "socket: $!";

bind (S, $this) || die "bind: $!";

listen (S, 5) || die "listen: $!";

while (1)  	
{
    &new_connection ();
}
