diff --git a/tools/ChangeLog b/tools/ChangeLog index 69af2eb99..154ec55e8 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,6 +1,10 @@ 2004-02-26 Marcus Brinkmann - * README.gpgconf (NAME): Add info about optional arg and arg type 0. + * README.gpgconf: Fix description of arguments. + * gpgconf-comp.c (option_check_validity): Rewritten to properly + support optional arguments in lists. + + * README.gpgconf: Add info about optional arg and arg type 0. * gpgconf-comp.c (gc_component_change_options): Parse list of arg type 0 options. (option_check_validity): Add new argument NEW_VALUE_NR. Perform diff --git a/tools/README.gpgconf b/tools/README.gpgconf index 2f6a2e073..0973939d0 100644 --- a/tools/README.gpgconf +++ b/tools/README.gpgconf @@ -80,17 +80,17 @@ Some fields contain an option argument. The format of an option argument depends on the type of the option and on some flags: The simplest case is that the option does not take an argument at all -(TYPE is 0). Then the option argument is either empty if the option -is not set, or an unsigned number that specifies how often the option -occurs. If the LIST flag is not set, then the only valid number is 1. -Options that don't take an argument never have the "default" flag set. +(TYPE is 0). Then the option argument is an unsigned number that +specifies how often the option occurs. If the LIST flag is not set, +then the only valid number is 1. Options that don't take an argument +never have the "default" or "optional arg" flag set. If the option takes a number argument (ALT-TYPE is 2 or 3), and it can only occur once (LIST flag is not set), then the option argument is -either empty if the option is not set, or it is a number. A number is -a string that begins with an optional minus character, followed by one -or more digits. The number must fit into an integer variable -(unsigned or signed, depending on ALT-TYPE). +either empty (only allowed if the argument is optional), or it is a +number. A number is a string that begins with an optional minus +character, followed by one or more digits. The number must fit into +an integer variable (unsigned or signed, depending on ALT-TYPE). If the option takes a number argument and it can occur more than once, then the option argument is either empty, or it is a comma-separated @@ -98,19 +98,16 @@ list of numbers as described above. If the option takes a string argument (ALT-TYPE is 1), and it can only occur once (LIST flag is not set) then the option argument is either -empty if the option is not set, or it starts with a double quote -character (") followed by a percent-escaped string that is the -argument value. Note that there is only a leading double quote +empty (only allowed if the argument is optional), or it starts with a +double quote character (") followed by a percent-escaped string that +is the argument value. Note that there is only a leading double quote character, no trailing one. The double quote character is only needed to be able to differentiate between no value and the empty string as value. -If the option takes a string argument and it can occur more than once, -then the option argument is either empty or it starts with a double -quote character (") followed by a comma-separated list of -percent-escaped strings. Obviously any commas in the individual -strings must be percent-escaped. - +If the option takes a number argument and it can occur more than once, +then the option argument is either empty, or it is a comma-separated +list of string arguments as described above. FIXME: Document the active language and active character set. Allow to change it via the command line? diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index dc8de903c..524f2170d 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -1223,6 +1223,8 @@ static void option_check_validity (gc_option_t *option, unsigned long flags, char *new_value, unsigned long *new_value_nr) { + char *arg; + if (option->new_flags || option->new_value) gc_error (1, 0, "option %s already changed", option->name); @@ -1231,101 +1233,89 @@ option_check_validity (gc_option_t *option, unsigned long flags, if (*new_value) gc_error (1, 0, "argument %s provided for deleted option %s", new_value, option->name); + + return; } - else + + /* GC_ARG_TYPE_NONE options have special list treatment. */ + if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE) { - /* This is even correct for GC_ARG_TYPE_NONE options, for which - GC_OPT_FLAG_ARG_OPT is never set. */ - if (!(option->flags & GC_OPT_FLAG_ARG_OPT) && (*new_value == '\0')) - gc_error (1, 0, "no argument for option %s", option->name); + char *tail; - if (*new_value) + errno = 0; + *new_value_nr = strtoul (new_value, &tail, 0); + + if (errno) + gc_error (1, errno, "invalid argument for option %s", + option->name); + if (*tail) + gc_error (1, 0, "garbage after argument for option %s", + option->name); + + if (!(option->flags & GC_OPT_FLAG_LIST)) { - if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE) - { - char *tail; - - errno = 0; - *new_value_nr = strtoul (new_value, &tail, 0); - - if (errno) - gc_error (1, errno, "invalid argument for option %s", - option->name); - if (*tail) - gc_error (1, 0, "garbage after argument for option %s", - option->name); - - if (!(option->flags & GC_OPT_FLAG_LIST)) - { - if (*new_value_nr != 1) - gc_error (1, 0, "argument for non-list option %s of type 0 " - "(none) must be 1", option->name); - } - else - { - if (*new_value_nr == 0) - gc_error (1, 0, "argument for option %s of type 0 (none) " - "must be positive", option->name); - } - } - else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_STRING) - { - if (*new_value != '"') - gc_error (1, 0, "string argument for option %s must begin " - "with a quote (\") character", option->name); - } - else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_INT32) - { - char *tail = new_value; - - while (*tail) - { - errno = 0; - (void) strtol (new_value, &tail, 0); - - if (errno) - gc_error (1, errno, "invalid argument for option %s", - option->name); - if (*tail == ',') - { - if (!(option->flags & GC_OPT_FLAG_LIST)) - gc_error (1, 0, "list found for non-list option %s", - option->name); - tail++; - } - else if (*tail) - gc_error (1, 0, "garbage after argument for option %s", - option->name); - } - } - else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_UINT32) - { - char *tail = new_value; - - while (*tail) - { - errno = 0; - (void) strtoul (new_value, &tail, 0); - - if (errno) - gc_error (1, errno, "invalid argument for option %s", - option->name); - if (*tail == ',') - { - if (!(option->flags & GC_OPT_FLAG_LIST)) - gc_error (1, 0, "list found for non-list option %s", - option->name); - tail++; - } - else if (*tail) - gc_error (1, 0, "garbage after argument for option %s", - option->name); - } - } - else - assert (!"Unexpected argument type"); + if (*new_value_nr != 1) + gc_error (1, 0, "argument for non-list option %s of type 0 " + "(none) must be 1", option->name); } + else + { + if (*new_value_nr == 0) + gc_error (1, 0, "argument for option %s of type 0 (none) " + "must be positive", option->name); + } + + return; } + + arg = new_value; + do + { + if (*arg == '\0' || *arg == ',') + { + if (!(option->flags & GC_OPT_FLAG_ARG_OPT)) + gc_error (1, 0, "argument required for option %s", option->name); + + if (*arg == ',' && !(option->flags & GC_OPT_FLAG_LIST)) + gc_error (1, 0, "list found for non-list option %s", option->name); + } + else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_STRING) + { + if (*arg != '"') + gc_error (1, 0, "string argument for option %s must begin " + "with a quote (\") character", option->name); + } + else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_INT32) + { + errno = 0; + (void) strtol (arg, &arg, 0); + + if (errno) + gc_error (1, errno, "invalid argument for option %s", + option->name); + + if (*arg != '\0' && *arg != ',') + gc_error (1, 0, "garbage after argument for option %s", + option->name); + } + else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_INT32) + { + errno = 0; + (void) strtoul (arg, &arg, 0); + + if (errno) + gc_error (1, errno, "invalid argument for option %s", + option->name); + + if (*arg != '\0' && *arg != ',') + gc_error (1, 0, "garbage after argument for option %s", + option->name); + } + arg = strchr (arg, ','); + if (arg) + arg++; + } + while (arg && *arg); } @@ -1377,6 +1367,7 @@ change_options_program (gc_component_t component, gc_backend_t backend, xfree (orig_filename); orig_filename = NULL; } + /* We now initialize the return strings, so the caller can do the cleanup for us. */ *src_filenamep = src_filename;