#!/usr/bin/perl -Tw require 5.003; use strict; BEGIN { $ENV{PATH} = '/usr/ucb:/bin' } use Socket; use Carp; sub spawn; # forward declaration sub logmsg { print "$0 $$: @_ at ", scalar localtime, "\n" } my $port = shift || 2345; my $proto = getprotobyname('tcp'); socket(Server, PF_INET, SOCK_STREAM, $proto) or die "socket: $!"; setsockopt(Server, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) or die "setsockopt: $!"; bind(Server, sockaddr_in($port, INADDR_ANY)) or die "bind: $!"; listen(Server,SOMAXCONN) or die "listen: $!"; logmsg "server started on port $port"; my $waitedpid = 0; my $paddr; sub REAPER { $SIG{CHLD} = \&REAPER; # if you don't have sigaction(2) $waitedpid = wait; logmsg "reaped $waitedpid" . ($? ? " with exit $?" : ''); } $SIG{CHLD} = \&REAPER; for ( ; $paddr = accept(Client,Server); close Client) { my($port,$iaddr) = sockaddr_in($paddr); my $name = gethostbyaddr($iaddr,AF_INET); logmsg "connection from $name [", inet_ntoa($iaddr), "] at port $port"; spawn sub { print "Hello there, $name, it's now ", scalar localtime, "\n"; exec '/usr/games/fortune' or confess "can't exec fortune: $!"; }; } sub spawn { my $coderef = shift; unless (@_ == 0 && $coderef && ref($coderef) eq 'CODE') { confess "usage: spawn CODEREF"; } my $pid; if (!defined($pid = fork)) { logmsg "cannot fork: $!"; return; } elsif ($pid) { logmsg "begat $pid"; return; # i'm the parent } # else i'm the child -- go spawn open(STDIN, "<&Client") or die "can't dup client to stdin"; open(STDOUT, ">&Client") or die "can't dup client to stdout"; ## open(STDERR, ">&STDOUT") or die "can't dup stdout to stderr"; exit &$coderef(); }