Project

General

Profile

Bug #2133 ยป x.pl

tpchin, 09/20/2011 12:01 PM

 
#!/usr/bin/env perl -Tw
use strict;
use Socket;
use Carp;

sub spawn; # forward declaration
sub logmsg { print STDERR "$0 $$: @_ at ", scalar localtime(), "\n" }

my $port = 3128;
die "invalid port" unless $port =~ /^ \d+ $/x;

my $proto = getprotobyname("tcp");

socket(Server, PF_INET, SOCK_STREAM, $proto) || die "socket: $!";
setsockopt(Server, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) || die "setsockopt: $!";
bind(Server, sockaddr_in($port, INADDR_ANY)) || die "bind: $!";
listen(Server, SOMAXCONN) || die "listen: $!";

logmsg "server started on port $port";

my $paddr;

use POSIX ":sys_wait_h";
use Errno;

sub REAPER {
local $!;
while ((my $pid = waitpid(-1, WNOHANG)) > 0 && WIFEXITED($?)) {
logmsg "reaped $pid" . ($? ? " with exit $?" : "");
}
$SIG{CHLD} = \&REAPER;
}

$SIG{CHLD} = \&REAPER;

for (;;) {
$paddr = accept(Client, Server) || do {
next if $!{EINTR};
die "accept: $!";
};
my ($port, $iaddr) = sockaddr_in($paddr);
my $name = gethostbyaddr($iaddr, AF_INET);

logmsg "connection from $name [", inet_ntoa($iaddr), "] at port $port";

spawn sub { $| = 1; while (<>) { print; print STDERR $_; } };
close Client;
}

sub spawn {
my $coderef = shift;
confess "usage: spawn CODEREF" unless @_ == 0 && $coderef && ref($coderef) eq "CODE";

my $pid;
unless (defined($pid = fork())) {
logmsg "cannot fork: $!";
return;
}
if ($pid) {
logmsg "begat $pid";
return;
}

open(STDIN, "<&Client") || die "can't dup client to stdin";
open(STDOUT, ">&Client") || die "can't dup client to stdout";
exit($coderef->());
}
    (1-1/1)