summaryrefslogtreecommitdiffstats
path: root/doc
diff options
context:
space:
mode:
authorRich Salz <rsalz@akamai.com>2021-05-01 13:11:49 +0200
committerDr. David von Oheimb <dev@ddvo.net>2021-05-01 13:11:49 +0200
commitf4407385f58242dcc6ae95a60c2a3dc8782bee42 (patch)
tree7b89ff8ead447d4d0bb3812e5d9c1fc36f32d526 /doc
parentc0f4400c4051cc26fbe385b6af9fc67e7c66dbdd (diff)
APPS: Document the core of the opt_ API
Reviewed-by: Tomas Mraz <tomas@openssl.org> Reviewed-by: David von Oheimb <david.von.oheimb@siemens.com> (Merged from https://github.com/openssl/openssl/pull/14995)
Diffstat (limited to 'doc')
-rw-r--r--doc/internal/man3/OPTIONS.pod301
1 files changed, 301 insertions, 0 deletions
diff --git a/doc/internal/man3/OPTIONS.pod b/doc/internal/man3/OPTIONS.pod
new file mode 100644
index 0000000000..3c0fcdaf80
--- /dev/null
+++ b/doc/internal/man3/OPTIONS.pod
@@ -0,0 +1,301 @@
+=pod
+
+=head1 NAME
+
+OPTIONS, OPT_PAIR,
+opt_progname, opt_appname, opt_getprog, opt_init, opt_format,
+opt_int, opt_long, opt_imax, opt_umax, opt_ulong, opt_pair,
+opt_string, opt_cipher, opt_md, opt_next, opt_arg, opt_flag, opt_unknown,
+opt_num_rest, opt_rest, opt_help, opt_isdir
+- Option parsing for commands and tests
+
+=head1 SYNOPSIS
+
+ #include "opt.h"
+
+ typedef struct { ... } OPTIONS;
+ typedef struct { ... } OPT_PAIR;
+
+ char *opt_progname(const char *argv0);
+ char *opt_appname(const char *arg0);
+ char *opt_getprog(void);
+ char *opt_init(int argc, char **argv, const OPTIONS *o);
+
+ int opt_next(void);
+ void opt_help(const OPTIONS *list);
+ char *opt_arg(void);
+ char *opt_flag(void);
+ char *opt_unknown(void);
+ int opt_cipher(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_long(const char *value, long *result);
+ int opt_imax(const char *value, intmax_t *result);
+ int opt_umax(const char *value, uintmax_t *result);
+ int opt_ulong(const char *value, unsigned long *result);
+
+ int opt_isdir(const char *name);
+
+ int opt_format(const char *s, unsigned long flags, int *result);
+ 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);
+
+=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_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_YES, OPT_NAME, OPT_COUNT, OPT_OFILE,
+ ...
+ } OPTION_CHOICE;
+
+The first two lines must appear exactly as shown. 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 ths 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 "argc, argv" arguments given to main() and
+a pointer 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]>, and returns
+the simple short name of the executable, to be used for error messages and
+the like. The opt_appname() functions takes 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. Once set, opt_getprog()
+also returns the value.
+
+Once opt_init() has been called, opt_next() can be called in a loop to
+fetch each option in turn. It returns -1, or 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...
+ }
+ }
+
+The opt_help() function takes a list of option definitions and prints a
+nicely-formatted output.
+
+Within the option parsing loop, opt_flag() returns the option,
+without any leading hyphens. The opt_arg() function returns
+the option's value, if there is one.
+
+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_cipher() takes the specified I<name> and fills in
+the cipher into I<cipherp>. The function opt_md() does the same
+thing for message digest.
+
+There are a several useful functions for parsing numbers. These are
+opt_int(), opt_long(), opt_ulong(), opt_imax(), and opt_umax(). 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_isdir() function returns 1 if the specified I<name> is
+a directory, or 0 if not. 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_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.
+
+After processing all the options, the opt_num_rest() returns what is
+left, and opt_rest() 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 B<argv> array.
+
+=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 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