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