Skip to content
Snippets Groups Projects
runtests.pl 94.6 KiB
Newer Older
  • Learn to ignore specific revisions
  • Daniel Stenberg's avatar
    Daniel Stenberg committed
    #!/usr/bin/env perl
    
    #***************************************************************************
    #                                  _   _ ____  _
    #  Project                     ___| | | |  _ \| |
    #                             / __| | | | |_) | |
    #                            | (__| |_| |  _ <| |___
    
    #                             \___|\___/|_| \_\_____|
    #
    
    # Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
    
    # This software is licensed as described in the file COPYING, which
    # you should have received as part of this distribution. The terms
    # are also available at http://curl.haxx.se/docs/copyright.html.
    
    # You may opt to use, copy, modify, merge, publish, distribute and/or sell
    # copies of the Software, and permit persons to whom the Software is
    
    # furnished to do so, under the terms of the COPYING file.
    
    # This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
    # KIND, either express or implied.
    #
    # $Id$
    
    ###########################################################################
    
    
    # Experimental hooks are available to run tests remotely on machines that
    # are able to run curl but are unable to run the test harness.  
    # The following sections need to be modified:
    
    #  $HOSTIP, $HOST6IP - Set to the address of the host running the test suite
    #  $CLIENTIP, $CLIENT6IP - Set to the address of the host running curl
    
    #  runclient, runclientoutput - Modify to copy all the files in the log/
    #    directory to the system running curl, run the given command remotely
    #    and save the return code or returned stdout (respectively), then
    #    copy all the files from the remote system's log/ directory back to
    #    the host running the test suite.  This can be done a few ways, such
    #    as using scp & ssh, rsync & telnet, or using a NFS shared directory
    #    and ssh.
    #
    # 'make && make test' needs to be done on both machines before making the
    # above changes and running runtests.pl manually.  In the shared NFS case,
    # the contents of the tests/server/ directory must be from the host
    # running the test suite, while the rest must be from the host running curl.
    #
    # Note that even with these changes a number of tests will still fail (mainly
    # to do with cookies, those that set environment variables, or those that
    # do more than touch the file system in a <precheck> or <postcheck>
    # section). These can be added to the $TESTCASES line below,
    
    # e.g. $TESTCASES="!8 !31 !63 !cookies..."
    
    #
    # Finally, to properly support -g and -n, checktestcmd needs to change
    # to check the remote system's PATH, and the places in the code where
    # the curl binary is read directly to determine its type also need to be
    # fixed. As long as the -g option is never given, and the -n is always
    # given, this won't be a problem.
    
    # These should be the only variables that might be needed to get edited:
    
    
    BEGIN {
        @INC=(@INC, $ENV{'srcdir'}, ".");
    
        if($] > 5.006) {
            use Time::HiRes qw(time);
        }
    
    # Variables and subs imported from sshhelp module
    use sshhelp qw(
    
    require "getpart.pm"; # array functions
    
    require "valgrind.pm"; # valgrind report parser
    
    my $HOSTIP="127.0.0.1";   # address on which the test server listens
    my $HOST6IP="[::1]";      # address on which the test server listens
    my $CLIENTIP="127.0.0.1"; # address which curl uses for incoming connections
    my $CLIENT6IP="[::1]";    # address which curl uses for incoming connections
    
    
    my $base = 8990; # base port number
    
    my $HTTPPORT; # HTTP server port
    
    my $HTTP6PORT; # HTTP IPv6 server port
    
    my $HTTPSPORT; # HTTPS server port
    my $FTPPORT; # FTP server port
    
    my $TFTPPORT; # TFTP
    my $TFTP6PORT; # TFTP
    
    my $POP3PORT; # POP3
    my $IMAPPORT; # IMAP
    my $SMTPPORT; # SMTP
    
    my $srcdir = $ENV{'srcdir'} || '.';
    
    my $CURL="../src/curl"; # what curl executable to run on the tests
    
    my $VCURL=$CURL;   # what curl binary to use to verify the servers with
                       # VCURL is handy to set to the system one when the one you
                       # just built hangs or crashes and thus prevent verification
    
    my $DBGCURL=$CURL; #"../src/.libs/curl";  # alternative for debugging
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    my $LOGDIR="log";
    
    my $LIBDIR="./libtest";
    
    my $SERVERIN="$LOGDIR/server.input"; # what curl sent the server
    
    my $SERVER2IN="$LOGDIR/server2.input"; # what curl sent the second server
    
    my $CURLLOG="$LOGDIR/curl.log"; # all command lines run
    
    my $FTPDCMD="$LOGDIR/ftpserver.cmd"; # copy ftp server instructions here
    
    my $SERVERLOGS_LOCK="$LOGDIR/serverlogs.lock"; # server logs advisor read lock
    
    
    # Normally, all test cases should be run, but at times it is handy to
    # simply run a particular one:
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    my $TESTCASES="all";
    
    
    # To run specific test cases, set them like:
    # $TESTCASES="1 2 3 7 8";
    
    #######################################################################
    # No variables below this point should need to be modified
    #
    
    
    my $HTTP6PIDFILE=".http6.pid";
    
    my $HTTPSPIDFILE=".https.pid";
    
    my $TFTPPIDFILE=".tftpd.pid";
    my $TFTP6PIDFILE=".tftp6.pid";
    
    my $POP3PIDFILE=".pop3.pid";
    my $IMAPPIDFILE=".imap.pid";
    my $SMTPPIDFILE=".smtp.pid";
    
    # invoke perl like this:
    my $perl="perl -I$srcdir";
    
    my $debug_build=0; # curl built with --enable-debug
    my $curl_debug=0;  # curl built with --enable-curldebug (memory tracking)
    
    # name of the file that the memory debugging creates:
    
    
    # the path to the script that analyzes the memory debug output file:
    
    my $memanalyze="$perl $srcdir/memanalyze.pl";
    
    my $pwd = getcwd();          # current working directory
    
    my $ftpchecktime; # time it took to verify our test FTP server
    
    my $stunnel = checkcmd("stunnel4") || checkcmd("stunnel");
    my $valgrind = checktestcmd("valgrind");
    my $valgrind_logfile="--logfile";
    
    my $gdb = checktestcmd("gdb");
    
    my $ssl_version; # set if libcurl is built with SSL support
    
    my $large_file;  # set if libcurl is built with large file support
    
    my $has_idn;     # set if libcurl is built with IDN support
    
    my $http_ipv6;   # set if HTTP server has IPv6 support
    
    my $ftp_ipv6;    # set if FTP server has IPv6 support
    
    my $tftp_ipv6;   # set if TFTP server has IPv6 support
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    my $has_ipv6;    # set if libcurl is built with IPv6 support
    
    my $has_libz;    # set if libcurl is built with libz support
    
    my $has_getrlimit;  # set if system has getrlimit()
    
    my $has_ntlm;    # set if libcurl is built with NTLM support
    
    my $has_charconv;# set if libcurl is built with CharConv support
    
    
    my $has_openssl; # built with a lib using an OpenSSL-like API
    my $has_gnutls;  # built with GnuTLS
    my $has_nss;     # built with NSS
    my $has_yassl;   # built with yassl
    
    my $ssllib;      # name of the lib we use (for human presentation)
    
    my $has_crypto;  # set if libcurl is built with cryptographic support
    
    my $has_textaware; # set if running on a system that has a text mode concept
      # on files. Windows for example
    
    my @protocols;   # array of supported protocols
    
    my $skipped=0;  # number of tests skipped; reported in main loop
    
    my %skipped;    # skipped{reason}=counter, reasons for skip
    my @teststat;   # teststat[testnum]=reason, reasons for skip
    
    my %disabled_keywords;	# key words of tests to skip
    
    my %enabled_keywords;	# key words of tests to run
    
    my $sshdid;      # for socks server, ssh daemon version id
    my $sshdvernum;  # for socks server, ssh daemon version number
    my $sshdverstr;  # for socks server, ssh daemon version string
    my $sshderror;   # for socks server, ssh daemon version error
    
    my $defserverlogslocktimeout = 20; # timeout to await server logs lock removal
    my $defpostcommanddelay = 0; # delay between command and postcheck sections
    
    my $timestats=1; # time stamping and stats generation
    my %timetoolini; # timestamp for each test command run starting
    my %timetoolend; # timestamp for each test command run stopping
    my %timesrvrlog; # timestamp for each test server logs lock removal
    
    
    my $testnumcheck; # test number, set in singletest sub.
    
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #######################################################################
    # variables the command line options may set
    #
    
    my $short;
    my $verbose;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    my $anyway;
    
    my $gdbthis;      # run test case with gdb debugger
    my $keepoutfiles; # keep stdout and stderr files after tests
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    my $listonly;     # only list the tests
    
    my $postmortem;   # display detailed info about failed tests
    
    my %run;          # running server
    my %doesntrun;    # servers that don't work, identified by pidfile
    
    # torture test variables
    my $torture;
    my $tortnum;
    my $tortalloc;
    
    
    #######################################################################
    # logmsg is our general message logging subroutine.
    #
    
            print "$_";
    
    # perl newer than 5.6 required for time stamping and stats generation
    if(($] > 5.006) && $timestats) {
        keys(%timetoolini) = 1000;
        keys(%timetoolend) = 1000;
        keys(%timesrvrlog) = 1000;
    }
    else {
        $timestats = 0;
    }
    
    
    # get the name of the current user
    my $USER = $ENV{USER};	# Linux
    if (!$USER) {
        $USER = $ENV{USERNAME};	# Windows
        if (!$USER) {
            $USER = $ENV{LOGNAME};	# Some UNIX (I think)
        }
    }
    
    
    # enable memory debugging if curl is compiled with it
    
    sub catch_zap {
        my $signame = shift;
    
        logmsg "runtests.pl received SIG$signame, exiting\n";
    
        stopservers($verbose);
    
        die "Somebody sent me a SIG$signame";
    }
    $SIG{INT} = \&catch_zap;
    $SIG{KILL} = \&catch_zap;
    
    
    ##########################################################################
    # Clear all possible '*_proxy' environment variables for various protocols
    # to prevent them to interfere with our testing!
    
    my $protocol;
    
    foreach $protocol (('ftp', 'http', 'ftps', 'https', 'no')) {
    
        my $proxy = "${protocol}_proxy";
        # clear lowercase version
        $ENV{$proxy}=undef;
        # clear uppercase version
        $ENV{uc($proxy)}=undef;
    }
    
    
    # make sure we don't get affected by other variables that control our
    # behaviour
    
    $ENV{'SSL_CERT_DIR'}=undef;
    $ENV{'SSL_CERT_PATH'}=undef;
    $ENV{'CURL_CA_BUNDLE'}=undef;
    
    
    #######################################################################
    # Check if a given child process has just died. Reaps it if so.
    #
    sub checkdied {
        use POSIX ":sys_wait_h";
        my $pid = $_[0];
    
        if(not defined $pid || $pid <= 0) {
            return 0;
        }
    
        my $rc = waitpid($pid, &WNOHANG);
    
        return ($rc == $pid)?1:0;
    
    #######################################################################
    # Start a new thread/process and run the given command line in there.
    
    # Return the pids (yes plural) of the new child process to the parent.
    
        my ($cmd, $pidfile, $timeout, $fake)=@_;
    
        logmsg "startnew: $cmd\n" if ($verbose);
    
            logmsg "startnew: fork() failure detected\n";
    
            return (-1,-1);
    
            # Here we are the child. Run the given command.
    
            # Put an "exec" in front of the command so that the child process
            # keeps this child's process ID.
            exec("exec $cmd") || die "Can't exec() $cmd: $!";
    
            # exec() should never return back here to this process. We protect
    
            # ourselves by calling die() just in case something goes really bad.
    
            die "error: exec() has returned";
    
        # Ugly hack but ssh client doesn't support pid files
    
            if(open(OUT, ">$pidfile")) {
                print OUT $child . "\n";
                close(OUT);
                logmsg "startnew: $pidfile faked with pid=$child\n" if($verbose);
            }
            else {
                logmsg "startnew: failed to write fake $pidfile with pid=$child\n";
            }
            # could/should do a while connect fails sleep a bit and loop
    
            if (checkdied($child)) {
    
                logmsg "startnew: child process has failed to start\n" if($verbose);
    
        while($count--) {
    
            if(-f $pidfile && -s $pidfile && open(PID, "<$pidfile")) {
    
                $pid2 = 0 + <PID>;
                close(PID);
    
                if(($pid2 > 0) && kill(0, $pid2)) {
    
                    # if $pid2 is valid, then make sure this pid is alive, as
                    # otherwise it is just likely to be the _previous_ pidfile or
                    # similar!
                    last;
                }
    
                # invalidate $pid2 if not actually alive
                $pid2 = 0;
    
                logmsg "startnew: child process has died, server might start up\n"
                    if($verbose);
    
                # We can't just abort waiting for the server with a
                # return (-1,-1);
                # because the server might have forked and could still start
                # up normally. Instead, just reduce the amount of time we remain
                # waiting.
                $count >>= 2;
            }
    
        # Return two PIDs, the one for the child process we spawned and the one
        # reported by the server itself (in case it forked again on its own).
        # Both (potentially) need to be killed at the end of the test.
    
        return ($child, $pid2);
    
    #######################################################################
    
    # Check for a command in the PATH of the test server.
    
        my @paths=(split(":", $ENV{'PATH'}), "/usr/sbin", "/usr/local/sbin",
    
                   "/sbin", "/usr/bin", "/usr/local/bin" );
    
            if( -x "$_/$cmd" && ! -d "$_/$cmd") {
                # executable bit but not a directory!
    
    #######################################################################
    # Check for a command in the PATH of the machine running curl.
    #
    sub checktestcmd {
        my ($cmd)=@_;
        return checkcmd($cmd);
    }
    
    #######################################################################
    
    # Run the application under test and return its return code
    
        my ($cmd)=@_;
        return system($cmd);
    
    
    # This is one way to test curl on a remote machine
    #    my $out = system("ssh $CLIENTIP cd \'$pwd\' \\; \'$cmd\'");
    #    sleep 2;	# time to allow the NFS server to be updated
    #    return $out;
    
    #######################################################################
    # Run the application under test and return its stdout
    #
    sub runclientoutput {
        my ($cmd)=@_;
        return `$cmd`;
    
    # This is one way to test curl on a remote machine
    #    my @out = `ssh $CLIENTIP cd \'$pwd\' \\; \'$cmd\'`;
    #    sleep 2;	# time to allow the NFS server to be updated
    #    return @out;
     }
    
    
    #######################################################################
    # Memory allocation test and failure torture testing.
    #
    sub torture {
    
        my $testcmd = shift;
        my $gdbline = shift;
    
        # remove memdump first to be sure we get a new nice and clean one
        unlink($memdump);
    
        # First get URL from test server, ignore the output/result
    
        logmsg " CMD: $testcmd\n" if($verbose);
    
        # memanalyze -v is our friend, get the number of allocations made
    
        my @out = `$memanalyze -v $memdump`;
        for(@out) {
            if(/^Allocations: (\d+)/) {
                $count = $1;
                last;
    
            logmsg " found no allocs to make fail\n";
    
        logmsg " $count allocations to make fail\n";
    
        for ( 1 .. $count ) {
            my $limit = $_;
            my $fail;
            my $dumped_core;
    
            if($tortalloc && ($tortalloc != $limit)) {
    
            logmsg "Fail alloc no: $limit @ " . strftime ("%H:%M:%S", localtime) . "\r" if($verbose);
    
            # make the memory allocation function number $limit return failure
            $ENV{'CURL_MEMLIMIT'} = $limit;
    
            # remove memdump first to be sure we get a new nice and clean one
            unlink($memdump);
    
            logmsg "**> Alloc number $limit is now set to fail <**\n" if($gdbthis);
    
                $ret = runclient($testcmd);
    
            #logmsg "$_ Returned " . $ret / 256 . "\n";
    
            # Now clear the variable again
            $ENV{'CURL_MEMLIMIT'} = undef;
    
    
            if(-r "core") {
                # there's core file present now!
    
                $dumped_core = 1;
                $fail = 2;
            }
    
            # verify that it returns a proper error code, doesn't leak memory
            # and doesn't core dump
            if($ret & 255) {
    
                logmsg " system() returned $ret\n";
    
                $fail=1;
            }
            else {
                my @memdata=`$memanalyze $memdump`;
                my $leak=0;
                for(@memdata) {
                    if($_ ne "") {
                        # well it could be other memory problems as well, but
                        # we call it leak for short here
                        $leak=1;
    
                    logmsg "** MEMORY FAILURE\n";
                    logmsg @memdata;
                    logmsg `$memanalyze -l $memdump`;
    
                logmsg " Failed on alloc number $limit in test.\n",
    
                " invoke with -t$limit to repeat this single case.\n";
    
                stopservers($verbose);
    
        logmsg "torture OK\n";
    
    #######################################################################
    
    # stop the given test server (pid)
    
    sub stopserver {
    
        my ($pidlist) = @_;
    
        killpid($verbose, $pidlist);
    
    #######################################################################
    # Verify that the server that runs on $ip, $port is our server.  This also
    # implies that we can speak with it, as there might be occasions when the
    # server runs fine but we cannot talk to it ("Failed to connect to ::1: Can't
    # assign requested address" #
    
    sub verifyhttp {
        my ($proto, $ip, $port) = @_;
    
        my $cmd = "$VCURL --max-time $server_response_maxtime --output $LOGDIR/verifiedserver --insecure --silent --verbose --globoff \"$proto://$ip:$port/verifiedserver\" 2>$LOGDIR/verifyhttp";
    
        my $pid;
    
        # verify if our/any server is running on this port
    
        logmsg "CMD; $cmd\n" if ($verbose);
    
        my $res = runclient($cmd);
    
    
        $res >>= 8; # rotate the result
        my $data;
    
        if($res && $verbose) {
    
            open(ERR, "<$LOGDIR/verifyhttp");
    
            logmsg "RUN: curl command returned $res\n";
    
        open(FILE, "<$LOGDIR/verifiedserver");
    
        my @file=<FILE>;
        close(FILE);
    
        $data=$file[0]; # first line
    
        if ( $data =~ /WE ROOLZ: (\d+)/ ) {
            $pid = 0+$1;
        }
        elsif($res == 6) {
            # curl: (6) Couldn't resolve host '::1'
    
            logmsg "RUN: failed to resolve host ($proto://$ip:$port/verifiedserver)\n";
            return -1;
    
            logmsg "RUN: Unknown server is running on port $port\n";
    
        }
        return $pid;
    }
    
    #######################################################################
    # Verify that the server that runs on $ip, $port is our server.  This also
    # implies that we can speak with it, as there might be occasions when the
    # server runs fine but we cannot talk to it ("Failed to connect to ::1: Can't
    # assign requested address" #
    
    sub verifyftp {
        my ($proto, $ip, $port) = @_;
        my $pid;
        my $time=time();
    
        	$extra = "--insecure --ftp-ssl-control ";
    
        my $cmd="$VCURL --max-time $server_response_maxtime --silent --verbose --globoff $extra\"$proto://$ip:$port/verifiedserver\" 2>$LOGDIR/verifyftp";
    
        # check if this is our server running on this port:
    
        my @data=runclientoutput($cmd);
    
        logmsg "RUN: $cmd\n" if($verbose);
    
        my $line;
    
        foreach $line (@data) {
            if ( $line =~ /WE ROOLZ: (\d+)/ ) {
                # this is our test server with a known pid!
                $pid = 0+$1;
                last;
            }
        }
        if($pid <= 0 && $data[0]) {
            # this is not a known server
    
            logmsg "RUN: Unknown server on our ". uc($proto) ." port: $port\n";
    
        # we can/should use the time it took to verify the FTP server as a measure
        # on how fast/slow this host/FTP is.
        my $took = time()-$time;
    
        if($verbose) {
    
            logmsg "RUN: Verifying our test ". uc($proto) .
                   " server took $took seconds\n";
    
        }
        $ftpchecktime = $took?$took:1; # make sure it never is zero
    
    
    #######################################################################
    
    # Verify that the ssh server has written out its pidfile, recovering
    # the pid from the file and returning it if a process with that pid is
    # actually alive.
    
    
    sub verifyssh {
        my ($proto, $ip, $port) = @_;
    
        if(open(FILE, "<$SSHPIDFILE")) {
            $pid=0+<FILE>;
            close(FILE);
        }
    
        if($pid > 0) {
            # if we have a pid it is actually our ssh server,
            # since runsshserver() unlinks previous pidfile
    
    Yang Tse's avatar
    Yang Tse committed
            if(!kill(0, $pid)) {
    
                logmsg "RUN: SSH server has died after starting up\n";
    
    Yang Tse's avatar
    Yang Tse committed
                checkdied($pid);
    
    #######################################################################
    # Verify that we can connect to the sftp server, properly authenticate
    # with generated config and key files and run a simple remote pwd.
    
    sub verifysftp {
        my ($proto, $ip, $port) = @_;
        my $verified = 0;
        # Find out sftp client canonical file name
        my $sftp = find_sftp();
        if(!$sftp) {
            logmsg "RUN: SFTP server cannot find $sftpexe\n";
            return -1;
        }
    
        # Find out ssh client canonical file name
        my $ssh = find_ssh();
        if(!$ssh) {
            logmsg "RUN: SFTP server cannot find $sshexe\n";
            return -1;
        }
    
        # Connect to sftp server, authenticate and run a remote pwd
        # command using our generated configuration and key files
    
        my $cmd = "$sftp -b $sftpcmds -F $sftpconfig -S $ssh $ip > $sftplog 2>&1";
    
        my $res = runclient($cmd);
        # Search for pwd command response in log file
        if(open(SFTPLOGFILE, "<$sftplog")) {
            while(<SFTPLOGFILE>) {
                if(/^Remote working directory: /) {
                    $verified = 1;
                    last;
                }
            }
            close(SFTPLOGFILE);
        }
        return $verified;
    }
    
    
    
    #######################################################################
    # STUB for verifying socks
    
    sub verifysocks {
        my ($proto, $ip, $port) = @_;
    
        my $pid = 0;
        if(open(FILE, "<$SOCKSPIDFILE")) {
            $pid=0+<FILE>;
            close(FILE);
        }
        if($pid > 0) {
            # if we have a pid it is actually our socks server,
            # since runsocksserver() unlinks previous pidfile
    
    Yang Tse's avatar
    Yang Tse committed
            if(!kill(0, $pid)) {
    
                logmsg "RUN: SOCKS server has died after starting up\n";
    
    Yang Tse's avatar
    Yang Tse committed
                checkdied($pid);
    
    #######################################################################
    # Verify that the server that runs on $ip, $port is our server.
    
    # Retry over several seconds before giving up.  The ssh server in
    # particular can take a long time to start if it needs to generate
    # keys on a slow or loaded host.
    
    #
    
    my %protofunc = ('http' => \&verifyhttp,
                     'https' => \&verifyhttp,
    
                     'ftp' => \&verifyftp,
    
                     'pop3' => \&verifyftp,
                     'imap' => \&verifyftp,
                     'smtp' => \&verifyftp,
    
                     'ssh' => \&verifyssh,
                     'socks' => \&verifysocks);
    
        my $count = 30; # try for this many seconds
    
        my $pid;
    
        while($count--) {
            my $fun = $protofunc{$proto};
    
            $pid = &$fun($proto, $ip, $port);
    
    
            elsif($pid < 0) {
                # a real failure, stop trying and bail out
                return 0;
            }
    
    #######################################################################
    
    # start the http server
    
    #
    sub runhttpserver {
    
        my ($verbose, $ipv6) = @_;
    
        my $RUNNING;
    
        my $pidfile = $HTTPPIDFILE;
        my $port = $HTTPPORT;
        my $ip = $HOSTIP;
        my $nameext;
    
    
        if($ipv6) {
            # if IPv6, use a different setup
            $pidfile = $HTTP6PIDFILE;
            $port = $HTTP6PORT;
            $ip = $HOST6IP;
            $nameext="-ipv6";
        }
    
    
        # don't retry if the server doesn't work
        if ($doesntrun{$pidfile}) {
            return (0,0);
        }
    
    
    Yang Tse's avatar
     
    Yang Tse committed
        my $pid = processexists($pidfile);
    
        if($pid > 0) {
            stopserver($pid);
        }
    
        my $dir=$ENV{'srcdir'};
        if($dir) {
            $flag .= "-d \"$dir\" ";
        }
    
        my $cmd="$perl $srcdir/httpserver.pl -p $pidfile $fork$flag $port $ipv6";
    
        my ($httppid, $pid2) =
    
            startnew($cmd, $pidfile, 15, 0); # start the server in a new process
    
        if($httppid <= 0 || !kill(0, $httppid)) {
    
            logmsg "RUN: failed to start the HTTP$nameext server\n";
    
            return (0,0);
    
        # Server is up. Verify that we can speak to it.
    
        my $pid3 = verifyserver("http", $ip, $port);
        if(!$pid3) {
    
            logmsg "RUN: HTTP$nameext server failed verification\n";
            # failed to talk to it properly. Kill the server and return failure
            stopserver("$httppid $pid2");
    
            return (0,0);
    
            logmsg "RUN: HTTP$nameext server is now running PID $httppid\n";
    
        return ($httppid, $pid2);
    
    #######################################################################
    
    # start the https server (or rather, tunnel)
    
    #
    sub runhttpsserver {
    
        my $STATUS;
        my $RUNNING;
    
        # don't retry if the server doesn't work
        if ($doesntrun{$pidfile}) {
            return (0,0);
        }
    
    
    Yang Tse's avatar
     
    Yang Tse committed
        my $pid = processexists($pidfile);
    
        if($pid > 0) {
            # kill previous stunnel!
            stopserver($pid);
        }
    
    
        my $flag=$debugprotocol?"-v ":"";
    
        my $cmd="$perl $srcdir/httpsserver.pl $flag -p https -s \"$stunnel\" -d $srcdir -r $HTTPPORT $HTTPSPORT";
    
        my ($httpspid, $pid2) = startnew($cmd, $pidfile, 15, 0);
    
        if($httpspid <= 0 || !kill(0, $httpspid)) {
    
            logmsg "RUN: failed to start the HTTPS server\n";
    
            stopservers($verbose);
    
            return(0,0);
    
        # Server is up. Verify that we can speak to it.
    
        my $pid3 = verifyserver("https", $ip, $HTTPSPORT);
        if(!$pid3) {
    
            logmsg "RUN: HTTPS server failed verification\n";
            # failed to talk to it properly. Kill the server and return failure
            stopserver("$httpspid $pid2");
    
            return (0,0);
    
        # Here pid3 is actually the pid returned by the unsecure-http server.
    
            logmsg "RUN: HTTPS server is now running PID $httpspid\n";
    
        return ($httpspid, $pid2);
    
    }
    
    #######################################################################
    
    # start the pingpong server (FTP, POP3, IMAP, SMTP)
    
    sub runpingpongserver {
        my ($proto, $id, $verbose, $ipv6) = @_;
    
        my $STATUS;
        my $RUNNING;
    
        if($proto eq "ftp") {
            $port = $id?$FTP2PORT:$FTPPORT;
            $pidfile = $id?$FTP2PIDFILE:$FTPPIDFILE;
    
            if($ipv6) {
                # if IPv6, use a different setup
                $pidfile = $FTP6PIDFILE;
                $port = $FTP6PORT;
                $ip = $HOST6IP;
                $nameext="-ipv6";
            }
        }
        elsif($proto eq "pop3") {
            $port = $POP3PORT;
            $pidfile = $POP3PIDFILE;
        }
        elsif($proto eq "imap") {
            $port = $IMAPPORT;
            $pidfile = $IMAPPIDFILE;
    
        elsif($proto eq "smtp") {
            $port = $SMTPPORT;
            $pidfile = $SMTPPIDFILE;
        }
        else {
            print STDERR "Unsupported protocol $proto!!\n";
            return 0;
        }
        $flag .= "--proto $proto ";
    
        # don't retry if the server doesn't work
        if ($doesntrun{$pidfile}) {
            return (0,0);
        }
    
    
    Yang Tse's avatar
     
    Yang Tse committed
        my $pid = processexists($pidfile);
    
            stopserver($pid);
        }
    
        $flag .= $debugprotocol?"-v ":"";
    
            $addr = $HOST6IP;
        } else {
            $addr = $HOSTIP;
    
        $cmd="$perl $srcdir/ftpserver.pl --pidfile $pidfile $flag --port $port --addr \"$addr\"";
    
        my ($ftppid, $pid2) = startnew($cmd, $pidfile, 15, 0);
    
        if($ftppid <= 0 || !kill(0, $ftppid)) {