1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
|
=pod
=head1 NAME
OPTIONS, OPT_PAIR, OPT_COMMON, OPT_ERR, OPT_EOF, OPT_HELP,
opt_init, opt_progname, opt_appname, opt_getprog, opt_help,
opt_begin, opt_next, opt_flag, opt_arg, opt_unknown, opt_cipher,
opt_cipher_any, opt_cipher_silent, opt_md,
opt_int, opt_int_arg, opt_long, opt_ulong, opt_intmax, opt_uintmax,
opt_format, opt_isdir, opt_string, opt_pair,
opt_num_rest, opt_rest, opt_legacy_okay
- Option parsing for commands and tests
=head1 SYNOPSIS
#include "opt.h"
typedef struct { ... } OPTIONS;
typedef struct { ... } OPT_PAIR;
#define OPT_COMMON
#define OPT_ERR
#define OPT_EOF
#define OPT_HELP
char *opt_init(int argc, char **argv, const OPTIONS *o);
char *opt_progname(const char *argv0);
char *opt_appname(const char *argv0);
char *opt_getprog(void);
void opt_help(const OPTIONS *list);
void opt_begin(void);
int opt_next(void);
char *opt_flag(void);
char *opt_arg(void);
char *opt_unknown(void);
int opt_cipher(const char *name, EVP_CIPHER **cipherp);
int opt_cipher_any(const char *name, EVP_CIPHER **cipherp);
int opt_cipher_silent(const char *name, EVP_CIPHER **cipherp);
int opt_md(const char *name, EVP_MD **mdp);
int opt_int(const char *value, int *result);
int opt_int_arg(void);
int opt_long(const char *value, long *result);
int opt_ulong(const char *value, unsigned long *result);
int opt_intmax(const char *value, intmax_t *result);
int opt_uintmax(const char *value, uintmax_t *result);
int opt_format(const char *s, unsigned long flags, int *result);
int opt_isdir(const char *name);
int opt_string(const char *name, const char **options);
int opt_pair(const char *name, const OPT_PAIR* pairs, int *result);
int opt_num_rest(void);
char **opt_rest(void);
int opt_legacy_okay(void);
=head1 DESCRIPTION
The functions on this page provide a common set of option-parsing for
the OpenSSL command and the internal test programs.
It is intended to be used like the standard getopt(3) routine, except
that multi-character flag names are supported, and a variety of parsing
and other utility functions are also provided.
Programs that use this should make sure to set the appropriate C<-I>
flag.
These routines expect a global B<BIO> named B<bio_err> to point to
the equivalent of B<stderr>. This is already done in the OpenSSL
application.
=head2 Data Types
Each program should define, near the main() routine, an enumeration
that is the set of options the program accepts. For example:
typedef enum OPTION_choice {
OPT_COMMON,
OPT_YES, OPT_NAME, OPT_COUNT, OPT_OFILE,
...
} OPTION_CHOICE;
The first two lines must appear exactly as shown.
OPT_COMMON is a macro that expands to C<OPT_ERR = -1, OPT_EOF = 0, OPT_HELP>.
In addition to defining symbolic names for the constants that opt_next()
returns, it also helps guarantee that every command has a C<-help> option.
The third line is a sample
set of flags, and the closing C<typedef> name is used for error-checking
as discussed below.
By declaring the variable as an C<OPTION_CHOICE>, with the right warning
flags, the compiler could check that all specified options are handled.
The B<OPTIONS> C<typedef> specifies an option: what type of argument
it takes (if any), and an optional "help" string. It is a C<struct>
containing these fields:
const char *name;
int retval;
int valtype;
const char *helpstr;
The B<name> is the name of the option that the user would type. Options
are words prefaced with a minus sign. If the user uses two minus signs,
this is also accepted for compatibility with other GNU software. Some
names are special, and are described below.
The B<retval> is the value to return if the option is found. It should be
one of the choices in the enumeration above.
The B<valtype> defines what the option's parameter must be. It should
be chosen from the following set:
\0 No value
'-' No value
's' A text string
'/' A directory
'<' Name of file to open for input
'>' Name of file to open for output
'n' A signed number that fits in the C<int> type
'p' A positive number that fits in the C<int> type
'N' A nonnegative number that fits in the C<int> type
'M' A signed number that fits in the C<intmax_t> type
'U' An unsigned number that fits in the C<uintmax_t> type
'l' A signed number that fits in the C<long> type
'u' An unsigned number that fits in the C<unsigned long> type
'c' File in PEM, DER, or S/MIME format
'F' A file in PEM or DER format
'E' Like 'F' but also allows ENGINE
'f' Any file format
The B<helpstr> is what to display when the user uses the help option,
which should be C<"help">.
A program should declare its options right after the enumeration,
and should follow the ordering of the enumeration as this helps
readability and maintainability:
static OPTIONS my_options[] = {
{"help", OPT_HELP, '-', "Display this summary"},
{"yes", OPT_YES, '-', "Print an affirmative reply"},
{"count", OPT_COUNT, 'p', "Repeat count"},
{"output" OPT_OFILE, '>', "Output file; default is stdout"},
{NULL}
};
Note that the B<OPT_HELP> option is explicitly listed, and the list ends with
an entry of all-null's. The other two special options, B<OPT_ERR> and B<OPT_EOF>
should not appear in the array.
If the help string is too long to fit into one line, it may be continued
on multiple lines; each entry should use B<OPT_MORE_STR>, like this:
{"output" OPT_OFILE, '>', "Output file; default is stdout"},
{OPT_MORE_STR, 0, 0,
"This flag is not really needed on Unix systems"},
{OPT_MORE_STR, 0, 0,
"(Unix and descendents for the win!)"}
Each subsequent line will be indented the correct amount.
By default, the help display will include a standard prolog:
Usage: PROGRAM [options]
Valid options are:
...detailed list of options...
Sometimes there are parameters that should appear in the synopsis.
Use B<OPT_HELP_STR> as the first entry in your array:
{OPT_HELP_STR, 1, '-', Usage: %s [options] [text...]\n"}
The B<retval> and B<valtype> are ignored, and the B<helpstr> should
follow the general construction as shown. The C<%s> will get the program
name.
If a command has a large set of options, it can be useful to break them
into sections. Use the macro B<OPT_SECTION> or B<OPT_SECTION_STR>
to indicate this. The two lines below are equivalent:
OPT_SECTION("Validation"),
{OPT_SECTION_STR, 1, '-', "Validation options:\n"},
In addition to providing help about options, you can provide a description
of the parameters a command takes. These should appear at the end of
the options and are indicated by using B<OPT_PARAM_STR> or the
B<OPT_PARAMETERS> macro:
OPT_PARAMETERS()
{OPT_PARAM_STR, 1, '-', "Parameters:\n"}
Every "option" after after this should contain the parameter and
the help string:
{"text", 0, 0, "Words to display (optional)"},
=head2 Functions
The opt_init() function takes the I<argc> and I<argv> arguments given to main()
and a pointer I<o> to the list of options. It returns the simple program
name, as defined by opt_progname().
The opt_progname() function takes the full pathname C<argv[0]> in its I<arg0>
parameter and returns
the simple short name of the executable, to be used for error messages and
the like.
The opt_appname() function takes in its I<argv0> parameter
the "application" name (such
as the specific command from L<openssl(1)> and appends it to the program
name. This function should only be called once.
The opt_getprog() function returns the value set by opt_appname().
The opt_help() function takes a list of option definitions and prints a
nicely-formatted output.
The opt_begin() function, which is called automatically by opt_init(),
can be used to reset the option parsing loop.
The opt_next() function is called, once opt_init() has been called,
in a loop to fetch each option in turn. It returns -1, or B<OPT_EOF> when the
end of arguments has been reached. This is typically done like this:
prog = opt_init(argc, argv, my_options);
while ((o = opt_next()) != OPT_EOF) {
switch (o) {
case OPT_EOF:
case OPT_ERR:
opthelp:
fprintf(stderr, "%s: Use -help for summary\n", prog);
exit(1);
case OPT_HELP:
opt_help(my_options);
exit(0);
...other options...
}
}
Within the option parsing loop, the following functions may be called.
The opt_flag() function returns the most recent option name
including the preceding C<->.
The opt_arg() function returns the option's argument value, if there is one.
The opt_unknown() function returns the unknown option.
In an option list, there can be at most one option with the empty string.
This is a "wildcard" or "unknown" option. For example, it allows an
option to be be taken as digest algorithm, like C<-sha1>. The function
opt_md() takes the specified I<name> and fills in the digest into I<mdp>.
The functions opt_cipher(), opt_cipher_any() and opt_cipher_silent()
each takes the specified I<name> and fills in the cipher into I<cipherp>.
The function opt_cipher() only accepts ciphers which are not
AEAD and are not using XTS mode. The functions opt_cipher_any() and
opt_cipher_silent() accept any cipher, the latter not emitting an error
if the cipher is not located.
There are a several useful functions for parsing numbers. These are
opt_int(), opt_long(), opt_ulong(), opt_intmax(), and opt_uintmax(). They all
take C<0x> to mean hexadecimal and C<0> to mean octal, and will do the
necessary range-checking. They return 1 if successful and fill in the
C<result> pointer with the value, or 0 on error. Note that opt_next()
will also do range-check on the argument if the appropriate B<valtype>
field is specified for the option. This means that error-checking inside
the C<switch> C<case> can often be elided.
The opt_int_arg() function is a convenience abbreviation to opt_int().
It parses and returns an integer, assuming its range has been checked before.
The opt_format() function takes a string value,
such as used with the B<-informat> or similar option, and fills
the value from the constants in F<fmt.h> file.
The opt_isdir() function returns 1 if the specified I<name> is
a directory, or 0 if not.
The opt_string() function checks that I<name> appears in the
NULL-terminated array of strings. It returns 1 if found,
or prints a diagnostic and returns 0 if not.
The opt_pair() function takes a list of I<pairs>, each of which
has a text name and an integer. The specified I<name> is
found on the list, it puts the index in I<*result>, and returns
1. If not found, it returns 0.
The following functions can be used after processing all the options.
The opt_num_rest() function returns what is left.
The opt_rest() function returns a pointer to the first non-option.
If there were no parameters, it will point to the NULL that is
at the end of the standard I<argv> array.
The opt_legacy_okay() function returns true if no options have been
specified that would preclude using legacy code paths. Currently,
the various provider options preclude legacy operation. This means,
for example, that specifying both B<-provider> and B<-engine> in the
same command line will not work as expected.
=head2 Common Options
There are a few groups of options that are common to many OpenSSL programs.
These are handled with sets of macros that define common option names
and common code to handle them. The categories are identified by a
letter:
V Validation
X Extended certificate
S TLS/SSL
R Random state
The B<OPT_x_ENUM> macro is used to define the numeration values, where B<x>
is one of the letters above. The B<OPT_x_OPTIONS> macro is used to
list the set of common options, and the B<OPT_x_CASES> is used in
the C<switch> statement.
The common options are used throughout the sources for the OpenSSL commands.
They are also used with common descriptions when generating the
manpages, in the file F<doc/perlvars.pm>, which follow a similar naming
convention.
=head1 RETURN VALUES
Detailed above.
=head1 EXAMPLES
The best examples can be found in sources for the commands in the F<apps>
directory of the source tree.
A notable exception is F<apps/cmp.c> which uses this API, but does
things very differently.
=head1 COPYRIGHT
Copyright 2021-2022 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not use this
file except in compliance with the License. You can obtain a copy in the file
LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
|