Big apps cleanup (option-parsing, etc)
[openssl.git] / apps / s_time.c
index 8f4980b..5bca72b 100644 (file)
@@ -1,4 +1,3 @@
-/* apps/s_time.c */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
@@ -82,9 +81,6 @@
 # include OPENSSL_UNISTD
 #endif
 
-#undef PROG
-#define PROG s_time_main
-
 #undef ioctl
 #define ioctl ioctlsocket
 
 
 #undef SECONDS
 #define SECONDS 30
+#define SECONDSSTR "30"
+
 extern int verify_depth;
 extern int verify_error;
 
-static void s_time_usage(void);
-static int parseArgs(int argc, char **argv);
-static SSL *doConnection(SSL *scon);
-static void s_time_init(void);
-
-/***********************************************************************
- * Static data declarations
- */
+static SSL *doConnection(SSL *scon, const char *host, SSL_CTX *ctx);
 
-/* static char *port=PORT_STR;*/
-static char *host = SSL_CONNECT_NAME;
-static char *t_cert_file = NULL;
-static char *t_key_file = NULL;
-static char *CApath = NULL;
-static char *CAfile = NULL;
-static char *tm_cipher = NULL;
-static int tm_verify = SSL_VERIFY_NONE;
-static int maxTime = SECONDS;
-static SSL_CTX *tm_ctx = NULL;
-static const SSL_METHOD *s_time_meth = NULL;
-static char *s_www_path = NULL;
-static long bytes_read = 0;
-static int st_bugs = 0;
-static int perform = 0;
-#ifdef FIONBIO
-static int t_nbio = 0;
+typedef enum OPTION_choice {
+    OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+    OPT_CONNECT, OPT_CIPHER, OPT_CERT, OPT_KEY, OPT_CAPATH,
+    OPT_CAFILE, OPT_NEW, OPT_REUSE, OPT_BUGS, OPT_VERIFY, OPT_TIME,
+#ifndef OPENSSL_NO_SSL3
+    OPT_SSL3,
 #endif
-#ifdef OPENSSL_SYS_WIN32
-static int exitNow = 0;         /* Set when it's time to exit main */
+    OPT_WWW
+} OPTION_CHOICE;
+
+OPTIONS s_time_options[] = {
+    {"help", OPT_HELP, '-', "Display this summary"},
+    {"connect", OPT_CONNECT, 's',
+     "Where to connect as post:port (default is " SSL_CONNECT_NAME ")"},
+    {"cipher", OPT_CIPHER, 's', "Cipher to use, see 'openssl ciphers'"},
+    {"cert", OPT_CERT, '<', "Cert file to use, PEM format assumed"},
+    {"key", OPT_KEY, '<', "File with key, PEM; default is -cert file"},
+    {"CApath", OPT_CAPATH, '/', "PEM format directory of CA's"},
+    {"cafile", OPT_CAFILE, '<', "PEM format file of CA's"},
+    {"new", OPT_NEW, '-', "Just time new connections"},
+    {"reuse", OPT_REUSE, '-', "Just time connection reuse"},
+    {"bugs", OPT_BUGS, '-', "Turn on SSL bug compatibility"},
+    {"verify", OPT_VERIFY, 'p',
+     "Turn on peer certificate verification, set depth"},
+    {"time", OPT_TIME, 'p', "Sf seconds to collect data, default" SECONDSSTR},
+    {"www", OPT_WWW, 's', "Fetch specified page from the site"},
+#ifndef OPENSSL_NO_SSL3
+    {"ssl3", OPT_SSL3, '-', "Just use SSLv3"},
 #endif
+    {NULL}
+};
 
