[openssl] master update

dev at ddvo.net dev at ddvo.net
Sat May 1 11:13:22 UTC 2021

The branch master has been updated
       via  f4407385f58242dcc6ae95a60c2a3dc8782bee42 (commit)
      from  c0f4400c4051cc26fbe385b6af9fc67e7c66dbdd (commit)

- Log -----------------------------------------------------------------
commit f4407385f58242dcc6ae95a60c2a3dc8782bee42
Author: Rich Salz <rsalz at akamai.com>
Date:   Sat May 1 13:11:49 2021 +0200

    APPS: Document the core of the opt_ API
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    Reviewed-by: David von Oheimb <david.von.oheimb at siemens.com>
    (Merged from https://github.com/openssl/openssl/pull/14995)


Summary of changes:
 apps/include/fmt.h            |   3 +-
 apps/include/opt.h            |   3 -
 apps/lib/opt.c                |   6 +-
 doc/internal/man3/OPTIONS.pod | 301 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 306 insertions(+), 7 deletions(-)
 create mode 100644 doc/internal/man3/OPTIONS.pod

diff --git a/apps/include/fmt.h b/apps/include/fmt.h
index c9edd4707e..f235899bf8 100644
--- a/apps/include/fmt.h
+++ b/apps/include/fmt.h
@@ -17,7 +17,8 @@
 #ifndef OSSL_APPS_FMT_H
 #define OSSL_APPS_FMT_H
-/* On some platforms, it's important to distinguish between text and binary
+ * On some platforms, it's important to distinguish between text and binary
  * files.  On some, there might even be specific file formats for different
  * contents.  The FORMAT_xxx macros are meant to express an intent with the
  * file being read or created.
diff --git a/apps/include/opt.h b/apps/include/opt.h
index f9ac5accae..f22e9af05e 100644
--- a/apps/include/opt.h
+++ b/apps/include/opt.h
@@ -349,7 +349,6 @@ char *opt_init(int ac, char **av, const OPTIONS * o);
 int opt_next(void);
 void opt_begin(void);
 int opt_format(const char *s, unsigned long flags, int *result);
-const char *format2str(int format);
 int opt_int(const char *arg, int *result);
 int opt_int_arg(void);
 int opt_ulong(const char *arg, unsigned long *result);
@@ -381,8 +380,6 @@ int opt_verify(int i, X509_VERIFY_PARAM *vpm);
 int opt_rand(int i);
 int opt_provider(int i);
 void opt_help(const OPTIONS * list);
-void opt_print(const OPTIONS * opt, int doingparams, int width);
-int opt_format_error(const char *s, unsigned long flags);
 void print_format_error(int format, unsigned long flags);
 int opt_isdir(const char *name);
 int opt_printf_stderr(const char *fmt, ...);
diff --git a/apps/lib/opt.c b/apps/lib/opt.c
index 83ae28cdc1..a6b6f7ce4f 100644
--- a/apps/lib/opt.c
+++ b/apps/lib/opt.c
@@ -227,7 +227,7 @@ static OPT_PAIR formats[] = {
 /* Print an error message about a failed format parse. */
-int opt_format_error(const char *s, unsigned long flags)
+static int opt_format_error(const char *s, unsigned long flags)
     OPT_PAIR *ap;
@@ -325,7 +325,7 @@ int opt_format(const char *s, unsigned long flags, int *result)
 /* Return string representing the given format. */
-const char *format2str(int format)
+static const char *format2str(int format)
     switch (format) {
@@ -973,7 +973,7 @@ static const char *valtype2param(const OPTIONS *o)
     return "parm";
-void opt_print(const OPTIONS *o, int doingparams, int width)
+static void opt_print(const OPTIONS *o, int doingparams, int width)
     const char* help;
     char start[80 + 1];
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 @@
+=head1 NAME
+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);
+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>
+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
+=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,
+        ...
+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
+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
+    {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
+    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
+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.
+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

More information about the openssl-commits mailing list