[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) {
default:
@@ -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 @@
+=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
More information about the openssl-commits
mailing list