#!/usr/bin/perl use strict; use Socket; use Carp; my $EOL = "\015\012"; sub spawn; # forward declaration my $port = shift || 2345; my $proto = getprotobyname('tcp'); $port = $1 if $port =~ /(\d+)/; # untaint port number 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: $!"; my $waitedpid = 0; my $paddr; sub REAPER { $waitedpid = wait; $SIG{CHLD} = \&REAPER; # loathe sysV } $SIG{CHLD} = \&REAPER; for ( $waitedpid = 0; ($paddr = accept(Client,Server)) || $waitedpid; $waitedpid = 0, close Client) { next if $waitedpid and not $paddr; my($port,$iaddr) = sockaddr_in($paddr); my $name = gethostbyaddr($iaddr,AF_INET); spawn sub { # start my $cmd = ""; my $line; while ((defined($line = )) && (($cmd .= $line) !~ /\n[\t\s]*\n/s)) { } my ($remote,$port, $iaddr, $paddr, $proto, $line); ($remote) = ($cmd =~ /http:\/\/(.*?)\//s); if ($remote =~ /^(.*):(.*?)$/) { $remote = $1; $port = $2; } else { $port = 80; } if ($port =~ /\D/) { $port = getservbyname($port, 'tcp') } die "No port" unless $port; $iaddr = inet_aton($remote) || die "no host: $remote"; $paddr = sockaddr_in($port, $iaddr); $proto = getprotobyname('tcp'); socket(SOCK, PF_INET, SOCK_STREAM, $proto) || die "socket: $!"; connect(SOCK, $paddr) || die "connect: $!"; send(SOCK,"$cmd\n",0); while (defined($line = )) { send(Client,$line,0); } close (SOCK) || die "close: $!"; # end }; } sub spawn { my $coderef = shift; unless (@_ == 0 && $coderef && ref($coderef) eq 'CODE') { confess "usage: spawn CODEREF"; } my $pid; if (!defined($pid = fork)) { print "cannot fork: $!"; return; } elsif ($pid) { return; # I'm the parent } # else I'm the child -- go spawn exit &$coderef(); }