6 sub spawn; # forward declaration
7 sub logmsg { #print "$0 $$: @_ at ", scalar localtime, "\n"
11 my $proto = getprotobyname('tcp');
12 $port = $1 if $port =~ /(\d+)/; # untaint port number
14 if($ARGV[1] =~ /^ftp$/i) {
21 socket(Server, PF_INET, SOCK_STREAM, $proto)|| die "socket: $!";
22 setsockopt(Server, SOL_SOCKET, SO_REUSEADDR,
23 pack("l", 1)) || die "setsockopt: $!";
24 bind(Server, sockaddr_in($port, INADDR_ANY))|| die "bind: $!";
25 listen(Server,SOMAXCONN) || die "listen: $!";
27 print "$protocol server started on port $port\n";
29 open(PID, ">.server.pid");
38 $SIG{CHLD} = \&REAPER; # loathe sysV
39 logmsg "reaped $waitedpid" . ($? ? " with exit $?" : '');
42 # USER is ok in fresh state
43 %commandok = ( "USER" => "fresh",
48 %statechange = ( 'USER' => 'passwd', # USER goes to passwd state
49 'PASS' => 'loggedin', # PASS goes to loggedin state
52 %displaytext = ('USER' => '331 We are happy you popped in!', # output FTP line
53 'PASS' => '230 Welcome you silly person',
56 $SIG{CHLD} = \&REAPER;
59 ($paddr = accept(Client,Server)) || $waitedpid;
60 $waitedpid = 0, close Client)
62 next if $waitedpid and not $paddr;
63 my($port,$iaddr) = sockaddr_in($paddr);
64 my $name = gethostbyaddr($iaddr,AF_INET);
66 logmsg "connection from $name [", inet_ntoa($iaddr), "] at port $port";
68 # this code is forked and run
70 my ($request, $path, $ver, $left, $cl);
72 if($protocol eq "FTP") {
74 # < 220 pm1 FTP server (SunOS 5.7) ready.
76 # < 331 Guest login ok, send ident as password.
77 # > PASS curl_by_daniel@haxx.se
78 # < 230 Guest login ok, access restrictions apply.
79 # * We have successfully logged in
80 # * Connected to pm1 (193.15.23.1)
82 # < 227 Entering Passive Mode (193,15,23,1,231,59)
83 # * Connecting to pm1 (193.15.23.1) port 59195
85 # < 200 Type set to A.
87 # < 150 ASCII data connection for /bin/ls (193.15.23.1,59196) (0 bytes).
88 # * Getting file with size: -1
93 print "220-running the curl suite test server\r\n",
94 "220-running the curl suite test server\r\n",
95 "220 running the curl suite test server\r\n";
101 last unless defined ($_ = <STDIN>);
103 # Remove trailing CRLF.
106 unless (m/^([A-Z]{3,4})\s?(.*)/i)
109 "badly formed command received: ".$_;
115 print STDERR "GOT: ($1) $_\n";
117 $ok = $commandok{$FTPCMD};
118 if($ok !~ /$state/) {
119 print "314 $FTPCMD not OK ($ok) in state: $state!\r\n";
123 $state=$statechange{$FTPCMD};
125 print "314 Wwwwweeeeird internal error state: $state\r\n";
128 print STDERR "gone to state $state\n";
130 $text = $displaytext{$FTPCMD};
135 # otherwise, we're doing HTTP
138 if($_ =~ /([A-Z]*) (.*) HTTP\/1.(\d)/) {
143 elsif($_ =~ /^Content-Length: (\d*)/) {
152 $left = -1; # just to force a loop break here
155 # print STDERR "RCV ($left): $_";
158 ($_ eq "\r\n") or ($_ eq "")) {
159 if($request =~ /^(POST|PUT)$/) {
163 $left = -1; # force abort
171 if($path =~ /verifiedserver/) {
172 # this is a hard-coded query-string for the test script
173 # to verify that this is the server actually running!
174 print "HTTP/1.1 999 WE ROOLZ\r\n";
180 # we always start the path with a number, this is the
181 # test number that this server will use to know what
182 # contents to pass back to the client
184 if($path =~ /.*\/(\d*)/) {
188 print STDERR "UKNOWN TEST CASE\n";
191 open(INPUT, ">log/server.input");
197 # send a reply to the client
198 open(DATA, "<data/reply$testnum.txt");
204 # print "Hello there, $name, it's now ", scalar localtime, "\r\n";
213 unless (@_ == 0 && $coderef && ref($coderef) eq 'CODE') {
214 confess "usage: spawn CODEREF";
219 if (!defined($pid = fork)) {
220 logmsg "cannot fork: $!";
224 return; # I'm the parent
226 # else I'm the child -- go spawn
229 open(STDIN, "<&Client") || die "can't dup client to stdin";
230 open(STDOUT, ">&Client") || die "can't dup client to stdout";
231 ## open(STDERR, ">&STDOUT") || die "can't dup stdout to stderr";