aboutsummaryrefslogtreecommitdiff
path: root/apps/lib/opt.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/lib/opt.c')
-rw-r--r--apps/lib/opt.c213
1 files changed, 145 insertions, 68 deletions
diff --git a/apps/lib/opt.c b/apps/lib/opt.c
index 88db9ad6947b..0018c268c0b4 100644
--- a/apps/lib/opt.c
+++ b/apps/lib/opt.c
@@ -41,6 +41,7 @@ static int opt_index;
static char *arg;
static char *flag;
static char *dunno;
+static const char *unknown_name;
static const OPTIONS *unknown;
static const OPTIONS *opts;
static char prog[40];
@@ -166,7 +167,6 @@ char *opt_init(int ac, char **av, const OPTIONS *o)
opt_begin();
opts = o;
unknown = NULL;
-
/* Make sure prog name is set for usage output */
(void)opt_progname(argv[0]);
@@ -194,7 +194,7 @@ char *opt_init(int ac, char **av, const OPTIONS *o)
case 0: case '-': case '.':
case '/': case '<': case '>': case 'E': case 'F':
case 'M': case 'U': case 'f': case 'l': case 'n': case 'p': case 's':
- case 'u': case 'c': case ':': case 'N':
+ case 'u': case 'c': case ':': case 'N': case 'A':
break;
default:
OPENSSL_assert(0);
@@ -215,6 +215,7 @@ char *opt_init(int ac, char **av, const OPTIONS *o)
}
#endif
if (o->name[0] == '\0') {
+ OPENSSL_assert(unknown_name != NULL);
OPENSSL_assert(unknown == NULL);
unknown = o;
OPENSSL_assert(unknown->valtype == 0 || unknown->valtype == '-');
@@ -224,7 +225,9 @@ char *opt_init(int ac, char **av, const OPTIONS *o)
}
static OPT_PAIR formats[] = {
- {"PEM/DER", OPT_FMT_PEMDER},
+ {"pem", OPT_FMT_PEM},
+ {"der", OPT_FMT_DER},
+ {"b64", OPT_FMT_B64},
{"pkcs12", OPT_FMT_PKCS12},
{"smime", OPT_FMT_SMIME},
{"engine", OPT_FMT_ENGINE},
@@ -236,21 +239,22 @@ static OPT_PAIR formats[] = {
{NULL}
};
+void opt_set_unknown_name(const char *name)
+{
+ unknown_name = name;
+}
+
/* Print an error message about a failed format parse. */
static int opt_format_error(const char *s, unsigned long flags)
{
OPT_PAIR *ap;
- if (flags == OPT_FMT_PEMDER) {
- opt_printf_stderr("%s: Bad format \"%s\"; must be pem or der\n",
- prog, s);
- } else {
- opt_printf_stderr("%s: Bad format \"%s\"; must be one of:\n",
- prog, s);
- for (ap = formats; ap->name; ap++)
- if (flags & ap->retval)
- opt_printf_stderr(" %s\n", ap->name);
- }
+ opt_printf_stderr("%s: Bad format \"%s\"; must be one of: ", prog, s);
+ for (ap = formats; ap->name; ap++)
+ if (flags & ap->retval)
+ opt_printf_stderr(" %s", ap->name);
+ opt_printf_stderr("\n");
+
return 0;
}
@@ -261,9 +265,21 @@ int opt_format(const char *s, unsigned long flags, int *result)
default:
opt_printf_stderr("%s: Bad format \"%s\"\n", prog, s);
return 0;
+ case 'B':
+ case 'b':
+ if (s[1] == '\0'
+ || strcmp(s, "B64") == 0 || strcmp(s, "b64") == 0
+ || strcmp(s, "BASE64") == 0 || strcmp(s, "base64") == 0 ) {
+ if ((flags & OPT_FMT_B64) == 0)
+ return opt_format_error(s, flags);
+ *result = FORMAT_BASE64;
+ } else {
+ return 0;
+ }
+ break;
case 'D':
case 'd':
- if ((flags & OPT_FMT_PEMDER) == 0)
+ if ((flags & OPT_FMT_DER) == 0)
return opt_format_error(s, flags);
*result = FORMAT_ASN1;
break;
@@ -313,7 +329,7 @@ int opt_format(const char *s, unsigned long flags, int *result)
case 'P':
case 'p':
if (s[1] == '\0' || strcmp(s, "PEM") == 0 || strcmp(s, "pem") == 0) {
- if ((flags & OPT_FMT_PEMDER) == 0)
+ if ((flags & OPT_FMT_PEM) == 0)
return opt_format_error(s, flags);
*result = FORMAT_PEM;
} else if (strcmp(s, "PVK") == 0 || strcmp(s, "pvk") == 0) {
@@ -399,8 +415,10 @@ int opt_cipher_any(const char *name, EVP_CIPHER **cipherp)
{
int ret;
+ if (name == NULL)
+ return 1;
if ((ret = opt_cipher_silent(name, cipherp)) == 0)
- opt_printf_stderr("%s: Unknown cipher: %s\n", prog, name);
+ opt_printf_stderr("%s: Unknown option or cipher: %s\n", prog, name);
return ret;
}
@@ -410,6 +428,8 @@ int opt_cipher(const char *name, EVP_CIPHER **cipherp)
unsigned long int flags;
EVP_CIPHER *c = NULL;
+ if (name == NULL)
+ return 1;
if (opt_cipher_any(name, &c)) {
mode = EVP_CIPHER_get_mode(c);
flags = EVP_CIPHER_get_flags(c);
@@ -454,12 +474,22 @@ int opt_md(const char *name, EVP_MD **mdp)
{
int ret;
+ if (name == NULL)
+ return 1;
if ((ret = opt_md_silent(name, mdp)) == 0)
- opt_printf_stderr("%s: Unknown option or message digest: %s\n", prog,
- name != NULL ? name : "\"\"");
+ opt_printf_stderr("%s: Unknown option or message digest: %s\n",
+ prog, name);
return ret;
}
+int opt_check_md(const char *name)
+{
+ if (opt_md(name, NULL))
+ return 1;
+ ERR_clear_error();
+ return 0;
+}
+
/* Look through a list of name/value pairs. */
int opt_pair(const char *name, const OPT_PAIR* pairs, int *result)
{
@@ -961,11 +991,14 @@ int opt_next(void)
case 'E':
case 'F':
case 'f':
+ case 'A':
+ case 'a':
if (opt_format(arg,
o->valtype == 'c' ? OPT_FMT_PDS :
o->valtype == 'E' ? OPT_FMT_PDE :
- o->valtype == 'F' ? OPT_FMT_PEMDER
- : OPT_FMT_ANY, &ival))
+ o->valtype == 'F' ? OPT_FMT_PEMDER :
+ o->valtype == 'A' ? OPT_FMT_ASN1 :
+ OPT_FMT_ANY, &ival))
break;
opt_printf_stderr("%s: Invalid format \"%s\" for option -%s\n",
prog, arg, o->name);
@@ -976,6 +1009,11 @@ int opt_next(void)
return o->retval;
}
if (unknown != NULL) {
+ if (dunno != NULL) {
+ opt_printf_stderr("%s: Multiple %s or unknown options: -%s and -%s\n",
+ prog, unknown_name, dunno, p);
+ return -1;
+ }
dunno = p;
return unknown->retval;
}
@@ -1001,6 +1039,12 @@ char *opt_unknown(void)
return dunno;
}
+/* Reset the unknown option; needed by ocsp to allow multiple digest options. */
+void reset_unknown(void)
+{
+ dunno = NULL;
+}
+
/* Return the rest of the arguments after parsing flags. */
char **opt_rest(void)
{
@@ -1018,6 +1062,31 @@ int opt_num_rest(void)
return i;
}
+int opt_check_rest_arg(const char *expected)
+{
+ char *opt = *opt_rest();
+
+ if (opt == NULL || *opt == '\0') {
+ if (expected == NULL)
+ return 1;
+ opt_printf_stderr("%s: Missing argument: %s\n", prog, expected);
+ return 0;
+ }
+ if (expected != NULL) {
+ opt = argv[opt_index + 1];
+ if (opt == NULL || *opt == '\0')
+ return 1;
+ opt_printf_stderr("%s: Extra argument after %s: \"%s\"\n", prog, expected, opt);
+ return 0;
+ }
+ if (opt_unknown() == NULL)
+ opt_printf_stderr("%s: Extra option: \"%s\"\n", prog, opt);
+ else
+ opt_printf_stderr("%s: Extra (unknown) options: \"%s\" \"%s\"\n",
+ prog, opt_unknown(), opt);
+ return 0;
+}
+
/* Return a string describing the parameter type. */
static const char *valtype2param(const OPTIONS *o)
{
@@ -1063,55 +1132,60 @@ static void opt_print(const OPTIONS *o, int doingparams, int width)
{
const char* help;
char start[80 + 1];
- char *p;
-
- help = o->helpstr ? o->helpstr : "(No additional info)";
- if (o->name == OPT_HELP_STR) {
- opt_printf_stderr(help, prog);
- return;
- }
- if (o->name == OPT_SECTION_STR) {
- opt_printf_stderr("\n");
- opt_printf_stderr(help, prog);
- return;
- }
- if (o->name == OPT_PARAM_STR) {
- opt_printf_stderr("\nParameters:\n");
- return;
- }
-
- /* Pad out prefix */
- memset(start, ' ', sizeof(start) - 1);
- start[sizeof(start) - 1] = '\0';
+ int linelen, printlen;
+
+ /* Avoid OOB if width is beyond the buffer size of start */
+ if (width >= (int)sizeof(start))
+ width = (int)sizeof(start) - 1;
+
+ help = o->helpstr ? o->helpstr : "(No additional info)";
+ if (o->name == OPT_HELP_STR) {
+ opt_printf_stderr(help, prog);
+ return;
+ } else if (o->name == OPT_SECTION_STR) {
+ opt_printf_stderr("\n");
+ opt_printf_stderr(help, prog);
+ return;
+ } else if (o->name == OPT_PARAM_STR) {
+ opt_printf_stderr("\nParameters:\n");
+ return;
+ }
- if (o->name == OPT_MORE_STR) {
- /* Continuation of previous line; pad and print. */
- start[width] = '\0';
- opt_printf_stderr("%s %s\n", start, help);
- return;
- }
+ /* Pad out prefix */
+ memset(start, ' ', sizeof(start) - 1);
+ start[sizeof(start) - 1] = '\0';
- /* Build up the "-flag [param]" part. */
- p = start;
- *p++ = ' ';
- if (!doingparams)
- *p++ = '-';
- if (o->name[0])
- p += strlen(strcpy(p, o->name));
- else
- *p++ = '*';
- if (o->valtype != '-') {
- *p++ = ' ';
- p += strlen(strcpy(p, valtype2param(o)));
- }
- *p = ' ';
- if ((int)(p - start) >= MAX_OPT_HELP_WIDTH) {
- *p = '\0';
- opt_printf_stderr("%s\n", start);
- memset(start, ' ', sizeof(start));
- }
+ if (o->name == OPT_MORE_STR) {
+ /* Continuation of previous line; pad and print. */
start[width] = '\0';
opt_printf_stderr("%s %s\n", start, help);
+ return;
+ }
+
+ /* Build up the "-flag [param]" part. */
+ linelen = 0;
+
+ printlen = opt_printf_stderr(" %s", !doingparams ? "-" : "");
+ linelen += (printlen > 0) ? printlen : MAX_OPT_HELP_WIDTH;
+
+ printlen = opt_printf_stderr("%s" , o->name[0] ? o->name : "*");
+ linelen += (printlen > 0) ? printlen : MAX_OPT_HELP_WIDTH;
+
+ if (o->valtype != '-') {
+ printlen = opt_printf_stderr(" %s" , valtype2param(o));
+ linelen += (printlen > 0) ? printlen : MAX_OPT_HELP_WIDTH;
+ }
+
+ if (linelen >= MAX_OPT_HELP_WIDTH || linelen > width) {
+ opt_printf_stderr("%s", "\n");
+ memset(start, ' ', sizeof(start));
+ linelen = 0;
+ }
+
+ width -= linelen;
+
+ start[width] = '\0';
+ opt_printf_stderr("%s %s\n", start, help);
}
void opt_help(const OPTIONS *list)
@@ -1119,7 +1193,6 @@ void opt_help(const OPTIONS *list)
const OPTIONS *o;
int i, sawparams = 0, width = 5;
int standard_prolog;
- char start[80 + 1];
/* Starts with its own help message? */
standard_prolog = list[0].name != OPT_HELP_STR;
@@ -1128,14 +1201,18 @@ void opt_help(const OPTIONS *list)
for (o = list; o->name; o++) {
if (o->name == OPT_MORE_STR)
continue;
+
i = 2 + (int)strlen(o->name);
if (o->valtype != '-')
i += 1 + strlen(valtype2param(o));
- if (i < MAX_OPT_HELP_WIDTH && i > width)
+
+ if (i > width)
width = i;
- OPENSSL_assert(i < (int)sizeof(start));
}
+ if (width > MAX_OPT_HELP_WIDTH)
+ width = MAX_OPT_HELP_WIDTH;
+
if (standard_prolog) {
opt_printf_stderr("Usage: %s [options]\n", prog);
if (list[0].name != OPT_SECTION_STR)