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