Home | History | Annotate | Download | only in tests
      1 #!/usr/bin/env perl
      2 #***************************************************************************
      3 #                                  _   _ ____  _
      4 #  Project                     ___| | | |  _ \| |
      5 #                             / __| | | | |_) | |
      6 #                            | (__| |_| |  _ <| |___
      7 #                             \___|\___/|_| \_\_____|
      8 #
      9 # Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel (at] haxx.se>, et al.
     10 #
     11 # This software is licensed as described in the file COPYING, which
     12 # you should have received as part of this distribution. The terms
     13 # are also available at http://curl.haxx.se/docs/copyright.html.
     14 #
     15 # You may opt to use, copy, modify, merge, publish, distribute and/or sell
     16 # copies of the Software, and permit persons to whom the Software is
     17 # furnished to do so, under the terms of the COPYING file.
     18 #
     19 # This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     20 # KIND, either express or implied.
     21 #
     22 ###########################################################################
     23 
     24 # Experimental hooks are available to run tests remotely on machines that
     25 # are able to run curl but are unable to run the test harness.
     26 # The following sections need to be modified:
     27 #
     28 #  $HOSTIP, $HOST6IP - Set to the address of the host running the test suite
     29 #  $CLIENTIP, $CLIENT6IP - Set to the address of the host running curl
     30 #  runclient, runclientoutput - Modify to copy all the files in the log/
     31 #    directory to the system running curl, run the given command remotely
     32 #    and save the return code or returned stdout (respectively), then
     33 #    copy all the files from the remote system's log/ directory back to
     34 #    the host running the test suite.  This can be done a few ways, such
     35 #    as using scp & ssh, rsync & telnet, or using a NFS shared directory
     36 #    and ssh.
     37 #
     38 # 'make && make test' needs to be done on both machines before making the
     39 # above changes and running runtests.pl manually.  In the shared NFS case,
     40 # the contents of the tests/server/ directory must be from the host
     41 # running the test suite, while the rest must be from the host running curl.
     42 #
     43 # Note that even with these changes a number of tests will still fail (mainly
     44 # to do with cookies, those that set environment variables, or those that
     45 # do more than touch the file system in a <precheck> or <postcheck>
     46 # section). These can be added to the $TESTCASES line below,
     47 # e.g. $TESTCASES="!8 !31 !63 !cookies..."
     48 #
     49 # Finally, to properly support -g and -n, checktestcmd needs to change
     50 # to check the remote system's PATH, and the places in the code where
     51 # the curl binary is read directly to determine its type also need to be
     52 # fixed. As long as the -g option is never given, and the -n is always
     53 # given, this won't be a problem.
     54 
     55 
     56 # These should be the only variables that might be needed to get edited:
     57 
     58 BEGIN {
     59     push(@INC, $ENV{'srcdir'}) if(defined $ENV{'srcdir'});
     60     push(@INC, ".");
     61     # run time statistics needs Time::HiRes
     62     eval {
     63         no warnings "all";
     64         require Time::HiRes;
     65         import  Time::HiRes qw( time );
     66     }
     67 }
     68 
     69 use strict;
     70 use warnings;
     71 use Cwd;
     72 
     73 # Subs imported from serverhelp module
     74 use serverhelp qw(
     75     serverfactors
     76     servername_id
     77     servername_str
     78     servername_canon
     79     server_pidfilename
     80     server_logfilename
     81     );
     82 
     83 # Variables and subs imported from sshhelp module
     84 use sshhelp qw(
     85     $sshdexe
     86     $sshexe
     87     $sftpexe
     88     $sshconfig
     89     $sftpconfig
     90     $sshdlog
     91     $sshlog
     92     $sftplog
     93     $sftpcmds
     94     display_sshdconfig
     95     display_sshconfig
     96     display_sftpconfig
     97     display_sshdlog
     98     display_sshlog
     99     display_sftplog
    100     exe_ext
    101     find_sshd
    102     find_ssh
    103     find_sftp
    104     find_httptlssrv
    105     sshversioninfo
    106     );
    107 
    108 require "getpart.pm"; # array functions
    109 require "valgrind.pm"; # valgrind report parser
    110 require "ftp.pm";
    111 
    112 my $HOSTIP="127.0.0.1";   # address on which the test server listens
    113 my $HOST6IP="[::1]";      # address on which the test server listens
    114 my $CLIENTIP="127.0.0.1"; # address which curl uses for incoming connections
    115 my $CLIENT6IP="[::1]";    # address which curl uses for incoming connections
    116 
    117 my $base = 8990; # base port number
    118 
    119 my $HTTPPORT;            # HTTP server port
    120 my $HTTP6PORT;           # HTTP IPv6 server port
    121 my $HTTPSPORT;           # HTTPS (stunnel) server port
    122 my $FTPPORT;             # FTP server port
    123 my $FTP2PORT;            # FTP server 2 port
    124 my $FTPSPORT;            # FTPS (stunnel) server port
    125 my $FTP6PORT;            # FTP IPv6 server port
    126 my $TFTPPORT;            # TFTP
    127 my $TFTP6PORT;           # TFTP
    128 my $SSHPORT;             # SCP/SFTP
    129 my $SOCKSPORT;           # SOCKS4/5 port
    130 my $POP3PORT;            # POP3
    131 my $POP36PORT;           # POP3 IPv6 server port
    132 my $IMAPPORT;            # IMAP
    133 my $IMAP6PORT;           # IMAP IPv6 server port
    134 my $SMTPPORT;            # SMTP
    135 my $SMTP6PORT;           # SMTP IPv6 server port
    136 my $RTSPPORT;            # RTSP
    137 my $RTSP6PORT;           # RTSP IPv6 server port
    138 my $GOPHERPORT;          # Gopher
    139 my $GOPHER6PORT;         # Gopher IPv6 server port
    140 my $HTTPTLSPORT;         # HTTP TLS (non-stunnel) server port
    141 my $HTTPTLS6PORT;        # HTTP TLS (non-stunnel) IPv6 server port
    142 my $HTTPPROXYPORT;       # HTTP proxy port, when using CONNECT
    143 my $HTTPPIPEPORT;        # HTTP pipelining port
    144 my $HTTPUNIXPATH;        # HTTP server Unix domain socket path
    145 
    146 my $srcdir = $ENV{'srcdir'} || '.';
    147 my $CURL="../src/curl".exe_ext(); # what curl executable to run on the tests
    148 my $VCURL=$CURL;   # what curl binary to use to verify the servers with
    149                    # VCURL is handy to set to the system one when the one you
    150                    # just built hangs or crashes and thus prevent verification
    151 my $DBGCURL=$CURL; #"../src/.libs/curl";  # alternative for debugging
    152 my $LOGDIR="log";
    153 my $TESTDIR="$srcdir/data";
    154 my $LIBDIR="./libtest";
    155 my $UNITDIR="./unit";
    156 # TODO: change this to use server_inputfilename()
    157 my $SERVERIN="$LOGDIR/server.input"; # what curl sent the server
    158 my $SERVER2IN="$LOGDIR/server2.input"; # what curl sent the second server
    159 my $PROXYIN="$LOGDIR/proxy.input"; # what curl sent the proxy
    160 my $CURLLOG="$LOGDIR/curl.log"; # all command lines run
    161 my $FTPDCMD="$LOGDIR/ftpserver.cmd"; # copy ftp server instructions here
    162 my $SERVERLOGS_LOCK="$LOGDIR/serverlogs.lock"; # server logs advisor read lock
    163 my $CURLCONFIG="../curl-config"; # curl-config from current build
    164 
    165 # Normally, all test cases should be run, but at times it is handy to
    166 # simply run a particular one:
    167 my $TESTCASES="all";
    168 
    169 # To run specific test cases, set them like:
    170 # $TESTCASES="1 2 3 7 8";
    171 
    172 #######################################################################
    173 # No variables below this point should need to be modified
    174 #
    175 
    176 # invoke perl like this:
    177 my $perl="perl -I$srcdir";
    178 my $server_response_maxtime=13;
    179 
    180 my $debug_build=0;          # built debug enabled (--enable-debug)
    181 my $has_memory_tracking=0;  # built with memory tracking (--enable-curldebug)
    182 my $libtool;
    183 
    184 # name of the file that the memory debugging creates:
    185 my $memdump="$LOGDIR/memdump";
    186 
    187 # the path to the script that analyzes the memory debug output file:
    188 my $memanalyze="$perl $srcdir/memanalyze.pl";
    189 
    190 my $pwd = getcwd();          # current working directory
    191 
    192 my $start;
    193 my $ftpchecktime=1; # time it took to verify our test FTP server
    194 
    195 my $stunnel = checkcmd("stunnel4") || checkcmd("tstunnel") || checkcmd("stunnel");
    196 my $valgrind = checktestcmd("valgrind");
    197 my $valgrind_logfile="--logfile";
    198 my $valgrind_tool;
    199 my $gdb = checktestcmd("gdb");
    200 my $httptlssrv = find_httptlssrv();
    201 
    202 my $ssl_version;    # set if libcurl is built with SSL support
    203 my $large_file;     # set if libcurl is built with large file support
    204 my $has_idn;        # set if libcurl is built with IDN support
    205 my $http_ipv6;      # set if HTTP server has IPv6 support
    206 my $http_unix;      # set if HTTP server has Unix sockets support
    207 my $ftp_ipv6;       # set if FTP server has IPv6 support
    208 my $tftp_ipv6;      # set if TFTP server has IPv6 support
    209 my $gopher_ipv6;    # set if Gopher server has IPv6 support
    210 my $has_ipv6;       # set if libcurl is built with IPv6 support
    211 my $has_unix;       # set if libcurl is built with Unix sockets support
    212 my $has_libz;       # set if libcurl is built with libz support
    213 my $has_getrlimit;  # set if system has getrlimit()
    214 my $has_ntlm;       # set if libcurl is built with NTLM support
    215 my $has_ntlm_wb;    # set if libcurl is built with NTLM delegation to winbind
    216 my $has_sspi;       # set if libcurl is built with Windows SSPI
    217 my $has_gssapi;     # set if libcurl is built with a GSS-API library
    218 my $has_kerberos;   # set if libcurl is built with Kerberos support
    219 my $has_spnego;     # set if libcurl is built with SPNEGO support
    220 my $has_charconv;   # set if libcurl is built with CharConv support
    221 my $has_tls_srp;    # set if libcurl is built with TLS-SRP support
    222 my $has_metalink;   # set if curl is built with Metalink support
    223 my $has_http2;      # set if libcurl is built with HTTP2 support
    224 my $has_crypto;     # set if libcurl is built with cryptographic support
    225 my $has_cares;      # set if built with c-ares
    226 my $has_threadedres;# set if built with threaded resolver
    227 
    228 # this version is decided by the particular nghttp2 library that is being used
    229 my $h2cver = "h2c";
    230 
    231 my $has_openssl;    # built with a lib using an OpenSSL-like API
    232 my $has_gnutls;     # built with GnuTLS
    233 my $has_nss;        # built with NSS
    234 my $has_yassl;      # built with yassl
    235 my $has_polarssl;   # built with polarssl
    236 my $has_axtls;      # built with axTLS
    237 my $has_winssl;     # built with WinSSL    (Secure Channel aka Schannel)
    238 my $has_darwinssl;  # built with DarwinSSL (Secure Transport)
    239 my $has_boringssl;  # built with BoringSSL
    240 my $has_libressl;   # built with libressl 
    241 
    242 my $has_sslpinning; # built with a TLS backend that supports pinning
    243 
    244 my $has_shared = "unknown";  # built shared
    245 
    246 my $resolver;       # name of the resolver backend (for human presentation)
    247 my $ssllib;         # name of the SSL library we use (for human presentation)
    248 
    249 my $has_textaware;  # set if running on a system that has a text mode concept
    250                     # on files. Windows for example
    251 
    252 my @protocols;   # array of lowercase supported protocol servers
    253 
    254 my $skipped=0;  # number of tests skipped; reported in main loop
    255 my %skipped;    # skipped{reason}=counter, reasons for skip
    256 my @teststat;   # teststat[testnum]=reason, reasons for skip
    257 my %disabled_keywords;  # key words of tests to skip
    258 my %enabled_keywords;   # key words of tests to run
    259 my %disabled;           # disabled test cases
    260 
    261 my $sshdid;      # for socks server, ssh daemon version id
    262 my $sshdvernum;  # for socks server, ssh daemon version number
    263 my $sshdverstr;  # for socks server, ssh daemon version string
    264 my $sshderror;   # for socks server, ssh daemon version error
    265 
    266 my $defserverlogslocktimeout = 20; # timeout to await server logs lock removal
    267 my $defpostcommanddelay = 0; # delay between command and postcheck sections
    268 
    269 my $timestats;   # time stamping and stats generation
    270 my $fullstats;   # show time stats for every single test
    271 my %timeprepini; # timestamp for each test preparation start
    272 my %timesrvrini; # timestamp for each test required servers verification start
    273 my %timesrvrend; # timestamp for each test required servers verification end
    274 my %timetoolini; # timestamp for each test command run starting
    275 my %timetoolend; # timestamp for each test command run stopping
    276 my %timesrvrlog; # timestamp for each test server logs lock removal
    277 my %timevrfyend; # timestamp for each test result verification end
    278 
    279 my $testnumcheck; # test number, set in singletest sub.
    280 my %oldenv;
    281 
    282 #######################################################################
    283 # variables that command line options may set
    284 #
    285 
    286 my $short;
    287 my $automakestyle;
    288 my $verbose;
    289 my $debugprotocol;
    290 my $anyway;
    291 my $gdbthis;      # run test case with gdb debugger
    292 my $gdbxwin;      # use windowed gdb when using gdb
    293 my $keepoutfiles; # keep stdout and stderr files after tests
    294 my $listonly;     # only list the tests
    295 my $postmortem;   # display detailed info about failed tests
    296 my $run_event_based; # run curl with --test-event to test the event API
    297 
    298 my %run;          # running server
    299 my %doesntrun;    # servers that don't work, identified by pidfile
    300 my %serverpidfile;# all server pid file names, identified by server id
    301 my %runcert;      # cert file currently in use by an ssl running server
    302 
    303 # torture test variables
    304 my $torture;
    305 my $tortnum;
    306 my $tortalloc;
    307 
    308 #######################################################################
    309 # logmsg is our general message logging subroutine.
    310 #
    311 sub logmsg {
    312     for(@_) {
    313         print "$_";
    314     }
    315 }
    316 
    317 # get the name of the current user
    318 my $USER = $ENV{USER};          # Linux
    319 if (!$USER) {
    320     $USER = $ENV{USERNAME};     # Windows
    321     if (!$USER) {
    322         $USER = $ENV{LOGNAME};  # Some Unix (I think)
    323     }
    324 }
    325 
    326 # enable memory debugging if curl is compiled with it
    327 $ENV{'CURL_MEMDEBUG'} = $memdump;
    328 $ENV{'CURL_ENTROPY'}="12345678";
    329 $ENV{'CURL_FORCETIME'}=1; # for debug NTLM magic
    330 $ENV{'HOME'}=$pwd;
    331 
    332 sub catch_zap {
    333     my $signame = shift;
    334     logmsg "runtests.pl received SIG$signame, exiting\n";
    335     stopservers($verbose);
    336     die "Somebody sent me a SIG$signame";
    337 }
    338 $SIG{INT} = \&catch_zap;
    339 $SIG{TERM} = \&catch_zap;
    340 
    341 ##########################################################################
    342 # Clear all possible '*_proxy' environment variables for various protocols
    343 # to prevent them to interfere with our testing!
    344 
    345 my $protocol;
    346 foreach $protocol (('ftp', 'http', 'ftps', 'https', 'no', 'all')) {
    347     my $proxy = "${protocol}_proxy";
    348     # clear lowercase version
    349     delete $ENV{$proxy} if($ENV{$proxy});
    350     # clear uppercase version
    351     delete $ENV{uc($proxy)} if($ENV{uc($proxy)});
    352 }
    353 
    354 # make sure we don't get affected by other variables that control our
    355 # behaviour
    356 
    357 delete $ENV{'SSL_CERT_DIR'} if($ENV{'SSL_CERT_DIR'});
    358 delete $ENV{'SSL_CERT_PATH'} if($ENV{'SSL_CERT_PATH'});
    359 delete $ENV{'CURL_CA_BUNDLE'} if($ENV{'CURL_CA_BUNDLE'});
    360 
    361 #######################################################################
    362 # Load serverpidfile hash with pidfile names for all possible servers.
    363 #
    364 sub init_serverpidfile_hash {
    365   for my $proto (('ftp', 'http', 'imap', 'pop3', 'smtp')) {
    366     for my $ssl (('', 's')) {
    367       for my $ipvnum ((4, 6)) {
    368         for my $idnum ((1, 2, 3)) {
    369           my $serv = servername_id("$proto$ssl", $ipvnum, $idnum);
    370           my $pidf = server_pidfilename("$proto$ssl", $ipvnum, $idnum);
    371           $serverpidfile{$serv} = $pidf;
    372         }
    373       }
    374     }
    375   }
    376   for my $proto (('tftp', 'sftp', 'socks', 'ssh', 'rtsp', 'gopher', 'httptls')) {
    377     for my $ipvnum ((4, 6)) {
    378       for my $idnum ((1, 2)) {
    379         my $serv = servername_id($proto, $ipvnum, $idnum);
    380         my $pidf = server_pidfilename($proto, $ipvnum, $idnum);
    381         $serverpidfile{$serv} = $pidf;
    382       }
    383     }
    384   }
    385   for my $proto (('http', 'imap', 'pop3', 'smtp')) {
    386     for my $ssl (('', 's')) {
    387       my $serv = servername_id("$proto$ssl", "unix", 1);
    388       my $pidf = server_pidfilename("$proto$ssl", "unix", 1);
    389       $serverpidfile{$serv} = $pidf;
    390     }
    391   }
    392 }
    393 
    394 #######################################################################
    395 # Check if a given child process has just died. Reaps it if so.
    396 #
    397 sub checkdied {
    398     use POSIX ":sys_wait_h";
    399     my $pid = $_[0];
    400     if(not defined $pid || $pid <= 0) {
    401         return 0;
    402     }
    403     my $rc = waitpid($pid, &WNOHANG);
    404     return ($rc == $pid)?1:0;
    405 }
    406 
    407 #######################################################################
    408 # Start a new thread/process and run the given command line in there.
    409 # Return the pids (yes plural) of the new child process to the parent.
    410 #
    411 sub startnew {
    412     my ($cmd, $pidfile, $timeout, $fake)=@_;
    413 
    414     logmsg "startnew: $cmd\n" if ($verbose);
    415 
    416     my $child = fork();
    417     my $pid2 = 0;
    418 
    419     if(not defined $child) {
    420         logmsg "startnew: fork() failure detected\n";
    421         return (-1,-1);
    422     }
    423 
    424     if(0 == $child) {
    425         # Here we are the child. Run the given command.
    426 
    427         # Put an "exec" in front of the command so that the child process
    428         # keeps this child's process ID.
    429         exec("exec $cmd") || die "Can't exec() $cmd: $!";
    430 
    431         # exec() should never return back here to this process. We protect
    432         # ourselves by calling die() just in case something goes really bad.
    433         die "error: exec() has returned";
    434     }
    435 
    436     # Ugly hack but ssh client and gnutls-serv don't support pid files
    437     if ($fake) {
    438         if(open(OUT, ">$pidfile")) {
    439             print OUT $child . "\n";
    440             close(OUT);
    441             logmsg "startnew: $pidfile faked with pid=$child\n" if($verbose);
    442         }
    443         else {
    444             logmsg "startnew: failed to write fake $pidfile with pid=$child\n";
    445         }
    446         # could/should do a while connect fails sleep a bit and loop
    447         sleep $timeout;
    448         if (checkdied($child)) {
    449             logmsg "startnew: child process has failed to start\n" if($verbose);
    450             return (-1,-1);
    451         }
    452     }
    453 
    454     my $count = $timeout;
    455     while($count--) {
    456         if(-f $pidfile && -s $pidfile && open(PID, "<$pidfile")) {
    457             $pid2 = 0 + <PID>;
    458             close(PID);
    459             if(($pid2 > 0) && pidexists($pid2)) {
    460                 # if $pid2 is valid, then make sure this pid is alive, as
    461                 # otherwise it is just likely to be the _previous_ pidfile or
    462                 # similar!
    463                 last;
    464             }
    465             # invalidate $pid2 if not actually alive
    466             $pid2 = 0;
    467         }
    468         if (checkdied($child)) {
    469             logmsg "startnew: child process has died, server might start up\n"
    470                 if($verbose);
    471             # We can't just abort waiting for the server with a
    472             # return (-1,-1);
    473             # because the server might have forked and could still start
    474             # up normally. Instead, just reduce the amount of time we remain
    475             # waiting.
    476             $count >>= 2;
    477         }
    478         sleep(1);
    479     }
    480 
    481     # Return two PIDs, the one for the child process we spawned and the one
    482     # reported by the server itself (in case it forked again on its own).
    483     # Both (potentially) need to be killed at the end of the test.
    484     return ($child, $pid2);
    485 }
    486 
    487 
    488 #######################################################################
    489 # Check for a command in the PATH of the test server.
    490 #
    491 sub checkcmd {
    492     my ($cmd)=@_;
    493     my @paths=(split(":", $ENV{'PATH'}), "/usr/sbin", "/usr/local/sbin",
    494                "/sbin", "/usr/bin", "/usr/local/bin",
    495                "./libtest/.libs", "./libtest");
    496     for(@paths) {
    497         if( -x "$_/$cmd" && ! -d "$_/$cmd") {
    498             # executable bit but not a directory!
    499             return "$_/$cmd";
    500         }
    501     }
    502 }
    503 
    504 #######################################################################
    505 # Get the list of tests that the tests/data/Makefile.am knows about!
    506 #
    507 my $disttests;
    508 sub get_disttests {
    509     my @dist = `cd data && make show`;
    510     $disttests = join("", @dist);
    511 }
    512 
    513 #######################################################################
    514 # Check for a command in the PATH of the machine running curl.
    515 #
    516 sub checktestcmd {
    517     my ($cmd)=@_;
    518     return checkcmd($cmd);
    519 }
    520 
    521 #######################################################################
    522 # Run the application under test and return its return code
    523 #
    524 sub runclient {
    525     my ($cmd)=@_;
    526     my $ret = system($cmd);
    527     print "CMD ($ret): $cmd\n" if($verbose && !$torture);
    528     return $ret;
    529 
    530 # This is one way to test curl on a remote machine
    531 #    my $out = system("ssh $CLIENTIP cd \'$pwd\' \\; \'$cmd\'");
    532 #    sleep 2;    # time to allow the NFS server to be updated
    533 #    return $out;
    534 }
    535 
    536 #######################################################################
    537 # Run the application under test and return its stdout
    538 #
    539 sub runclientoutput {
    540     my ($cmd)=@_;
    541     return `$cmd`;
    542 
    543 # This is one way to test curl on a remote machine
    544 #    my @out = `ssh $CLIENTIP cd \'$pwd\' \\; \'$cmd\'`;
    545 #    sleep 2;    # time to allow the NFS server to be updated
    546 #    return @out;
    547  }
    548 
    549 #######################################################################
    550 # Memory allocation test and failure torture testing.
    551 #
    552 sub torture {
    553     my $testcmd = shift;
    554     my $gdbline = shift;
    555 
    556     # remove memdump first to be sure we get a new nice and clean one
    557     unlink($memdump);
    558 
    559     # First get URL from test server, ignore the output/result
    560     runclient($testcmd);
    561 
    562     logmsg " CMD: $testcmd\n" if($verbose);
    563 
    564     # memanalyze -v is our friend, get the number of allocations made
    565     my $count=0;
    566     my @out = `$memanalyze -v $memdump`;
    567     for(@out) {
    568         if(/^Allocations: (\d+)/) {
    569             $count = $1;
    570             last;
    571         }
    572     }
    573     if(!$count) {
    574         logmsg " found no allocs to make fail\n";
    575         return 0;
    576     }
    577 
    578     logmsg " $count allocations to make fail\n";
    579 
    580     for ( 1 .. $count ) {
    581         my $limit = $_;
    582         my $fail;
    583         my $dumped_core;
    584 
    585         if($tortalloc && ($tortalloc != $limit)) {
    586             next;
    587         }
    588 
    589         if($verbose) {
    590             my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
    591                 localtime(time());
    592             my $now = sprintf("%02d:%02d:%02d ", $hour, $min, $sec);
    593             logmsg "Fail alloc no: $limit at $now\r";
    594         }
    595 
    596         # make the memory allocation function number $limit return failure
    597         $ENV{'CURL_MEMLIMIT'} = $limit;
    598 
    599         # remove memdump first to be sure we get a new nice and clean one
    600         unlink($memdump);
    601 
    602         logmsg "*** Alloc number $limit is now set to fail ***\n" if($gdbthis);
    603 
    604         my $ret = 0;
    605         if($gdbthis) {
    606             runclient($gdbline);
    607         }
    608         else {
    609             $ret = runclient($testcmd);
    610         }
    611         #logmsg "$_ Returned " . ($ret >> 8) . "\n";
    612 
    613         # Now clear the variable again
    614         delete $ENV{'CURL_MEMLIMIT'} if($ENV{'CURL_MEMLIMIT'});
    615 
    616         if(-r "core") {
    617             # there's core file present now!
    618             logmsg " core dumped\n";
    619             $dumped_core = 1;
    620             $fail = 2;
    621         }
    622 
    623         # verify that it returns a proper error code, doesn't leak memory
    624         # and doesn't core dump
    625         if(($ret & 255) || ($ret >> 8) >= 128) {
    626             logmsg " system() returned $ret\n";
    627             $fail=1;
    628         }
    629         else {
    630             my @memdata=`$memanalyze $memdump`;
    631             my $leak=0;
    632             for(@memdata) {
    633                 if($_ ne "") {
    634                     # well it could be other memory problems as well, but
    635                     # we call it leak for short here
    636                     $leak=1;
    637                 }
    638             }
    639             if($leak) {
    640                 logmsg "** MEMORY FAILURE\n";
    641                 logmsg @memdata;
    642                 logmsg `$memanalyze -l $memdump`;
    643                 $fail = 1;
    644             }
    645         }
    646         if($fail) {
    647             logmsg " Failed on alloc number $limit in test.\n",
    648             " invoke with \"-t$limit\" to repeat this single case.\n";
    649             stopservers($verbose);
    650             return 1;
    651         }
    652     }
    653 
    654     logmsg "torture OK\n";
    655     return 0;
    656 }
    657 
    658 #######################################################################
    659 # Stop a test server along with pids which aren't in the %run hash yet.
    660 # This also stops all servers which are relative to the given one.
    661 #
    662 sub stopserver {
    663     my ($server, $pidlist) = @_;
    664     #
    665     # kill sockfilter processes for pingpong relative server
    666     #
    667     if($server =~ /^(ftp|imap|pop3|smtp)s?(\d*)(-ipv6|)$/) {
    668         my $proto  = $1;
    669         my $idnum  = ($2 && ($2 > 1)) ? $2 : 1;
    670         my $ipvnum = ($3 && ($3 =~ /6$/)) ? 6 : 4;
    671         killsockfilters($proto, $ipvnum, $idnum, $verbose);
    672     }
    673     #
    674     # All servers relative to the given one must be stopped also
    675     #
    676     my @killservers;
    677     if($server =~ /^(ftp|http|imap|pop3|smtp|httppipe)s((\d*)(-ipv6|-unix|))$/) {
    678         # given a stunnel based ssl server, also kill non-ssl underlying one
    679         push @killservers, "${1}${2}";
    680     }
    681     elsif($server =~ /^(ftp|http|imap|pop3|smtp|httppipe)((\d*)(-ipv6|-unix|))$/) {
    682         # given a non-ssl server, also kill stunnel based ssl piggybacking one
    683         push @killservers, "${1}s${2}";
    684     }
    685     elsif($server =~ /^(socks)((\d*)(-ipv6|))$/) {
    686         # given a socks server, also kill ssh underlying one
    687         push @killservers, "ssh${2}";
    688     }
    689     elsif($server =~ /^(ssh)((\d*)(-ipv6|))$/) {
    690         # given a ssh server, also kill socks piggybacking one
    691         push @killservers, "socks${2}";
    692     }
    693     push @killservers, $server;
    694     #
    695     # kill given pids and server relative ones clearing them in %run hash
    696     #
    697     foreach my $server (@killservers) {
    698         if($run{$server}) {
    699             # we must prepend a space since $pidlist may already contain a pid
    700             $pidlist .= " $run{$server}";
    701             $run{$server} = 0;
    702         }
    703         $runcert{$server} = 0 if($runcert{$server});
    704     }
    705     killpid($verbose, $pidlist);
    706     #
    707     # cleanup server pid files
    708     #
    709     foreach my $server (@killservers) {
    710         my $pidfile = $serverpidfile{$server};
    711         my $pid = processexists($pidfile);
    712         if($pid > 0) {
    713             logmsg "Warning: $server server unexpectedly alive\n";
    714             killpid($verbose, $pid);
    715         }
    716         unlink($pidfile) if(-f $pidfile);
    717     }
    718 }
    719 
    720 #######################################################################
    721 # Verify that the server that runs on $ip, $port is our server.  This also
    722 # implies that we can speak with it, as there might be occasions when the
    723 # server runs fine but we cannot talk to it ("Failed to connect to ::1: Can't
    724 # assign requested address")
    725 #
    726 sub verifyhttp {
    727     my ($proto, $ipvnum, $idnum, $ip, $port_or_path) = @_;
    728     my $server = servername_id($proto, $ipvnum, $idnum);
    729     my $pid = 0;
    730     my $bonus="";
    731     # $port_or_path contains a path for Unix sockets, sws ignores the port
    732     my $port = ($ipvnum eq "unix") ? 80 : $port_or_path;
    733 
    734     my $verifyout = "$LOGDIR/".
    735         servername_canon($proto, $ipvnum, $idnum) .'_verify.out';
    736     unlink($verifyout) if(-f $verifyout);
    737 
    738     my $verifylog = "$LOGDIR/".
    739         servername_canon($proto, $ipvnum, $idnum) .'_verify.log';
    740     unlink($verifylog) if(-f $verifylog);
    741 
    742     if($proto eq "gopher") {
    743         # gopher is funny
    744         $bonus="1/";
    745     }
    746 
    747     my $flags = "--max-time $server_response_maxtime ";
    748     $flags .= "--output $verifyout ";
    749     $flags .= "--silent ";
    750     $flags .= "--verbose ";
    751     $flags .= "--globoff ";
    752     $flags .= "--unix-socket '$port_or_path' " if $ipvnum eq "unix";
    753     $flags .= "-1 "         if($has_axtls);
    754     $flags .= "--insecure " if($proto eq 'https');
    755     $flags .= "\"$proto://$ip:$port/${bonus}verifiedserver\"";
    756 
    757     my $cmd = "$VCURL $flags 2>$verifylog";
    758 
    759     # verify if our/any server is running on this port
    760     logmsg "RUN: $cmd\n" if($verbose);
    761     my $res = runclient($cmd);
    762 
    763     $res >>= 8; # rotate the result
    764     if($res & 128) {
    765         logmsg "RUN: curl command died with a coredump\n";
    766         return -1;
    767     }
    768 
    769     if($res && $verbose) {
    770         logmsg "RUN: curl command returned $res\n";
    771         if(open(FILE, "<$verifylog")) {
    772             while(my $string = <FILE>) {
    773                 logmsg "RUN: $string" if($string !~ /^([ \t]*)$/);
    774             }
    775             close(FILE);
    776         }
    777     }
    778 
    779     my $data;
    780     if(open(FILE, "<$verifyout")) {
    781         while(my $string = <FILE>) {
    782             $data = $string;
    783             last; # only want first line
    784         }
    785         close(FILE);
    786     }
    787 
    788     if($data && ($data =~ /WE ROOLZ: (\d+)/)) {
    789         $pid = 0+$1;
    790     }
    791     elsif($res == 6) {
    792         # curl: (6) Couldn't resolve host '::1'
    793         logmsg "RUN: failed to resolve host ($proto://$ip:$port/verifiedserver)\n";
    794         return -1;
    795     }
    796     elsif($data || ($res && ($res != 7))) {
    797         logmsg "RUN: Unknown server on our $server port: $port ($res)\n";
    798         return -1;
    799     }
    800     return $pid;
    801 }
    802 
    803 #######################################################################
    804 # Verify that the server that runs on $ip, $port is our server.  This also
    805 # implies that we can speak with it, as there might be occasions when the
    806 # server runs fine but we cannot talk to it ("Failed to connect to ::1: Can't
    807 # assign requested address")
    808 #
    809 sub verifyftp {
    810     my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
    811     my $server = servername_id($proto, $ipvnum, $idnum);
    812     my $pid = 0;
    813     my $time=time();
    814     my $extra="";
    815 
    816     my $verifylog = "$LOGDIR/".
    817         servername_canon($proto, $ipvnum, $idnum) .'_verify.log';
    818     unlink($verifylog) if(-f $verifylog);
    819 
    820     if($proto eq "ftps") {
    821         $extra .= "--insecure --ftp-ssl-control ";
    822     }
    823 
    824     my $flags = "--max-time $server_response_maxtime ";
    825     $flags .= "--silent ";
    826     $flags .= "--verbose ";
    827     $flags .= "--globoff ";
    828     $flags .= $extra;
    829     $flags .= "\"$proto://$ip:$port/verifiedserver\"";
    830 
    831     my $cmd = "$VCURL $flags 2>$verifylog";
    832 
    833     # check if this is our server running on this port:
    834     logmsg "RUN: $cmd\n" if($verbose);
    835     my @data = runclientoutput($cmd);
    836 
    837     my $res = $? >> 8; # rotate the result
    838     if($res & 128) {
    839         logmsg "RUN: curl command died with a coredump\n";
    840         return -1;
    841     }
    842 
    843     foreach my $line (@data) {
    844         if($line =~ /WE ROOLZ: (\d+)/) {
    845             # this is our test server with a known pid!
    846             $pid = 0+$1;
    847             last;
    848         }
    849     }
    850     if($pid <= 0 && @data && $data[0]) {
    851         # this is not a known server
    852         logmsg "RUN: Unknown server on our $server port: $port\n";
    853         return 0;
    854     }
    855     # we can/should use the time it took to verify the FTP server as a measure
    856     # on how fast/slow this host/FTP is.
    857     my $took = int(0.5+time()-$time);
    858 
    859     if($verbose) {
    860         logmsg "RUN: Verifying our test $server server took $took seconds\n";
    861     }
    862     $ftpchecktime = $took>=1?$took:1; # make sure it never is below 1
    863 
    864     return $pid;
    865 }
    866 
    867 #######################################################################
    868 # Verify that the server that runs on $ip, $port is our server.  This also
    869 # implies that we can speak with it, as there might be occasions when the
    870 # server runs fine but we cannot talk to it ("Failed to connect to ::1: Can't
    871 # assign requested address")
    872 #
    873 sub verifyrtsp {
    874     my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
    875     my $server = servername_id($proto, $ipvnum, $idnum);
    876     my $pid = 0;
    877 
    878     my $verifyout = "$LOGDIR/".
    879         servername_canon($proto, $ipvnum, $idnum) .'_verify.out';
    880     unlink($verifyout) if(-f $verifyout);
    881 
    882     my $verifylog = "$LOGDIR/".
    883         servername_canon($proto, $ipvnum, $idnum) .'_verify.log';
    884     unlink($verifylog) if(-f $verifylog);
    885 
    886     my $flags = "--max-time $server_response_maxtime ";
    887     $flags .= "--output $verifyout ";
    888     $flags .= "--silent ";
    889     $flags .= "--verbose ";
    890     $flags .= "--globoff ";
    891     # currently verification is done using http
    892     $flags .= "\"http://$ip:$port/verifiedserver\"";
    893 
    894     my $cmd = "$VCURL $flags 2>$verifylog";
    895 
    896     # verify if our/any server is running on this port
    897     logmsg "RUN: $cmd\n" if($verbose);
    898     my $res = runclient($cmd);
    899 
    900     $res >>= 8; # rotate the result
    901     if($res & 128) {
    902         logmsg "RUN: curl command died with a coredump\n";
    903         return -1;
    904     }
    905 
    906     if($res && $verbose) {
    907         logmsg "RUN: curl command returned $res\n";
    908         if(open(FILE, "<$verifylog")) {
    909             while(my $string = <FILE>) {
    910                 logmsg "RUN: $string" if($string !~ /^([ \t]*)$/);
    911             }
    912             close(FILE);
    913         }
    914     }
    915 
    916     my $data;
    917     if(open(FILE, "<$verifyout")) {
    918         while(my $string = <FILE>) {
    919             $data = $string;
    920             last; # only want first line
    921         }
    922         close(FILE);
    923     }
    924 
    925     if($data && ($data =~ /RTSP_SERVER WE ROOLZ: (\d+)/)) {
    926         $pid = 0+$1;
    927     }
    928     elsif($res == 6) {
    929         # curl: (6) Couldn't resolve host '::1'
    930         logmsg "RUN: failed to resolve host ($proto://$ip:$port/verifiedserver)\n";
    931         return -1;
    932     }
    933     elsif($data || ($res != 7)) {
    934         logmsg "RUN: Unknown server on our $server port: $port\n";
    935         return -1;
    936     }
    937     return $pid;
    938 }
    939 
    940 #######################################################################
    941 # Verify that the ssh server has written out its pidfile, recovering
    942 # the pid from the file and returning it if a process with that pid is
    943 # actually alive.
    944 #
    945 sub verifyssh {
    946     my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
    947     my $server = servername_id($proto, $ipvnum, $idnum);
    948     my $pidfile = server_pidfilename($proto, $ipvnum, $idnum);
    949     my $pid = 0;
    950     if(open(FILE, "<$pidfile")) {
    951         $pid=0+<FILE>;
    952         close(FILE);
    953     }
    954     if($pid > 0) {
    955         # if we have a pid it is actually our ssh server,
    956         # since runsshserver() unlinks previous pidfile
    957         if(!pidexists($pid)) {
    958             logmsg "RUN: SSH server has died after starting up\n";
    959             checkdied($pid);
    960             unlink($pidfile);
    961             $pid = -1;
    962         }
    963     }
    964     return $pid;
    965 }
    966 
    967 #######################################################################
    968 # Verify that we can connect to the sftp server, properly authenticate
    969 # with generated config and key files and run a simple remote pwd.
    970 #
    971 sub verifysftp {
    972     my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
    973     my $server = servername_id($proto, $ipvnum, $idnum);
    974     my $verified = 0;
    975     # Find out sftp client canonical file name
    976     my $sftp = find_sftp();
    977     if(!$sftp) {
    978         logmsg "RUN: SFTP server cannot find $sftpexe\n";
    979         return -1;
    980     }
    981     # Find out ssh client canonical file name
    982     my $ssh = find_ssh();
    983     if(!$ssh) {
    984         logmsg "RUN: SFTP server cannot find $sshexe\n";
    985         return -1;
    986     }
    987     # Connect to sftp server, authenticate and run a remote pwd
    988     # command using our generated configuration and key files
    989     my $cmd = "\"$sftp\" -b $sftpcmds -F $sftpconfig -S \"$ssh\" $ip > $sftplog 2>&1";
    990     my $res = runclient($cmd);
    991     # Search for pwd command response in log file
    992     if(open(SFTPLOGFILE, "<$sftplog")) {
    993         while(<SFTPLOGFILE>) {
    994             if(/^Remote working directory: /) {
    995                 $verified = 1;
    996                 last;
    997             }
    998         }
    999         close(SFTPLOGFILE);
   1000     }
   1001     return $verified;
   1002 }
   1003 
   1004 #######################################################################
   1005 # Verify that the non-stunnel HTTP TLS extensions capable server that runs
   1006 # on $ip, $port is our server.  This also implies that we can speak with it,
   1007 # as there might be occasions when the server runs fine but we cannot talk
   1008 # to it ("Failed to connect to ::1: Can't assign requested address")
   1009 #
   1010 sub verifyhttptls {
   1011     my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
   1012     my $server = servername_id($proto, $ipvnum, $idnum);
   1013     my $pidfile = server_pidfilename($proto, $ipvnum, $idnum);
   1014     my $pid = 0;
   1015 
   1016     my $verifyout = "$LOGDIR/".
   1017         servername_canon($proto, $ipvnum, $idnum) .'_verify.out';
   1018     unlink($verifyout) if(-f $verifyout);
   1019 
   1020     my $verifylog = "$LOGDIR/".
   1021         servername_canon($proto, $ipvnum, $idnum) .'_verify.log';
   1022     unlink($verifylog) if(-f $verifylog);
   1023 
   1024     my $flags = "--max-time $server_response_maxtime ";
   1025     $flags .= "--output $verifyout ";
   1026     $flags .= "--verbose ";
   1027     $flags .= "--globoff ";
   1028     $flags .= "--insecure ";
   1029     $flags .= "--tlsauthtype SRP ";
   1030     $flags .= "--tlsuser jsmith ";
   1031     $flags .= "--tlspassword abc ";
   1032     $flags .= "\"https://$ip:$port/verifiedserver\"";
   1033 
   1034     my $cmd = "$VCURL $flags 2>$verifylog";
   1035 
   1036     # verify if our/any server is running on this port
   1037     logmsg "RUN: $cmd\n" if($verbose);
   1038     my $res = runclient($cmd);
   1039 
   1040     $res >>= 8; # rotate the result
   1041     if($res & 128) {
   1042         logmsg "RUN: curl command died with a coredump\n";
   1043         return -1;
   1044     }
   1045 
   1046     if($res && $verbose) {
   1047         logmsg "RUN: curl command returned $res\n";
   1048         if(open(FILE, "<$verifylog")) {
   1049             while(my $string = <FILE>) {
   1050                 logmsg "RUN: $string" if($string !~ /^([ \t]*)$/);
   1051             }
   1052             close(FILE);
   1053         }
   1054     }
   1055 
   1056     my $data;
   1057     if(open(FILE, "<$verifyout")) {
   1058         while(my $string = <FILE>) {
   1059             $data .= $string;
   1060         }
   1061         close(FILE);
   1062     }
   1063 
   1064     if($data && ($data =~ /(GNUTLS|GnuTLS)/) && open(FILE, "<$pidfile")) {
   1065         $pid=0+<FILE>;
   1066         close(FILE);
   1067         if($pid > 0) {
   1068             # if we have a pid it is actually our httptls server,
   1069             # since runhttptlsserver() unlinks previous pidfile
   1070             if(!pidexists($pid)) {
   1071                 logmsg "RUN: $server server has died after starting up\n";
   1072                 checkdied($pid);
   1073                 unlink($pidfile);
   1074                 $pid = -1;
   1075             }
   1076         }
   1077         return $pid;
   1078     }
   1079     elsif($res == 6) {
   1080         # curl: (6) Couldn't resolve host '::1'
   1081         logmsg "RUN: failed to resolve host (https://$ip:$port/verifiedserver)\n";
   1082         return -1;
   1083     }
   1084     elsif($data || ($res && ($res != 7))) {
   1085         logmsg "RUN: Unknown server on our $server port: $port ($res)\n";
   1086         return -1;
   1087     }
   1088     return $pid;
   1089 }
   1090 
   1091 #######################################################################
   1092 # STUB for verifying socks
   1093 #
   1094 sub verifysocks {
   1095     my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
   1096     my $server = servername_id($proto, $ipvnum, $idnum);
   1097     my $pidfile = server_pidfilename($proto, $ipvnum, $idnum);
   1098     my $pid = 0;
   1099     if(open(FILE, "<$pidfile")) {
   1100         $pid=0+<FILE>;
   1101         close(FILE);
   1102     }
   1103     if($pid > 0) {
   1104         # if we have a pid it is actually our socks server,
   1105         # since runsocksserver() unlinks previous pidfile
   1106         if(!pidexists($pid)) {
   1107             logmsg "RUN: SOCKS server has died after starting up\n";
   1108             checkdied($pid);
   1109             unlink($pidfile);
   1110             $pid = -1;
   1111         }
   1112     }
   1113     return $pid;
   1114 }
   1115 
   1116 #######################################################################
   1117 # Verify that the server that runs on $ip, $port is our server.
   1118 # Retry over several seconds before giving up.  The ssh server in
   1119 # particular can take a long time to start if it needs to generate
   1120 # keys on a slow or loaded host.
   1121 #
   1122 # Just for convenience, test harness uses 'https' and 'httptls' literals
   1123 # as values for 'proto' variable in order to differentiate different
   1124 # servers. 'https' literal is used for stunnel based https test servers,
   1125 # and 'httptls' is used for non-stunnel https test servers.
   1126 #
   1127 
   1128 my %protofunc = ('http' => \&verifyhttp,
   1129                  'https' => \&verifyhttp,
   1130                  'rtsp' => \&verifyrtsp,
   1131                  'ftp' => \&verifyftp,
   1132                  'pop3' => \&verifyftp,
   1133                  'imap' => \&verifyftp,
   1134                  'smtp' => \&verifyftp,
   1135                  'httppipe' => \&verifyhttp,
   1136                  'ftps' => \&verifyftp,
   1137                  'tftp' => \&verifyftp,
   1138                  'ssh' => \&verifyssh,
   1139                  'socks' => \&verifysocks,
   1140                  'gopher' => \&verifyhttp,
   1141                  'httptls' => \&verifyhttptls);
   1142 
   1143 sub verifyserver {
   1144     my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
   1145 
   1146     my $count = 30; # try for this many seconds
   1147     my $pid;
   1148 
   1149     while($count--) {
   1150         my $fun = $protofunc{$proto};
   1151 
   1152         $pid = &$fun($proto, $ipvnum, $idnum, $ip, $port);
   1153 
   1154         if($pid > 0) {
   1155             last;
   1156         }
   1157         elsif($pid < 0) {
   1158             # a real failure, stop trying and bail out
   1159             return 0;
   1160         }
   1161         sleep(1);
   1162     }
   1163     return $pid;
   1164 }
   1165 
   1166 #######################################################################
   1167 # Single shot server responsiveness test. This should only be used
   1168 # to verify that a server present in %run hash is still functional
   1169 #
   1170 sub responsiveserver {
   1171     my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
   1172     my $prev_verbose = $verbose;
   1173 
   1174     $verbose = 0;
   1175     my $fun = $protofunc{$proto};
   1176     my $pid = &$fun($proto, $ipvnum, $idnum, $ip, $port);
   1177     $verbose = $prev_verbose;
   1178 
   1179     if($pid > 0) {
   1180         return 1; # responsive
   1181     }
   1182 
   1183     my $srvrname = servername_str($proto, $ipvnum, $idnum);
   1184     logmsg " server precheck FAILED (unresponsive $srvrname server)\n";
   1185     return 0;
   1186 }
   1187 
   1188 #######################################################################
   1189 # start the http server
   1190 #
   1191 sub runhttpserver {
   1192     my ($proto, $verbose, $alt, $port_or_path) = @_;
   1193     my $ip = $HOSTIP;
   1194     my $ipvnum = 4;
   1195     my $idnum = 1;
   1196     my $server;
   1197     my $srvrname;
   1198     my $pidfile;
   1199     my $logfile;
   1200     my $flags = "";
   1201     my $exe = "$perl $srcdir/httpserver.pl";
   1202     my $verbose_flag = "--verbose ";
   1203 
   1204     if($alt eq "ipv6") {
   1205         # if IPv6, use a different setup
   1206         $ipvnum = 6;
   1207         $ip = $HOST6IP;
   1208     }
   1209     elsif($alt eq "proxy") {
   1210         # basically the same, but another ID
   1211         $idnum = 2;
   1212     }
   1213     elsif($alt eq "pipe") {
   1214         # basically the same, but another ID
   1215         $idnum = 3;
   1216         $exe = "python $srcdir/http_pipe.py";
   1217         $verbose_flag .= "1 ";
   1218     }
   1219     elsif($alt eq "unix") {
   1220         # IP (protocol) is mutually exclusive with Unix sockets
   1221         $ipvnum = "unix";
   1222     }
   1223 
   1224     $server = servername_id($proto, $ipvnum, $idnum);
   1225 
   1226     $pidfile = $serverpidfile{$server};
   1227 
   1228     # don't retry if the server doesn't work
   1229     if ($doesntrun{$pidfile}) {
   1230         return (0,0);
   1231     }
   1232 
   1233     my $pid = processexists($pidfile);
   1234     if($pid > 0) {
   1235         stopserver($server, "$pid");
   1236     }
   1237     unlink($pidfile) if(-f $pidfile);
   1238 
   1239     $srvrname = servername_str($proto, $ipvnum, $idnum);
   1240 
   1241     $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
   1242 
   1243     $flags .= "--gopher " if($proto eq "gopher");
   1244     $flags .= "--connect $HOSTIP " if($alt eq "proxy");
   1245     $flags .= $verbose_flag if($debugprotocol);
   1246     $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
   1247     $flags .= "--id $idnum " if($idnum > 1);
   1248     if($ipvnum eq "unix") {
   1249         $flags .= "--unix-socket '$port_or_path' ";
   1250     } else {
   1251         $flags .= "--ipv$ipvnum --port $port_or_path ";
   1252     }
   1253     $flags .= "--srcdir \"$srcdir\"";
   1254 
   1255     my $cmd = "$exe $flags";
   1256     my ($httppid, $pid2) = startnew($cmd, $pidfile, 15, 0);
   1257 
   1258     if($httppid <= 0 || !pidexists($httppid)) {
   1259         # it is NOT alive
   1260         logmsg "RUN: failed to start the $srvrname server\n";
   1261         stopserver($server, "$pid2");
   1262         displaylogs($testnumcheck);
   1263         $doesntrun{$pidfile} = 1;
   1264         return (0,0);
   1265     }
   1266 
   1267     # Server is up. Verify that we can speak to it.
   1268     my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port_or_path);
   1269     if(!$pid3) {
   1270         logmsg "RUN: $srvrname server failed verification\n";
   1271         # failed to talk to it properly. Kill the server and return failure
   1272         stopserver($server, "$httppid $pid2");
   1273         displaylogs($testnumcheck);
   1274         $doesntrun{$pidfile} = 1;
   1275         return (0,0);
   1276     }
   1277     $pid2 = $pid3;
   1278 
   1279     if($verbose) {
   1280         logmsg "RUN: $srvrname server is now running PID $httppid\n";
   1281     }
   1282 
   1283     sleep(1);
   1284 
   1285     return ($httppid, $pid2);
   1286 }
   1287 
   1288 #######################################################################
   1289 # start the http server
   1290 #
   1291 sub runhttp_pipeserver {
   1292     my ($proto, $verbose, $alt, $port) = @_;
   1293     my $ip = $HOSTIP;
   1294     my $ipvnum = 4;
   1295     my $idnum = 1;
   1296     my $server;
   1297     my $srvrname;
   1298     my $pidfile;
   1299     my $logfile;
   1300     my $flags = "";
   1301 
   1302     if($alt eq "ipv6") {
   1303         # No IPv6
   1304     }
   1305 
   1306     $server = servername_id($proto, $ipvnum, $idnum);
   1307 
   1308     $pidfile = $serverpidfile{$server};
   1309 
   1310     # don't retry if the server doesn't work
   1311     if ($doesntrun{$pidfile}) {
   1312         return (0,0);
   1313     }
   1314 
   1315     my $pid = processexists($pidfile);
   1316     if($pid > 0) {
   1317         stopserver($server, "$pid");
   1318     }
   1319     unlink($pidfile) if(-f $pidfile);
   1320 
   1321     $srvrname = servername_str($proto, $ipvnum, $idnum);
   1322 
   1323     $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
   1324 
   1325     $flags .= "--verbose 1 " if($debugprotocol);
   1326     $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
   1327     $flags .= "--id $idnum " if($idnum > 1);
   1328     $flags .= "--port $port --srcdir \"$srcdir\"";
   1329 
   1330     my $cmd = "$srcdir/http_pipe.py $flags";
   1331     my ($httppid, $pid2) = startnew($cmd, $pidfile, 15, 0);
   1332 
   1333     if($httppid <= 0 || !pidexists($httppid)) {
   1334         # it is NOT alive
   1335         logmsg "RUN: failed to start the $srvrname server\n";
   1336         stopserver($server, "$pid2");
   1337         displaylogs($testnumcheck);
   1338         $doesntrun{$pidfile} = 1;
   1339         return (0,0);
   1340     }
   1341 
   1342     # Server is up. Verify that we can speak to it.
   1343     my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port);
   1344     if(!$pid3) {
   1345         logmsg "RUN: $srvrname server failed verification\n";
   1346         # failed to talk to it properly. Kill the server and return failure
   1347         stopserver($server, "$httppid $pid2");
   1348         displaylogs($testnumcheck);
   1349         $doesntrun{$pidfile} = 1;
   1350         return (0,0);
   1351     }
   1352     $pid2 = $pid3;
   1353 
   1354     if($verbose) {
   1355         logmsg "RUN: $srvrname server is now running PID $httppid\n";
   1356     }
   1357 
   1358     sleep(1);
   1359 
   1360     return ($httppid, $pid2);
   1361 }
   1362 
   1363 #######################################################################
   1364 # start the https stunnel based server
   1365 #
   1366 sub runhttpsserver {
   1367     my ($verbose, $ipv6, $certfile) = @_;
   1368     my $proto = 'https';
   1369     my $ip = ($ipv6 && ($ipv6 =~ /6$/)) ? "$HOST6IP" : "$HOSTIP";
   1370     my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4;
   1371     my $idnum = 1;
   1372     my $server;
   1373     my $srvrname;
   1374     my $pidfile;
   1375     my $logfile;
   1376     my $flags = "";
   1377 
   1378     if(!$stunnel) {
   1379         return (0,0);
   1380     }
   1381 
   1382     $server = servername_id($proto, $ipvnum, $idnum);
   1383 
   1384     $pidfile = $serverpidfile{$server};
   1385 
   1386     # don't retry if the server doesn't work
   1387     if ($doesntrun{$pidfile}) {
   1388         return (0,0);
   1389     }
   1390 
   1391     my $pid = processexists($pidfile);
   1392     if($pid > 0) {
   1393         stopserver($server, "$pid");
   1394     }
   1395     unlink($pidfile) if(-f $pidfile);
   1396 
   1397     $srvrname = servername_str($proto, $ipvnum, $idnum);
   1398 
   1399     $certfile = 'stunnel.pem' unless($certfile);
   1400 
   1401     $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
   1402 
   1403     $flags .= "--verbose " if($debugprotocol);
   1404     $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
   1405     $flags .= "--id $idnum " if($idnum > 1);
   1406     $flags .= "--ipv$ipvnum --proto $proto ";
   1407     $flags .= "--certfile \"$certfile\" " if($certfile ne 'stunnel.pem');
   1408     $flags .= "--stunnel \"$stunnel\" --srcdir \"$srcdir\" ";
   1409     $flags .= "--connect $HTTPPORT --accept $HTTPSPORT";
   1410 
   1411     my $cmd = "$perl $srcdir/secureserver.pl $flags";
   1412     my ($httpspid, $pid2) = startnew($cmd, $pidfile, 15, 0);
   1413 
   1414     if($httpspid <= 0 || !pidexists($httpspid)) {
   1415         # it is NOT alive
   1416         logmsg "RUN: failed to start the $srvrname server\n";
   1417         stopserver($server, "$pid2");
   1418         displaylogs($testnumcheck);
   1419         $doesntrun{$pidfile} = 1;
   1420         return(0,0);
   1421     }
   1422 
   1423     # Server is up. Verify that we can speak to it.
   1424     my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $HTTPSPORT);
   1425     if(!$pid3) {
   1426         logmsg "RUN: $srvrname server failed verification\n";
   1427         # failed to talk to it properly. Kill the server and return failure
   1428         stopserver($server, "$httpspid $pid2");
   1429         displaylogs($testnumcheck);
   1430         $doesntrun{$pidfile} = 1;
   1431         return (0,0);
   1432     }
   1433     # Here pid3 is actually the pid returned by the unsecure-http server.
   1434 
   1435     $runcert{$server} = $certfile;
   1436 
   1437     if($verbose) {
   1438         logmsg "RUN: $srvrname server is now running PID $httpspid\n";
   1439     }
   1440 
   1441     sleep(1);
   1442 
   1443     return ($httpspid, $pid2);
   1444 }
   1445 
   1446 #######################################################################
   1447 # start the non-stunnel HTTP TLS extensions capable server
   1448 #
   1449 sub runhttptlsserver {
   1450     my ($verbose, $ipv6) = @_;
   1451     my $proto = "httptls";
   1452     my $port = ($ipv6 && ($ipv6 =~ /6$/)) ? $HTTPTLS6PORT : $HTTPTLSPORT;
   1453     my $ip = ($ipv6 && ($ipv6 =~ /6$/)) ? "$HOST6IP" : "$HOSTIP";
   1454     my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4;
   1455     my $idnum = 1;
   1456     my $server;
   1457     my $srvrname;
   1458     my $pidfile;
   1459     my $logfile;
   1460     my $flags = "";
   1461 
   1462     if(!$httptlssrv) {
   1463         return (0,0);
   1464     }
   1465 
   1466     $server = servername_id($proto, $ipvnum, $idnum);
   1467 
   1468     $pidfile = $serverpidfile{$server};
   1469 
   1470     # don't retry if the server doesn't work
   1471     if ($doesntrun{$pidfile}) {
   1472         return (0,0);
   1473     }
   1474 
   1475     my $pid = processexists($pidfile);
   1476     if($pid > 0) {
   1477         stopserver($server, "$pid");
   1478     }
   1479     unlink($pidfile) if(-f $pidfile);
   1480 
   1481     $srvrname = servername_str($proto, $ipvnum, $idnum);
   1482 
   1483     $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
   1484 
   1485     $flags .= "--http ";
   1486     $flags .= "--debug 1 " if($debugprotocol);
   1487     $flags .= "--port $port ";
   1488     $flags .= "--priority NORMAL:+SRP ";
   1489     $flags .= "--srppasswd $srcdir/certs/srp-verifier-db ";
   1490     $flags .= "--srppasswdconf $srcdir/certs/srp-verifier-conf";
   1491 
   1492     my $cmd = "$httptlssrv $flags > $logfile 2>&1";
   1493     my ($httptlspid, $pid2) = startnew($cmd, $pidfile, 10, 1); # fake pidfile
   1494 
   1495     if($httptlspid <= 0 || !pidexists($httptlspid)) {
   1496         # it is NOT alive
   1497         logmsg "RUN: failed to start the $srvrname server\n";
   1498         stopserver($server, "$pid2");
   1499         displaylogs($testnumcheck);
   1500         $doesntrun{$pidfile} = 1;
   1501         return (0,0);
   1502     }
   1503 
   1504     # Server is up. Verify that we can speak to it. PID is from fake pidfile
   1505     my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port);
   1506     if(!$pid3) {
   1507         logmsg "RUN: $srvrname server failed verification\n";
   1508         # failed to talk to it properly. Kill the server and return failure
   1509         stopserver($server, "$httptlspid $pid2");
   1510         displaylogs($testnumcheck);
   1511         $doesntrun{$pidfile} = 1;
   1512         return (0,0);
   1513     }
   1514     $pid2 = $pid3;
   1515 
   1516     if($verbose) {
   1517         logmsg "RUN: $srvrname server is now running PID $httptlspid\n";
   1518     }
   1519 
   1520     sleep(1);
   1521 
   1522     return ($httptlspid, $pid2);
   1523 }
   1524 
   1525 #######################################################################
   1526 # start the pingpong server (FTP, POP3, IMAP, SMTP)
   1527 #
   1528 sub runpingpongserver {
   1529     my ($proto, $id, $verbose, $ipv6) = @_;
   1530     my $port;
   1531     my $ip = ($ipv6 && ($ipv6 =~ /6$/)) ? "$HOST6IP" : "$HOSTIP";
   1532     my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4;
   1533     my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
   1534     my $server;
   1535     my $srvrname;
   1536     my $pidfile;
   1537     my $logfile;
   1538     my $flags = "";
   1539 
   1540     if($proto eq "ftp") {
   1541         $port = ($idnum>1)?$FTP2PORT:$FTPPORT;
   1542 
   1543         if($ipvnum==6) {
   1544             # if IPv6, use a different setup
   1545             $port = $FTP6PORT;
   1546         }
   1547     }
   1548     elsif($proto eq "pop3") {
   1549         $port = ($ipvnum==6) ? $POP36PORT : $POP3PORT;
   1550     }
   1551     elsif($proto eq "imap") {
   1552         $port = ($ipvnum==6) ? $IMAP6PORT : $IMAPPORT;
   1553     }
   1554     elsif($proto eq "smtp") {
   1555         $port = ($ipvnum==6) ? $SMTP6PORT : $SMTPPORT;
   1556     }
   1557     else {
   1558         print STDERR "Unsupported protocol $proto!!\n";
   1559         return 0;
   1560     }
   1561 
   1562     $server = servername_id($proto, $ipvnum, $idnum);
   1563 
   1564     $pidfile = $serverpidfile{$server};
   1565 
   1566     # don't retry if the server doesn't work
   1567     if ($doesntrun{$pidfile}) {
   1568         return (0,0);
   1569     }
   1570 
   1571     my $pid = processexists($pidfile);
   1572     if($pid > 0) {
   1573         stopserver($server, "$pid");
   1574     }
   1575     unlink($pidfile) if(-f $pidfile);
   1576 
   1577     $srvrname = servername_str($proto, $ipvnum, $idnum);
   1578 
   1579     $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
   1580 
   1581     $flags .= "--verbose " if($debugprotocol);
   1582     $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
   1583     $flags .= "--srcdir \"$srcdir\" --proto $proto ";
   1584     $flags .= "--id $idnum " if($idnum > 1);
   1585     $flags .= "--ipv$ipvnum --port $port --addr \"$ip\"";
   1586 
   1587     my $cmd = "$perl $srcdir/ftpserver.pl $flags";
   1588     my ($ftppid, $pid2) = startnew($cmd, $pidfile, 15, 0);
   1589 
   1590     if($ftppid <= 0 || !pidexists($ftppid)) {
   1591         # it is NOT alive
   1592         logmsg "RUN: failed to start the $srvrname server\n";
   1593         stopserver($server, "$pid2");
   1594         displaylogs($testnumcheck);
   1595         $doesntrun{$pidfile} = 1;
   1596         return (0,0);
   1597     }
   1598 
   1599     # Server is up. Verify that we can speak to it.
   1600     my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port);
   1601     if(!$pid3) {
   1602         logmsg "RUN: $srvrname server failed verification\n";
   1603         # failed to talk to it properly. Kill the server and return failure
   1604         stopserver($server, "$ftppid $pid2");
   1605         displaylogs($testnumcheck);
   1606         $doesntrun{$pidfile} = 1;
   1607         return (0,0);
   1608     }
   1609 
   1610     $pid2 = $pid3;
   1611 
   1612     if($verbose) {
   1613         logmsg "RUN: $srvrname server is now running PID $ftppid\n";
   1614     }
   1615 
   1616     sleep(1);
   1617 
   1618     return ($pid2, $ftppid);
   1619 }
   1620 
   1621 #######################################################################
   1622 # start the ftps server (or rather, tunnel)
   1623 #
   1624 sub runftpsserver {
   1625     my ($verbose, $ipv6, $certfile) = @_;
   1626     my $proto = 'ftps';
   1627     my $ip = ($ipv6 && ($ipv6 =~ /6$/)) ? "$HOST6IP" : "$HOSTIP";
   1628     my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4;
   1629     my $idnum = 1;
   1630     my $server;
   1631     my $srvrname;
   1632     my $pidfile;
   1633     my $logfile;
   1634     my $flags = "";
   1635 
   1636     if(!$stunnel) {
   1637         return (0,0);
   1638     }
   1639 
   1640     $server = servername_id($proto, $ipvnum, $idnum);
   1641 
   1642     $pidfile = $serverpidfile{$server};
   1643 
   1644     # don't retry if the server doesn't work
   1645     if ($doesntrun{$pidfile}) {
   1646         return (0,0);
   1647     }
   1648 
   1649     my $pid = processexists($pidfile);
   1650     if($pid > 0) {
   1651         stopserver($server, "$pid");
   1652     }
   1653     unlink($pidfile) if(-f $pidfile);
   1654 
   1655     $srvrname = servername_str($proto, $ipvnum, $idnum);
   1656 
   1657     $certfile = 'stunnel.pem' unless($certfile);
   1658 
   1659     $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
   1660 
   1661     $flags .= "--verbose " if($debugprotocol);
   1662     $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
   1663     $flags .= "--id $idnum " if($idnum > 1);
   1664     $flags .= "--ipv$ipvnum --proto $proto ";
   1665     $flags .= "--certfile \"$certfile\" " if($certfile ne 'stunnel.pem');
   1666     $flags .= "--stunnel \"$stunnel\" --srcdir \"$srcdir\" ";
   1667     $flags .= "--connect $FTPPORT --accept $FTPSPORT";
   1668 
   1669     my $cmd = "$perl $srcdir/secureserver.pl $flags";
   1670     my ($ftpspid, $pid2) = startnew($cmd, $pidfile, 15, 0);
   1671 
   1672     if($ftpspid <= 0 || !pidexists($ftpspid)) {
   1673         # it is NOT alive
   1674         logmsg "RUN: failed to start the $srvrname server\n";
   1675         stopserver($server, "$pid2");
   1676         displaylogs($testnumcheck);
   1677         $doesntrun{$pidfile} = 1;
   1678         return(0,0);
   1679     }
   1680 
   1681     # Server is up. Verify that we can speak to it.
   1682     my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $FTPSPORT);
   1683     if(!$pid3) {
   1684         logmsg "RUN: $srvrname server failed verification\n";
   1685         # failed to talk to it properly. Kill the server and return failure
   1686         stopserver($server, "$ftpspid $pid2");
   1687         displaylogs($testnumcheck);
   1688         $doesntrun{$pidfile} = 1;
   1689         return (0,0);
   1690     }
   1691     # Here pid3 is actually the pid returned by the unsecure-ftp server.
   1692 
   1693     $runcert{$server} = $certfile;
   1694 
   1695     if($verbose) {
   1696         logmsg "RUN: $srvrname server is now running PID $ftpspid\n";
   1697     }
   1698 
   1699     sleep(1);
   1700 
   1701     return ($ftpspid, $pid2);
   1702 }
   1703 
   1704 #######################################################################
   1705 # start the tftp server
   1706 #
   1707 sub runtftpserver {
   1708     my ($id, $verbose, $ipv6) = @_;
   1709     my $port = $TFTPPORT;
   1710     my $ip = $HOSTIP;
   1711     my $proto = 'tftp';
   1712     my $ipvnum = 4;
   1713     my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
   1714     my $server;
   1715     my $srvrname;
   1716     my $pidfile;
   1717     my $logfile;
   1718     my $flags = "";
   1719 
   1720     if($ipv6) {
   1721         # if IPv6, use a different setup
   1722         $ipvnum = 6;
   1723         $port = $TFTP6PORT;
   1724         $ip = $HOST6IP;
   1725     }
   1726 
   1727     $server = servername_id($proto, $ipvnum, $idnum);
   1728 
   1729     $pidfile = $serverpidfile{$server};
   1730 
   1731     # don't retry if the server doesn't work
   1732     if ($doesntrun{$pidfile}) {
   1733         return (0,0);
   1734     }
   1735 
   1736     my $pid = processexists($pidfile);
   1737     if($pid > 0) {
   1738         stopserver($server, "$pid");
   1739     }
   1740     unlink($pidfile) if(-f $pidfile);
   1741 
   1742     $srvrname = servername_str($proto, $ipvnum, $idnum);
   1743 
   1744     $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
   1745 
   1746     $flags .= "--verbose " if($debugprotocol);
   1747     $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
   1748     $flags .= "--id $idnum " if($idnum > 1);
   1749     $flags .= "--ipv$ipvnum --port $port --srcdir \"$srcdir\"";
   1750 
   1751     my $cmd = "$perl $srcdir/tftpserver.pl $flags";
   1752     my ($tftppid, $pid2) = startnew($cmd, $pidfile, 15, 0);
   1753 
   1754     if($tftppid <= 0 || !pidexists($tftppid)) {
   1755         # it is NOT alive
   1756         logmsg "RUN: failed to start the $srvrname server\n";
   1757         stopserver($server, "$pid2");
   1758         displaylogs($testnumcheck);
   1759         $doesntrun{$pidfile} = 1;
   1760         return (0,0);
   1761     }
   1762 
   1763     # Server is up. Verify that we can speak to it.
   1764     my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port);
   1765     if(!$pid3) {
   1766         logmsg "RUN: $srvrname server failed verification\n";
   1767         # failed to talk to it properly. Kill the server and return failure
   1768         stopserver($server, "$tftppid $pid2");
   1769         displaylogs($testnumcheck);
   1770         $doesntrun{$pidfile} = 1;
   1771         return (0,0);
   1772     }
   1773     $pid2 = $pid3;
   1774 
   1775     if($verbose) {
   1776         logmsg "RUN: $srvrname server is now running PID $tftppid\n";
   1777     }
   1778 
   1779     sleep(1);
   1780 
   1781     return ($pid2, $tftppid);
   1782 }
   1783 
   1784 
   1785 #######################################################################
   1786 # start the rtsp server
   1787 #
   1788 sub runrtspserver {
   1789     my ($verbose, $ipv6) = @_;
   1790     my $port = $RTSPPORT;
   1791     my $ip = $HOSTIP;
   1792     my $proto = 'rtsp';
   1793     my $ipvnum = 4;
   1794     my $idnum = 1;
   1795     my $server;
   1796     my $srvrname;
   1797     my $pidfile;
   1798     my $logfile;
   1799     my $flags = "";
   1800 
   1801     if($ipv6) {
   1802         # if IPv6, use a different setup
   1803         $ipvnum = 6;
   1804         $port = $RTSP6PORT;
   1805         $ip = $HOST6IP;
   1806     }
   1807 
   1808     $server = servername_id($proto, $ipvnum, $idnum);
   1809 
   1810     $pidfile = $serverpidfile{$server};
   1811 
   1812     # don't retry if the server doesn't work
   1813     if ($doesntrun{$pidfile}) {
   1814         return (0,0);
   1815     }
   1816 
   1817     my $pid = processexists($pidfile);
   1818     if($pid > 0) {
   1819         stopserver($server, "$pid");
   1820     }
   1821     unlink($pidfile) if(-f $pidfile);
   1822 
   1823     $srvrname = servername_str($proto, $ipvnum, $idnum);
   1824 
   1825     $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
   1826 
   1827     $flags .= "--verbose " if($debugprotocol);
   1828     $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
   1829     $flags .= "--id $idnum " if($idnum > 1);
   1830     $flags .= "--ipv$ipvnum --port $port --srcdir \"$srcdir\"";
   1831 
   1832     my $cmd = "$perl $srcdir/rtspserver.pl $flags";
   1833     my ($rtsppid, $pid2) = startnew($cmd, $pidfile, 15, 0);
   1834 
   1835     if($rtsppid <= 0 || !pidexists($rtsppid)) {
   1836         # it is NOT alive
   1837         logmsg "RUN: failed to start the $srvrname server\n";
   1838         stopserver($server, "$pid2");
   1839         displaylogs($testnumcheck);
   1840         $doesntrun{$pidfile} = 1;
   1841         return (0,0);
   1842     }
   1843 
   1844     # Server is up. Verify that we can speak to it.
   1845     my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port);
   1846     if(!$pid3) {
   1847         logmsg "RUN: $srvrname server failed verification\n";
   1848         # failed to talk to it properly. Kill the server and return failure
   1849         stopserver($server, "$rtsppid $pid2");
   1850         displaylogs($testnumcheck);
   1851         $doesntrun{$pidfile} = 1;
   1852         return (0,0);
   1853     }
   1854     $pid2 = $pid3;
   1855 
   1856     if($verbose) {
   1857         logmsg "RUN: $srvrname server is now running PID $rtsppid\n";
   1858     }
   1859 
   1860     sleep(1);
   1861 
   1862     return ($rtsppid, $pid2);
   1863 }
   1864 
   1865 
   1866 #######################################################################
   1867 # Start the ssh (scp/sftp) server
   1868 #
   1869 sub runsshserver {
   1870     my ($id, $verbose, $ipv6) = @_;
   1871     my $ip=$HOSTIP;
   1872     my $port = $SSHPORT;
   1873     my $socksport = $SOCKSPORT;
   1874     my $proto = 'ssh';
   1875     my $ipvnum = 4;
   1876     my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
   1877     my $server;
   1878     my $srvrname;
   1879     my $pidfile;
   1880     my $logfile;
   1881     my $flags = "";
   1882 
   1883     $server = servername_id($proto, $ipvnum, $idnum);
   1884 
   1885     $pidfile = $serverpidfile{$server};
   1886 
   1887     # don't retry if the server doesn't work
   1888     if ($doesntrun{$pidfile}) {
   1889         return (0,0);
   1890     }
   1891 
   1892     my $pid = processexists($pidfile);
   1893     if($pid > 0) {
   1894         stopserver($server, "$pid");
   1895     }
   1896     unlink($pidfile) if(-f $pidfile);
   1897 
   1898     $srvrname = servername_str($proto, $ipvnum, $idnum);
   1899 
   1900     $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
   1901 
   1902     $flags .= "--verbose " if($verbose);
   1903     $flags .= "--debugprotocol " if($debugprotocol);
   1904     $flags .= "--pidfile \"$pidfile\" ";
   1905     $flags .= "--id $idnum " if($idnum > 1);
   1906     $flags .= "--ipv$ipvnum --addr \"$ip\" ";
   1907     $flags .= "--sshport $port --socksport $socksport ";
   1908     $flags .= "--user \"$USER\"";
   1909 
   1910     my $cmd = "$perl $srcdir/sshserver.pl $flags";
   1911     my ($sshpid, $pid2) = startnew($cmd, $pidfile, 60, 0);
   1912 
   1913     # on loaded systems sshserver start up can take longer than the timeout
   1914     # passed to startnew, when this happens startnew completes without being
   1915     # able to read the pidfile and consequently returns a zero pid2 above.
   1916 
   1917     if($sshpid <= 0 || !pidexists($sshpid)) {
   1918         # it is NOT alive
   1919         logmsg "RUN: failed to start the $srvrname server\n";
   1920         stopserver($server, "$pid2");
   1921         $doesntrun{$pidfile} = 1;
   1922         return (0,0);
   1923     }
   1924 
   1925     # ssh server verification allows some extra time for the server to start up
   1926     # and gives us the opportunity of recovering the pid from the pidfile, when
   1927     # this verification succeeds the recovered pid is assigned to pid2.
   1928 
   1929     my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port);
   1930     if(!$pid3) {
   1931         logmsg "RUN: $srvrname server failed verification\n";
   1932         # failed to fetch server pid. Kill the server and return failure
   1933         stopserver($server, "$sshpid $pid2");
   1934         $doesntrun{$pidfile} = 1;
   1935         return (0,0);
   1936     }
   1937     $pid2 = $pid3;
   1938 
   1939     # once it is known that the ssh server is alive, sftp server verification
   1940     # is performed actually connecting to it, authenticating and performing a
   1941     # very simple remote command.  This verification is tried only one time.
   1942 
   1943     $sshdlog = server_logfilename($LOGDIR, 'ssh', $ipvnum, $idnum);
   1944     $sftplog = server_logfilename($LOGDIR, 'sftp', $ipvnum, $idnum);
   1945 
   1946     if(verifysftp('sftp', $ipvnum, $idnum, $ip, $port) < 1) {
   1947         logmsg "RUN: SFTP server failed verification\n";
   1948         # failed to talk to it properly. Kill the server and return failure
   1949         display_sftplog();
   1950         display_sftpconfig();
   1951         display_sshdlog();
   1952         display_sshdconfig();
   1953         stopserver($server, "$sshpid $pid2");
   1954         $doesntrun{$pidfile} = 1;
   1955         return (0,0);
   1956     }
   1957 
   1958     if($verbose) {
   1959         logmsg "RUN: $srvrname server is now running PID $pid2\n";
   1960     }
   1961 
   1962     return ($pid2, $sshpid);
   1963 }
   1964 
   1965 #######################################################################
   1966 # Start the socks server
   1967 #
   1968 sub runsocksserver {
   1969     my ($id, $verbose, $ipv6) = @_;
   1970     my $ip=$HOSTIP;
   1971     my $port = $SOCKSPORT;
   1972     my $proto = 'socks';
   1973     my $ipvnum = 4;
   1974     my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
   1975     my $server;
   1976     my $srvrname;
   1977     my $pidfile;
   1978     my $logfile;
   1979     my $flags = "";
   1980 
   1981     $server = servername_id($proto, $ipvnum, $idnum);
   1982 
   1983     $pidfile = $serverpidfile{$server};
   1984 
   1985     # don't retry if the server doesn't work
   1986     if ($doesntrun{$pidfile}) {
   1987         return (0,0);
   1988     }
   1989 
   1990     my $pid = processexists($pidfile);
   1991     if($pid > 0) {
   1992         stopserver($server, "$pid");
   1993     }
   1994     unlink($pidfile) if(-f $pidfile);
   1995 
   1996     $srvrname = servername_str($proto, $ipvnum, $idnum);
   1997 
   1998     $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
   1999 
   2000     # The ssh server must be already running
   2001     if(!$run{'ssh'}) {
   2002         logmsg "RUN: SOCKS server cannot find running SSH server\n";
   2003         $doesntrun{$pidfile} = 1;
   2004         return (0,0);
   2005     }
   2006 
   2007     # Find out ssh daemon canonical file name
   2008     my $sshd = find_sshd();
   2009     if(!$sshd) {
   2010         logmsg "RUN: SOCKS server cannot find $sshdexe\n";
   2011         $doesntrun{$pidfile} = 1;
   2012         return (0,0);
   2013     }
   2014 
   2015     # Find out ssh daemon version info
   2016     ($sshdid, $sshdvernum, $sshdverstr, $sshderror) = sshversioninfo($sshd);
   2017     if(!$sshdid) {
   2018         # Not an OpenSSH or SunSSH ssh daemon
   2019         logmsg "$sshderror\n" if($verbose);
   2020         logmsg "SCP, SFTP and SOCKS tests require OpenSSH 2.9.9 or later\n";
   2021         $doesntrun{$pidfile} = 1;
   2022         return (0,0);
   2023     }
   2024     logmsg "ssh server found $sshd is $sshdverstr\n" if($verbose);
   2025 
   2026     # Find out ssh client canonical file name
   2027     my $ssh = find_ssh();
   2028     if(!$ssh) {
   2029         logmsg "RUN: SOCKS server cannot find $sshexe\n";
   2030         $doesntrun{$pidfile} = 1;
   2031         return (0,0);
   2032     }
   2033 
   2034     # Find out ssh client version info
   2035     my ($sshid, $sshvernum, $sshverstr, $ssherror) = sshversioninfo($ssh);
   2036     if(!$sshid) {
   2037         # Not an OpenSSH or SunSSH ssh client
   2038         logmsg "$ssherror\n" if($verbose);
   2039         logmsg "SCP, SFTP and SOCKS tests require OpenSSH 2.9.9 or later\n";
   2040         $doesntrun{$pidfile} = 1;
   2041         return (0,0);
   2042     }
   2043 
   2044     # Verify minimum ssh client version
   2045     if((($sshid =~ /OpenSSH/) && ($sshvernum < 299)) ||
   2046        (($sshid =~ /SunSSH/)  && ($sshvernum < 100))) {
   2047         logmsg "ssh client found $ssh is $sshverstr\n";
   2048         logmsg "SCP, SFTP and SOCKS tests require OpenSSH 2.9.9 or later\n";
   2049         $doesntrun{$pidfile} = 1;
   2050         return (0,0);
   2051     }
   2052     logmsg "ssh client found $ssh is $sshverstr\n" if($verbose);
   2053 
   2054     # Verify if ssh client and ssh daemon versions match
   2055     if(($sshdid ne $sshid) || ($sshdvernum != $sshvernum)) {
   2056         # Our test harness might work with slightly mismatched versions
   2057         logmsg "Warning: version mismatch: sshd $sshdverstr - ssh $sshverstr\n"
   2058             if($verbose);
   2059     }
   2060 
   2061     # Config file options for ssh client are previously set from sshserver.pl
   2062     if(! -e $sshconfig) {
   2063         logmsg "RUN: SOCKS server cannot find $sshconfig\n";
   2064         $doesntrun{$pidfile} = 1;
   2065         return (0,0);
   2066     }
   2067 
   2068     $sshlog  = server_logfilename($LOGDIR, 'socks', $ipvnum, $idnum);
   2069 
   2070     # start our socks server
   2071     my $cmd="\"$ssh\" -N -F $sshconfig $ip > $sshlog 2>&1";
   2072     my ($sshpid, $pid2) = startnew($cmd, $pidfile, 30, 1); # fake pidfile
   2073 
   2074     if($sshpid <= 0 || !pidexists($sshpid)) {
   2075         # it is NOT alive
   2076         logmsg "RUN: failed to start the $srvrname server\n";
   2077         display_sshlog();
   2078         display_sshconfig();
   2079         display_sshdlog();
   2080         display_sshdconfig();
   2081         stopserver($server, "$pid2");
   2082         $doesntrun{$pidfile} = 1;
   2083         return (0,0);
   2084     }
   2085 
   2086     # Ugly hack but ssh doesn't support pid files. PID is from fake pidfile.
   2087     my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port);
   2088     if(!$pid3) {
   2089         logmsg "RUN: $srvrname server failed verification\n";
   2090         # failed to talk to it properly. Kill the server and return failure
   2091         stopserver($server, "$sshpid $pid2");
   2092         $doesntrun{$pidfile} = 1;
   2093         return (0,0);
   2094     }
   2095     $pid2 = $pid3;
   2096 
   2097     if($verbose) {
   2098         logmsg "RUN: $srvrname server is now running PID $pid2\n";
   2099     }
   2100 
   2101     return ($pid2, $sshpid);
   2102 }
   2103 
   2104 #######################################################################
   2105 # Single shot http and gopher server responsiveness test. This should only
   2106 # be used to verify that a server present in %run hash is still functional
   2107 #
   2108 sub responsive_http_server {
   2109     my ($proto, $verbose, $alt, $port_or_path) = @_;
   2110     my $ip = $HOSTIP;
   2111     my $ipvnum = 4;
   2112     my $idnum = 1;
   2113 
   2114     if($alt eq "ipv6") {
   2115         # if IPv6, use a different setup
   2116         $ipvnum = 6;
   2117         $ip = $HOST6IP;
   2118     }
   2119     elsif($alt eq "proxy") {
   2120         $idnum = 2;
   2121     }
   2122     elsif($alt eq "unix") {
   2123         # IP (protocol) is mutually exclusive with Unix sockets
   2124         $ipvnum = "unix";
   2125     }
   2126 
   2127     return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port_or_path);
   2128 }
   2129 
   2130 #######################################################################
   2131 # Single shot pingpong server responsiveness test. This should only be
   2132 # used to verify that a server present in %run hash is still functional
   2133 #
   2134 sub responsive_pingpong_server {
   2135     my ($proto, $id, $verbose, $ipv6) = @_;
   2136     my $port;
   2137     my $ip = ($ipv6 && ($ipv6 =~ /6$/)) ? "$HOST6IP" : "$HOSTIP";
   2138     my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4;
   2139     my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
   2140 
   2141     if($proto eq "ftp") {
   2142         $port = ($idnum>1)?$FTP2PORT:$FTPPORT;
   2143 
   2144         if($ipvnum==6) {
   2145             # if IPv6, use a different setup
   2146             $port = $FTP6PORT;
   2147         }
   2148     }
   2149     elsif($proto eq "pop3") {
   2150         $port = ($ipvnum==6) ? $POP36PORT : $POP3PORT;
   2151     }
   2152     elsif($proto eq "imap") {
   2153         $port = ($ipvnum==6) ? $IMAP6PORT : $IMAPPORT;
   2154     }
   2155     elsif($proto eq "smtp") {
   2156         $port = ($ipvnum==6) ? $SMTP6PORT : $SMTPPORT;
   2157     }
   2158     else {
   2159         print STDERR "Unsupported protocol $proto!!\n";
   2160         return 0;
   2161     }
   2162 
   2163     return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port);
   2164 }
   2165 
   2166 #######################################################################
   2167 # Single shot rtsp server responsiveness test. This should only be
   2168 # used to verify that a server present in %run hash is still functional
   2169 #
   2170 sub responsive_rtsp_server {
   2171     my ($verbose, $ipv6) = @_;
   2172     my $port = $RTSPPORT;
   2173     my $ip = $HOSTIP;
   2174     my $proto = 'rtsp';
   2175     my $ipvnum = 4;
   2176     my $idnum = 1;
   2177 
   2178     if($ipv6) {
   2179         # if IPv6, use a different setup
   2180         $ipvnum = 6;
   2181         $port = $RTSP6PORT;
   2182         $ip = $HOST6IP;
   2183     }
   2184 
   2185     return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port);
   2186 }
   2187 
   2188 #######################################################################
   2189 # Single shot tftp server responsiveness test. This should only be
   2190 # used to verify that a server present in %run hash is still functional
   2191 #
   2192 sub responsive_tftp_server {
   2193     my ($id, $verbose, $ipv6) = @_;
   2194     my $port = $TFTPPORT;
   2195     my $ip = $HOSTIP;
   2196     my $proto = 'tftp';
   2197     my $ipvnum = 4;
   2198     my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
   2199 
   2200     if($ipv6) {
   2201         # if IPv6, use a different setup
   2202         $ipvnum = 6;
   2203         $port = $TFTP6PORT;
   2204         $ip = $HOST6IP;
   2205     }
   2206 
   2207     return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port);
   2208 }
   2209 
   2210 #######################################################################
   2211 # Single shot non-stunnel HTTP TLS extensions capable server
   2212 # responsiveness test. This should only be used to verify that a
   2213 # server present in %run hash is still functional
   2214 #
   2215 sub responsive_httptls_server {
   2216     my ($verbose, $ipv6) = @_;
   2217     my $proto = "httptls";
   2218     my $port = ($ipv6 && ($ipv6 =~ /6$/)) ? $HTTPTLS6PORT : $HTTPTLSPORT;
   2219     my $ip = ($ipv6 && ($ipv6 =~ /6$/)) ? "$HOST6IP" : "$HOSTIP";
   2220     my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4;
   2221     my $idnum = 1;
   2222 
   2223     return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port);
   2224 }
   2225 
   2226 #######################################################################
   2227 # Remove all files in the specified directory
   2228 #
   2229 sub cleardir {
   2230     my $dir = $_[0];
   2231     my $count;
   2232     my $file;
   2233 
   2234     # Get all files
   2235     opendir(DIR, $dir) ||
   2236         return 0; # can't open dir
   2237     while($file = readdir(DIR)) {
   2238         if($file !~ /^\./) {
   2239             unlink("$dir/$file");
   2240             $count++;
   2241         }
   2242     }
   2243     closedir DIR;
   2244     return $count;
   2245 }
   2246 
   2247 #######################################################################
   2248 # compare test results with the expected output, we might filter off
   2249 # some pattern that is allowed to differ, output test results
   2250 #
   2251 sub compare {
   2252     my ($testnum, $testname, $subject, $firstref, $secondref)=@_;
   2253 
   2254     my $result = compareparts($firstref, $secondref);
   2255 
   2256     if($result) {
   2257         # timestamp test result verification end
   2258         $timevrfyend{$testnum} = Time::HiRes::time() if($timestats);
   2259 
   2260         if(!$short) {
   2261             logmsg "\n $testnum: $subject FAILED:\n";
   2262             logmsg showdiff($LOGDIR, $firstref, $secondref);
   2263         }
   2264         elsif(!$automakestyle) {
   2265             logmsg "FAILED\n";
   2266         }
   2267         else {
   2268             # automakestyle
   2269             logmsg "FAIL: $testnum - $testname - $subject\n";
   2270         }
   2271     }
   2272     return $result;
   2273 }
   2274 
   2275 #######################################################################
   2276 # display information about curl and the host the test suite runs on
   2277 #
   2278 sub checksystem {
   2279 
   2280     unlink($memdump); # remove this if there was one left
   2281 
   2282     my $feat;
   2283     my $curl;
   2284     my $libcurl;
   2285     my $versretval;
   2286     my $versnoexec;
   2287     my @version=();
   2288 
   2289     my $curlverout="$LOGDIR/curlverout.log";
   2290     my $curlvererr="$LOGDIR/curlvererr.log";
   2291     my $versioncmd="$CURL --version 1>$curlverout 2>$curlvererr";
   2292 
   2293     unlink($curlverout);
   2294     unlink($curlvererr);
   2295 
   2296     $versretval = runclient($versioncmd);
   2297     $versnoexec = $!;
   2298 
   2299     open(VERSOUT, "<$curlverout");
   2300     @version = <VERSOUT>;
   2301     close(VERSOUT);
   2302 
   2303     $resolver="stock";
   2304     for(@version) {
   2305         chomp;
   2306 
   2307         if($_ =~ /^curl/) {
   2308             $curl = $_;
   2309             $curl =~ s/^(.*)(libcurl.*)/$1/g;
   2310 
   2311             $libcurl = $2;
   2312             if($curl =~ /mingw32/) {
   2313                 # This is a windows minw32 build, we need to translate the
   2314                 # given path to the "actual" windows path. The MSYS shell
   2315                 # has a builtin 'pwd -W' command which converts the path.
   2316                 $pwd = `sh -c "echo \$(pwd -W)"`;
   2317                 chomp($pwd);
   2318             }
   2319             elsif ($curl =~ /win32/) {
   2320                # Native Windows builds don't understand the
   2321                # output of cygwin's pwd.  It will be
   2322                # something like /cygdrive/c/<some path>.
   2323                #
   2324                # Use the cygpath utility to convert the
   2325                # working directory to a Windows friendly
   2326                # path.  The -m option converts to use drive
   2327                # letter:, but it uses / instead \.  Forward
   2328                # slashes (/) are easier for us.  We don't
   2329                # have to escape them to get them to curl
   2330                # through a shell.
   2331                chomp($pwd = `cygpath -m $pwd`);
   2332            }
   2333            if ($libcurl =~ /winssl/i) {
   2334                $has_winssl=1;
   2335                $ssllib="WinSSL";
   2336            }
   2337            elsif ($libcurl =~ /openssl/i) {
   2338                $has_openssl=1;
   2339                $has_sslpinning=1;
   2340                $ssllib="OpenSSL";
   2341            }
   2342            elsif ($libcurl =~ /gnutls/i) {
   2343                $has_gnutls=1;
   2344                $has_sslpinning=1;
   2345                $ssllib="GnuTLS";
   2346            }
   2347            elsif ($libcurl =~ /nss/i) {
   2348                $has_nss=1;
   2349                $has_sslpinning=1;
   2350                $ssllib="NSS";
   2351            }
   2352            elsif ($libcurl =~ /(yassl|wolfssl)/i) {
   2353                $has_yassl=1;
   2354                $has_sslpinning=1;
   2355                $ssllib="yassl";
   2356            }
   2357            elsif ($libcurl =~ /polarssl/i) {
   2358                $has_polarssl=1;
   2359                $ssllib="polarssl";
   2360            }
   2361            elsif ($libcurl =~ /axtls/i) {
   2362                $has_axtls=1;
   2363                $ssllib="axTLS";
   2364            }
   2365            elsif ($libcurl =~ /securetransport/i) {
   2366                $has_darwinssl=1;
   2367                $ssllib="DarwinSSL";
   2368            }
   2369            elsif ($libcurl =~ /BoringSSL/i) {
   2370                $has_boringssl=1;
   2371                $ssllib="BoringSSL";
   2372            }
   2373            elsif ($libcurl =~ /libressl/i) {
   2374                $has_libressl=1;
   2375                $ssllib="libressl";
   2376            }
   2377            if ($libcurl =~ /ares/i) {
   2378                $has_cares=1;
   2379                $resolver="c-ares";
   2380            }
   2381         }
   2382         elsif($_ =~ /^Protocols: (.*)/i) {
   2383             # these are the protocols compiled in to this libcurl
   2384             @protocols = split(' ', lc($1));
   2385 
   2386             # Generate a "proto-ipv6" version of each protocol to match the
   2387             # IPv6 <server> name and a "proto-unix" to match the variant which
   2388             # uses Unix domain sockets. This works even if support isn't
   2389             # compiled in because the <features> test will fail.
   2390             push @protocols, map(("$_-ipv6", "$_-unix"), @protocols);
   2391 
   2392             # 'http-proxy' is used in test cases to do CONNECT through
   2393             push @protocols, 'http-proxy';
   2394 
   2395             # 'http-pipe' is the special server for testing pipelining
   2396             push @protocols, 'http-pipe';
   2397 
   2398             # 'none' is used in test cases to mean no server
   2399             push @protocols, 'none';
   2400         }
   2401         elsif($_ =~ /^Features: (.*)/i) {
   2402             $feat = $1;
   2403             if($feat =~ /TrackMemory/i) {
   2404                 # built with memory tracking support (--enable-curldebug)
   2405                 $has_memory_tracking = 1;
   2406             }
   2407             if($feat =~ /debug/i) {
   2408                 # curl was built with --enable-debug
   2409                 $debug_build = 1;
   2410             }
   2411             if($feat =~ /SSL/i) {
   2412                 # ssl enabled
   2413                 $ssl_version=1;
   2414             }
   2415             if($feat =~ /Largefile/i) {
   2416                 # large file support
   2417                 $large_file=1;
   2418             }
   2419             if($feat =~ /IDN/i) {
   2420                 # IDN support
   2421                 $has_idn=1;
   2422             }
   2423             if($feat =~ /IPv6/i) {
   2424                 $has_ipv6 = 1;
   2425             }
   2426             if($feat =~ /UnixSockets/i) {
   2427                 $has_unix = 1;
   2428             }
   2429             if($feat =~ /libz/i) {
   2430                 $has_libz = 1;
   2431             }
   2432             if($feat =~ /NTLM/i) {
   2433                 # NTLM enabled
   2434                 $has_ntlm=1;
   2435 
   2436                 # Use this as a proxy for any cryptographic authentication
   2437                 $has_crypto=1;
   2438             }
   2439             if($feat =~ /NTLM_WB/i) {
   2440                 # NTLM delegation to winbind daemon ntlm_auth helper enabled
   2441                 $has_ntlm_wb=1;
   2442             }
   2443             if($feat =~ /SSPI/i) {
   2444                 # SSPI enabled
   2445                 $has_sspi=1;
   2446             }
   2447             if($feat =~ /GSS-API/i) {
   2448                 # GSS-API enabled
   2449                 $has_gssapi=1;
   2450             }
   2451             if($feat =~ /Kerberos/i) {
   2452                 # Kerberos enabled
   2453                 $has_kerberos=1;
   2454 
   2455                 # Use this as a proxy for any cryptographic authentication
   2456                 $has_crypto=1;
   2457             }
   2458             if($feat =~ /SPNEGO/i) {
   2459                 # SPNEGO enabled
   2460                 $has_spnego=1;
   2461 
   2462                 # Use this as a proxy for any cryptographic authentication
   2463                 $has_crypto=1;
   2464             }
   2465             if($feat =~ /CharConv/i) {
   2466                 # CharConv enabled
   2467                 $has_charconv=1;
   2468             }
   2469             if($feat =~ /TLS-SRP/i) {
   2470                 # TLS-SRP enabled
   2471                 $has_tls_srp=1;
   2472             }
   2473             if($feat =~ /Metalink/i) {
   2474                 # Metalink enabled
   2475                 $has_metalink=1;
   2476             }
   2477             if($feat =~ /AsynchDNS/i) {
   2478                 if(!$has_cares) {
   2479                     # this means threaded resolver
   2480                     $has_threadedres=1;
   2481                     $resolver="threaded";
   2482                 }
   2483             }
   2484             if($feat =~ /HTTP2/) {
   2485                 # http2 enabled
   2486                 $has_http2=1;
   2487             }
   2488         }
   2489         #
   2490         # Test harness currently uses a non-stunnel server in order to
   2491         # run HTTP TLS-SRP tests required when curl is built with https
   2492         # protocol support and TLS-SRP feature enabled. For convenience
   2493         # 'httptls' may be included in the test harness protocols array
   2494         # to differentiate this from classic stunnel based 'https' test
   2495         # harness server.
   2496         #
   2497         if($has_tls_srp) {
   2498             my $add_httptls;
   2499             for(@protocols) {
   2500                 if($_ =~ /^https(-ipv6|)$/) {
   2501                     $add_httptls=1;
   2502                     last;
   2503                 }
   2504             }
   2505             if($add_httptls && (! grep /^httptls$/, @protocols)) {
   2506                 push @protocols, 'httptls';
   2507                 push @protocols, 'httptls-ipv6';
   2508             }
   2509         }
   2510     }
   2511     if(!$curl) {
   2512         logmsg "unable to get curl's version, further details are:\n";
   2513         logmsg "issued command: \n";
   2514         logmsg "$versioncmd \n";
   2515         if ($versretval == -1) {
   2516             logmsg "command failed with: \n";
   2517             logmsg "$versnoexec \n";
   2518         }
   2519         elsif ($versretval & 127) {
   2520             logmsg sprintf("command died with signal %d, and %s coredump.\n",
   2521                            ($versretval & 127), ($versretval & 128)?"a":"no");
   2522         }
   2523         else {
   2524             logmsg sprintf("command exited with value %d \n", $versretval >> 8);
   2525         }
   2526         logmsg "contents of $curlverout: \n";
   2527         displaylogcontent("$curlverout");
   2528         logmsg "contents of $curlvererr: \n";
   2529         displaylogcontent("$curlvererr");
   2530         die "couldn't get curl's version";
   2531     }
   2532 
   2533     if(-r "../lib/curl_config.h") {
   2534         open(CONF, "<../lib/curl_config.h");
   2535         while(<CONF>) {
   2536             if($_ =~ /^\#define HAVE_GETRLIMIT/) {
   2537                 $has_getrlimit = 1;
   2538             }
   2539         }
   2540         close(CONF);
   2541     }
   2542 
   2543     if($has_ipv6) {
   2544         # client has IPv6 support
   2545 
   2546         # check if the HTTP server has it!
   2547         my @sws = `server/sws --version`;
   2548         if($sws[0] =~ /IPv6/) {
   2549             # HTTP server has IPv6 support!
   2550             $http_ipv6 = 1;
   2551             $gopher_ipv6 = 1;
   2552         }
   2553 
   2554         # check if the FTP server has it!
   2555         @sws = `server/sockfilt --version`;
   2556         if($sws[0] =~ /IPv6/) {
   2557             # FTP server has IPv6 support!
   2558             $ftp_ipv6 = 1;
   2559         }
   2560     }
   2561 
   2562     if($has_unix) {
   2563         # client has Unix sockets support, check whether the HTTP server has it
   2564         my @sws = `server/sws --version`;
   2565         $http_unix = 1 if($sws[0] =~ /unix/);
   2566     }
   2567 
   2568     if(!$has_memory_tracking && $torture) {
   2569         die "can't run torture tests since curl was built without ".
   2570             "TrackMemory feature (--enable-curldebug)";
   2571     }
   2572 
   2573     $has_shared = `sh $CURLCONFIG --built-shared`;
   2574     chomp $has_shared;
   2575 
   2576     my $hostname=join(' ', runclientoutput("hostname"));
   2577     my $hosttype=join(' ', runclientoutput("uname -a"));
   2578 
   2579     logmsg ("********* System characteristics ******** \n",
   2580     "* $curl\n",
   2581     "* $libcurl\n",
   2582     "* Features: $feat\n",
   2583     "* Host: $hostname",
   2584     "* System: $hosttype");
   2585 
   2586     if($has_memory_tracking && $has_threadedres) {
   2587         $has_memory_tracking = 0;
   2588         logmsg("*\n",
   2589                "*** DISABLES memory tracking when using threaded resolver\n",
   2590                "*\n");
   2591     }
   2592 
   2593     logmsg sprintf("* Server SSL:   %8s", $stunnel?"ON ":"OFF");
   2594     logmsg sprintf("  libcurl SSL:  %s\n", $ssl_version?"ON ":"OFF");
   2595     logmsg sprintf("* debug build:  %8s", $debug_build?"ON ":"OFF");
   2596     logmsg sprintf("  track memory: %s\n", $has_memory_tracking?"ON ":"OFF");
   2597     logmsg sprintf("* valgrind:     %8s", $valgrind?"ON ":"OFF");
   2598     logmsg sprintf("  HTTP IPv6     %s\n", $http_ipv6?"ON ":"OFF");
   2599     logmsg sprintf("* HTTP Unix     %s\n", $http_unix?"ON ":"OFF");
   2600     logmsg sprintf("* FTP IPv6      %8s", $ftp_ipv6?"ON ":"OFF");
   2601     logmsg sprintf("  Libtool lib:  %s\n", $libtool?"ON ":"OFF");
   2602     logmsg sprintf("* Shared build:      %-3s", $has_shared);
   2603     logmsg sprintf("  Resolver:     %s\n", $resolver);
   2604     if($ssl_version) {
   2605         logmsg sprintf("* SSL library: %13s\n", $ssllib);
   2606     }
   2607 
   2608     logmsg "* Ports:\n";
   2609 
   2610     logmsg sprintf("*   HTTP/%d ", $HTTPPORT);
   2611     logmsg sprintf("FTP/%d ", $FTPPORT);
   2612     logmsg sprintf("FTP2/%d ", $FTP2PORT);
   2613     logmsg sprintf("RTSP/%d ", $RTSPPORT);
   2614     if($stunnel) {
   2615         logmsg sprintf("FTPS/%d ", $FTPSPORT);
   2616         logmsg sprintf("HTTPS/%d ", $HTTPSPORT);
   2617     }
   2618     logmsg sprintf("\n*   TFTP/%d ", $TFTPPORT);
   2619     if($http_ipv6) {
   2620         logmsg sprintf("HTTP-IPv6/%d ", $HTTP6PORT);
   2621         logmsg sprintf("RTSP-IPv6/%d ", $RTSP6PORT);
   2622     }
   2623     if($ftp_ipv6) {
   2624         logmsg sprintf("FTP-IPv6/%d ", $FTP6PORT);
   2625     }
   2626     if($tftp_ipv6) {
   2627         logmsg sprintf("TFTP-IPv6/%d ", $TFTP6PORT);
   2628     }
   2629     logmsg sprintf("\n*   GOPHER/%d ", $GOPHERPORT);
   2630     if($gopher_ipv6) {
   2631         logmsg sprintf("GOPHER-IPv6/%d", $GOPHERPORT);
   2632     }
   2633     logmsg sprintf("\n*   SSH/%d ", $SSHPORT);
   2634     logmsg sprintf("SOCKS/%d ", $SOCKSPORT);
   2635     logmsg sprintf("POP3/%d ", $POP3PORT);
   2636     logmsg sprintf("IMAP/%d ", $IMAPPORT);
   2637     logmsg sprintf("SMTP/%d\n", $SMTPPORT);
   2638     if($ftp_ipv6) {
   2639         logmsg sprintf("*   POP3-IPv6/%d ", $POP36PORT);
   2640         logmsg sprintf("IMAP-IPv6/%d ", $IMAP6PORT);
   2641         logmsg sprintf("SMTP-IPv6/%d\n", $SMTP6PORT);
   2642     }
   2643     if($httptlssrv) {
   2644         logmsg sprintf("*   HTTPTLS/%d ", $HTTPTLSPORT);
   2645         if($has_ipv6) {
   2646             logmsg sprintf("HTTPTLS-IPv6/%d ", $HTTPTLS6PORT);
   2647         }
   2648         logmsg "\n";
   2649     }
   2650     logmsg sprintf("*   HTTP-PIPE/%d \n", $HTTPPIPEPORT);
   2651 
   2652     if($has_unix) {
   2653         logmsg "* Unix socket paths:\n";
   2654         if($http_unix) {
   2655             logmsg sprintf("*   HTTP-Unix:%s\n", $HTTPUNIXPATH);
   2656         }
   2657     }
   2658 
   2659     $has_textaware = ($^O eq 'MSWin32') || ($^O eq 'msys');
   2660 
   2661     logmsg "***************************************** \n";
   2662 }
   2663 
   2664 #######################################################################
   2665 # substitute the variable stuff into either a joined up file or
   2666 # a command, in either case passed by reference
   2667 #
   2668 sub subVariables {
   2669   my ($thing) = @_;
   2670 
   2671   # ports
   2672 
   2673   $$thing =~ s/%FTP6PORT/$FTP6PORT/g;
   2674   $$thing =~ s/%FTP2PORT/$FTP2PORT/g;
   2675   $$thing =~ s/%FTPSPORT/$FTPSPORT/g;
   2676   $$thing =~ s/%FTPPORT/$FTPPORT/g;
   2677 
   2678   $$thing =~ s/%GOPHER6PORT/$GOPHER6PORT/g;
   2679   $$thing =~ s/%GOPHERPORT/$GOPHERPORT/g;
   2680 
   2681   $$thing =~ s/%HTTPTLS6PORT/$HTTPTLS6PORT/g;
   2682   $$thing =~ s/%HTTPTLSPORT/$HTTPTLSPORT/g;
   2683   $$thing =~ s/%HTTP6PORT/$HTTP6PORT/g;
   2684   $$thing =~ s/%HTTPSPORT/$HTTPSPORT/g;
   2685   $$thing =~ s/%HTTPPORT/$HTTPPORT/g;
   2686   $$thing =~ s/%HTTPPIPEPORT/$HTTPPIPEPORT/g;
   2687   $$thing =~ s/%PROXYPORT/$HTTPPROXYPORT/g;
   2688 
   2689   $$thing =~ s/%IMAP6PORT/$IMAP6PORT/g;
   2690   $$thing =~ s/%IMAPPORT/$IMAPPORT/g;
   2691 
   2692   $$thing =~ s/%POP36PORT/$POP36PORT/g;
   2693   $$thing =~ s/%POP3PORT/$POP3PORT/g;
   2694 
   2695   $$thing =~ s/%RTSP6PORT/$RTSP6PORT/g;
   2696   $$thing =~ s/%RTSPPORT/$RTSPPORT/g;
   2697 
   2698   $$thing =~ s/%SMTP6PORT/$SMTP6PORT/g;
   2699   $$thing =~ s/%SMTPPORT/$SMTPPORT/g;
   2700 
   2701   $$thing =~ s/%SOCKSPORT/$SOCKSPORT/g;
   2702   $$thing =~ s/%SSHPORT/$SSHPORT/g;
   2703 
   2704   $$thing =~ s/%TFTP6PORT/$TFTP6PORT/g;
   2705   $$thing =~ s/%TFTPPORT/$TFTPPORT/g;
   2706 
   2707   # server Unix domain socket paths
   2708 
   2709   $$thing =~ s/%HTTPUNIXPATH/$HTTPUNIXPATH/g;
   2710 
   2711   # client IP addresses
   2712 
   2713   $$thing =~ s/%CLIENT6IP/$CLIENT6IP/g;
   2714   $$thing =~ s/%CLIENTIP/$CLIENTIP/g;
   2715 
   2716   # server IP addresses
   2717 
   2718   $$thing =~ s/%HOST6IP/$HOST6IP/g;
   2719   $$thing =~ s/%HOSTIP/$HOSTIP/g;
   2720 
   2721   # misc
   2722 
   2723   $$thing =~ s/%CURL/$CURL/g;
   2724   $$thing =~ s/%PWD/$pwd/g;
   2725   $$thing =~ s/%SRCDIR/$srcdir/g;
   2726   $$thing =~ s/%USER/$USER/g;
   2727 
   2728   # The purpose of FTPTIME2 and FTPTIME3 is to provide times that can be
   2729   # used for time-out tests and that whould work on most hosts as these
   2730   # adjust for the startup/check time for this particular host. We needed
   2731   # to do this to make the test suite run better on very slow hosts.
   2732 
   2733   my $ftp2 = $ftpchecktime * 2;
   2734   my $ftp3 = $ftpchecktime * 3;
   2735 
   2736   $$thing =~ s/%FTPTIME2/$ftp2/g;
   2737   $$thing =~ s/%FTPTIME3/$ftp3/g;
   2738 
   2739   # HTTP2
   2740 
   2741   $$thing =~ s/%H2CVER/$h2cver/g;  
   2742 }
   2743 
   2744 sub fixarray {
   2745     my @in = @_;
   2746 
   2747     for(@in) {
   2748         subVariables \$_;
   2749     }
   2750     return @in;
   2751 }
   2752 
   2753 #######################################################################
   2754 # Provide time stamps for single test skipped events
   2755 #
   2756 sub timestampskippedevents {
   2757     my $testnum = $_[0];
   2758 
   2759     return if((not defined($testnum)) || ($testnum < 1));
   2760 
   2761     if($timestats) {
   2762 
   2763         if($timevrfyend{$testnum}) {
   2764             return;
   2765         }
   2766         elsif($timesrvrlog{$testnum}) {
   2767             $timevrfyend{$testnum} = $timesrvrlog{$testnum};
   2768             return;
   2769         }
   2770         elsif($timetoolend{$testnum}) {
   2771             $timevrfyend{$testnum} = $timetoolend{$testnum};
   2772             $timesrvrlog{$testnum} = $timetoolend{$testnum};
   2773         }
   2774         elsif($timetoolini{$testnum}) {
   2775             $timevrfyend{$testnum} = $timetoolini{$testnum};
   2776             $timesrvrlog{$testnum} = $timetoolini{$testnum};
   2777             $timetoolend{$testnum} = $timetoolini{$testnum};
   2778         }
   2779         elsif($timesrvrend{$testnum}) {
   2780             $timevrfyend{$testnum} = $timesrvrend{$testnum};
   2781             $timesrvrlog{$testnum} = $timesrvrend{$testnum};
   2782             $timetoolend{$testnum} = $timesrvrend{$testnum};
   2783             $timetoolini{$testnum} = $timesrvrend{$testnum};
   2784         }
   2785         elsif($timesrvrini{$testnum}) {
   2786             $timevrfyend{$testnum} = $timesrvrini{$testnum};
   2787             $timesrvrlog{$testnum} = $timesrvrini{$testnum};
   2788             $timetoolend{$testnum} = $timesrvrini{$testnum};
   2789             $timetoolini{$testnum} = $timesrvrini{$testnum};
   2790             $timesrvrend{$testnum} = $timesrvrini{$testnum};
   2791         }
   2792         elsif($timeprepini{$testnum}) {
   2793             $timevrfyend{$testnum} = $timeprepini{$testnum};
   2794             $timesrvrlog{$testnum} = $timeprepini{$testnum};
   2795             $timetoolend{$testnum} = $timeprepini{$testnum};
   2796             $timetoolini{$testnum} = $timeprepini{$testnum};
   2797             $timesrvrend{$testnum} = $timeprepini{$testnum};
   2798             $timesrvrini{$testnum} = $timeprepini{$testnum};
   2799         }
   2800     }
   2801 }
   2802 
   2803 #######################################################################
   2804 # Run a single specified test case
   2805 #
   2806 sub singletest {
   2807     my ($evbased, # 1 means switch on if possible (and "curl" is tested)
   2808                   # returns "not a test" if it can't be used for this test
   2809         $testnum,
   2810         $count,
   2811         $total)=@_;
   2812 
   2813     my @what;
   2814     my $why;
   2815     my %feature;
   2816     my $cmd;
   2817     my $disablevalgrind;
   2818 
   2819     # copy test number to a global scope var, this allows
   2820     # testnum checking when starting test harness servers.
   2821     $testnumcheck = $testnum;
   2822 
   2823     # timestamp test preparation start
   2824     $timeprepini{$testnum} = Time::HiRes::time() if($timestats);
   2825 
   2826     if($disttests !~ /test$testnum\W/ ) {
   2827         logmsg "Warning: test$testnum not present in tests/data/Makefile.inc\n";
   2828     }
   2829     if($disabled{$testnum}) {
   2830         logmsg "Warning: test$testnum is explicitly disabled\n";
   2831     }
   2832 
   2833     # load the test case file definition
   2834     if(loadtest("${TESTDIR}/test${testnum}")) {
   2835         if($verbose) {
   2836             # this is not a test
   2837             logmsg "RUN: $testnum doesn't look like a test case\n";
   2838         }
   2839         $why = "no test";
   2840     }
   2841     else {
   2842         @what = getpart("client", "features");
   2843     }
   2844 
   2845     # We require a feature to be present
   2846     for(@what) {
   2847         my $f = $_;
   2848         $f =~ s/\s//g;
   2849 
   2850         if($f =~ /^([^!].*)$/) {
   2851             # Store the feature for later
   2852             $feature{$1} = $1;
   2853 
   2854             if($1 eq "SSL") {
   2855                 if($ssl_version) {
   2856                     next;
   2857                 }
   2858             }
   2859             elsif($1 eq "SSLpinning") {
   2860                 if($has_sslpinning) {
   2861                     next;
   2862                 }
   2863             }
   2864             elsif($1 eq "OpenSSL") {
   2865                 if($has_openssl) {
   2866                     next;
   2867                 }
   2868             }
   2869             elsif($1 eq "GnuTLS") {
   2870                 if($has_gnutls) {
   2871                     next;
   2872                 }
   2873             }
   2874             elsif($1 eq "NSS") {
   2875                 if($has_nss) {
   2876                     next;
   2877                 }
   2878             }
   2879             elsif($1 eq "axTLS") {
   2880                 if($has_axtls) {
   2881                     next;
   2882                 }
   2883             }
   2884             elsif($1 eq "WinSSL") {
   2885                 if($has_winssl) {
   2886                     next;
   2887                 }
   2888             }
   2889             elsif($1 eq "DarwinSSL") {
   2890                 if($has_darwinssl) {
   2891                     next;
   2892                 }
   2893             }
   2894             elsif($1 eq "unittest") {
   2895                 if($debug_build) {
   2896                     next;
   2897                 }
   2898             }
   2899             elsif($1 eq "debug") {
   2900                 if($debug_build) {
   2901                     next;
   2902                 }
   2903             }
   2904             elsif($1 eq "TrackMemory") {
   2905                 if($has_memory_tracking) {
   2906                     next;
   2907                 }
   2908             }
   2909             elsif($1 eq "large_file") {
   2910                 if($large_file) {
   2911                     next;
   2912                 }
   2913             }
   2914             elsif($1 eq "idn") {
   2915                 if($has_idn) {
   2916                     next;
   2917                 }
   2918             }
   2919             elsif($1 eq "ipv6") {
   2920                 if($has_ipv6) {
   2921                     next;
   2922                 }
   2923             }
   2924             elsif($1 eq "libz") {
   2925                 if($has_libz) {
   2926                     next;
   2927                 }
   2928             }
   2929             elsif($1 eq "NTLM") {
   2930                 if($has_ntlm) {
   2931                     next;
   2932                 }
   2933             }
   2934             elsif($1 eq "NTLM_WB") {
   2935                 if($has_ntlm_wb) {
   2936                     next;
   2937                 }
   2938             }
   2939             elsif($1 eq "SSPI") {
   2940                 if($has_sspi) {
   2941                     next;
   2942                 }
   2943             }
   2944             elsif($1 eq "GSS-API") {
   2945                 if($has_gssapi) {
   2946                     next;
   2947                 }
   2948             }
   2949             elsif($1 eq "Kerberos") {
   2950                 if($has_kerberos) {
   2951                     next;
   2952                 }
   2953             }
   2954             elsif($1 eq "SPNEGO") {
   2955                 if($has_spnego) {
   2956                     next;
   2957                 }
   2958             }
   2959             elsif($1 eq "getrlimit") {
   2960                 if($has_getrlimit) {
   2961                     next;
   2962                 }
   2963             }
   2964             elsif($1 eq "crypto") {
   2965                 if($has_crypto) {
   2966                     next;
   2967                 }
   2968             }
   2969             elsif($1 eq "TLS-SRP") {
   2970                 if($has_tls_srp) {
   2971                     next;
   2972                 }
   2973             }
   2974             elsif($1 eq "Metalink") {
   2975                 if($has_metalink) {
   2976                     next;
   2977                 }
   2978             }
   2979             elsif($1 eq "http2") {
   2980                 if($has_http2) {
   2981                     next;
   2982                 }
   2983             }
   2984             elsif($1 eq "socks") {
   2985                 next;
   2986             }
   2987             elsif($1 eq "unix-sockets") {
   2988                 next if $has_unix;
   2989             }
   2990             # See if this "feature" is in the list of supported protocols
   2991             elsif (grep /^\Q$1\E$/i, @protocols) {
   2992                 next;
   2993             }
   2994 
   2995             $why = "curl lacks $1 support";
   2996             last;
   2997         }
   2998     }
   2999 
   3000     # We require a feature to not be present
   3001     if(!$why) {
   3002         for(@what) {
   3003             my $f = $_;
   3004             $f =~ s/\s//g;
   3005 
   3006             if($f =~ /^!(.*)$/) {
   3007                 if($1 eq "SSL") {
   3008                     if(!$ssl_version) {
   3009                         next;
   3010                     }
   3011                 }
   3012                 elsif($1 eq "OpenSSL") {
   3013                     if(!$has_openssl) {
   3014                         next;
   3015                     }
   3016                 }
   3017                 elsif($1 eq "GnuTLS") {
   3018                     if(!$has_gnutls) {
   3019                         next;
   3020                     }
   3021                 }
   3022                 elsif($1 eq "NSS") {
   3023                     if(!$has_nss) {
   3024                         next;
   3025                     }
   3026                 }
   3027                 elsif($1 eq "axTLS") {
   3028                     if(!$has_axtls) {
   3029                         next;
   3030                     }
   3031                 }
   3032                 elsif($1 eq "WinSSL") {
   3033                     if(!$has_winssl) {
   3034                         next;
   3035                     }
   3036                 }
   3037                 elsif($1 eq "DarwinSSL") {
   3038                     if(!$has_darwinssl) {
   3039                         next;
   3040                     }
   3041                 }
   3042                 elsif($1 eq "TrackMemory") {
   3043                     if(!$has_memory_tracking) {
   3044                         next;
   3045                     }
   3046                 }
   3047                 elsif($1 eq "large_file") {
   3048                     if(!$large_file) {
   3049                         next;
   3050                     }
   3051                 }
   3052                 elsif($1 eq "idn") {
   3053                     if(!$has_idn) {
   3054                         next;
   3055                     }
   3056                 }
   3057                 elsif($1 eq "ipv6") {
   3058                     if(!$has_ipv6) {
   3059                         next;
   3060                     }
   3061                 }
   3062                 elsif($1 eq "unix-sockets") {
   3063                     next if !$has_unix;
   3064                 }
   3065                 elsif($1 eq "libz") {
   3066                     if(!$has_libz) {
   3067                         next;
   3068                     }
   3069                 }
   3070                 elsif($1 eq "NTLM") {
   3071                     if(!$has_ntlm) {
   3072                         next;
   3073                     }
   3074                 }
   3075                 elsif($1 eq "NTLM_WB") {
   3076                     if(!$has_ntlm_wb) {
   3077                         next;
   3078                     }
   3079                 }
   3080                 elsif($1 eq "SSPI") {
   3081                     if(!$has_sspi) {
   3082                         next;
   3083                     }
   3084                 }
   3085                 elsif($1 eq "GSS-API") {
   3086                     if(!$has_gssapi) {
   3087                         next;
   3088                     }
   3089                 }
   3090                 elsif($1 eq "Kerberos") {
   3091                     if(!$has_kerberos) {
   3092                         next;
   3093                     }
   3094                 }
   3095                 elsif($1 eq "SPNEGO") {
   3096                     if(!$has_spnego) {
   3097                         next;
   3098                     }
   3099                 }
   3100                 elsif($1 eq "getrlimit") {
   3101                     if(!$has_getrlimit) {
   3102                         next;
   3103                     }
   3104                 }
   3105                 elsif($1 eq "crypto") {
   3106                     if(!$has_crypto) {
   3107                         next;
   3108                     }
   3109                 }
   3110                 elsif($1 eq "TLS-SRP") {
   3111                     if(!$has_tls_srp) {
   3112                         next;
   3113                     }
   3114                 }
   3115                 elsif($1 eq "Metalink") {
   3116                     if(!$has_metalink) {
   3117                         next;
   3118                     }
   3119                 }
   3120                 else {
   3121                     next;
   3122                 }
   3123             }
   3124             else {
   3125                 next;
   3126             }
   3127 
   3128             $why = "curl has $1 support";
   3129             last;
   3130         }
   3131     }
   3132 
   3133     if(!$why) {
   3134         my @keywords = getpart("info", "keywords");
   3135         my $match;
   3136         my $k;
   3137 
   3138         if(!$keywords[0]) {
   3139             $why = "missing the <keywords> section!";
   3140         }
   3141 
   3142         for $k (@keywords) {
   3143             chomp $k;
   3144             if ($disabled_keywords{$k}) {
   3145                 $why = "disabled by keyword";
   3146             } elsif ($enabled_keywords{$k}) {
   3147                 $match = 1;
   3148             }
   3149         }
   3150 
   3151         if(!$why && !$match && %enabled_keywords) {
   3152             $why = "disabled by missing keyword";
   3153         }
   3154     }
   3155 
   3156     # test definition may instruct to (un)set environment vars
   3157     # this is done this early, so that the precheck can use environment
   3158     # variables and still bail out fine on errors
   3159 
   3160     # restore environment variables that were modified in a previous run
   3161     foreach my $var (keys %oldenv) {
   3162         if($oldenv{$var} eq 'notset') {
   3163             delete $ENV{$var} if($ENV{$var});
   3164         }
   3165         else {
   3166             $ENV{$var} = $oldenv{$var};
   3167         }
   3168         delete $oldenv{$var};
   3169     }
   3170 
   3171     # remove test server commands file before servers are started/verified
   3172     unlink($FTPDCMD) if(-f $FTPDCMD);
   3173 
   3174     # timestamp required servers verification start
   3175     $timesrvrini{$testnum} = Time::HiRes::time() if($timestats);
   3176 
   3177     if(!$why) {
   3178         $why = serverfortest($testnum);
   3179     }
   3180 
   3181     # timestamp required servers verification end
   3182     $timesrvrend{$testnum} = Time::HiRes::time() if($timestats);
   3183 
   3184     my @setenv = getpart("client", "setenv");
   3185     if(@setenv) {
   3186         foreach my $s (@setenv) {
   3187             chomp $s;
   3188             subVariables \$s;
   3189             if($s =~ /([^=]*)=(.*)/) {
   3190                 my ($var, $content) = ($1, $2);
   3191                 # remember current setting, to restore it once test runs
   3192                 $oldenv{$var} = ($ENV{$var})?"$ENV{$var}":'notset';
   3193                 # set new value
   3194                 if(!$content) {
   3195                     delete $ENV{$var} if($ENV{$var});
   3196                 }
   3197                 else {
   3198                     if($var =~ /^LD_PRELOAD/) {
   3199                         if(exe_ext() && (exe_ext() eq '.exe')) {
   3200                             # print "Skipping LD_PRELOAD due to lack of OS support\n";
   3201                             next;
   3202                         }
   3203                         if($debug_build || ($has_shared ne "yes")) {
   3204                             # print "Skipping LD_PRELOAD due to no release shared build\n";
   3205                             next;
   3206                         }
   3207                     }
   3208                     $ENV{$var} = "$content";
   3209                 }
   3210             }
   3211         }
   3212     }
   3213 
   3214     if(!$why) {
   3215         # TODO:
   3216         # Add a precheck cache. If a precheck command was already invoked
   3217         # exactly like this, then use the previous result to speed up
   3218         # successive test invokes!
   3219 
   3220         my @precheck = getpart("client", "precheck");
   3221         if(@precheck) {
   3222             $cmd = $precheck[0];
   3223             chomp $cmd;
   3224             subVariables \$cmd;
   3225             if($cmd) {
   3226                 my @p = split(/ /, $cmd);
   3227                 if($p[0] !~ /\//) {
   3228                     # the first word, the command, does not contain a slash so
   3229                     # we will scan the "improved" PATH to find the command to
   3230                     # be able to run it
   3231                     my $fullp = checktestcmd($p[0]);
   3232 
   3233                     if($fullp) {
   3234                         $p[0] = $fullp;
   3235                     }
   3236                     $cmd = join(" ", @p);
   3237                 }
   3238 
   3239                 my @o = `$cmd 2>/dev/null`;
   3240                 if($o[0]) {
   3241                     $why = $o[0];
   3242                     chomp $why;
   3243                 } elsif($?) {
   3244                     $why = "precheck command error";
   3245                 }
   3246                 logmsg "prechecked $cmd\n" if($verbose);
   3247             }
   3248         }
   3249     }
   3250 
   3251     if($why && !$listonly) {
   3252         # there's a problem, count it as "skipped"
   3253         $skipped++;
   3254         $skipped{$why}++;
   3255         $teststat[$testnum]=$why; # store reason for this test case
   3256 
   3257         if(!$short) {
   3258             if($skipped{$why} <= 3) {
   3259                 # show only the first three skips for each reason
   3260                 logmsg sprintf("test %04d SKIPPED: $why\n", $testnum);
   3261             }
   3262         }
   3263 
   3264         timestampskippedevents($testnum);
   3265         return -1;
   3266     }
   3267     logmsg sprintf("test %04d...", $testnum) if(!$automakestyle);
   3268 
   3269     # extract the reply data
   3270     my @reply = getpart("reply", "data");
   3271     my @replycheck = getpart("reply", "datacheck");
   3272 
   3273     my %replyattr = getpartattr("reply", "data");
   3274     my %replycheckattr = getpartattr("reply", "datacheck");
   3275 
   3276     if (@replycheck) {
   3277         # we use this file instead to check the final output against
   3278 
   3279         if($replycheckattr{'nonewline'}) {
   3280             # Yes, we must cut off the final newline from the final line
   3281             # of the datacheck
   3282             chomp($replycheck[$#replycheck]);
   3283         }
   3284         if($replycheckattr{'mode'}) {
   3285             $replyattr{'mode'} = $replycheckattr{'mode'};
   3286         }
   3287 
   3288         @reply=@replycheck;
   3289     }
   3290 
   3291     # this is the valid protocol blurb curl should generate
   3292     my @protocol= fixarray ( getpart("verify", "protocol") );
   3293 
   3294     # this is the valid protocol blurb curl should generate to a proxy
   3295     my @proxyprot = fixarray ( getpart("verify", "proxy") );
   3296 
   3297     # redirected stdout/stderr to these files
   3298     $STDOUT="$LOGDIR/stdout$testnum";
   3299     $STDERR="$LOGDIR/stderr$testnum";
   3300 
   3301     # if this section exists, we verify that the stdout contained this:
   3302     my @validstdout = fixarray ( getpart("verify", "stdout") );
   3303 
   3304     # if this section exists, we verify upload
   3305     my @upload = getpart("verify", "upload");
   3306 
   3307     # if this section exists, it might be FTP server instructions:
   3308     my @ftpservercmd = getpart("reply", "servercmd");
   3309 
   3310     my $CURLOUT="$LOGDIR/curl$testnum.out"; # curl output if not stdout
   3311 
   3312     # name of the test
   3313     my @testname= getpart("client", "name");
   3314     my $testname = $testname[0];
   3315     $testname =~ s/\n//g;
   3316     logmsg "[$testname]\n" if(!$short);
   3317 
   3318     if($listonly) {
   3319         timestampskippedevents($testnum);
   3320         return 0; # look successful
   3321     }
   3322 
   3323     my @codepieces = getpart("client", "tool");
   3324 
   3325     my $tool="";
   3326     if(@codepieces) {
   3327         $tool = $codepieces[0];
   3328         chomp $tool;
   3329     }
   3330 
   3331     # remove server output logfile
   3332     unlink($SERVERIN);
   3333     unlink($SERVER2IN);
   3334     unlink($PROXYIN);
   3335 
   3336     if(@ftpservercmd) {
   3337         # write the instructions to file
   3338         writearray($FTPDCMD, \@ftpservercmd);
   3339     }
   3340 
   3341     # get the command line options to use
   3342     my @blaha;
   3343     ($cmd, @blaha)= getpart("client", "command");
   3344 
   3345     if($cmd) {
   3346         # make some nice replace operations
   3347         $cmd =~ s/\n//g; # no newlines please
   3348         # substitute variables in the command line
   3349         subVariables \$cmd;
   3350     }
   3351     else {
   3352         # there was no command given, use something silly
   3353         $cmd="-";
   3354     }
   3355     if($has_memory_tracking) {
   3356         unlink($memdump);
   3357     }
   3358 
   3359     # create a (possibly-empty) file before starting the test
   3360     my @inputfile=getpart("client", "file");
   3361     my %fileattr = getpartattr("client", "file");
   3362     my $filename=$fileattr{'name'};
   3363     if(@inputfile || $filename) {
   3364         if(!$filename) {
   3365             logmsg "ERROR: section client=>file has no name attribute\n";
   3366             timestampskippedevents($testnum);
   3367             return -1;
   3368         }
   3369         my $fileContent = join('', @inputfile);
   3370         subVariables \$fileContent;
   3371 #        logmsg "DEBUG: writing file " . $filename . "\n";
   3372         open(OUTFILE, ">$filename");
   3373         binmode OUTFILE; # for crapage systems, use binary
   3374         print OUTFILE $fileContent;
   3375         close(OUTFILE);
   3376     }
   3377 
   3378     my %cmdhash = getpartattr("client", "command");
   3379 
   3380     my $out="";
   3381 
   3382     if((!$cmdhash{'option'}) || ($cmdhash{'option'} !~ /no-output/)) {
   3383         #We may slap on --output!
   3384         if (!@validstdout) {
   3385             $out=" --output $CURLOUT ";
   3386         }
   3387     }
   3388 
   3389     my $serverlogslocktimeout = $defserverlogslocktimeout;
   3390     if($cmdhash{'timeout'}) {
   3391         # test is allowed to override default server logs lock timeout
   3392         if($cmdhash{'timeout'} =~ /(\d+)/) {
   3393             $serverlogslocktimeout = $1 if($1 >= 0);
   3394         }
   3395     }
   3396 
   3397     my $postcommanddelay = $defpostcommanddelay;
   3398     if($cmdhash{'delay'}) {
   3399         # test is allowed to specify a delay after command is executed
   3400         if($cmdhash{'delay'} =~ /(\d+)/) {
   3401             $postcommanddelay = $1 if($1 > 0);
   3402         }
   3403     }
   3404 
   3405     my $CMDLINE;
   3406     my $cmdargs;
   3407     my $cmdtype = $cmdhash{'type'} || "default";
   3408     my $fail_due_event_based = $evbased;
   3409     if($cmdtype eq "perl") {
   3410         # run the command line prepended with "perl"
   3411         $cmdargs ="$cmd";
   3412         $CMDLINE = "perl ";
   3413         $tool=$CMDLINE;
   3414         $disablevalgrind=1;
   3415     }
   3416     elsif($cmdtype eq "shell") {
   3417         # run the command line prepended with "/bin/sh"
   3418         $cmdargs ="$cmd";
   3419         $CMDLINE = "/bin/sh ";
   3420         $tool=$CMDLINE;
   3421         $disablevalgrind=1;
   3422     }
   3423     elsif(!$tool) {
   3424         # run curl, add suitable command line options
   3425         $cmd = "-1 ".$cmd if(exists $feature{"SSL"} && ($has_axtls));
   3426 
   3427         my $inc="";
   3428         if((!$cmdhash{'option'}) || ($cmdhash{'option'} !~ /no-include/)) {
   3429             $inc = " --include";
   3430         }
   3431 
   3432         $cmdargs = "$out$inc ";
   3433         $cmdargs .= "--trace-ascii log/trace$testnum ";
   3434         $cmdargs .= "--trace-time ";
   3435         if($evbased) {
   3436             $cmdargs .= "--test-event ";
   3437             $fail_due_event_based--;
   3438         }
   3439         $cmdargs .= $cmd;
   3440     }
   3441     else {
   3442         $cmdargs = " $cmd"; # $cmd is the command line for the test file
   3443         $CURLOUT = $STDOUT; # sends received data to stdout
   3444 
   3445         if($tool =~ /^lib/) {
   3446             $CMDLINE="$LIBDIR/$tool";
   3447         }
   3448         elsif($tool =~ /^unit/) {
   3449             $CMDLINE="$UNITDIR/$tool";
   3450         }
   3451 
   3452         if(! -f $CMDLINE) {
   3453             logmsg "The tool set in the test case for this: '$tool' does not exist\n";
   3454             timestampskippedevents($testnum);
   3455             return -1;
   3456         }
   3457         $DBGCURL=$CMDLINE;
   3458     }
   3459 
   3460     if($gdbthis) {
   3461         # gdb is incompatible with valgrind, so disable it when debugging
   3462         # Perhaps a better approach would be to run it under valgrind anyway
   3463         # with --db-attach=yes or --vgdb=yes.
   3464         $disablevalgrind=1;
   3465     }
   3466 
   3467     if($fail_due_event_based) {
   3468         logmsg "This test cannot run event based\n";
   3469         return -1;
   3470     }
   3471 
   3472     my @stdintest = getpart("client", "stdin");
   3473 
   3474     if(@stdintest) {
   3475         my $stdinfile="$LOGDIR/stdin-for-$testnum";
   3476 
   3477         my %hash = getpartattr("client", "stdin");
   3478         if($hash{'nonewline'}) {
   3479             # cut off the final newline from the final line of the stdin data
   3480             chomp($stdintest[$#stdintest]);
   3481         }
   3482 
   3483         writearray($stdinfile, \@stdintest);
   3484 
   3485         $cmdargs .= " <$stdinfile";
   3486     }
   3487 
   3488     if(!$tool) {
   3489         $CMDLINE="$CURL";
   3490     }
   3491 
   3492     my $usevalgrind;
   3493     if($valgrind && !$disablevalgrind) {
   3494         my @valgrindoption = getpart("verify", "valgrind");
   3495         if((!@valgrindoption) || ($valgrindoption[0] !~ /disable/)) {
   3496             $usevalgrind = 1;
   3497             my $valgrindcmd = "$valgrind ";
   3498             $valgrindcmd .= "$valgrind_tool " if($valgrind_tool);
   3499             $valgrindcmd .= "--leak-check=yes ";
   3500             $valgrindcmd .= "--suppressions=$srcdir/valgrind.supp ";
   3501            # $valgrindcmd .= "--gen-suppressions=all ";
   3502             $valgrindcmd .= "--num-callers=16 ";
   3503             $valgrindcmd .= "${valgrind_logfile}=$LOGDIR/valgrind$testnum";
   3504             $CMDLINE = "$valgrindcmd $CMDLINE";
   3505         }
   3506     }
   3507 
   3508     $CMDLINE .= "$cmdargs >$STDOUT 2>$STDERR";
   3509 
   3510     if($verbose) {
   3511         logmsg "$CMDLINE\n";
   3512     }
   3513 
   3514     print CMDLOG "$CMDLINE\n";
   3515 
   3516     unlink("core");
   3517 
   3518     my $dumped_core;
   3519     my $cmdres;
   3520 
   3521     # Apr 2007: precommand isn't being used and could be removed
   3522     my @precommand= getpart("client", "precommand");
   3523     if($precommand[0]) {
   3524         # this is pure perl to eval!
   3525         my $code = join("", @precommand);
   3526         eval $code;
   3527         if($@) {
   3528             logmsg "perl: $code\n";
   3529             logmsg "precommand: $@";
   3530             stopservers($verbose);
   3531             timestampskippedevents($testnum);
   3532             return -1;
   3533         }
   3534     }
   3535 
   3536     if($gdbthis) {
   3537         my $gdbinit = "$TESTDIR/gdbinit$testnum";
   3538         open(GDBCMD, ">$LOGDIR/gdbcmd");
   3539         print GDBCMD "set args $cmdargs\n";
   3540         print GDBCMD "show args\n";
   3541         print GDBCMD "source $gdbinit\n" if -e $gdbinit;
   3542         close(GDBCMD);
   3543     }
   3544 
   3545     # timestamp starting of test command
   3546     $timetoolini{$testnum} = Time::HiRes::time() if($timestats);
   3547 
   3548     # run the command line we built
   3549     if ($torture) {
   3550         $cmdres = torture($CMDLINE,
   3551                        "$gdb --directory libtest $DBGCURL -x $LOGDIR/gdbcmd");
   3552     }
   3553     elsif($gdbthis) {
   3554         my $GDBW = ($gdbxwin) ? "-w" : "";
   3555         runclient("$gdb --directory libtest $DBGCURL $GDBW -x $LOGDIR/gdbcmd");
   3556         $cmdres=0; # makes it always continue after a debugged run
   3557     }
   3558     else {
   3559         $cmdres = runclient("$CMDLINE");
   3560         my $signal_num  = $cmdres & 127;
   3561         $dumped_core = $cmdres & 128;
   3562 
   3563         if(!$anyway && ($signal_num || $dumped_core)) {
   3564             $cmdres = 1000;
   3565         }
   3566         else {
   3567             $cmdres >>= 8;
   3568             $cmdres = (2000 + $signal_num) if($signal_num && !$cmdres);
   3569         }
   3570     }
   3571 
   3572     # timestamp finishing of test command
   3573     $timetoolend{$testnum} = Time::HiRes::time() if($timestats);
   3574 
   3575     if(!$dumped_core) {
   3576         if(-r "core") {
   3577             # there's core file present now!
   3578             $dumped_core = 1;
   3579         }
   3580     }
   3581 
   3582     if($dumped_core) {
   3583         logmsg "core dumped\n";
   3584         if(0 && $gdb) {
   3585             logmsg "running gdb for post-mortem analysis:\n";
   3586             open(GDBCMD, ">$LOGDIR/gdbcmd2");
   3587             print GDBCMD "bt\n";
   3588             close(GDBCMD);
   3589             runclient("$gdb --directory libtest -x $LOGDIR/gdbcmd2 -batch $DBGCURL core ");
   3590      #       unlink("$LOGDIR/gdbcmd2");
   3591         }
   3592     }
   3593 
   3594     # If a server logs advisor read lock file exists, it is an indication
   3595     # that the server has not yet finished writing out all its log files,
   3596     # including server request log files used for protocol verification.
   3597     # So, if the lock file exists the script waits here a certain amount
   3598     # of time until the server removes it, or the given time expires.
   3599 
   3600     if($serverlogslocktimeout) {
   3601         my $lockretry = $serverlogslocktimeout * 20;
   3602         while((-f $SERVERLOGS_LOCK) && $lockretry--) {
   3603             select(undef, undef, undef, 0.05);
   3604         }
   3605         if(($lockretry < 0) &&
   3606            ($serverlogslocktimeout >= $defserverlogslocktimeout)) {
   3607             logmsg "Warning: server logs lock timeout ",
   3608                    "($serverlogslocktimeout seconds) expired\n";
   3609         }
   3610     }
   3611 
   3612     # Test harness ssh server does not have this synchronization mechanism,
   3613     # this implies that some ssh server based tests might need a small delay
   3614     # once that the client command has run to avoid false test failures.
   3615     #
   3616     # gnutls-serv also lacks this synchronization mechanism, so gnutls-serv
   3617     # based tests might need a small delay once that the client command has
   3618     # run to avoid false test failures.
   3619 
   3620     sleep($postcommanddelay) if($postcommanddelay);
   3621 
   3622     # timestamp removal of server logs advisor read lock
   3623     $timesrvrlog{$testnum} = Time::HiRes::time() if($timestats);
   3624 
   3625     # test definition might instruct to stop some servers
   3626     # stop also all servers relative to the given one
   3627 
   3628     my @killtestservers = getpart("client", "killserver");
   3629     if(@killtestservers) {
   3630         #
   3631         # All servers relative to the given one must be stopped also
   3632         #
   3633         my @killservers;
   3634         foreach my $server (@killtestservers) {
   3635             chomp $server;
   3636             if($server =~ /^(ftp|http|imap|pop3|smtp)s((\d*)(-ipv6|-unix|))$/) {
   3637                 # given a stunnel ssl server, also kill non-ssl underlying one
   3638                 push @killservers, "${1}${2}";
   3639             }
   3640             elsif($server =~ /^(ftp|http|imap|pop3|smtp)((\d*)(-ipv6|-unix|))$/) {
   3641                 # given a non-ssl server, also kill stunnel piggybacking one
   3642                 push @killservers, "${1}s${2}";
   3643             }
   3644             elsif($server =~ /^(socks)((\d*)(-ipv6|))$/) {
   3645                 # given a socks server, also kill ssh underlying one
   3646                 push @killservers, "ssh${2}";
   3647             }
   3648             elsif($server =~ /^(ssh)((\d*)(-ipv6|))$/) {
   3649                 # given a ssh server, also kill socks piggybacking one
   3650                 push @killservers, "socks${2}";
   3651             }
   3652             push @killservers, $server;
   3653         }
   3654         #
   3655         # kill sockfilter processes for pingpong relative servers
   3656         #
   3657         foreach my $server (@killservers) {
   3658             if($server =~ /^(ftp|imap|pop3|smtp)s?(\d*)(-ipv6|)$/) {
   3659                 my $proto  = $1;
   3660                 my $idnum  = ($2 && ($2 > 1)) ? $2 : 1;
   3661                 my $ipvnum = ($3 && ($3 =~ /6$/)) ? 6 : 4;
   3662                 killsockfilters($proto, $ipvnum, $idnum, $verbose);
   3663             }
   3664         }
   3665         #
   3666         # kill server relative pids clearing them in %run hash
   3667         #
   3668         my $pidlist;
   3669         foreach my $server (@killservers) {
   3670             if($run{$server}) {
   3671                 $pidlist .= "$run{$server} ";
   3672                 $run{$server} = 0;
   3673             }
   3674             $runcert{$server} = 0 if($runcert{$server});
   3675         }
   3676         killpid($verbose, $pidlist);
   3677         #
   3678         # cleanup server pid files
   3679         #
   3680         foreach my $server (@killservers) {
   3681             my $pidfile = $serverpidfile{$server};
   3682             my $pid = processexists($pidfile);
   3683             if($pid > 0) {
   3684                 logmsg "Warning: $server server unexpectedly alive\n";
   3685                 killpid($verbose, $pid);
   3686             }
   3687             unlink($pidfile) if(-f $pidfile);
   3688         }
   3689     }
   3690 
   3691     # remove the test server commands file after each test
   3692     unlink($FTPDCMD) if(-f $FTPDCMD);
   3693 
   3694     # run the postcheck command
   3695     my @postcheck= getpart("client", "postcheck");
   3696     if(@postcheck) {
   3697         $cmd = $postcheck[0];
   3698         chomp $cmd;
   3699         subVariables \$cmd;
   3700         if($cmd) {
   3701             logmsg "postcheck $cmd\n" if($verbose);
   3702             my $rc = runclient("$cmd");
   3703             # Must run the postcheck command in torture mode in order
   3704             # to clean up, but the result can't be relied upon.
   3705             if($rc != 0 && !$torture) {
   3706                 logmsg " postcheck FAILED\n";
   3707                 # timestamp test result verification end
   3708                 $timevrfyend{$testnum} = Time::HiRes::time() if($timestats);
   3709                 return 1;
   3710             }
   3711         }
   3712     }
   3713 
   3714     # restore environment variables that were modified
   3715     if(%oldenv) {
   3716         foreach my $var (keys %oldenv) {
   3717             if($oldenv{$var} eq 'notset') {
   3718                 delete $ENV{$var} if($ENV{$var});
   3719             }
   3720             else {
   3721                 $ENV{$var} = "$oldenv{$var}";
   3722             }
   3723         }
   3724     }
   3725 
   3726     # Skip all the verification on torture tests
   3727     if ($torture) {
   3728         if(!$cmdres && !$keepoutfiles) {
   3729             cleardir($LOGDIR);
   3730         }
   3731         # timestamp test result verification end
   3732         $timevrfyend{$testnum} = Time::HiRes::time() if($timestats);
   3733         return $cmdres;
   3734     }
   3735 
   3736     my @err = getpart("verify", "errorcode");
   3737     my $errorcode = $err[0] || "0";
   3738     my $ok="";
   3739     my $res;
   3740     chomp $errorcode;
   3741     if (@validstdout) {
   3742         # verify redirected stdout
   3743         my @actual = loadarray($STDOUT);
   3744 
   3745         # variable-replace in the stdout we have from the test case file
   3746         @validstdout = fixarray(@validstdout);
   3747 
   3748         # get all attributes
   3749         my %hash = getpartattr("verify", "stdout");
   3750 
   3751         # get the mode attribute
   3752         my $filemode=$hash{'mode'};
   3753         if($filemode && ($filemode eq "text") && $has_textaware) {
   3754             # text mode when running on windows: fix line endings
   3755             map s/\r\n/\n/g, @validstdout;
   3756             map s/\n/\r\n/g, @validstdout;
   3757         }
   3758 
   3759         if($hash{'nonewline'}) {
   3760             # Yes, we must cut off the final newline from the final line
   3761             # of the protocol data
   3762             chomp($validstdout[$#validstdout]);
   3763         }
   3764 
   3765         $res = compare($testnum, $testname, "stdout", \@actual, \@validstdout);
   3766         if($res) {
   3767             return 1;
   3768         }
   3769         $ok .= "s";
   3770     }
   3771     else {
   3772         $ok .= "-"; # stdout not checked
   3773     }
   3774 
   3775     if(@protocol) {
   3776         # Verify the sent request
   3777         my @out = loadarray($SERVERIN);
   3778 
   3779         # what to cut off from the live protocol sent by curl
   3780         my @strip = getpart("verify", "strip");
   3781 
   3782         my @protstrip=@protocol;
   3783 
   3784         # check if there's any attributes on the verify/protocol section
   3785         my %hash = getpartattr("verify", "protocol");
   3786 
   3787         if($hash{'nonewline'}) {
   3788             # Yes, we must cut off the final newline from the final line
   3789             # of the protocol data
   3790             chomp($protstrip[$#protstrip]);
   3791         }
   3792 
   3793         for(@strip) {
   3794             # strip off all lines that match the patterns from both arrays
   3795             chomp $_;
   3796             @out = striparray( $_, \@out);
   3797             @protstrip= striparray( $_, \@protstrip);
   3798         }
   3799 
   3800         # what parts to cut off from the protocol
   3801         my @strippart = getpart("verify", "strippart");
   3802         my $strip;
   3803         for $strip (@strippart) {
   3804             chomp $strip;
   3805             for(@out) {
   3806                 eval $strip;
   3807             }
   3808         }
   3809 
   3810         $res = compare($testnum, $testname, "protocol", \@out, \@protstrip);
   3811         if($res) {
   3812             return 1;
   3813         }
   3814 
   3815         $ok .= "p";
   3816 
   3817     }
   3818     else {
   3819         $ok .= "-"; # protocol not checked
   3820     }
   3821 
   3822     if(!$replyattr{'nocheck'} && (@reply || $replyattr{'sendzero'})) {
   3823         # verify the received data
   3824         my @out = loadarray($CURLOUT);
   3825         # get the mode attribute
   3826         my $filemode=$replyattr{'mode'};
   3827         if($filemode && ($filemode eq "text") && $has_textaware) {
   3828             # text mode when running on windows: fix line endings
   3829             map s/\r\n/\n/g, @reply;
   3830             map s/\n/\r\n/g, @reply;
   3831         }
   3832 
   3833         $res = compare($testnum, $testname, "data", \@out, \@reply);
   3834         if ($res) {
   3835             return 1;
   3836         }
   3837         $ok .= "d";
   3838     }
   3839     else {
   3840         $ok .= "-"; # data not checked
   3841     }
   3842 
   3843     if(@upload) {
   3844         # verify uploaded data
   3845         my @out = loadarray("$LOGDIR/upload.$testnum");
   3846         $res = compare($testnum, $testname, "upload", \@out, \@upload);
   3847         if ($res) {
   3848             return 1;
   3849         }
   3850         $ok .= "u";
   3851     }
   3852     else {
   3853         $ok .= "-"; # upload not checked
   3854     }
   3855 
   3856     if(@proxyprot) {
   3857         # Verify the sent proxy request
   3858         my @out = loadarray($PROXYIN);
   3859 
   3860         # what to cut off from the live protocol sent by curl, we use the
   3861         # same rules as for <protocol>
   3862         my @strip = getpart("verify", "strip");
   3863 
   3864         my @protstrip=@proxyprot;
   3865 
   3866         # check if there's any attributes on the verify/protocol section
   3867         my %hash = getpartattr("verify", "proxy");
   3868 
   3869         if($hash{'nonewline'}) {
   3870             # Yes, we must cut off the final newline from the final line
   3871             # of the protocol data
   3872             chomp($protstrip[$#protstrip]);
   3873         }
   3874 
   3875         for(@strip) {
   3876             # strip off all lines that match the patterns from both arrays
   3877             chomp $_;
   3878             @out = striparray( $_, \@out);
   3879             @protstrip= striparray( $_, \@protstrip);
   3880         }
   3881 
   3882         # what parts to cut off from the protocol
   3883         my @strippart = getpart("verify", "strippart");
   3884         my $strip;
   3885         for $strip (@strippart) {
   3886             chomp $strip;
   3887             for(@out) {
   3888                 eval $strip;
   3889             }
   3890         }
   3891 
   3892         $res = compare($testnum, $testname, "proxy", \@out, \@protstrip);
   3893         if($res) {
   3894             return 1;
   3895         }
   3896 
   3897         $ok .= "P";
   3898 
   3899     }
   3900     else {
   3901         $ok .= "-"; # protocol not checked
   3902     }
   3903 
   3904     my $outputok;
   3905     for my $partsuffix (('', '1', '2', '3', '4')) {
   3906         my @outfile=getpart("verify", "file".$partsuffix);
   3907         if(@outfile || partexists("verify", "file".$partsuffix) ) {
   3908             # we're supposed to verify a dynamically generated file!
   3909             my %hash = getpartattr("verify", "file".$partsuffix);
   3910 
   3911             my $filename=$hash{'name'};
   3912             if(!$filename) {
   3913                 logmsg "ERROR: section verify=>file$partsuffix ".
   3914                        "has no name attribute\n";
   3915                 stopservers($verbose);
   3916                 # timestamp test result verification end
   3917                 $timevrfyend{$testnum} = Time::HiRes::time() if($timestats);
   3918                 return -1;
   3919             }
   3920             my @generated=loadarray($filename);
   3921 
   3922             # what parts to cut off from the file
   3923             my @stripfile = getpart("verify", "stripfile".$partsuffix);
   3924 
   3925             my $filemode=$hash{'mode'};
   3926             if($filemode && ($filemode eq "text") && $has_textaware) {
   3927                 # text mode when running on windows: fix line endings
   3928                 map s/\r\n/\n/g, @outfile;
   3929                 map s/\n/\r\n/g, @outfile;
   3930             }
   3931 
   3932             my $strip;
   3933             for $strip (@stripfile) {
   3934                 chomp $strip;
   3935                 my @newgen;
   3936                 for(@generated) {
   3937                     eval $strip;
   3938                     if($_) {
   3939                         push @newgen, $_;
   3940                     }
   3941                 }
   3942                 # this is to get rid of array entries that vanished (zero
   3943                 # length) because of replacements
   3944                 @generated = @newgen;
   3945             }
   3946 
   3947             @outfile = fixarray(@outfile);
   3948 
   3949             $res = compare($testnum, $testname, "output ($filename)",
   3950                            \@generated, \@outfile);
   3951             if($res) {
   3952                 return 1;
   3953             }
   3954 
   3955             $outputok = 1; # output checked
   3956         }
   3957     }
   3958     $ok .= ($outputok) ? "o" : "-"; # output checked or not
   3959 
   3960     # accept multiple comma-separated error codes
   3961     my @splerr = split(/ *, */, $errorcode);
   3962     my $errok;
   3963     foreach my $e (@splerr) {
   3964         if($e == $cmdres) {
   3965             # a fine error code
   3966             $errok = 1;
   3967             last;
   3968         }
   3969     }
   3970 
   3971     if($errok) {
   3972         $ok .= "e";
   3973     }
   3974     else {
   3975         if(!$short) {
   3976             logmsg sprintf("\n%s returned $cmdres, when expecting %s\n",
   3977                            (!$tool)?"curl":$tool, $errorcode);
   3978         }
   3979         logmsg " exit FAILED\n";
   3980         # timestamp test result verification end
   3981         $timevrfyend{$testnum} = Time::HiRes::time() if($timestats);
   3982         return 1;
   3983     }
   3984 
   3985     if($has_memory_tracking) {
   3986         if(! -f $memdump) {
   3987             logmsg "\n** ALERT! memory tracking with no output file?\n"
   3988                 if(!$cmdtype eq "perl");
   3989         }
   3990         else {
   3991             my @memdata=`$memanalyze $memdump`;
   3992             my $leak=0;
   3993             for(@memdata) {
   3994                 if($_ ne "") {
   3995                     # well it could be other memory problems as well, but
   3996                     # we call it leak for short here
   3997                     $leak=1;
   3998                 }
   3999             }
   4000             if($leak) {
   4001                 logmsg "\n** MEMORY FAILURE\n";
   4002                 logmsg @memdata;
   4003                 # timestamp test result verification end
   4004                 $timevrfyend{$testnum} = Time::HiRes::time() if($timestats);
   4005                 return 1;
   4006             }
   4007             else {
   4008                 $ok .= "m";
   4009             }
   4010         }
   4011     }
   4012     else {
   4013         $ok .= "-"; # memory not checked
   4014     }
   4015 
   4016     if($valgrind) {
   4017         if($usevalgrind) {
   4018             unless(opendir(DIR, "$LOGDIR")) {
   4019                 logmsg "ERROR: unable to read $LOGDIR\n";
   4020                 # timestamp test result verification end
   4021                 $timevrfyend{$testnum} = Time::HiRes::time() if($timestats);
   4022                 return 1;
   4023             }
   4024             my @files = readdir(DIR);
   4025             closedir(DIR);
   4026             my $vgfile;
   4027             foreach my $file (@files) {
   4028                 if($file =~ /^valgrind$testnum(\..*|)$/) {
   4029                     $vgfile = $file;
   4030                     last;
   4031                 }
   4032             }
   4033             if(!$vgfile) {
   4034                 logmsg "ERROR: valgrind log file missing for test $testnum\n";
   4035                 # timestamp test result verification end
   4036                 $timevrfyend{$testnum} = Time::HiRes::time() if($timestats);
   4037                 return 1;
   4038             }
   4039             my @e = valgrindparse($srcdir, $feature{'SSL'}, "$LOGDIR/$vgfile");
   4040             if(@e && $e[0]) {
   4041                 if($automakestyle) {
   4042                     logmsg "FAIL: $testnum - $testname - valgrind\n";
   4043                 }
   4044                 else {
   4045                     logmsg " valgrind ERROR ";
   4046                     logmsg @e;
   4047                 }
   4048                 # timestamp test result verification end
   4049                 $timevrfyend{$testnum} = Time::HiRes::time() if($timestats);
   4050                 return 1;
   4051             }
   4052             $ok .= "v";
   4053         }
   4054         else {
   4055             if(!$short && !$disablevalgrind) {
   4056                 logmsg " valgrind SKIPPED\n";
   4057             }
   4058             $ok .= "-"; # skipped
   4059         }
   4060     }
   4061     else {
   4062         $ok .= "-"; # valgrind not checked
   4063     }
   4064     # add 'E' for event-based
   4065     $ok .= $evbased ? "E" : "-";
   4066 
   4067     logmsg "$ok " if(!$short);
   4068 
   4069     my $sofar= time()-$start;
   4070     my $esttotal = $sofar/$count * $total;
   4071     my $estleft = $esttotal - $sofar;
   4072     my $left=sprintf("remaining: %02d:%02d",
   4073                      $estleft/60,
   4074                      $estleft%60);
   4075 
   4076     if(!$automakestyle) {
   4077         logmsg sprintf("OK (%-3d out of %-3d, %s)\n", $count, $total, $left);
   4078     }
   4079     else {
   4080         logmsg "PASS: $testnum - $testname\n";
   4081     }
   4082 
   4083     # the test succeeded, remove all log files
   4084     if(!$keepoutfiles) {
   4085         cleardir($LOGDIR);
   4086     }
   4087 
   4088     # timestamp test result verification end
   4089     $timevrfyend{$testnum} = Time::HiRes::time() if($timestats);
   4090 
   4091     return 0;
   4092 }
   4093 
   4094 #######################################################################
   4095 # Stop all running test servers
   4096 #
   4097 sub stopservers {
   4098     my $verbose = $_[0];
   4099     #
   4100     # kill sockfilter processes for all pingpong servers
   4101     #
   4102     killallsockfilters($verbose);
   4103     #
   4104     # kill all server pids from %run hash clearing them
   4105     #
   4106     my $pidlist;
   4107     foreach my $server (keys %run) {
   4108         if($run{$server}) {
   4109             if($verbose) {
   4110                 my $prev = 0;
   4111                 my $pids = $run{$server};
   4112                 foreach my $pid (split(' ', $pids)) {
   4113                     if($pid != $prev) {
   4114                         logmsg sprintf("* kill pid for %s => %d\n",
   4115                             $server, $pid);
   4116                         $prev = $pid;
   4117                     }
   4118                 }
   4119             }
   4120             $pidlist .= "$run{$server} ";
   4121             $run{$server} = 0;
   4122         }
   4123         $runcert{$server} = 0 if($runcert{$server});
   4124     }
   4125     killpid($verbose, $pidlist);
   4126     #
   4127     # cleanup all server pid files
   4128     #
   4129     foreach my $server (keys %serverpidfile) {
   4130         my $pidfile = $serverpidfile{$server};
   4131         my $pid = processexists($pidfile);
   4132         if($pid > 0) {
   4133             logmsg "Warning: $server server unexpectedly alive\n";
   4134             killpid($verbose, $pid);
   4135         }
   4136         unlink($pidfile) if(-f $pidfile);
   4137     }
   4138 }
   4139 
   4140 #######################################################################
   4141 # startservers() starts all the named servers
   4142 #
   4143 # Returns: string with error reason or blank for success
   4144 #
   4145 sub startservers {
   4146     my @what = @_;
   4147     my ($pid, $pid2);
   4148     for(@what) {
   4149         my (@whatlist) = split(/\s+/,$_);
   4150         my $what = lc($whatlist[0]);
   4151         $what =~ s/[^a-z0-9-]//g;
   4152 
   4153         my $certfile;
   4154         if($what =~ /^(ftp|http|imap|pop3|smtp)s((\d*)(-ipv6|-unix|))$/) {
   4155             $certfile = ($whatlist[1]) ? $whatlist[1] : 'stunnel.pem';
   4156         }
   4157 
   4158         if(($what eq "pop3") ||
   4159            ($what eq "ftp") ||
   4160            ($what eq "imap") ||
   4161            ($what eq "smtp")) {
   4162             if($torture && $run{$what} &&
   4163                !responsive_pingpong_server($what, "", $verbose)) {
   4164                 stopserver($what);
   4165             }
   4166             if(!$run{$what}) {
   4167                 ($pid, $pid2) = runpingpongserver($what, "", $verbose);
   4168                 if($pid <= 0) {
   4169                     return "failed starting ". uc($what) ." server";
   4170                 }
   4171                 printf ("* pid $what => %d %d\n", $pid, $pid2) if($verbose);
   4172                 $run{$what}="$pid $pid2";
   4173             }
   4174         }
   4175         elsif($what eq "ftp2") {
   4176             if($torture && $run{'ftp2'} &&
   4177                !responsive_pingpong_server("ftp", "2", $verbose)) {
   4178                 stopserver('ftp2');
   4179             }
   4180             if(!$run{'ftp2'}) {
   4181                 ($pid, $pid2) = runpingpongserver("ftp", "2", $verbose);
   4182                 if($pid <= 0) {
   4183                     return "failed starting FTP2 server";
   4184                 }
   4185                 printf ("* pid ftp2 => %d %d\n", $pid, $pid2) if($verbose);
   4186                 $run{'ftp2'}="$pid $pid2";
   4187             }
   4188         }
   4189         elsif($what eq "ftp-ipv6") {
   4190             if($torture && $run{'ftp-ipv6'} &&
   4191                !responsive_pingpong_server("ftp", "", $verbose, "ipv6")) {
   4192                 stopserver('ftp-ipv6');
   4193             }
   4194             if(!$run{'ftp-ipv6'}) {
   4195                 ($pid, $pid2) = runpingpongserver("ftp", "", $verbose, "ipv6");
   4196                 if($pid <= 0) {
   4197                     return "failed starting FTP-IPv6 server";
   4198                 }
   4199                 logmsg sprintf("* pid ftp-ipv6 => %d %d\n", $pid,
   4200                        $pid2) if($verbose);
   4201                 $run{'ftp-ipv6'}="$pid $pid2";
   4202             }
   4203         }
   4204         elsif($what eq "gopher") {
   4205             if($torture && $run{'gopher'} &&
   4206                !responsive_http_server("gopher", $verbose, 0, $GOPHERPORT)) {
   4207                 stopserver('gopher');
   4208             }
   4209             if(!$run{'gopher'}) {
   4210                 ($pid, $pid2) = runhttpserver("gopher", $verbose, 0,
   4211                                               $GOPHERPORT);
   4212                 if($pid <= 0) {
   4213                     return "failed starting GOPHER server";
   4214                 }
   4215                 logmsg sprintf ("* pid gopher => %d %d\n", $pid, $pid2)
   4216                     if($verbose);
   4217                 $run{'gopher'}="$pid $pid2";
   4218             }
   4219         }
   4220         elsif($what eq "gopher-ipv6") {
   4221             if($torture && $run{'gopher-ipv6'} &&
   4222                !responsive_http_server("gopher", $verbose, "ipv6",
   4223                                        $GOPHER6PORT)) {
   4224                 stopserver('gopher-ipv6');
   4225             }
   4226             if(!$run{'gopher-ipv6'}) {
   4227                 ($pid, $pid2) = runhttpserver("gopher", $verbose, "ipv6",
   4228                                               $GOPHER6PORT);
   4229                 if($pid <= 0) {
   4230                     return "failed starting GOPHER-IPv6 server";
   4231                 }
   4232                 logmsg sprintf("* pid gopher-ipv6 => %d %d\n", $pid,
   4233                                $pid2) if($verbose);
   4234                 $run{'gopher-ipv6'}="$pid $pid2";
   4235             }
   4236         }
   4237         elsif($what eq "http") {
   4238             if($torture && $run{'http'} &&
   4239                !responsive_http_server("http", $verbose, 0, $HTTPPORT)) {
   4240                 stopserver('http');
   4241             }
   4242             if(!$run{'http'}) {
   4243                 ($pid, $pid2) = runhttpserver("http", $verbose, 0,
   4244                                               $HTTPPORT);
   4245                 if($pid <= 0) {
   4246                     return "failed starting HTTP server";
   4247                 }
   4248                 logmsg sprintf ("* pid http => %d %d\n", $pid, $pid2)
   4249                     if($verbose);
   4250                 $run{'http'}="$pid $pid2";
   4251             }
   4252         }
   4253         elsif($what eq "http-proxy") {
   4254             if($torture && $run{'http-proxy'} &&
   4255                !responsive_http_server("http", $verbose, "proxy",
   4256                                        $HTTPPROXYPORT)) {
   4257                 stopserver('http-proxy');
   4258             }
   4259             if(!$run{'http-proxy'}) {
   4260                 ($pid, $pid2) = runhttpserver("http", $verbose, "proxy",
   4261                                               $HTTPPROXYPORT);
   4262                 if($pid <= 0) {
   4263                     return "failed starting HTTP-proxy server";
   4264                 }
   4265                 logmsg sprintf ("* pid http-proxy => %d %d\n", $pid, $pid2)
   4266                     if($verbose);
   4267                 $run{'http-proxy'}="$pid $pid2";
   4268             }
   4269         }
   4270         elsif($what eq "http-ipv6") {
   4271             if($torture && $run{'http-ipv6'} &&
   4272                !responsive_http_server("http", $verbose, "ipv6", $HTTP6PORT)) {
   4273                 stopserver('http-ipv6');
   4274             }
   4275             if(!$run{'http-ipv6'}) {
   4276                 ($pid, $pid2) = runhttpserver("http", $verbose, "ipv6",
   4277                                               $HTTP6PORT);
   4278                 if($pid <= 0) {
   4279                     return "failed starting HTTP-IPv6 server";
   4280                 }
   4281                 logmsg sprintf("* pid http-ipv6 => %d %d\n", $pid, $pid2)
   4282                     if($verbose);
   4283                 $run{'http-ipv6'}="$pid $pid2";
   4284             }
   4285         }
   4286         elsif($what eq "http-pipe") {
   4287             if($torture && $run{'http-pipe'} &&
   4288                !responsive_http_server("http", $verbose, "pipe",
   4289                                        $HTTPPIPEPORT)) {
   4290                 stopserver('http-pipe');
   4291             }
   4292             if(!$run{'http-pipe'}) {
   4293                 ($pid, $pid2) = runhttpserver("http", $verbose, "pipe",
   4294                                               $HTTPPIPEPORT);
   4295                 if($pid <= 0) {
   4296                     return "failed starting HTTP-pipe server";
   4297                 }
   4298                 logmsg sprintf ("* pid http-pipe => %d %d\n", $pid, $pid2)
   4299                     if($verbose);
   4300                 $run{'http-pipe'}="$pid $pid2";
   4301             }
   4302         }
   4303         elsif($what eq "rtsp") {
   4304             if($torture && $run{'rtsp'} &&
   4305                !responsive_rtsp_server($verbose)) {
   4306                 stopserver('rtsp');
   4307             }
   4308             if(!$run{'rtsp'}) {
   4309                 ($pid, $pid2) = runrtspserver($verbose);
   4310                 if($pid <= 0) {
   4311                     return "failed starting RTSP server";
   4312                 }
   4313                 printf ("* pid rtsp => %d %d\n", $pid, $pid2) if($verbose);
   4314                 $run{'rtsp'}="$pid $pid2";
   4315             }
   4316         }
   4317         elsif($what eq "rtsp-ipv6") {
   4318             if($torture && $run{'rtsp-ipv6'} &&
   4319                !responsive_rtsp_server($verbose, "ipv6")) {
   4320                 stopserver('rtsp-ipv6');
   4321             }
   4322             if(!$run{'rtsp-ipv6'}) {
   4323                 ($pid, $pid2) = runrtspserver($verbose, "ipv6");
   4324                 if($pid <= 0) {
   4325                     return "failed starting RTSP-IPv6 server";
   4326                 }
   4327                 logmsg sprintf("* pid rtsp-ipv6 => %d %d\n", $pid, $pid2)
   4328                     if($verbose);
   4329                 $run{'rtsp-ipv6'}="$pid $pid2";
   4330             }
   4331         }
   4332         elsif($what eq "ftps") {
   4333             if(!$stunnel) {
   4334                 # we can't run ftps tests without stunnel
   4335                 return "no stunnel";
   4336             }
   4337             if(!$ssl_version) {
   4338                 # we can't run ftps tests if libcurl is SSL-less
   4339                 return "curl lacks SSL support";
   4340             }
   4341             if($runcert{'ftps'} && ($runcert{'ftps'} ne $certfile)) {
   4342                 # stop server when running and using a different cert
   4343                 stopserver('ftps');
   4344             }
   4345             if($torture && $run{'ftp'} &&
   4346                !responsive_pingpong_server("ftp", "", $verbose)) {
   4347                 stopserver('ftp');
   4348             }
   4349             if(!$run{'ftp'}) {
   4350                 ($pid, $pid2) = runpingpongserver("ftp", "", $verbose);
   4351                 if($pid <= 0) {
   4352                     return "failed starting FTP server";
   4353                 }
   4354                 printf ("* pid ftp => %d %d\n", $pid, $pid2) if($verbose);
   4355                 $run{'ftp'}="$pid $pid2";
   4356             }
   4357             if(!$run{'ftps'}) {
   4358                 ($pid, $pid2) = runftpsserver($verbose, "", $certfile);
   4359                 if($pid <= 0) {
   4360                     return "failed starting FTPS server (stunnel)";
   4361                 }
   4362                 logmsg sprintf("* pid ftps => %d %d\n", $pid, $pid2)
   4363                     if($verbose);
   4364                 $run{'ftps'}="$pid $pid2";
   4365             }
   4366         }
   4367         elsif($what eq "file") {
   4368             # we support it but have no server!
   4369         }
   4370         elsif($what eq "https") {
   4371             if(!$stunnel) {
   4372                 # we can't run https tests without stunnel
   4373                 return "no stunnel";
   4374             }
   4375             if(!$ssl_version) {
   4376                 # we can't run https tests if libcurl is SSL-less
   4377                 return "curl lacks SSL support";
   4378             }
   4379             if($runcert{'https'} && ($runcert{'https'} ne $certfile)) {
   4380                 # stop server when running and using a different cert
   4381                 stopserver('https');
   4382             }
   4383             if($torture && $run{'http'} &&
   4384                !responsive_http_server("http", $verbose, 0, $HTTPPORT)) {
   4385                 stopserver('http');
   4386             }
   4387             if(!$run{'http'}) {
   4388                 ($pid, $pid2) = runhttpserver("http", $verbose, 0,
   4389                                               $HTTPPORT);
   4390                 if($pid <= 0) {
   4391                     return "failed starting HTTP server";
   4392                 }
   4393                 printf ("* pid http => %d %d\n", $pid, $pid2) if($verbose);
   4394                 $run{'http'}="$pid $pid2";
   4395             }
   4396             if(!$run{'https'}) {
   4397                 ($pid, $pid2) = runhttpsserver($verbose, "", $certfile);
   4398                 if($pid <= 0) {
   4399                     return "failed starting HTTPS server (stunnel)";
   4400                 }
   4401                 logmsg sprintf("* pid https => %d %d\n", $pid, $pid2)
   4402                     if($verbose);
   4403                 $run{'https'}="$pid $pid2";
   4404             }
   4405         }
   4406         elsif($what eq "httptls") {
   4407             if(!$httptlssrv) {
   4408                 # for now, we can't run http TLS-EXT tests without gnutls-serv
   4409                 return "no gnutls-serv";
   4410             }
   4411             if($torture && $run{'httptls'} &&
   4412                !responsive_httptls_server($verbose, "IPv4")) {
   4413                 stopserver('httptls');
   4414             }
   4415             if(!$run{'httptls'}) {
   4416                 ($pid, $pid2) = runhttptlsserver($verbose, "IPv4");
   4417                 if($pid <= 0) {
   4418                     return "failed starting HTTPTLS server (gnutls-serv)";
   4419                 }
   4420                 logmsg sprintf("* pid httptls => %d %d\n", $pid, $pid2)
   4421                     if($verbose);
   4422                 $run{'httptls'}="$pid $pid2";
   4423             }
   4424         }
   4425         elsif($what eq "httptls-ipv6") {
   4426             if(!$httptlssrv) {
   4427                 # for now, we can't run http TLS-EXT tests without gnutls-serv
   4428                 return "no gnutls-serv";
   4429             }
   4430             if($torture && $run{'httptls-ipv6'} &&
   4431                !responsive_httptls_server($verbose, "ipv6")) {
   4432                 stopserver('httptls-ipv6');
   4433             }
   4434             if(!$run{'httptls-ipv6'}) {
   4435                 ($pid, $pid2) = runhttptlsserver($verbose, "ipv6");
   4436                 if($pid <= 0) {
   4437                     return "failed starting HTTPTLS-IPv6 server (gnutls-serv)";
   4438                 }
   4439                 logmsg sprintf("* pid httptls-ipv6 => %d %d\n", $pid, $pid2)
   4440                     if($verbose);
   4441                 $run{'httptls-ipv6'}="$pid $pid2";
   4442             }
   4443         }
   4444         elsif($what eq "tftp") {
   4445             if($torture && $run{'tftp'} &&
   4446                !responsive_tftp_server("", $verbose)) {
   4447                 stopserver('tftp');
   4448             }
   4449             if(!$run{'tftp'}) {
   4450                 ($pid, $pid2) = runtftpserver("", $verbose);
   4451                 if($pid <= 0) {
   4452                     return "failed starting TFTP server";
   4453                 }
   4454                 printf ("* pid tftp => %d %d\n", $pid, $pid2) if($verbose);
   4455                 $run{'tftp'}="$pid $pid2";
   4456             }
   4457         }
   4458         elsif($what eq "tftp-ipv6") {
   4459             if($torture && $run{'tftp-ipv6'} &&
   4460                !responsive_tftp_server("", $verbose, "ipv6")) {
   4461                 stopserver('tftp-ipv6');
   4462             }
   4463             if(!$run{'tftp-ipv6'}) {
   4464                 ($pid, $pid2) = runtftpserver("", $verbose, "ipv6");
   4465                 if($pid <= 0) {
   4466                     return "failed starting TFTP-IPv6 server";
   4467                 }
   4468                 printf("* pid tftp-ipv6 => %d %d\n", $pid, $pid2) if($verbose);
   4469                 $run{'tftp-ipv6'}="$pid $pid2";
   4470             }
   4471         }
   4472         elsif($what eq "sftp" || $what eq "scp" || $what eq "socks4" || $what eq "socks5" ) {
   4473             if(!$run{'ssh'}) {
   4474                 ($pid, $pid2) = runsshserver("", $verbose);
   4475                 if($pid <= 0) {
   4476                     return "failed starting SSH server";
   4477                 }
   4478                 printf ("* pid ssh => %d %d\n", $pid, $pid2) if($verbose);
   4479                 $run{'ssh'}="$pid $pid2";
   4480             }
   4481             if($what eq "socks4" || $what eq "socks5") {
   4482                 if(!$run{'socks'}) {
   4483                     ($pid, $pid2) = runsocksserver("", $verbose);
   4484                     if($pid <= 0) {
   4485                         return "failed starting socks server";
   4486                     }
   4487                     printf ("* pid socks => %d %d\n", $pid, $pid2) if($verbose);
   4488                     $run{'socks'}="$pid $pid2";
   4489                 }
   4490             }
   4491             if($what eq "socks5") {
   4492                 if(!$sshdid) {
   4493                     # Not an OpenSSH or SunSSH ssh daemon
   4494                     logmsg "Not OpenSSH or SunSSH; socks5 tests need at least OpenSSH 3.7\n";
   4495                     return "failed starting socks5 server";
   4496                 }
   4497                 elsif(($sshdid =~ /OpenSSH/) && ($sshdvernum < 370)) {
   4498                     # Need OpenSSH 3.7 for socks5 - http://www.openssh.com/txt/release-3.7
   4499                     logmsg "$sshdverstr insufficient; socks5 tests need at least OpenSSH 3.7\n";
   4500                     return "failed starting socks5 server";
   4501                 }
   4502                 elsif(($sshdid =~ /SunSSH/)  && ($sshdvernum < 100)) {
   4503                     # Need SunSSH 1.0 for socks5
   4504                     logmsg "$sshdverstr insufficient; socks5 tests need at least SunSSH 1.0\n";
   4505                     return "failed starting socks5 server";
   4506                 }
   4507             }
   4508         }
   4509         elsif($what eq "http-unix") {
   4510             if($torture && $run{'http-unix'} &&
   4511                !responsive_http_server("http", $verbose, "unix", $HTTPUNIXPATH)) {
   4512                 stopserver('http-unix');
   4513             }
   4514             if(!$run{'http-unix'}) {
   4515                 ($pid, $pid2) = runhttpserver("http", $verbose, "unix",
   4516                                               $HTTPUNIXPATH);
   4517                 if($pid <= 0) {
   4518                     return "failed starting HTTP-unix server";
   4519                 }
   4520                 logmsg sprintf("* pid http-unix => %d %d\n", $pid, $pid2)
   4521                     if($verbose);
   4522                 $run{'http-unix'}="$pid $pid2";
   4523             }
   4524         }
   4525         elsif($what eq "none") {
   4526             logmsg "* starts no server\n" if ($verbose);
   4527         }
   4528         else {
   4529             warn "we don't support a server for $what";
   4530             return "no server for $what";
   4531         }
   4532     }
   4533     return 0;
   4534 }
   4535 
   4536 ##############################################################################
   4537 # This function makes sure the right set of server is running for the
   4538 # specified test case. This is a useful design when we run single tests as not
   4539 # all servers need to run then!
   4540 #
   4541 # Returns: a string, blank if everything is fine or a reason why it failed
   4542 #
   4543 sub serverfortest {
   4544     my ($testnum)=@_;
   4545 
   4546     my @what = getpart("client", "server");
   4547 
   4548     if(!$what[0]) {
   4549         warn "Test case $testnum has no server(s) specified";
   4550         return "no server specified";
   4551     }
   4552 
   4553     for(my $i = scalar(@what) - 1; $i >= 0; $i--) {
   4554         my $srvrline = $what[$i];
   4555         chomp $srvrline if($srvrline);
   4556         if($srvrline =~ /^(\S+)((\s*)(.*))/) {
   4557             my $server = "${1}";
   4558             my $lnrest = "${2}";
   4559             my $tlsext;
   4560             if($server =~ /^(httptls)(\+)(ext|srp)(\d*)(-ipv6|)$/) {
   4561                 $server = "${1}${4}${5}";
   4562                 $tlsext = uc("TLS-${3}");
   4563             }
   4564             if(! grep /^\Q$server\E$/, @protocols) {
   4565                 if(substr($server,0,5) ne "socks") {
   4566                     if($tlsext) {
   4567                         return "curl lacks $tlsext support";
   4568                     }
   4569                     else {
   4570                         return "curl lacks $server server support";
   4571                     }
   4572                 }
   4573             }
   4574             $what[$i] = "$server$lnrest" if($tlsext);
   4575         }
   4576     }
   4577 
   4578     return &startservers(@what);
   4579 }
   4580 
   4581 #######################################################################
   4582 # runtimestats displays test-suite run time statistics
   4583 #
   4584 sub runtimestats {
   4585     my $lasttest = $_[0];
   4586 
   4587     return if(not $timestats);
   4588 
   4589     logmsg "\nTest suite total running time breakdown per task...\n\n";
   4590 
   4591     my @timesrvr;
   4592     my @timeprep;
   4593     my @timetool;
   4594     my @timelock;
   4595     my @timevrfy;
   4596     my @timetest;
   4597     my $timesrvrtot = 0.0;
   4598     my $timepreptot = 0.0;
   4599     my $timetooltot = 0.0;
   4600     my $timelocktot = 0.0;
   4601     my $timevrfytot = 0.0;
   4602     my $timetesttot = 0.0;
   4603     my $counter;
   4604 
   4605     for my $testnum (1 .. $lasttest) {
   4606         if($timesrvrini{$testnum}) {
   4607             $timesrvrtot += $timesrvrend{$testnum} - $timesrvrini{$testnum};
   4608             $timepreptot +=
   4609                 (($timetoolini{$testnum} - $timeprepini{$testnum}) -
   4610                  ($timesrvrend{$testnum} - $timesrvrini{$testnum}));
   4611             $timetooltot += $timetoolend{$testnum} - $timetoolini{$testnum};
   4612             $timelocktot += $timesrvrlog{$testnum} - $timetoolend{$testnum};
   4613             $timevrfytot += $timevrfyend{$testnum} - $timesrvrlog{$testnum};
   4614             $timetesttot += $timevrfyend{$testnum} - $timeprepini{$testnum};
   4615             push @timesrvr, sprintf("%06.3f  %04d",
   4616                 $timesrvrend{$testnum} - $timesrvrini{$testnum}, $testnum);
   4617             push @timeprep, sprintf("%06.3f  %04d",
   4618                 ($timetoolini{$testnum} - $timeprepini{$testnum}) -
   4619                 ($timesrvrend{$testnum} - $timesrvrini{$testnum}), $testnum);
   4620             push @timetool, sprintf("%06.3f  %04d",
   4621                 $timetoolend{$testnum} - $timetoolini{$testnum}, $testnum);
   4622             push @timelock, sprintf("%06.3f  %04d",
   4623                 $timesrvrlog{$testnum} - $timetoolend{$testnum}, $testnum);
   4624             push @timevrfy, sprintf("%06.3f  %04d",
   4625                 $timevrfyend{$testnum} - $timesrvrlog{$testnum}, $testnum);
   4626             push @timetest, sprintf("%06.3f  %04d",
   4627                 $timevrfyend{$testnum} - $timeprepini{$testnum}, $testnum);
   4628         }
   4629     }
   4630 
   4631     {
   4632         no warnings 'numeric';
   4633         @timesrvr = sort { $b <=> $a } @timesrvr;
   4634         @timeprep = sort { $b <=> $a } @timeprep;
   4635         @timetool = sort { $b <=> $a } @timetool;
   4636         @timelock = sort { $b <=> $a } @timelock;
   4637         @timevrfy = sort { $b <=> $a } @timevrfy;
   4638         @timetest = sort { $b <=> $a } @timetest;
   4639     }
   4640 
   4641     logmsg "Spent ". sprintf("%08.3f ", $timesrvrtot) .
   4642            "seconds starting and verifying test harness servers.\n";
   4643     logmsg "Spent ". sprintf("%08.3f ", $timepreptot) .
   4644            "seconds reading definitions and doing test preparations.\n";
   4645     logmsg "Spent ". sprintf("%08.3f ", $timetooltot) .
   4646            "seconds actually running test tools.\n";
   4647     logmsg "Spent ". sprintf("%08.3f ", $timelocktot) .
   4648            "seconds awaiting server logs lock removal.\n";
   4649     logmsg "Spent ". sprintf("%08.3f ", $timevrfytot) .
   4650            "seconds verifying test results.\n";
   4651     logmsg "Spent ". sprintf("%08.3f ", $timetesttot) .
   4652            "seconds doing all of the above.\n";
   4653 
   4654     $counter = 25;
   4655     logmsg "\nTest server starting and verification time per test ".
   4656         sprintf("(%s)...\n\n", (not $fullstats)?"top $counter":"full");
   4657     logmsg "-time-  test\n";
   4658     logmsg "------  ----\n";
   4659     foreach my $txt (@timesrvr) {
   4660         last if((not $fullstats) && (not $counter--));
   4661         logmsg "$txt\n";
   4662     }
   4663 
   4664     $counter = 10;
   4665     logmsg "\nTest definition reading and preparation time per test ".
   4666         sprintf("(%s)...\n\n", (not $fullstats)?"top $counter":"full");
   4667     logmsg "-time-  test\n";
   4668     logmsg "------  ----\n";
   4669     foreach my $txt (@timeprep) {
   4670         last if((not $fullstats) && (not $counter--));
   4671         logmsg "$txt\n";
   4672     }
   4673 
   4674     $counter = 25;
   4675     logmsg "\nTest tool execution time per test ".
   4676         sprintf("(%s)...\n\n", (not $fullstats)?"top $counter":"full");
   4677     logmsg "-time-  test\n";
   4678     logmsg "------  ----\n";
   4679     foreach my $txt (@timetool) {
   4680         last if((not $fullstats) && (not $counter--));
   4681         logmsg "$txt\n";
   4682     }
   4683 
   4684     $counter = 15;
   4685     logmsg "\nTest server logs lock removal time per test ".
   4686         sprintf("(%s)...\n\n", (not $fullstats)?"top $counter":"full");
   4687     logmsg "-time-  test\n";
   4688     logmsg "------  ----\n";
   4689     foreach my $txt (@timelock) {
   4690         last if((not $fullstats) && (not $counter--));
   4691         logmsg "$txt\n";
   4692     }
   4693 
   4694     $counter = 10;
   4695     logmsg "\nTest results verification time per test ".
   4696         sprintf("(%s)...\n\n", (not $fullstats)?"top $counter":"full");
   4697     logmsg "-time-  test\n";
   4698     logmsg "------  ----\n";
   4699     foreach my $txt (@timevrfy) {
   4700         last if((not $fullstats) && (not $counter--));
   4701         logmsg "$txt\n";
   4702     }
   4703 
   4704     $counter = 50;
   4705     logmsg "\nTotal time per test ".
   4706         sprintf("(%s)...\n\n", (not $fullstats)?"top $counter":"full");
   4707     logmsg "-time-  test\n";
   4708     logmsg "------  ----\n";
   4709     foreach my $txt (@timetest) {
   4710         last if((not $fullstats) && (not $counter--));
   4711         logmsg "$txt\n";
   4712     }
   4713 
   4714     logmsg "\n";
   4715 }
   4716 
   4717 #######################################################################
   4718 # Check options to this test program
   4719 #
   4720 
   4721 my $number=0;
   4722 my $fromnum=-1;
   4723 my @testthis;
   4724 while(@ARGV) {
   4725     if ($ARGV[0] eq "-v") {
   4726         # verbose output
   4727         $verbose=1;
   4728     }
   4729     elsif($ARGV[0] =~ /^-b(.*)/) {
   4730         my $portno=$1;
   4731         if($portno =~ s/(\d+)$//) {
   4732             $base = int $1;
   4733         }
   4734     }
   4735     elsif ($ARGV[0] eq "-c") {
   4736         # use this path to curl instead of default
   4737         $DBGCURL=$CURL=$ARGV[1];
   4738         shift @ARGV;
   4739     }
   4740     elsif ($ARGV[0] eq "-vc") {
   4741         # use this path to a curl used to verify servers
   4742 
   4743         # Particularly useful when you introduce a crashing bug somewhere in
   4744         # the development version as then it won't be able to run any tests
   4745         # since it can't verify the servers!
   4746 
   4747         $VCURL=$ARGV[1];
   4748         shift @ARGV;
   4749     }
   4750     elsif ($ARGV[0] eq "-d") {
   4751         # have the servers display protocol output
   4752         $debugprotocol=1;
   4753     }
   4754     elsif ($ARGV[0] eq "-g") {
   4755         # run this test with gdb
   4756         $gdbthis=1;
   4757     }
   4758     elsif ($ARGV[0] eq "-gw") {
   4759         # run this test with windowed gdb
   4760         $gdbthis=1;
   4761         $gdbxwin=1;
   4762     }
   4763     elsif($ARGV[0] eq "-s") {
   4764         # short output
   4765         $short=1;
   4766     }
   4767     elsif($ARGV[0] eq "-am") {
   4768         # automake-style output
   4769         $short=1;
   4770         $automakestyle=1;
   4771     }
   4772     elsif($ARGV[0] eq "-n") {
   4773         # no valgrind
   4774         undef $valgrind;
   4775     }
   4776     elsif($ARGV[0] =~ /^-t(.*)/) {
   4777         # torture
   4778         $torture=1;
   4779         my $xtra = $1;
   4780 
   4781         if($xtra =~ s/(\d+)$//) {
   4782             $tortalloc = $1;
   4783         }
   4784         # we undef valgrind to make this fly in comparison
   4785         undef $valgrind;
   4786     }
   4787     elsif($ARGV[0] eq "-a") {
   4788         # continue anyway, even if a test fail
   4789         $anyway=1;
   4790     }
   4791     elsif($ARGV[0] eq "-e") {
   4792         # run the tests cases event based if possible
   4793         $run_event_based=1;
   4794     }
   4795     elsif($ARGV[0] eq "-p") {
   4796         $postmortem=1;
   4797     }
   4798     elsif($ARGV[0] eq "-l") {
   4799         # lists the test case names only
   4800         $listonly=1;
   4801     }
   4802     elsif($ARGV[0] eq "-k") {
   4803         # keep stdout and stderr files after tests
   4804         $keepoutfiles=1;
   4805     }
   4806     elsif($ARGV[0] eq "-r") {
   4807         # run time statistics needs Time::HiRes
   4808         if($Time::HiRes::VERSION) {
   4809             keys(%timeprepini) = 1000;
   4810             keys(%timesrvrini) = 1000;
   4811             keys(%timesrvrend) = 1000;
   4812             keys(%timetoolini) = 1000;
   4813             keys(%timetoolend) = 1000;
   4814             keys(%timesrvrlog) = 1000;
   4815             keys(%timevrfyend) = 1000;
   4816             $timestats=1;
   4817             $fullstats=0;
   4818         }
   4819     }
   4820     elsif($ARGV[0] eq "-rf") {
   4821         # run time statistics needs Time::HiRes
   4822         if($Time::HiRes::VERSION) {
   4823             keys(%timeprepini) = 1000;
   4824             keys(%timesrvrini) = 1000;
   4825             keys(%timesrvrend) = 1000;
   4826             keys(%timetoolini) = 1000;
   4827             keys(%timetoolend) = 1000;
   4828             keys(%timesrvrlog) = 1000;
   4829             keys(%timevrfyend) = 1000;
   4830             $timestats=1;
   4831             $fullstats=1;
   4832         }
   4833     }
   4834     elsif(($ARGV[0] eq "-h") || ($ARGV[0] eq "--help")) {
   4835         # show help text
   4836         print <<EOHELP
   4837 Usage: runtests.pl [options] [test selection(s)]
   4838   -a       continue even if a test fails
   4839   -bN      use base port number N for test servers (default $base)
   4840   -c path  use this curl executable
   4841   -d       display server debug info
   4842   -g       run the test case with gdb
   4843   -gw      run the test case with gdb as a windowed application
   4844   -h       this help text
   4845   -k       keep stdout and stderr files present after tests
   4846   -l       list all test case names/descriptions
   4847   -n       no valgrind
   4848   -p       print log file contents when a test fails
   4849   -r       run time statistics
   4850   -rf      full run time statistics
   4851   -s       short output
   4852   -am      automake style output PASS/FAIL: [number] [name]
   4853   -t[N]    torture (simulate memory alloc failures); N means fail Nth alloc
   4854   -v       verbose output
   4855   -vc path use this curl only to verify the existing servers
   4856   [num]    like "5 6 9" or " 5 to 22 " to run those tests only
   4857   [!num]   like "!5 !6 !9" to disable those tests
   4858   [keyword] like "IPv6" to select only tests containing the key word
   4859   [!keyword] like "!cookies" to disable any tests containing the key word
   4860 EOHELP
   4861     ;
   4862         exit;
   4863     }
   4864     elsif($ARGV[0] =~ /^(\d+)/) {
   4865         $number = $1;
   4866         if($fromnum >= 0) {
   4867             for($fromnum .. $number) {
   4868                 push @testthis, $_;
   4869             }
   4870             $fromnum = -1;
   4871         }
   4872         else {
   4873             push @testthis, $1;
   4874         }
   4875     }
   4876     elsif($ARGV[0] =~ /^to$/i) {
   4877         $fromnum = $number+1;
   4878     }
   4879     elsif($ARGV[0] =~ /^!(\d+)/) {
   4880         $fromnum = -1;
   4881         $disabled{$1}=$1;
   4882     }
   4883     elsif($ARGV[0] =~ /^!(.+)/) {
   4884         $disabled_keywords{$1}=$1;
   4885     }
   4886     elsif($ARGV[0] =~ /^([-[{a-zA-Z].*)/) {
   4887         $enabled_keywords{$1}=$1;
   4888     }
   4889     else {
   4890         print "Unknown option: $ARGV[0]\n";
   4891         exit;
   4892     }
   4893     shift @ARGV;
   4894 }
   4895 
   4896 if(@testthis && ($testthis[0] ne "")) {
   4897     $TESTCASES=join(" ", @testthis);
   4898 }
   4899 
   4900 if($valgrind) {
   4901     # we have found valgrind on the host, use it
   4902 
   4903     # verify that we can invoke it fine
   4904     my $code = runclient("valgrind >/dev/null 2>&1");
   4905 
   4906     if(($code>>8) != 1) {
   4907         #logmsg "Valgrind failure, disable it\n";
   4908         undef $valgrind;
   4909     } else {
   4910 
   4911         # since valgrind 2.1.x, '--tool' option is mandatory
   4912         # use it, if it is supported by the version installed on the system
   4913         runclient("valgrind --help 2>&1 | grep -- --tool > /dev/null 2>&1");
   4914         if (($? >> 8)==0) {
   4915             $valgrind_tool="--tool=memcheck";
   4916         }
   4917         open(C, "<$CURL");
   4918         my $l = <C>;
   4919         if($l =~ /^\#\!/) {
   4920             # A shell script. This is typically when built with libtool,
   4921             $valgrind="../libtool --mode=execute $valgrind";
   4922         }
   4923         close(C);
   4924 
   4925         # valgrind 3 renamed the --logfile option to --log-file!!!
   4926         my $ver=join(' ', runclientoutput("valgrind --version"));
   4927         # cut off all but digits and dots
   4928         $ver =~ s/[^0-9.]//g;
   4929 
   4930         if($ver =~ /^(\d+)/) {
   4931             $ver = $1;
   4932             if($ver >= 3) {
   4933                 $valgrind_logfile="--log-file";
   4934             }
   4935         }
   4936     }
   4937 }
   4938 
   4939 if ($gdbthis) {
   4940     # open the executable curl and read the first 4 bytes of it
   4941     open(CHECK, "<$CURL");
   4942     my $c;
   4943     sysread CHECK, $c, 4;
   4944     close(CHECK);
   4945     if($c eq "#! /") {
   4946         # A shell script. This is typically when built with libtool,
   4947         $libtool = 1;
   4948         $gdb = "../libtool --mode=execute gdb";
   4949     }
   4950 }
   4951 
   4952 $HTTPPORT        = $base++; # HTTP server port
   4953 $HTTPSPORT       = $base++; # HTTPS (stunnel) server port
   4954 $FTPPORT         = $base++; # FTP server port
   4955 $FTPSPORT        = $base++; # FTPS (stunnel) server port
   4956 $HTTP6PORT       = $base++; # HTTP IPv6 server port
   4957 $FTP2PORT        = $base++; # FTP server 2 port
   4958 $FTP6PORT        = $base++; # FTP IPv6 port
   4959 $TFTPPORT        = $base++; # TFTP (UDP) port
   4960 $TFTP6PORT       = $base++; # TFTP IPv6 (UDP) port
   4961 $SSHPORT         = $base++; # SSH (SCP/SFTP) port
   4962 $SOCKSPORT       = $base++; # SOCKS port
   4963 $POP3PORT        = $base++; # POP3 server port
   4964 $POP36PORT       = $base++; # POP3 IPv6 server port
   4965 $IMAPPORT        = $base++; # IMAP server port
   4966 $IMAP6PORT       = $base++; # IMAP IPv6 server port
   4967 $SMTPPORT        = $base++; # SMTP server port
   4968 $SMTP6PORT       = $base++; # SMTP IPv6 server port
   4969 $RTSPPORT        = $base++; # RTSP server port
   4970 $RTSP6PORT       = $base++; # RTSP IPv6 server port
   4971 $GOPHERPORT      = $base++; # Gopher IPv4 server port
   4972 $GOPHER6PORT     = $base++; # Gopher IPv6 server port
   4973 $HTTPTLSPORT     = $base++; # HTTP TLS (non-stunnel) server port
   4974 $HTTPTLS6PORT    = $base++; # HTTP TLS (non-stunnel) IPv6 server port
   4975 $HTTPPROXYPORT   = $base++; # HTTP proxy port, when using CONNECT
   4976 $HTTPPIPEPORT    = $base++; # HTTP pipelining port
   4977 $HTTPUNIXPATH    = 'http.sock'; # HTTP server Unix domain socket path
   4978 
   4979 #######################################################################
   4980 # clear and create logging directory:
   4981 #
   4982 
   4983 cleardir($LOGDIR);
   4984 mkdir($LOGDIR, 0777);
   4985 
   4986 #######################################################################
   4987 # initialize some variables
   4988 #
   4989 
   4990 get_disttests();
   4991 init_serverpidfile_hash();
   4992 
   4993 #######################################################################
   4994 # Output curl version and host info being tested
   4995 #
   4996 
   4997 if(!$listonly) {
   4998     checksystem();
   4999 }
   5000 
   5001 #######################################################################
   5002 # Fetch all disabled tests, if there are any
   5003 #
   5004 
   5005 sub disabledtests {
   5006     my ($file) = @_;
   5007 
   5008     if(open(D, "<$file")) {
   5009         while(<D>) {
   5010             if(/^ *\#/) {
   5011                 # allow comments
   5012                 next;
   5013             }
   5014             if($_ =~ /(\d+)/) {
   5015                 $disabled{$1}=$1; # disable this test number
   5016             }
   5017         }
   5018         close(D);
   5019     }
   5020 }
   5021 
   5022 # globally disabled tests
   5023 disabledtests("$TESTDIR/DISABLED");
   5024 
   5025 # locally disabled tests, ignored by git etc
   5026 disabledtests("$TESTDIR/DISABLED.local");
   5027 
   5028 #######################################################################
   5029 # If 'all' tests are requested, find out all test numbers
   5030 #
   5031 
   5032 if ( $TESTCASES eq "all") {
   5033     # Get all commands and find out their test numbers
   5034     opendir(DIR, $TESTDIR) || die "can't opendir $TESTDIR: $!";
   5035     my @cmds = grep { /^test([0-9]+)$/ && -f "$TESTDIR/$_" } readdir(DIR);
   5036     closedir(DIR);
   5037 
   5038     $TESTCASES=""; # start with no test cases
   5039 
   5040     # cut off everything but the digits
   5041     for(@cmds) {
   5042         $_ =~ s/[a-z\/\.]*//g;
   5043     }
   5044     # sort the numbers from low to high
   5045     foreach my $n (sort { $a <=> $b } @cmds) {
   5046         if($disabled{$n}) {
   5047             # skip disabled test cases
   5048             my $why = "configured as DISABLED";
   5049             $skipped++;
   5050             $skipped{$why}++;
   5051             $teststat[$n]=$why; # store reason for this test case
   5052             next;
   5053         }
   5054         $TESTCASES .= " $n";
   5055     }
   5056 }
   5057 else {
   5058     my $verified="";
   5059     map {
   5060         if (-e "$TESTDIR/test$_") {
   5061             $verified.="$_ ";
   5062         }
   5063     } split(" ", $TESTCASES);
   5064     if($verified eq "") {
   5065         print "No existing test cases were specified\n";
   5066         exit;
   5067     }
   5068     $TESTCASES = $verified;
   5069 }
   5070 
   5071 #######################################################################
   5072 # Start the command line log
   5073 #
   5074 open(CMDLOG, ">$CURLLOG") ||
   5075     logmsg "can't log command lines to $CURLLOG\n";
   5076 
   5077 #######################################################################
   5078 
   5079 # Display the contents of the given file.  Line endings are canonicalized
   5080 # and excessively long files are elided
   5081 sub displaylogcontent {
   5082     my ($file)=@_;
   5083     if(open(SINGLE, "<$file")) {
   5084         my $linecount = 0;
   5085         my $truncate;
   5086         my @tail;
   5087         while(my $string = <SINGLE>) {
   5088             $string =~ s/\r\n/\n/g;
   5089             $string =~ s/[\r\f\032]/\n/g;
   5090             $string .= "\n" unless ($string =~ /\n$/);
   5091             $string =~ tr/\n//;
   5092             for my $line (split("\n", $string)) {
   5093                 $line =~ s/\s*\!$//;
   5094                 if ($truncate) {
   5095                     push @tail, " $line\n";
   5096                 } else {
   5097                     logmsg " $line\n";
   5098                 }
   5099                 $linecount++;
   5100                 $truncate = $linecount > 1000;
   5101             }
   5102         }
   5103         if(@tail) {
   5104             my $tailshow = 200;
   5105             my $tailskip = 0;
   5106             my $tailtotal = scalar @tail;
   5107             if($tailtotal > $tailshow) {
   5108                 $tailskip = $tailtotal - $tailshow;
   5109                 logmsg "=== File too long: $tailskip lines omitted here\n";
   5110             }
   5111             for($tailskip .. $tailtotal-1) {
   5112                 logmsg "$tail[$_]";
   5113             }
   5114         }
   5115         close(SINGLE);
   5116     }
   5117 }
   5118 
   5119 sub displaylogs {
   5120     my ($testnum)=@_;
   5121     opendir(DIR, "$LOGDIR") ||
   5122         die "can't open dir: $!";
   5123     my @logs = readdir(DIR);
   5124     closedir(DIR);
   5125 
   5126     logmsg "== Contents of files in the $LOGDIR/ dir after test $testnum\n";
   5127     foreach my $log (sort @logs) {
   5128         if($log =~ /\.(\.|)$/) {
   5129             next; # skip "." and ".."
   5130         }
   5131         if($log =~ /^\.nfs/) {
   5132             next; # skip ".nfs"
   5133         }
   5134         if(($log eq "memdump") || ($log eq "core")) {
   5135             next; # skip "memdump" and  "core"
   5136         }
   5137         if((-d "$LOGDIR/$log") || (! -s "$LOGDIR/$log")) {
   5138             next; # skip directory and empty files
   5139         }
   5140         if(($log =~ /^stdout\d+/) && ($log !~ /^stdout$testnum/)) {
   5141             next; # skip stdoutNnn of other tests
   5142         }
   5143         if(($log =~ /^stderr\d+/) && ($log !~ /^stderr$testnum/)) {
   5144             next; # skip stderrNnn of other tests
   5145         }
   5146         if(($log =~ /^upload\d+/) && ($log !~ /^upload$testnum/)) {
   5147             next; # skip uploadNnn of other tests
   5148         }
   5149         if(($log =~ /^curl\d+\.out/) && ($log !~ /^curl$testnum\.out/)) {
   5150             next; # skip curlNnn.out of other tests
   5151         }
   5152         if(($log =~ /^test\d+\.txt/) && ($log !~ /^test$testnum\.txt/)) {
   5153             next; # skip testNnn.txt of other tests
   5154         }
   5155         if(($log =~ /^file\d+\.txt/) && ($log !~ /^file$testnum\.txt/)) {
   5156             next; # skip fileNnn.txt of other tests
   5157         }
   5158         if(($log =~ /^netrc\d+/) && ($log !~ /^netrc$testnum/)) {
   5159             next; # skip netrcNnn of other tests
   5160         }
   5161         if(($log =~ /^trace\d+/) && ($log !~ /^trace$testnum/)) {
   5162             next; # skip traceNnn of other tests
   5163         }
   5164         if(($log =~ /^valgrind\d+/) && ($log !~ /^valgrind$testnum(\..*|)$/)) {
   5165             next; # skip valgrindNnn of other tests
   5166         }
   5167         logmsg "=== Start of file $log\n";
   5168         displaylogcontent("$LOGDIR/$log");
   5169         logmsg "=== End of file $log\n";
   5170     }
   5171 }
   5172 
   5173 #######################################################################
   5174 # The main test-loop
   5175 #
   5176 
   5177 my $failed;
   5178 my $testnum;
   5179 my $ok=0;
   5180 my $total=0;
   5181 my $lasttest=0;
   5182 my @at = split(" ", $TESTCASES);
   5183 my $count=0;
   5184 
   5185 $start = time();
   5186 
   5187 foreach $testnum (@at) {
   5188 
   5189     $lasttest = $testnum if($testnum > $lasttest);
   5190     $count++;
   5191 
   5192     my $error = singletest($run_event_based, $testnum, $count, scalar(@at));
   5193     if($error < 0) {
   5194         # not a test we can run
   5195         next;
   5196     }
   5197 
   5198     $total++; # number of tests we've run
   5199 
   5200     if($error>0) {
   5201         $failed.= "$testnum ";
   5202         if($postmortem) {
   5203             # display all files in log/ in a nice way
   5204             displaylogs($testnum);
   5205         }
   5206         if(!$anyway) {
   5207             # a test failed, abort
   5208             logmsg "\n - abort tests\n";
   5209             last;
   5210         }
   5211     }
   5212     elsif(!$error) {
   5213         $ok++; # successful test counter
   5214     }
   5215 
   5216     # loop for next test
   5217 }
   5218 
   5219 my $sofar = time() - $start;
   5220 
   5221 #######################################################################
   5222 # Close command log
   5223 #
   5224 close(CMDLOG);
   5225 
   5226 # Tests done, stop the servers
   5227 stopservers($verbose);
   5228 
   5229 my $all = $total + $skipped;
   5230 
   5231 runtimestats($lasttest);
   5232 
   5233 if($total) {
   5234     logmsg sprintf("TESTDONE: $ok tests out of $total reported OK: %d%%\n",
   5235                    $ok/$total*100);
   5236 
   5237     if($ok != $total) {
   5238         logmsg "TESTFAIL: These test cases failed: $failed\n";
   5239     }
   5240 }
   5241 else {
   5242     logmsg "TESTFAIL: No tests were performed\n";
   5243 }
   5244 
   5245 if($all) {
   5246     logmsg "TESTDONE: $all tests were considered during ".
   5247         sprintf("%.0f", $sofar) ." seconds.\n";
   5248 }
   5249 
   5250 if($skipped && !$short) {
   5251     my $s=0;
   5252     logmsg "TESTINFO: $skipped tests were skipped due to these restraints:\n";
   5253 
   5254     for(keys %skipped) {
   5255         my $r = $_;
   5256         printf "TESTINFO: \"%s\" %d times (", $r, $skipped{$_};
   5257 
   5258         # now show all test case numbers that had this reason for being
   5259         # skipped
   5260         my $c=0;
   5261         my $max = 9;
   5262         for(0 .. scalar @teststat) {
   5263             my $t = $_;
   5264             if($teststat[$_] && ($teststat[$_] eq $r)) {
   5265                 if($c < $max) {
   5266                     logmsg ", " if($c);
   5267                     logmsg $_;
   5268                 }
   5269                 $c++;
   5270             }
   5271         }
   5272         if($c > $max) {
   5273             logmsg " and ".($c-$max)." more";
   5274         }
   5275         logmsg ")\n";
   5276     }
   5277 }
   5278 
   5279 if($total && ($ok != $total)) {
   5280     exit 1;
   5281 }
   5282