-static void s_time_init(void)
-{
-    host = SSL_CONNECT_NAME;
-    t_cert_file = NULL;
-    t_key_file = NULL;
-    CApath = NULL;
-    CAfile = NULL;
-    tm_cipher = NULL;
-    tm_verify = SSL_VERIFY_NONE;
-    maxTime = SECONDS;
-    tm_ctx = NULL;
-    s_time_meth = NULL;
-    s_www_path = NULL;
-    bytes_read = 0;
-    st_bugs = 0;
-    perform = 0;
-
-#ifdef FIONBIO
-    t_nbio = 0;
-#endif
-#ifdef OPENSSL_SYS_WIN32
-    exitNow = 0;                /* Set when it's time to exit main */
-#endif
-}
+#define START   0
+#define STOP    1
 
-/***********************************************************************
- * usage - display usage message
- */
-static void s_time_usage(void)
+static double tm_Time_F(int s)
 {
-    static char umsg[] = "\
--time arg     - max number of seconds to collect data, default %d\n\
--verify arg   - turn on peer certificate verification, arg == depth\n\
--cert arg     - certificate file to use, PEM format assumed\n\
--key arg      - RSA file to use, PEM format assumed, key is in cert file\n\
-                file if not specified by this option\n\
--CApath arg   - PEM format directory of CA's\n\
--CAfile arg   - PEM format file of CA's\n\
--cipher       - preferred cipher to use, play with 'openssl ciphers'\n\n";
-
-    printf("usage: s_time <args>\n\n");
-
-    printf("-connect host:port - host:port to connect to (default is %s)\n",
-           SSL_CONNECT_NAME);
-#ifdef FIONBIO
-    printf("-nbio         - Run with non-blocking IO\n");
-    printf("-ssl3         - Just use SSLv3\n");
-    printf("-bugs         - Turn on SSL bug compatibility\n");
-    printf("-new          - Just time new connections\n");
-    printf("-reuse        - Just time connection reuse\n");
-    printf("-www page     - Retrieve 'page' from the site\n");
-#endif
-    printf(umsg, SECONDS);
+    return app_tminterval(s, 1);
 }
 
