Home | History | Annotate | Line # | Download | only in apps
opt.c revision 1.1.1.1
      1 /*
      2  * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
      3  *
      4  * Licensed under the OpenSSL license (the "License").  You may not use
      5  * this file except in compliance with the License.  You can obtain a copy
      6  * in the file LICENSE in the source distribution or at
      7  * https://www.openssl.org/source/license.html
      8  */
      9 #include "apps.h"
     10 #include <string.h>
     11 #if !defined(OPENSSL_SYS_MSDOS)
     12 # include OPENSSL_UNISTD
     13 #endif
     14 
     15 #include <stdlib.h>
     16 #include <errno.h>
     17 #include <ctype.h>
     18 #include <limits.h>
     19 #include <openssl/bio.h>
     20 #include <openssl/x509v3.h>
     21 
     22 #define MAX_OPT_HELP_WIDTH 30
     23 const char OPT_HELP_STR[] = "--";
     24 const char OPT_MORE_STR[] = "---";
     25 
     26 /* Our state */
     27 static char **argv;
     28 static int argc;
     29 static int opt_index;
     30 static char *arg;
     31 static char *flag;
     32 static char *dunno;
     33 static const OPTIONS *unknown;
     34 static const OPTIONS *opts;
     35 static char prog[40];
     36 
     37 /*
     38  * Return the simple name of the program; removing various platform gunk.
     39  */
     40 #if defined(OPENSSL_SYS_WIN32)
     41 char *opt_progname(const char *argv0)
     42 {
     43     size_t i, n;
     44     const char *p;
     45     char *q;
     46 
     47     /* find the last '/', '\' or ':' */
     48     for (p = argv0 + strlen(argv0); --p > argv0;)
     49         if (*p == '/' || *p == '\\' || *p == ':') {
     50             p++;
     51             break;
     52         }
     53 
     54     /* Strip off trailing nonsense. */
     55     n = strlen(p);
     56     if (n > 4 &&
     57         (strcmp(&p[n - 4], ".exe") == 0 || strcmp(&p[n - 4], ".EXE") == 0))
     58         n -= 4;
     59 
     60     /* Copy over the name, in lowercase. */
     61     if (n > sizeof(prog) - 1)
     62         n = sizeof(prog) - 1;
     63     for (q = prog, i = 0; i < n; i++, p++)
     64         *q++ = tolower((unsigned char)*p);
     65     *q = '\0';
     66     return prog;
     67 }
     68 
     69 #elif defined(OPENSSL_SYS_VMS)
     70 
     71 char *opt_progname(const char *argv0)
     72 {
     73     const char *p, *q;
     74 
     75     /* Find last special character sys:[foo.bar]openssl */
     76     for (p = argv0 + strlen(argv0); --p > argv0;)
     77         if (*p == ':' || *p == ']' || *p == '>') {
     78             p++;
     79             break;
     80         }
     81 
     82     q = strrchr(p, '.');
     83     strncpy(prog, p, sizeof(prog) - 1);
     84     prog[sizeof(prog) - 1] = '\0';
     85     if (q != NULL && q - p < sizeof(prog))
     86         prog[q - p] = '\0';
     87     return prog;
     88 }
     89 
     90 #else
     91 
     92 char *opt_progname(const char *argv0)
     93 {
     94     const char *p;
     95 
     96     /* Could use strchr, but this is like the ones above. */
     97     for (p = argv0 + strlen(argv0); --p > argv0;)
     98         if (*p == '/') {
     99             p++;
    100             break;
    101         }
    102     strncpy(prog, p, sizeof(prog) - 1);
    103     prog[sizeof(prog) - 1] = '\0';
    104     return prog;
    105 }
    106 #endif
    107 
    108 char *opt_getprog(void)
    109 {
    110     return prog;
    111 }
    112 
    113 /* Set up the arg parsing. */
    114 char *opt_init(int ac, char **av, const OPTIONS *o)
    115 {
    116     /* Store state. */
    117     argc = ac;
    118     argv = av;
    119     opt_index = 1;
    120     opts = o;
    121     opt_progname(av[0]);
    122     unknown = NULL;
    123 
    124     for (; o->name; ++o) {
    125 #ifndef NDEBUG
    126         const OPTIONS *next;
    127         int duplicated, i;
    128 #endif
    129 
    130         if (o->name == OPT_HELP_STR || o->name == OPT_MORE_STR)
    131             continue;
    132 #ifndef NDEBUG
    133         i = o->valtype;
    134 
    135         /* Make sure options are legit. */
    136         assert(o->name[0] != '-');
    137         assert(o->retval > 0);
    138         switch (i) {
    139         case   0: case '-': case '/': case '<': case '>': case 'E': case 'F':
    140         case 'M': case 'U': case 'f': case 'l': case 'n': case 'p': case 's':
    141         case 'u': case 'c':
    142             break;
    143         default:
    144             assert(0);
    145         }
    146 
    147         /* Make sure there are no duplicates. */
    148         for (next = o + 1; next->name; ++next) {
    149             /*
    150              * Some compilers inline strcmp and the assert string is too long.
    151              */
    152             duplicated = strcmp(o->name, next->name) == 0;
    153             assert(!duplicated);
    154         }
    155 #endif
    156         if (o->name[0] == '\0') {
    157             assert(unknown == NULL);
    158             unknown = o;
    159             assert(unknown->valtype == 0 || unknown->valtype == '-');
    160         }
    161     }
    162     return prog;
    163 }
    164 
    165 static OPT_PAIR formats[] = {
    166     {"PEM/DER", OPT_FMT_PEMDER},
    167     {"pkcs12", OPT_FMT_PKCS12},
    168     {"smime", OPT_FMT_SMIME},
    169     {"engine", OPT_FMT_ENGINE},
    170     {"msblob", OPT_FMT_MSBLOB},
    171     {"nss", OPT_FMT_NSS},
    172     {"text", OPT_FMT_TEXT},
    173     {"http", OPT_FMT_HTTP},
    174     {"pvk", OPT_FMT_PVK},
    175     {NULL}
    176 };
    177 
    178 /* Print an error message about a failed format parse. */
    179 int opt_format_error(const char *s, unsigned long flags)
    180 {
    181     OPT_PAIR *ap;
    182 
    183     if (flags == OPT_FMT_PEMDER) {
    184         BIO_printf(bio_err, "%s: Bad format \"%s\"; must be pem or der\n",
    185                    prog, s);
    186     } else {
    187         BIO_printf(bio_err, "%s: Bad format \"%s\"; must be one of:\n",
    188                    prog, s);
    189         for (ap = formats; ap->name; ap++)
    190             if (flags & ap->retval)
    191                 BIO_printf(bio_err, "   %s\n", ap->name);
    192     }
    193     return 0;
    194 }
    195 
    196 /* Parse a format string, put it into *result; return 0 on failure, else 1. */
    197 int opt_format(const char *s, unsigned long flags, int *result)
    198 {
    199     switch (*s) {
    200     default:
    201         return 0;
    202     case 'D':
    203     case 'd':
    204         if ((flags & OPT_FMT_PEMDER) == 0)
    205             return opt_format_error(s, flags);
    206         *result = FORMAT_ASN1;
    207         break;
    208     case 'T':
    209     case 't':
    210         if ((flags & OPT_FMT_TEXT) == 0)
    211             return opt_format_error(s, flags);
    212         *result = FORMAT_TEXT;
    213         break;
    214     case 'N':
    215     case 'n':
    216         if ((flags & OPT_FMT_NSS) == 0)
    217             return opt_format_error(s, flags);
    218         if (strcmp(s, "NSS") != 0 && strcmp(s, "nss") != 0)
    219             return opt_format_error(s, flags);
    220         *result = FORMAT_NSS;
    221         break;
    222     case 'S':
    223     case 's':
    224         if ((flags & OPT_FMT_SMIME) == 0)
    225             return opt_format_error(s, flags);
    226         *result = FORMAT_SMIME;
    227         break;
    228     case 'M':
    229     case 'm':
    230         if ((flags & OPT_FMT_MSBLOB) == 0)
    231             return opt_format_error(s, flags);
    232         *result = FORMAT_MSBLOB;
    233         break;
    234     case 'E':
    235     case 'e':
    236         if ((flags & OPT_FMT_ENGINE) == 0)
    237             return opt_format_error(s, flags);
    238         *result = FORMAT_ENGINE;
    239         break;
    240     case 'H':
    241     case 'h':
    242         if ((flags & OPT_FMT_HTTP) == 0)
    243             return opt_format_error(s, flags);
    244         *result = FORMAT_HTTP;
    245         break;
    246     case '1':
    247         if ((flags & OPT_FMT_PKCS12) == 0)
    248             return opt_format_error(s, flags);
    249         *result = FORMAT_PKCS12;
    250         break;
    251     case 'P':
    252     case 'p':
    253         if (s[1] == '\0' || strcmp(s, "PEM") == 0 || strcmp(s, "pem") == 0) {
    254             if ((flags & OPT_FMT_PEMDER) == 0)
    255                 return opt_format_error(s, flags);
    256             *result = FORMAT_PEM;
    257         } else if (strcmp(s, "PVK") == 0 || strcmp(s, "pvk") == 0) {
    258             if ((flags & OPT_FMT_PVK) == 0)
    259                 return opt_format_error(s, flags);
    260             *result = FORMAT_PVK;
    261         } else if (strcmp(s, "P12") == 0 || strcmp(s, "p12") == 0
    262                    || strcmp(s, "PKCS12") == 0 || strcmp(s, "pkcs12") == 0) {
    263             if ((flags & OPT_FMT_PKCS12) == 0)
    264                 return opt_format_error(s, flags);
    265             *result = FORMAT_PKCS12;
    266         } else {
    267             return 0;
    268         }
    269         break;
    270     }
    271     return 1;
    272 }
    273 
    274 /* Parse a cipher name, put it in *EVP_CIPHER; return 0 on failure, else 1. */
    275 int opt_cipher(const char *name, const EVP_CIPHER **cipherp)
    276 {
    277     *cipherp = EVP_get_cipherbyname(name);
    278     if (*cipherp != NULL)
    279         return 1;
    280     BIO_printf(bio_err, "%s: Unrecognized flag %s\n", prog, name);
    281     return 0;
    282 }
    283 
    284 /*
    285  * Parse message digest name, put it in *EVP_MD; return 0 on failure, else 1.
    286  */
    287 int opt_md(const char *name, const EVP_MD **mdp)
    288 {
    289     *mdp = EVP_get_digestbyname(name);
    290     if (*mdp != NULL)
    291         return 1;
    292     BIO_printf(bio_err, "%s: Unrecognized flag %s\n", prog, name);
    293     return 0;
    294 }
    295 
    296 /* Look through a list of name/value pairs. */
    297 int opt_pair(const char *name, const OPT_PAIR* pairs, int *result)
    298 {
    299     const OPT_PAIR *pp;
    300 
    301     for (pp = pairs; pp->name; pp++)
    302         if (strcmp(pp->name, name) == 0) {
    303             *result = pp->retval;
    304             return 1;
    305         }
    306     BIO_printf(bio_err, "%s: Value must be one of:\n", prog);
    307     for (pp = pairs; pp->name; pp++)
    308         BIO_printf(bio_err, "\t%s\n", pp->name);
    309     return 0;
    310 }
    311 
    312 /* Parse an int, put it into *result; return 0 on failure, else 1. */
    313 int opt_int(const char *value, int *result)
    314 {
    315     long l;
    316 
    317     if (!opt_long(value, &l))
    318         return 0;
    319     *result = (int)l;
    320     if (*result != l) {
    321         BIO_printf(bio_err, "%s: Value \"%s\" outside integer range\n",
    322                    prog, value);
    323         return 0;
    324     }
    325     return 1;
    326 }
    327 
    328 static void opt_number_error(const char *v)
    329 {
    330     size_t i = 0;
    331     struct strstr_pair_st {
    332         char *prefix;
    333         char *name;
    334     } b[] = {
    335         {"0x", "a hexadecimal"},
    336         {"0X", "a hexadecimal"},
    337         {"0", "an octal"}
    338     };
    339 
    340     for (i = 0; i < OSSL_NELEM(b); i++) {
    341         if (strncmp(v, b[i].prefix, strlen(b[i].prefix)) == 0) {
    342             BIO_printf(bio_err,
    343                        "%s: Can't parse \"%s\" as %s number\n",
    344                        prog, v, b[i].name);
    345             return;
    346         }
    347     }
    348     BIO_printf(bio_err, "%s: Can't parse \"%s\" as a number\n", prog, v);
    349     return;
    350 }
    351 
    352 /* Parse a long, put it into *result; return 0 on failure, else 1. */
    353 int opt_long(const char *value, long *result)
    354 {
    355     int oerrno = errno;
    356     long l;
    357     char *endp;
    358 
    359     errno = 0;
    360     l = strtol(value, &endp, 0);
    361     if (*endp
    362             || endp == value
    363             || ((l == LONG_MAX || l == LONG_MIN) && errno == ERANGE)
    364             || (l == 0 && errno != 0)) {
    365         opt_number_error(value);
    366         errno = oerrno;
    367         return 0;
    368     }
    369     *result = l;
    370     errno = oerrno;
    371     return 1;
    372 }
    373 
    374 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && \
    375     defined(INTMAX_MAX) && defined(UINTMAX_MAX)
    376 
    377 /* Parse an intmax_t, put it into *result; return 0 on failure, else 1. */
    378 int opt_imax(const char *value, intmax_t *result)
    379 {
    380     int oerrno = errno;
    381     intmax_t m;
    382     char *endp;
    383 
    384     errno = 0;
    385     m = strtoimax(value, &endp, 0);
    386     if (*endp
    387             || endp == value
    388             || ((m == INTMAX_MAX || m == INTMAX_MIN) && errno == ERANGE)
    389             || (m == 0 && errno != 0)) {
    390         opt_number_error(value);
    391         errno = oerrno;
    392         return 0;
    393     }
    394     *result = m;
    395     errno = oerrno;
    396     return 1;
    397 }
    398 
    399 /* Parse a uintmax_t, put it into *result; return 0 on failure, else 1. */
    400 int opt_umax(const char *value, uintmax_t *result)
    401 {
    402     int oerrno = errno;
    403     uintmax_t m;
    404     char *endp;
    405 
    406     errno = 0;
    407     m = strtoumax(value, &endp, 0);
    408     if (*endp
    409             || endp == value
    410             || (m == UINTMAX_MAX && errno == ERANGE)
    411             || (m == 0 && errno != 0)) {
    412         opt_number_error(value);
    413         errno = oerrno;
    414         return 0;
    415     }
    416     *result = m;
    417     errno = oerrno;
    418     return 1;
    419 }
    420 #endif
    421 
    422 /*
    423  * Parse an unsigned long, put it into *result; return 0 on failure, else 1.
    424  */
    425 int opt_ulong(const char *value, unsigned long *result)
    426 {
    427     int oerrno = errno;
    428     char *endptr;
    429     unsigned long l;
    430 
    431     errno = 0;
    432     l = strtoul(value, &endptr, 0);
    433     if (*endptr
    434             || endptr == value
    435             || ((l == ULONG_MAX) && errno == ERANGE)
    436             || (l == 0 && errno != 0)) {
    437         opt_number_error(value);
    438         errno = oerrno;
    439         return 0;
    440     }
    441     *result = l;
    442     errno = oerrno;
    443     return 1;
    444 }
    445 
    446 /*
    447  * We pass opt as an int but cast it to "enum range" so that all the
    448  * items in the OPT_V_ENUM enumeration are caught; this makes -Wswitch
    449  * in gcc do the right thing.
    450  */
    451 enum range { OPT_V_ENUM };
    452 
    453 int opt_verify(int opt, X509_VERIFY_PARAM *vpm)
    454 {
    455     int i;
    456     ossl_intmax_t t = 0;
    457     ASN1_OBJECT *otmp;
    458     X509_PURPOSE *xptmp;
    459     const X509_VERIFY_PARAM *vtmp;
    460 
    461     assert(vpm != NULL);
    462     assert(opt > OPT_V__FIRST);
    463     assert(opt < OPT_V__LAST);
    464 
    465     switch ((enum range)opt) {
    466     case OPT_V__FIRST:
    467     case OPT_V__LAST:
    468         return 0;
    469     case OPT_V_POLICY:
    470         otmp = OBJ_txt2obj(opt_arg(), 0);
    471         if (otmp == NULL) {
    472             BIO_printf(bio_err, "%s: Invalid Policy %s\n", prog, opt_arg());
    473             return 0;
    474         }
    475         X509_VERIFY_PARAM_add0_policy(vpm, otmp);
    476         break;
    477     case OPT_V_PURPOSE:
    478         /* purpose name -> purpose index */
    479         i = X509_PURPOSE_get_by_sname(opt_arg());
    480         if (i < 0) {
    481             BIO_printf(bio_err, "%s: Invalid purpose %s\n", prog, opt_arg());
    482             return 0;
    483         }
    484 
    485         /* purpose index -> purpose object */
    486         xptmp = X509_PURPOSE_get0(i);
    487 
    488         /* purpose object -> purpose value */
    489         i = X509_PURPOSE_get_id(xptmp);
    490 
    491         if (!X509_VERIFY_PARAM_set_purpose(vpm, i)) {
    492             BIO_printf(bio_err,
    493                        "%s: Internal error setting purpose %s\n",
    494                        prog, opt_arg());
    495             return 0;
    496         }
    497         break;
    498     case OPT_V_VERIFY_NAME:
    499         vtmp = X509_VERIFY_PARAM_lookup(opt_arg());
    500         if (vtmp == NULL) {
    501             BIO_printf(bio_err, "%s: Invalid verify name %s\n",
    502                        prog, opt_arg());
    503             return 0;
    504         }
    505         X509_VERIFY_PARAM_set1(vpm, vtmp);
    506         break;
    507     case OPT_V_VERIFY_DEPTH:
    508         i = atoi(opt_arg());
    509         if (i >= 0)
    510             X509_VERIFY_PARAM_set_depth(vpm, i);
    511         break;
    512     case OPT_V_VERIFY_AUTH_LEVEL:
    513         i = atoi(opt_arg());
    514         if (i >= 0)
    515             X509_VERIFY_PARAM_set_auth_level(vpm, i);
    516         break;
    517     case OPT_V_ATTIME:
    518         if (!opt_imax(opt_arg(), &t))
    519             return 0;
    520         if (t != (time_t)t) {
    521             BIO_printf(bio_err, "%s: epoch time out of range %s\n",
    522                        prog, opt_arg());
    523             return 0;
    524         }
    525         X509_VERIFY_PARAM_set_time(vpm, (time_t)t);
    526         break;
    527     case OPT_V_VERIFY_HOSTNAME:
    528         if (!X509_VERIFY_PARAM_set1_host(vpm, opt_arg(), 0))
    529             return 0;
    530         break;
    531     case OPT_V_VERIFY_EMAIL:
    532         if (!X509_VERIFY_PARAM_set1_email(vpm, opt_arg(), 0))
    533             return 0;
    534         break;
    535     case OPT_V_VERIFY_IP:
    536         if (!X509_VERIFY_PARAM_set1_ip_asc(vpm, opt_arg()))
    537             return 0;
    538         break;
    539     case OPT_V_IGNORE_CRITICAL:
    540         X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_IGNORE_CRITICAL);
    541         break;
    542     case OPT_V_ISSUER_CHECKS:
    543         /* NOP, deprecated */
    544         break;
    545     case OPT_V_CRL_CHECK:
    546         X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_CRL_CHECK);
    547         break;
    548     case OPT_V_CRL_CHECK_ALL:
    549         X509_VERIFY_PARAM_set_flags(vpm,
    550                                     X509_V_FLAG_CRL_CHECK |
    551                                     X509_V_FLAG_CRL_CHECK_ALL);
    552         break;
    553     case OPT_V_POLICY_CHECK:
    554         X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_POLICY_CHECK);
    555         break;
    556     case OPT_V_EXPLICIT_POLICY:
    557         X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_EXPLICIT_POLICY);
    558         break;
    559     case OPT_V_INHIBIT_ANY:
    560         X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_INHIBIT_ANY);
    561         break;
    562     case OPT_V_INHIBIT_MAP:
    563         X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_INHIBIT_MAP);
    564         break;
    565     case OPT_V_X509_STRICT:
    566         X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_X509_STRICT);
    567         break;
    568     case OPT_V_EXTENDED_CRL:
    569         X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_EXTENDED_CRL_SUPPORT);
    570         break;
    571     case OPT_V_USE_DELTAS:
    572         X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_USE_DELTAS);
    573         break;
    574     case OPT_V_POLICY_PRINT:
    575         X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NOTIFY_POLICY);
    576         break;
    577     case OPT_V_CHECK_SS_SIG:
    578         X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_CHECK_SS_SIGNATURE);
    579         break;
    580     case OPT_V_TRUSTED_FIRST:
    581         X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_TRUSTED_FIRST);
    582         break;
    583     case OPT_V_SUITEB_128_ONLY:
    584         X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_128_LOS_ONLY);
    585         break;
    586     case OPT_V_SUITEB_128:
    587         X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_128_LOS);
    588         break;
    589     case OPT_V_SUITEB_192:
    590         X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_192_LOS);
    591         break;
    592     case OPT_V_PARTIAL_CHAIN:
    593         X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_PARTIAL_CHAIN);
    594         break;
    595     case OPT_V_NO_ALT_CHAINS:
    596         X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NO_ALT_CHAINS);
    597         break;
    598     case OPT_V_NO_CHECK_TIME:
    599         X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NO_CHECK_TIME);
    600         break;
    601     case OPT_V_ALLOW_PROXY_CERTS:
    602         X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_ALLOW_PROXY_CERTS);
    603         break;
    604     }
    605     return 1;
    606 
    607 }
    608 
    609 /*
    610  * Parse the next flag (and value if specified), return 0 if done, -1 on
    611  * error, otherwise the flag's retval.
    612  */
    613 int opt_next(void)
    614 {
    615     char *p;
    616     const OPTIONS *o;
    617     int ival;
    618     long lval;
    619     unsigned long ulval;
    620     ossl_intmax_t imval;
    621     ossl_uintmax_t umval;
    622 
    623     /* Look at current arg; at end of the list? */
    624     arg = NULL;
    625     p = argv[opt_index];
    626     if (p == NULL)
    627         return 0;
    628 
    629     /* If word doesn't start with a -, we're done. */
    630     if (*p != '-')
    631         return 0;
    632 
    633     /* Hit "--" ? We're done. */
    634     opt_index++;
    635     if (strcmp(p, "--") == 0)
    636         return 0;
    637 
    638     /* Allow -nnn and --nnn */
    639     if (*++p == '-')
    640         p++;
    641     flag = p - 1;
    642 
    643     /* If we have --flag=foo, snip it off */
    644     if ((arg = strchr(p, '=')) != NULL)
    645         *arg++ = '\0';
    646     for (o = opts; o->name; ++o) {
    647         /* If not this option, move on to the next one. */
    648         if (strcmp(p, o->name) != 0)
    649             continue;
    650 
    651         /* If it doesn't take a value, make sure none was given. */
    652         if (o->valtype == 0 || o->valtype == '-') {
    653             if (arg) {
    654                 BIO_printf(bio_err,
    655                            "%s: Option -%s does not take a value\n", prog, p);
    656                 return -1;
    657             }
    658             return o->retval;
    659         }
    660 
    661         /* Want a value; get the next param if =foo not used. */
    662         if (arg == NULL) {
    663             if (argv[opt_index] == NULL) {
    664                 BIO_printf(bio_err,
    665                            "%s: Option -%s needs a value\n", prog, o->name);
    666                 return -1;
    667             }
    668             arg = argv[opt_index++];
    669         }
    670 
    671         /* Syntax-check value. */
    672         switch (o->valtype) {
    673         default:
    674         case 's':
    675             /* Just a string. */
    676             break;
    677         case '/':
    678             if (app_isdir(arg) > 0)
    679                 break;
    680             BIO_printf(bio_err, "%s: Not a directory: %s\n", prog, arg);
    681             return -1;
    682         case '<':
    683             /* Input file. */
    684             break;
    685         case '>':
    686             /* Output file. */
    687             break;
    688         case 'p':
    689         case 'n':
    690             if (!opt_int(arg, &ival)
    691                     || (o->valtype == 'p' && ival <= 0)) {
    692                 BIO_printf(bio_err,
    693                            "%s: Non-positive number \"%s\" for -%s\n",
    694                            prog, arg, o->name);
    695                 return -1;
    696             }
    697             break;
    698         case 'M':
    699             if (!opt_imax(arg, &imval)) {
    700                 BIO_printf(bio_err,
    701                            "%s: Invalid number \"%s\" for -%s\n",
    702                            prog, arg, o->name);
    703                 return -1;
    704             }
    705             break;
    706         case 'U':
    707             if (!opt_umax(arg, &umval)) {
    708                 BIO_printf(bio_err,
    709                            "%s: Invalid number \"%s\" for -%s\n",
    710                            prog, arg, o->name);
    711                 return -1;
    712             }
    713             break;
    714         case 'l':
    715             if (!opt_long(arg, &lval)) {
    716                 BIO_printf(bio_err,
    717                            "%s: Invalid number \"%s\" for -%s\n",
    718                            prog, arg, o->name);
    719                 return -1;
    720             }
    721             break;
    722         case 'u':
    723             if (!opt_ulong(arg, &ulval)) {
    724                 BIO_printf(bio_err,
    725                            "%s: Invalid number \"%s\" for -%s\n",
    726                            prog, arg, o->name);
    727                 return -1;
    728             }
    729             break;
    730         case 'c':
    731         case 'E':
    732         case 'F':
    733         case 'f':
    734             if (opt_format(arg,
    735                            o->valtype == 'c' ? OPT_FMT_PDS :
    736                            o->valtype == 'E' ? OPT_FMT_PDE :
    737                            o->valtype == 'F' ? OPT_FMT_PEMDER
    738                            : OPT_FMT_ANY, &ival))
    739                 break;
    740             BIO_printf(bio_err,
    741                        "%s: Invalid format \"%s\" for -%s\n",
    742                        prog, arg, o->name);
    743             return -1;
    744         }
    745 
    746         /* Return the flag value. */
    747         return o->retval;
    748     }
    749     if (unknown != NULL) {
    750         dunno = p;
    751         return unknown->retval;
    752     }
    753     BIO_printf(bio_err, "%s: Option unknown option -%s\n", prog, p);
    754     return -1;
    755 }
    756 
    757 /* Return the most recent flag parameter. */
    758 char *opt_arg(void)
    759 {
    760     return arg;
    761 }
    762 
    763 /* Return the most recent flag. */
    764 char *opt_flag(void)
    765 {
    766     return flag;
    767 }
    768 
    769 /* Return the unknown option. */
    770 char *opt_unknown(void)
    771 {
    772     return dunno;
    773 }
    774 
    775 /* Return the rest of the arguments after parsing flags. */
    776 char **opt_rest(void)
    777 {
    778     return &argv[opt_index];
    779 }
    780 
    781 /* How many items in remaining args? */
    782 int opt_num_rest(void)
    783 {
    784     int i = 0;
    785     char **pp;
    786 
    787     for (pp = opt_rest(); *pp; pp++, i++)
    788         continue;
    789     return i;
    790 }
    791 
    792 /* Return a string describing the parameter type. */
    793 static const char *valtype2param(const OPTIONS *o)
    794 {
    795     switch (o->valtype) {
    796     case 0:
    797     case '-':
    798         return "";
    799     case 's':
    800         return "val";
    801     case '/':
    802         return "dir";
    803     case '<':
    804         return "infile";
    805     case '>':
    806         return "outfile";
    807     case 'p':
    808         return "+int";
    809     case 'n':
    810         return "int";
    811     case 'l':
    812         return "long";
    813     case 'u':
    814         return "ulong";
    815     case 'E':
    816         return "PEM|DER|ENGINE";
    817     case 'F':
    818         return "PEM|DER";
    819     case 'f':
    820         return "format";
    821     case 'M':
    822         return "intmax";
    823     case 'U':
    824         return "uintmax";
    825     }
    826     return "parm";
    827 }
    828 
    829 void opt_help(const OPTIONS *list)
    830 {
    831     const OPTIONS *o;
    832     int i;
    833     int standard_prolog;
    834     int width = 5;
    835     char start[80 + 1];
    836     char *p;
    837     const char *help;
    838 
    839     /* Starts with its own help message? */
    840     standard_prolog = list[0].name != OPT_HELP_STR;
    841 
    842     /* Find the widest help. */
    843     for (o = list; o->name; o++) {
    844         if (o->name == OPT_MORE_STR)
    845             continue;
    846         i = 2 + (int)strlen(o->name);
    847         if (o->valtype != '-')
    848             i += 1 + strlen(valtype2param(o));
    849         if (i < MAX_OPT_HELP_WIDTH && i > width)
    850             width = i;
    851         assert(i < (int)sizeof(start));
    852     }
    853 
    854     if (standard_prolog)
    855         BIO_printf(bio_err, "Usage: %s [options]\nValid options are:\n",
    856                    prog);
    857 
    858     /* Now let's print. */
    859     for (o = list; o->name; o++) {
    860         help = o->helpstr ? o->helpstr : "(No additional info)";
    861         if (o->name == OPT_HELP_STR) {
    862             BIO_printf(bio_err, help, prog);
    863             continue;
    864         }
    865 
    866         /* Pad out prefix */
    867         memset(start, ' ', sizeof(start) - 1);
    868         start[sizeof(start) - 1] = '\0';
    869 
    870         if (o->name == OPT_MORE_STR) {
    871             /* Continuation of previous line; pad and print. */
    872             start[width] = '\0';
    873             BIO_printf(bio_err, "%s  %s\n", start, help);
    874             continue;
    875         }
    876 
    877         /* Build up the "-flag [param]" part. */
    878         p = start;
    879         *p++ = ' ';
    880         *p++ = '-';
    881         if (o->name[0])
    882             p += strlen(strcpy(p, o->name));
    883         else
    884             *p++ = '*';
    885         if (o->valtype != '-') {
    886             *p++ = ' ';
    887             p += strlen(strcpy(p, valtype2param(o)));
    888         }
    889         *p = ' ';
    890         if ((int)(p - start) >= MAX_OPT_HELP_WIDTH) {
    891             *p = '\0';
    892             BIO_printf(bio_err, "%s\n", start);
    893             memset(start, ' ', sizeof(start));
    894         }
    895         start[width] = '\0';
    896         BIO_printf(bio_err, "%s  %s\n", start, help);
    897     }
    898 }
    899