int main()

in support/ab.c [2992:3507]


int main(int argc, const char * const argv[])
{
    char tmp[1024];
    apr_status_t status;
    apr_getopt_t *opt;
    const char *opt_arg;
    char c;
#ifdef USE_SSL
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
    int max_prot = MAX_SSL_PROTO;
    int min_prot = MIN_SSL_PROTO;
#endif /* #if OPENSSL_VERSION_NUMBER >= 0x10100000L */
    AB_SSL_METHOD_CONST SSL_METHOD *meth = SSLv23_client_method();
#endif /* USE_SSL */

    srand((unsigned int)apr_time_now());

    /* table defaults  */
    tablestring = "";
    trstring = "";
    tdstring = "bgcolor=white";
    cookie = "";
    auth = "";
    proxyhost = "";
    hdrs = "";

    apr_app_initialize(&argc, &argv, NULL);
    if (apr_pool_create(&cntxt, NULL) != APR_SUCCESS) {
        abort_on_oom(APR_ENOMEM);
    }
    apr_pool_abort_set(abort_on_oom, cntxt);
    atexit(output_results_at_exit);

#ifdef NOT_ASCII
    status = apr_xlate_open(&to_ascii, "ISO-8859-1", APR_DEFAULT_CHARSET, cntxt);
    if (status) {
        fprintf(stderr, "apr_xlate_open(to ASCII)->%d\n", status);
        exit(1);
    }
    status = apr_xlate_open(&from_ascii, APR_DEFAULT_CHARSET, "ISO-8859-1", cntxt);
    if (status) {
        fprintf(stderr, "apr_xlate_open(from ASCII)->%d\n", status);
        exit(1);
    }
    status = apr_base64init_ebcdic(to_ascii, from_ascii);
    if (status) {
        fprintf(stderr, "apr_base64init_ebcdic()->%d\n", status);
        exit(1);
    }
#endif

    apr_getopt_init(&opt, cntxt, argc, argv);
    while ((status = apr_getopt(opt, "n:c:t:s:b:T:p:u:v:lrkVhwiIx:y:z:C:H:P:A:g:X:de:SqQDB:m:R:o:"
#if APR_HAS_THREADS
            "W:"
#endif
#ifdef USE_SSL
            "Z:f:E:"
#endif
            ,&c, &opt_arg)) == APR_SUCCESS) {
        switch (c) {
            case 'n':
                requests = atoi(opt_arg);
                if (requests <= 0) {
                    fatal_error("Invalid number of requests\n");
                }
                break;
#if APR_HAS_THREADS
            case 'W':
                num_workers = atoi(opt_arg);
                if (num_workers < 0) {
                    fatal_error("Invalid number of workers\n");
                }
                break;
#endif
            case 'k':
                keepalive = 1;
                break;
            case 'o':
                src_address = strdup(opt_arg);
                break;
            case 'q':
                heartbeatres = 0;
                break;
            case 'Q':
                no_banner = 1;
                break;
            case 'D':
                watchdog = 1;
                break;
            case 'c':
                concurrency = atoi(opt_arg);
                if (concurrency < 0) {
                    fatal_error("Invalid negative concurrency\n");
                }
                break;
            case 'b':
                windowsize = atoi(opt_arg);
                break;
            case 'i':
                if (method != NO_METH)
                    fatal_error("Cannot mix HEAD with other methods\n");
                method = HEAD;
                break;
            case 'g':
                gnuplot = apr_pstrdup(cntxt, opt_arg);
                break;
            case 'd':
                percentile = 0;
                break;
            case 'e':
                csvperc = apr_pstrdup(cntxt, opt_arg);
                break;
            case 'S':
                confidence = 0;
                break;
            case 's':
                aprtimeout = apr_time_from_sec(atoi(opt_arg)); /* timeout value */
                break;
            case 'R':
                ramp = apr_time_from_msec(atoi(opt_arg)); /* ramp delay */
                break;
            case 'p':
                if (method != NO_METH)
                    fatal_error("Cannot mix POST with other methods\n");
                if (open_postfile(opt_arg) != APR_SUCCESS) {
                    exit(1);
                }
                method = POST;
                send_body = 1;
                break;
            case 'u':
                if (method != NO_METH)
                    fatal_error("Cannot mix PUT with other methods\n");
                if (open_postfile(opt_arg) != APR_SUCCESS) {
                    exit(1);
                }
                method = PUT;
                send_body = 1;
                break;
            case 'l':
                nolength = 1;
                break;
            case 'r':
                recverrok = 1;
                break;
            case 'v':
                verbosity = atoi(opt_arg);
                break;
            case 't':
                tlimit = atoi(opt_arg);
                if (tlimit < 0)
                    fatal_error("Invalid negative timelimit\n");
                break;
            case 'T':
                content_type = apr_pstrdup(cntxt, opt_arg);
                break;
            case 'C':
                cookie = apr_pstrcat(cntxt, "Cookie: ", opt_arg, "\r\n", NULL);
                break;
            case 'A':
                /*
                 * assume username passwd already to be in colon separated form.
                 * Ready to be uu-encoded.
                 */
                while (apr_isspace(*opt_arg))
                    opt_arg++;
                if (apr_base64_encode_len(strlen(opt_arg)) > sizeof(tmp)) {
                    fatal_error("Authentication credentials too long\n");
                }
                apr_base64_encode(tmp, opt_arg, strlen(opt_arg));

                auth = apr_pstrcat(cntxt, auth, "Authorization: Basic ", tmp,
                                       "\r\n", NULL);
                break;
            case 'P':
                /*
                 * assume username passwd already to be in colon separated form.
                 */
                while (apr_isspace(*opt_arg))
                opt_arg++;
                if (apr_base64_encode_len(strlen(opt_arg)) > sizeof(tmp)) {
                    fatal_error("Proxy credentials too long\n");
                }
                apr_base64_encode(tmp, opt_arg, strlen(opt_arg));

                auth = apr_pstrcat(cntxt, auth, "Proxy-Authorization: Basic ",
                                       tmp, "\r\n", NULL);
                break;
            case 'H':
                hdrs = apr_pstrcat(cntxt, hdrs, opt_arg, "\r\n", NULL);
                /*
                 * allow override of some of the common headers that ab adds
                 */
                if (strncasecmp(opt_arg, "Host:", 5) == 0) {
                    char *host;
                    apr_size_t len;
                    opt_arg += 5;
                    while (apr_isspace(*opt_arg))
                        opt_arg++;
                    len = strlen(opt_arg);
                    host = strdup(opt_arg);
                    while (len && apr_isspace(host[len-1]))
                        host[--len] = '\0';
                    opt_host = host;
                } else if (strncasecmp(opt_arg, "Accept:", 7) == 0) {
                    opt_accept = 1;
                } else if (strncasecmp(opt_arg, "User-Agent:", 11) == 0) {
                    opt_useragent = 1;
                }
                break;
            case 'w':
                use_html = 1;
                break;
                /*
                 * if any of the following three are used, turn on html output
                 * automatically
                 */
            case 'x':
                use_html = 1;
                tablestring = opt_arg;
                break;
            case 'X':
                {
                    char *p;
                    /*
                     * assume proxy-name[:port]
                     */
                    if ((p = strchr(opt_arg, ':'))) {
                        *p = '\0';
                        p++;
                        proxyport = atoi(p);
                    }
                    proxyhost = apr_pstrdup(cntxt, opt_arg);
                    isproxy = 1;
                }
                break;
            case 'y':
                use_html = 1;
                trstring = opt_arg;
                break;
            case 'z':
                use_html = 1;
                tdstring = opt_arg;
                break;
            case 'h':
                usage(argv[0]);
                break;
            case 'V':
                copyright();
                return 0;
            case 'B':
                {
                    const char *ptr, *end;

                    bind_count = 1;
                    for (ptr = opt_arg; (end = strchr(ptr, ',')); ptr = end + 1) {
                        bind_count++;
                    }
                    bind_hosts = apr_palloc(cntxt, bind_count * sizeof(char*));

                    bind_count = 0;
                    for (ptr = opt_arg; (end = strchr(ptr, ',')); ptr = end + 1) {
                        if (end > ptr) {
                            bind_hosts[bind_count++] = apr_pstrmemdup(cntxt, ptr, end - ptr);
                        }
                    }
                    if (*ptr) {
                        bind_hosts[bind_count++] = apr_pstrdup(cntxt, ptr);
                    }

                    if (!bind_count) {
                        fprintf(stderr, "%s: Invalid bind address[es]\n", argv[0]);
                        usage(argv[0]);
                    }
                }
                break;
            case 'm':
                method = CUSTOM_METHOD;
                method_str[CUSTOM_METHOD] = strdup(opt_arg);
                break;
#ifdef USE_SSL
            case 'Z':
                ssl_cipher = strdup(opt_arg);
                break;
            case 'E':
                ssl_cert = strdup(opt_arg);
                break;
            case 'f':
#if OPENSSL_VERSION_NUMBER < 0x10100000L
                if (strncasecmp(opt_arg, "ALL", 3) == 0) {
                    meth = SSLv23_client_method();
#ifndef OPENSSL_NO_SSL2
                } else if (strncasecmp(opt_arg, "SSL2", 4) == 0) {
                    meth = SSLv2_client_method();
#ifdef HAVE_TLSEXT
                    tls_use_sni = 0;
#endif
#endif
#ifndef OPENSSL_NO_SSL3
                } else if (strncasecmp(opt_arg, "SSL3", 4) == 0) {
                    meth = SSLv3_client_method();
#ifdef HAVE_TLSEXT
                    tls_use_sni = 0;
#endif
#endif
#ifdef HAVE_TLSV1_X
                } else if (strncasecmp(opt_arg, "TLS1.1", 6) == 0) {
                    meth = TLSv1_1_client_method();
                } else if (strncasecmp(opt_arg, "TLS1.2", 6) == 0) {
                    meth = TLSv1_2_client_method();
#endif
                } else if (strncasecmp(opt_arg, "TLS1", 4) == 0) {
                    meth = TLSv1_client_method();
                }
#else /* #if OPENSSL_VERSION_NUMBER < 0x10100000L */
                meth = TLS_client_method();
                if (strncasecmp(opt_arg, "ALL", 3) == 0) {
                    max_prot = MAX_SSL_PROTO;
                    min_prot = MIN_SSL_PROTO;
#ifndef OPENSSL_NO_SSL3
                } else if (strncasecmp(opt_arg, "SSL3", 4) == 0) {
                    max_prot = SSL3_VERSION;
                    min_prot = SSL3_VERSION;
#endif
                } else if (strncasecmp(opt_arg, "TLS1.1", 6) == 0) {
                    max_prot = TLS1_1_VERSION;
                    min_prot = TLS1_1_VERSION;
                } else if (strncasecmp(opt_arg, "TLS1.2", 6) == 0) {
                    max_prot = TLS1_2_VERSION;
                    min_prot = TLS1_2_VERSION;
#ifdef TLS1_3_VERSION
                } else if (strncasecmp(opt_arg, "TLS1.3", 6) == 0) {
                    max_prot = TLS1_3_VERSION;
                    min_prot = TLS1_3_VERSION;
#endif
                } else if (strncasecmp(opt_arg, "TLS1", 4) == 0) {
                    max_prot = TLS1_VERSION;
                    min_prot = TLS1_VERSION;
                }
#endif /* #if OPENSSL_VERSION_NUMBER < 0x10100000L */
                break;
#ifdef HAVE_TLSEXT
            case 'I':
                tls_use_sni = 0;
                break;
#endif
#endif /* USE_SSL */
        }
    }

    if (status != APR_EOF || opt->ind != argc - 1) {
        fprintf(stderr, "%s: Invalid or missing arguments\n", argv[0]);
        usage(argv[0]);
    }

    if (method == NO_METH) {
        method = GET;
    }

    if (parse_url(apr_pstrdup(cntxt, opt->argv[opt->ind++]))) {
        fprintf(stderr, "%s: invalid URL\n", argv[0]);
        usage(argv[0]);
    }

    rlimited = !tlimit || requests > 0;
    if (requests == 0) {
        requests = tlimit ? TIMED_REQUESTS : 1;
    }

#if APR_HAS_THREADS
    if (num_workers == 0) {
#ifdef _SC_NPROCESSORS_ONLN
        num_workers = sysconf(_SC_NPROCESSORS_ONLN);
#else
        fatal_error("-W0 not implemented on this platform\n");
#endif
    }
    if (num_workers > 1) {
        requests = ROUND_UP(requests, num_workers);
        concurrency = ROUND_UP(concurrency, num_workers);
    }
    else {
        num_workers = 1;
    }
#endif /* APR_HAS_THREADS */

    if (concurrency == 0) {
        concurrency = num_workers;
    }
    if (concurrency > ROUND_UP(MAX_CONCURRENCY, num_workers)) {
        fprintf(stderr, "%s: Invalid Concurrency [Range 0..%d]\n",
                argv[0], ROUND_UP(MAX_CONCURRENCY, num_workers));
        usage(argv[0]);
    }
    if (concurrency > requests) {
        fprintf(stderr, "%s: Cannot use concurrency level greater than "
                "total number of requests\n", argv[0]);
        usage(argv[0]);
    }

    if (tlimit) {
        /* Print line every 10% of time */
        hbperiod = apr_time_from_sec(tlimit) / 10;
        if (hbperiod < apr_time_from_sec(1)) {
            hbperiod = apr_time_from_sec(1);
        }
        else if (hbperiod > apr_time_from_sec(60)) {
            hbperiod = apr_time_from_sec(60);
        }
    }
    else if ((heartbeatres) && (requests > 150)) {
        heartbeatres = requests / 10;   /* Print line every 10% of requests */
        if (heartbeatres < 100)
            heartbeatres = 100; /* but never more often than once every 100
                                 * connections. */
    }
    else
        heartbeatres = 0;

#ifdef USE_SSL
#ifdef RSAREF
    R_malloc_init();
#else
#if OPENSSL_VERSION_NUMBER < 0x10100000L
    CRYPTO_malloc_init();
#endif
#endif
    SSL_load_error_strings();
    SSL_library_init();
    if(!(bio_out = BIO_new_fp(stdout,BIO_NOCLOSE))) {
      fprintf(stderr, "%s: Cannot allocate memory", argv[0]);
      exit(1);
    }
    if(!(bio_err = BIO_new_fp(stderr,BIO_NOCLOSE))) {
      fprintf(stderr, "%s: Cannot allocate memory", argv[0]);
      exit(1);
    }

#if OPENSSL_VERSION_NUMBER >= 0x10101000
    if (RAND_status() == 0) {
        fprintf(stderr, "%s: Error: Crypto library PRNG does not contain "
                "sufficient randomness.\n"
                "%s: Build the library with a suitable entropy source configured.\n",
                argv[0], argv[0]);
        exit(1);
    }
#endif

    if (!(ssl_ctx = SSL_CTX_new(meth))) {
        BIO_printf(bio_err, "Could not initialize SSL Context.\n");
        ERR_print_errors(bio_err);
        fatal_error("SSL_CTX_new failed");
    }
    SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL);
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
    SSL_CTX_set_max_proto_version(ssl_ctx, max_prot);
    SSL_CTX_set_min_proto_version(ssl_ctx, min_prot);