-/***********************************************************************
- * parseArgs - Parse command line arguments and initialize data
- *
- * Returns 0 if ok, -1 on bad args
- */
-static int parseArgs(int argc, char **argv)
+int s_time_main(int argc, char **argv)
 {
-    int badop = 0;
+    char buf[1024 * 8];
+    SSL *scon = NULL;
+    SSL_CTX *ctx = NULL;
+    const SSL_METHOD *meth = NULL;
+    char *CApath = NULL, *CAfile = NULL, *cipher = NULL, *www_path = NULL;
+    char *host = SSL_CONNECT_NAME, *certfile = NULL, *keyfile = NULL, *prog;
+    double totalTime = 0.0;
+    int maxtime = SECONDS, nConn = 0, perform = 3, ret = 1, i, st_bugs =
+        0, ver;
+    long bytes_read = 0, finishtime = 0;
+    OPTION_CHOICE o;
+#ifdef OPENSSL_SYS_WIN32
+    int exitNow = 0;            /* Set when it's time to exit main */
+#endif
 
+    meth = SSLv23_client_method();
     verify_depth = 0;
     verify_error = X509_V_OK;
 
-    argc--;
-    argv++;
-
-    while (argc >= 1) {
-        if (strcmp(*argv, "-connect") == 0) {
-            if (--argc < 1)
-                goto bad;
-            host = *(++argv);
-        }
-        else if (strcmp(*argv, "-reuse") == 0)
+    prog = opt_init(argc, argv, s_time_options);
+    while ((o = opt_next()) != OPT_EOF) {
+        switch (o) {
+        case OPT_EOF:
+        case OPT_ERR:
+ opthelp:
+            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+            goto end;
+        case OPT_HELP:
+            opt_help(s_time_options);
+            ret = 0;
+            goto end;
+        case OPT_CONNECT:
+            host = opt_arg();
+            break;
+        case OPT_REUSE:
             perform = 2;
-        else if (strcmp(*argv, "-new") == 0)
+            break;
+        case OPT_NEW:
             perform = 1;
-        else if (strcmp(*argv, "-verify") == 0) {
-
-            tm_verify = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE;
-            if (--argc < 1)
-                goto bad;
-            verify_depth = atoi(*(++argv));
-            BIO_printf(bio_err, "verify depth is %d\n", verify_depth);
-
-        } else if (strcmp(*argv, "-cert") == 0) {
-
-            if (--argc < 1)
-                goto bad;
-            t_cert_file = *(++argv);
-
-        } else if (strcmp(*argv, "-key") == 0) {
-
-            if (--argc < 1)
-                goto bad;
-            t_key_file = *(++argv);
-
-        } else if (strcmp(*argv, "-CApath") == 0) {
-
-            if (--argc < 1)
-                goto bad;
-            CApath = *(++argv);
-
-        } else if (strcmp(*argv, "-CAfile") == 0) {
-
-            if (--argc < 1)
-                goto bad;
-            CAfile = *(++argv);
-
-        } else if (strcmp(*argv, "-cipher") == 0) {
-
-            if (--argc < 1)
-                goto bad;
-            tm_cipher = *(++argv);
-        }
-#ifdef FIONBIO
-        else if (strcmp(*argv, "-nbio") == 0) {
-            t_nbio = 1;
-        }
-#endif
-        else if (strcmp(*argv, "-www") == 0) {
-            if (--argc < 1)
-                goto bad;
-            s_www_path = *(++argv);
-            if (strlen(s_www_path) > MYBUFSIZ - 100) {
-                BIO_printf(bio_err, "-www option too long\n");
-                badop = 1;
-            }
-        } else if (strcmp(*argv, "-bugs") == 0)
+            break;
+        case OPT_VERIFY:
+            if (!opt_int(opt_arg(), &verify_depth))
+                goto opthelp;
+            BIO_printf(bio_err, "%s: verify depth is %d\n",
+                       prog, verify_depth);
+            break;
+        case OPT_CERT:
+            certfile = opt_arg();
+            break;
+        case OPT_KEY:
+            keyfile = opt_arg();
+            break;
+        case OPT_CAPATH:
+            CApath = opt_arg();
+            break;
+        case OPT_CAFILE:
+            CAfile = opt_arg();
+            break;
+        case OPT_CIPHER:
+            cipher = opt_arg();
+            break;
+        case OPT_BUGS:
             st_bugs = 1;
-#ifndef OPENSSL_NO_SSL3
-        else if (strcmp(*argv, "-ssl3") == 0)
-            s_time_meth = SSLv3_client_method();
-#endif
-        else if (strcmp(*argv, "-time") == 0) {
-
-            if (--argc < 1)
-                goto bad;
-            maxTime = atoi(*(++argv));
-            if (maxTime <= 0) {
-                BIO_printf(bio_err, "time must be > 0\n");
-                badop = 1;
+            break;
+        case OPT_TIME:
+            if (!opt_int(opt_arg(), &maxtime))
+                goto opthelp;
+            break;
+        case OPT_WWW:
+            www_path = opt_arg();
+            if (strlen(www_path) > MYBUFSIZ - 100) {
+                BIO_printf(bio_err, "%s: -www option too long\n", prog);
+                goto end;
             }
-        } else {
-            BIO_printf(bio_err, "unknown option %s\n", *argv);
-            badop = 1;
             break;
+#ifndef OPENSSL_NO_SSL3
+        case OPT_SSL3:
+            meth = SSLv3_client_method();
+            break;
+#endif
         }
-
-        argc--;
-        argv++;
     }
+    argc = opt_num_rest();
+    argv = opt_rest();
 
-    if (perform == 0)
-        perform = 3;
-
-    if (badop) {
- bad:
-        s_time_usage();
-        return -1;
+    if (cipher == NULL)
+        cipher = getenv("SSL_CIPHER");
+    if (cipher == NULL) {
+        fprintf(stderr, "No CIPHER specified\n");
+        goto end;
     }
 
-    return 0;                   /* Valid args */
-}
-
-/***********************************************************************
- * TIME - time functions
- */
-#define START   0
-#define STOP    1
-
-static double tm_Time_F(int s)
-{
-    return app_tminterval(s, 1);
-}
-
-/***********************************************************************
- * MAIN - main processing area for client
- *                      real name depends on MONOLITH
- */
-int MAIN(int, char **);
-
-int MAIN(int argc, char **argv)
-{
-    double totalTime = 0.0;
-    int nConn = 0;
-    SSL *scon = NULL;
-    long finishtime = 0;
-    int ret = 1, i;
-    char buf[1024 * 8];
-    int ver;
-
-    apps_startup();
-    s_time_init();
-
-    if (bio_err == NULL)
-        bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
-
-    s_time_meth = SSLv23_client_method();
-
-    /* parse the command line arguments */
-    if (parseArgs(argc, argv) < 0)
+    if ((ctx = SSL_CTX_new(meth)) == NULL)
         goto end;
 
-    OpenSSL_add_ssl_algorithms();
-    if ((tm_ctx = SSL_CTX_new(s_time_meth)) == NULL)
-        return (1);
-
-    SSL_CTX_set_quiet_shutdown(tm_ctx, 1);
+    SSL_CTX_set_quiet_shutdown(ctx, 1);
 
     if (st_bugs)
-        SSL_CTX_set_options(tm_ctx, SSL_OP_ALL);
-    if (!SSL_CTX_set_cipher_list(tm_ctx, tm_cipher))
+        SSL_CTX_set_options(ctx, SSL_OP_ALL);
+    if (!SSL_CTX_set_cipher_list(ctx, cipher))
         goto end;
-    if (!set_cert_stuff(tm_ctx, t_cert_file, t_key_file))
+    if (!set_cert_stuff(ctx, certfile, keyfile))
         goto end;
 
-    SSL_load_error_strings();
-
-    if ((!SSL_CTX_load_verify_locations(tm_ctx, CAfile, CApath)) ||
-        (!SSL_CTX_set_default_verify_paths(tm_ctx))) {
-        /*
-         * BIO_printf(bio_err,"error setting default verify locations\n");
-         */
+    if (!ctx_set_verify_locations(ctx, CAfile, CApath)) {
         ERR_print_errors(bio_err);
-        /* goto end; */
-    }
-
-    if (tm_cipher == NULL)
-        tm_cipher = getenv("SSL_CIPHER");
-
-    if (tm_cipher == NULL) {
-        fprintf(stderr, "No CIPHER specified\n");
+        goto end;
     }
-
     if (!(perform & 1))
         goto next;
-    printf("Collecting connection statistics for %d seconds\n", maxTime);
+    printf("Collecting connection statistics for %d seconds\n", maxtime);
 
     /* Loop and time how long it takes to make connections */
 
     bytes_read = 0;
-    finishtime = (long)time(NULL) + maxTime;
+    finishtime = (long)time(NULL) + maxtime;
     tm_Time_F(START);
     for (;;) {
         if (finishtime < (long)time(NULL))
@@ -400,12 +281,12 @@ int MAIN(int argc, char **argv)
             goto end;
 #endif
 
-        if ((scon = doConnection(NULL)) == NULL)
+        if ((scon = doConnection(NULL, host, ctx)) == NULL)
             goto end;
 
-        if (s_www_path != NULL) {
+        if (www_path != NULL) {
             BIO_snprintf(buf, sizeof buf, "GET %s HTTP/1.0\r\n\r\n",
-                         s_www_path);
+                         www_path);
             if (SSL_write(scon, buf, strlen(buf)) <= 0)
                 goto end;
             while ((i = SSL_read(scon, buf, sizeof(buf))) > 0)
@@ -438,13 +319,13 @@ int MAIN(int argc, char **argv)
     }
     totalTime += tm_Time_F(STOP); /* Add the time for this iteration */
 
-    i = (int)((long)time(NULL) - finishtime + maxTime);
+    i = (int)((long)time(NULL) - finishtime + maxtime);
     printf
         ("\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n",
          nConn, totalTime, ((double)nConn / totalTime), bytes_read);
     printf
         ("%d connections in %ld real seconds, %ld bytes read per connection\n",
-         nConn, (long)time(NULL) - finishtime + maxTime, bytes_read / nConn);
+         nConn, (long)time(NULL) - finishtime + maxtime, bytes_read / nConn);
 
     /*
      * Now loop and time connections using the same session id over and over
@@ -456,16 +337,17 @@ int MAIN(int argc, char **argv)
     printf("\n\nNow timing with session id reuse.\n");
 
     /* Get an SSL object so we can reuse the session id */
-    if ((scon = doConnection(NULL)) == NULL) {
+    if ((scon = doConnection(NULL, host, ctx)) == NULL) {
         fprintf(stderr, "Unable to get connection\n");
         goto end;
     }
 
-    if (s_www_path != NULL) {
-        BIO_snprintf(buf, sizeof buf, "GET %s HTTP/1.0\r\n\r\n", s_www_path);
+    if (www_path != NULL) {
+        BIO_snprintf(buf, sizeof buf, "GET %s HTTP/1.0\r\n\r\n", www_path);
         if (SSL_write(scon, buf, strlen(buf)) <= 0)
             goto end;
-        while (SSL_read(scon, buf, sizeof(buf)) > 0) ;
+        while (SSL_read(scon, buf, sizeof(buf)) > 0)
+            continue;
     }
 #ifdef NO_SHUTDOWN
     SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
@@ -477,7 +359,7 @@ int MAIN(int argc, char **argv)
     nConn = 0;
     totalTime = 0.0;
 
-    finishtime = (long)time(NULL) + maxTime;
+    finishtime = (long)time(NULL) + maxtime;
 
     printf("starting\n");
     bytes_read = 0;
@@ -495,12 +377,12 @@ int MAIN(int argc, char **argv)
             goto end;
 #endif
 
-        if ((doConnection(scon)) == NULL)
+        if ((doConnection(scon, host, ctx)) == NULL)
             goto end;
 
-        if (s_www_path) {
+        if (www_path) {
             BIO_snprintf(buf, sizeof buf, "GET %s HTTP/1.0\r\n\r\n",
-                         s_www_path);
+                         www_path);
             if (SSL_write(scon, buf, strlen(buf)) <= 0)
                 goto end;
             while ((i = SSL_read(scon, buf, sizeof(buf))) > 0)
@@ -535,27 +417,20 @@ int MAIN(int argc, char **argv)
          nConn, totalTime, ((double)nConn / totalTime), bytes_read);
     printf
         ("%d connections in %ld real seconds, %ld bytes read per connection\n",
-         nConn, (long)time(NULL) - finishtime + maxTime,
-         bytes_read / (nConn?nConn:1));
+         nConn, (long)time(NULL) - finishtime + maxtime, bytes_read / nConn);
 
     ret = 0;
+
  end:
     SSL_free(scon);
-
-    SSL_CTX_free(tm_ctx);
-    tm_ctx = NULL;
-    apps_shutdown();
-    OPENSSL_EXIT(ret);
+    SSL_CTX_free(ctx);
+    return (ret);
 }
 
 /*-
  * doConnection - make a connection
- * Args:
- *              scon    = earlier ssl connection for session id, or NULL
- * Returns:
- *              SSL *   = the connection pointer.
  */
-static SSL *doConnection(SSL *scon)
+static SSL *doConnection(SSL *scon, const char *host, SSL_CTX *ctx)
 {
     BIO *conn;
     SSL *serverCon;
@@ -565,11 +440,10 @@ static SSL *doConnection(SSL *scon)
     if ((conn = BIO_new(BIO_s_connect())) == NULL)
         return (NULL);
 
-/*      BIO_set_conn_port(conn,port);*/
     BIO_set_conn_hostname(conn, host);
 
     if (scon == NULL)
-        serverCon = SSL_new(tm_ctx);
+        serverCon = SSL_new(ctx);
     else {
         serverCon = scon;
         SSL_set_connect_state(serverCon);