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