#endif
#ifdef SSL_MODE_RELEASE_BUFFERS
    /* Keep memory usage as low as possible */
    SSL_CTX_set_mode (ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
#endif

    if (ssl_cipher != NULL) {
        int ok;
#if OPENSSL_VERSION_NUMBER >= 0x10101000L && defined(TLS1_3_VERSION)
        if (min_prot >= TLS1_3_VERSION)
            ok = SSL_CTX_set_ciphersuites(ssl_ctx, ssl_cipher);
        else
#endif
        ok = SSL_CTX_set_cipher_list(ssl_ctx, ssl_cipher);
        if (!ok) {
            BIO_printf(bio_err, "error setting ciphersuite list [%s]\n",
                       ssl_cipher);
            ERR_print_errors(bio_err);
            fatal_error("SSL_CTX_set_cipher_list failed");
        }
    }

    if (verbosity >= 3) {
        SSL_CTX_set_info_callback(ssl_ctx, ssl_state_cb);
    }
    if (ssl_cert != NULL) {
        if (SSL_CTX_use_certificate_chain_file(ssl_ctx, ssl_cert) <= 0) {
            BIO_printf(bio_err, "unable to get certificate from '%s'\n",
                    ssl_cert);
            ERR_print_errors(bio_err);
            fatal_error("SSL_CTX_use_certificate_chain_file failed");
        }
        if (SSL_CTX_use_PrivateKey_file(ssl_ctx, ssl_cert, SSL_FILETYPE_PEM) <= 0) {
            BIO_printf(bio_err, "unable to get private key from '%s'\n",
                ssl_cert);
            ERR_print_errors(bio_err);
            fatal_error("SSL_CTX_use_PrivateKey_file failed");
        }
        if (!SSL_CTX_check_private_key(ssl_ctx)) {
            BIO_printf(bio_err,
                       "private key does not match the certificate public key in %s\n", ssl_cert);
            ERR_print_errors(bio_err);
            fatal_error("SSL_CTX_check_private_key failed");
        }
    }

#endif
#ifdef SIGPIPE
    apr_signal(SIGPIPE, SIG_IGN);       /* Ignore writes to connections that
                                         * have been closed at the other end. */
#endif

    if (!no_banner) {
        copyright();
    }

    return test();
}