From 284076982de7529585c4c13a663203588bff8b12 Mon Sep 17 00:00:00 2001 From: "Dr. David von Oheimb" Date: Sat, 1 May 2021 14:35:21 +0200 Subject: [PATCH] APPS: Slightly extend and improve documentation of the opt_ API Also remove redundant opt_name() and make names of opt_{i,u}ntmax() consistent. Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/15111) --- apps/cmp.c | 4 +- apps/include/opt.h | 52 ++++++++++++---------- apps/lib/apps.c | 1 + apps/lib/opt.c | 29 +++++------- apps/x509.c | 2 +- doc/internal/man3/OPTIONS.pod | 84 ++++++++++++++++++++++------------- test/ecstresstest.c | 4 +- 7 files changed, 98 insertions(+), 78 deletions(-) diff --git a/apps/cmp.c b/apps/cmp.c index 51dd971162..14c3a73866 100644 --- a/apps/cmp.c +++ b/apps/cmp.c @@ -2188,10 +2188,10 @@ static char *opt_str(void) if (arg[0] == '\0') { CMP_warn1("%s option argument is empty string, resetting option", - opt_name()); + opt_flag()); arg = NULL; } else if (arg[0] == '-') { - CMP_warn1("%s option argument starts with hyphen", opt_name()); + CMP_warn1("%s option argument starts with hyphen", opt_flag()); } return arg; } diff --git a/apps/include/opt.h b/apps/include/opt.h index f22e9af05e..a80b6ee43a 100644 --- a/apps/include/opt.h +++ b/apps/include/opt.h @@ -342,46 +342,50 @@ typedef struct string_int_pair_st { #define OPT_PARAMETERS() { OPT_PARAM_STR, 1, '-', "Parameters:\n" } const char *opt_path_end(const char *filename); +char *opt_init(int ac, char **av, const OPTIONS * o); char *opt_progname(const char *argv0); -char *opt_appname(const char *arg0); +char *opt_appname(const char *argv0); char *opt_getprog(void); -char *opt_init(int ac, char **av, const OPTIONS * o); -int opt_next(void); +void opt_help(const OPTIONS * list); + void opt_begin(void); -int opt_format(const char *s, unsigned long flags, int *result); +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_silent(const char *name, EVP_CIPHER **cipherp); +int opt_md(const char *name, EVP_MD **mdp); +int opt_md_silent(const char *name, EVP_MD **mdp); + int opt_int(const char *arg, int *result); int opt_int_arg(void); -int opt_ulong(const char *arg, unsigned long *result); int opt_long(const char *arg, long *result); +int opt_ulong(const char *arg, unsigned long *result); #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && \ defined(INTMAX_MAX) && defined(UINTMAX_MAX) && \ !defined(OPENSSL_NO_INTTYPES_H) -int opt_imax(const char *arg, intmax_t *result); -int opt_umax(const char *arg, uintmax_t *result); +int opt_intmax(const char *arg, intmax_t *result); +int opt_uintmax(const char *arg, uintmax_t *result); #else -# define opt_imax opt_long -# define opt_umax opt_ulong +# define opt_intmax opt_long +# define opt_uintmax opt_ulong # define intmax_t long # define uintmax_t unsigned long #endif -int opt_pair(const char *arg, const OPT_PAIR * pairs, int *result); + +int opt_isdir(const char *name); +int opt_format(const char *s, unsigned long flags, int *result); +void print_format_error(int format, unsigned long flags); +int opt_printf_stderr(const char *fmt, ...); int opt_string(const char *name, const char **options); -int opt_cipher(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_md_silent(const char *name, EVP_MD **mdp); -char *opt_name(void); -char *opt_arg(void); -char *opt_flag(void); -char *opt_unknown(void); -char **opt_rest(void); -int opt_num_rest(void); +int opt_pair(const char *arg, const OPT_PAIR * pairs, int *result); + 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 print_format_error(int format, unsigned long flags); -int opt_isdir(const char *name); -int opt_printf_stderr(const char *fmt, ...); + +char **opt_rest(void); +int opt_num_rest(void); #endif /* OSSL_APPS_OPT_H */ diff --git a/apps/lib/apps.c b/apps/lib/apps.c index 81b543ec68..bfd938b555 100644 --- a/apps/lib/apps.c +++ b/apps/lib/apps.c @@ -3152,6 +3152,7 @@ void make_uppercase(char *string) string[i] = toupper((unsigned char)string[i]); } +/* This function is defined here due to visibility of bio_err */ int opt_printf_stderr(const char *fmt, ...) { va_list ap; diff --git a/apps/lib/opt.c b/apps/lib/opt.c index a6b6f7ce4f..4b75b46681 100644 --- a/apps/lib/opt.c +++ b/apps/lib/opt.c @@ -36,7 +36,6 @@ const char OPT_PARAM_STR[] = "-P"; static char **argv; static int argc; static int opt_index; -static char *param_name; static char *arg; static char *flag; static char *dunno; @@ -142,12 +141,12 @@ char *opt_progname(const char *argv0) } #endif -char *opt_appname(const char *arg0) +char *opt_appname(const char *argv0) { size_t len = strlen(prog); - if (arg0 != NULL) - BIO_snprintf(prog + len, sizeof(prog) - len - 1, " %s", arg0); + if (argv0 != NULL) + BIO_snprintf(prog + len, sizeof(prog) - len - 1, " %s", argv0); return prog; } @@ -456,7 +455,7 @@ int opt_int(const char *value, int *result) return 1; } -/* Parse and return a natural number, assuming range has been checked before. */ +/* Parse and return an integer, assuming range has been checked before. */ int opt_int_arg(void) { int result = -1; @@ -515,7 +514,7 @@ int opt_long(const char *value, long *result) !defined(OPENSSL_NO_INTTYPES_H) /* Parse an intmax_t, put it into *result; return 0 on failure, else 1. */ -int opt_imax(const char *value, intmax_t *result) +int opt_intmax(const char *value, intmax_t *result) { int oerrno = errno; intmax_t m; @@ -537,7 +536,7 @@ int opt_imax(const char *value, intmax_t *result) } /* Parse a uintmax_t, put it into *result; return 0 on failure, else 1. */ -int opt_umax(const char *value, uintmax_t *result) +int opt_uintmax(const char *value, uintmax_t *result) { int oerrno = errno; uintmax_t m; @@ -654,7 +653,7 @@ int opt_verify(int opt, X509_VERIFY_PARAM *vpm) X509_VERIFY_PARAM_set_auth_level(vpm, i); break; case OPT_V_ATTIME: - if (!opt_imax(opt_arg(), &t)) + if (!opt_intmax(opt_arg(), &t)) return 0; if (t != (time_t)t) { opt_printf_stderr("%s: epoch time out of range %s\n", @@ -768,7 +767,7 @@ int opt_next(void) /* Look at current arg; at end of the list? */ arg = NULL; - p = param_name = argv[opt_index]; + p = argv[opt_index]; if (p == NULL) return 0; @@ -850,11 +849,11 @@ int opt_next(void) } break; case 'M': - if (!opt_imax(arg, &imval)) + if (!opt_intmax(arg, &imval)) return -1; break; case 'U': - if (!opt_umax(arg, &umval)) + if (!opt_uintmax(arg, &umval)) return -1; break; case 'l': @@ -891,19 +890,13 @@ int opt_next(void) return -1; } -/* Return the name of the most recent flag parameter. */ -char *opt_name(void) -{ - return param_name; -} - /* Return the most recent flag parameter. */ char *opt_arg(void) { return arg; } -/* Return the most recent flag. */ +/* Return the most recent flag (option name including the preceding '-'). */ char *opt_flag(void) { return flag; diff --git a/apps/x509.c b/apps/x509.c index 50453c4b7c..8dffdb47c1 100644 --- a/apps/x509.c +++ b/apps/x509.c @@ -544,7 +544,7 @@ int x509_main(int argc, char **argv) checkend = 1; { intmax_t temp = 0; - if (!opt_imax(opt_arg(), &temp)) + if (!opt_intmax(opt_arg(), &temp)) goto opthelp; checkoffset = (time_t)temp; if ((intmax_t)checkoffset != temp) { diff --git a/doc/internal/man3/OPTIONS.pod b/doc/internal/man3/OPTIONS.pod index 3c0fcdaf80..cbe0ccd883 100644 --- a/doc/internal/man3/OPTIONS.pod +++ b/doc/internal/man3/OPTIONS.pod @@ -3,10 +3,11 @@ =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 +opt_init, opt_progname, opt_appname, opt_getprog, opt_help, +opt_begin, opt_next, opt_flag, opt_arg, opt_unknown, opt_cipher, 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 - Option parsing for commands and tests =head1 SYNOPSIS @@ -16,28 +17,29 @@ opt_num_rest, opt_rest, opt_help, opt_isdir typedef struct { ... } OPTIONS; typedef struct { ... } OPT_PAIR; + char *opt_init(int argc, char **argv, const OPTIONS *o); char *opt_progname(const char *argv0); - char *opt_appname(const char *arg0); + char *opt_appname(const char *argv0); char *opt_getprog(void); - char *opt_init(int argc, char **argv, const OPTIONS *o); + void opt_help(const OPTIONS *list); + void opt_begin(void); int opt_next(void); - void opt_help(const OPTIONS *list); - char *opt_arg(void); char *opt_flag(void); + char *opt_arg(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_int_arg(void); 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_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); @@ -184,19 +186,30 @@ the help string: =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 +The opt_init() function takes the I and I arguments given to main() +and a pointer I 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, and returns +The opt_progname() function takes the full pathname C in its I +parameter 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 +the like. + +The opt_appname() function takes in its I parameter +the "application" name (such as the specific command from L and appends it to the program -name. This function should only be called once. Once set, opt_getprog() -also returns the value. +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. -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 +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 OPT_EOF when the end of arguments has been reached. This is typically done like this: prog = opt_init(argc, argv, my_options); @@ -214,13 +227,14 @@ end of arguments has been reached. This is typically done like this: } } -The opt_help() function takes a list of option definitions and prints a -nicely-formatted output. +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<->. -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. +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 @@ -229,7 +243,7 @@ the cipher into I. 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 +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 pointer with the value, or 0 on error. Note that opt_next() @@ -237,11 +251,16 @@ will also do range-check on the argument if the appropriate B field is specified for the option. This means that error-checking inside the C C can often be elided. -The opt_isdir() function returns 1 if the specified I is -a directory, or 0 if not. The opt_format() function takes a string value, +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 file. +The opt_isdir() function returns 1 if the specified I is +a directory, or 0 if not. + The opt_string() function checks that I appears in the NULL-terminated array of strings. It returns 1 if found, or prints a diagnostic and returns 0 if not. @@ -251,10 +270,13 @@ has a text name and an integer. The specified I 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. +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 B array. +at the end of the standard I array. =head2 Common Options diff --git a/test/ecstresstest.c b/test/ecstresstest.c index 5a831e338a..f6adc4235e 100644 --- a/test/ecstresstest.c +++ b/test/ecstresstest.c @@ -127,7 +127,7 @@ int setup_tests(void) { OPTION_CHOICE o; - if (!opt_imax(NUM_REPEATS, &num_repeats)) { + if (!opt_intmax(NUM_REPEATS, &num_repeats)) { TEST_error("Cannot parse " NUM_REPEATS); return 0; } @@ -135,7 +135,7 @@ int setup_tests(void) while ((o = opt_next()) != OPT_EOF) { switch (o) { case OPT_NUM_REPEATS: - if (!opt_imax(opt_arg(), &num_repeats) + if (!opt_intmax(opt_arg(), &num_repeats) || num_repeats < 0) return 0; print_mode = 1; -- 2.34.1