From 54d5446797fc4c1e40e36a74fa7fa12c87ba5ab9 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann Date: Tue, 24 Feb 2004 14:31:59 +0000 Subject: [PATCH] 2004-02-24 Marcus Brinkmann * README.gpgconf: Revert last change. Add new flags "default", "default desc" and "no arg desc". Add new field ARGDEF. Add new field FLAG to backend interface. * gpgconf-comp.c (struct gc_option): Make flags of type unsigned long. (gc_component_list_options): Adjust type for flags. Add default argument field. (retrieve_options_from_program): Use "1" as value for non-option arguments, not "Y". (gc_component_change_options): Read in flags from input. --- tools/ChangeLog | 13 ++++ tools/README.gpgconf | 140 ++++++++++++++++++++++++++++------ tools/gpgconf-comp.c | 173 ++++++++++++++++++++++++++++++++++--------- 3 files changed, 266 insertions(+), 60 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index 1871f8b15..efb3794b9 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,16 @@ +2004-02-24 Marcus Brinkmann + + * README.gpgconf: Revert last change. Add new flags "default", + "default desc" and "no arg desc". Add new field ARGDEF. Add new + field FLAG to backend interface. + * gpgconf-comp.c (struct gc_option): Make flags of type unsigned + long. + (gc_component_list_options): Adjust type for flags. + Add default argument field. + (retrieve_options_from_program): Use "1" as value for non-option + arguments, not "Y". + (gc_component_change_options): Read in flags from input. + 2004-02-23 Marcus Brinkmann * README.gpgconf: Change meaning of type 0 options value if it is diff --git a/tools/README.gpgconf b/tools/README.gpgconf index 848e1c59f..84fed518b 100644 --- a/tools/README.gpgconf +++ b/tools/README.gpgconf @@ -82,9 +82,8 @@ 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 numbers are -0 and 1. 0 often has a special meaning in this context as it actually -negates setting the option one or more times. +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. 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 @@ -175,7 +174,7 @@ the next group and so on. The format of each line is: -NAME:FLAGS:LEVEL:DESCRIPTION:TYPE:ALT-TYPE:ARGNAME:DEFAULT:VALUE +NAME:FLAGS:LEVEL:DESCRIPTION:TYPE:ALT-TYPE:ARGNAME:DEFAULT:ARGDEF:VALUE NAME @@ -189,13 +188,19 @@ FLAGS The flags field contains an unsigned number. Its value is the OR-wise combination of the following flag values: - 1 group If this flag is set, this is a line describing + 1 group If this flag is set, this is a line describing a group and not an option. - O 2 optional arg If this flag is set, the argument is optional. - O 4 list If this flag is set, the option can be given + O 2 optional arg If this flag is set, the argument is optional. + O 4 list If this flag is set, the option can be given multiple times. - O 8 runtime If this flag is set, the option can be changed + O 8 runtime If this flag is set, the option can be changed at runtime. + O 16 default If this flag is set, a default value is available. + O 32 default desc If this flag is set, a (runtime) default is available. + This and the 'default' flag are mutually exclusive. + O 64 no arg desc If this flag is set, and the 'optional arg' flag + is set, then the option has a special meaning if no + argument is given. Flags marked with a 'O' are only defined for options (ie, if the GROUP flag is not set). @@ -230,13 +235,16 @@ This field is only defined for options. It contains an unsigned number that specifies the type of the option's argument, if any. The following types are defined: - 0 none No argument allowed. - 1 string An unformatted string. - 2 int32 A signed integer number. - 3 uint32 An unsigned integer number. - 4 pathname A string that describes the pathname of a file. + Basic types + 0 none No argument allowed. + 1 string An unformatted string. + 2 int32 A signed integer number. + 3 uint32 An unsigned integer number. + + Complex types + 32 pathname A string that describes the pathname of a file. The file does not necessarily need to exist. - 5 ldap server A string that describes an LDAP server in the format + 33 ldap server A string that describes an LDAP server in the format HOSTNAME:PORT:USERNAME:PASSWORD:BASE_DN. More types will be added in the future. Please see the ALT-TYPE field @@ -244,12 +252,14 @@ for information on how to cope with unknown types. ALT-TYPE -This field is identical to TYPE, except that only the types 0 to 3 are -allowed. The GUI is expected to present the user the option in the -format specified by TYPE. But if the argument type TYPE is not +This field is identical to TYPE, except that only the types 0 to 31 +are allowed. The GUI is expected to present the user the option in +the format specified by TYPE. But if the argument type TYPE is not supported by the GUI, it can still display the option in the more -generic basic type ALT-TYPE. The GUI must support the basic types 0 -to 3 to be able to display all options. +generic basic type ALT-TYPE. The GUI must support all the defined +basic types to be able to display all options. More basic types may +be added in future versions. If the GUI encounters a basic type it +doesn't support, it should report an error and abort the operation. ARGNAME @@ -267,6 +277,18 @@ value specifies the default value for this option. Note that this field is also meaningful if the option itself does not take a real argument. +ARGDEF + +This field is defined only for options for which the "optional arg" +flag is set. If the "no arg desc" flag is not set, its format is that +of an option argument (see section Format Conventions for details). +If the default value is empty, then no default is known. Otherwise, +the value specifies the default value for this option. If the "no arg +desc" flag is set, the field is either empty or contains a description +of the effect of this option if no argument is given. Note that this +field is also meaningful if the option itself does not take a real +argument. + VALUE This field is defined only for options. Its format is that of an @@ -283,18 +305,35 @@ CHANGING OPTIONS To change the options for a component, you must provide them in the following format: -NAME:NEW-VALUE +NAME:FLAGS:NEW-VALUE NAME This is the name of the option to change. +FLAGS + +The flags field contains an unsigned number. Its value is the +OR-wise combination of the following flag values: + + 16 default If this flag is set, the option is deleted and the + default value is used instead (if applicable). + NEW-VALUE -The new value for the option. The format is that of an option -argument. If it is empty (or the field is omitted), the option will -be deleted, so that the default value is used. Otherwise, the option -will be set to the specified value. +The new value for the option. This field is only defined if the +"default" flag is not set. The format is that of an option argument. +If it is empty (or the field is omitted), the default argument is used +(only allowed if the argument is optional for this option). +Otherwise, the option will be set to the specified value. + + +Example: +To set the option force, which is of basic type 0 (none). +$ echo 'force:0:1' | gpgconf --change-options dirmngr +To delete the option force: +$ echo 'force:16:0' | gpgconf --change-options dirmngr + Option --runtime ---------------- @@ -316,9 +355,62 @@ List the location of the configuration file, and all default values of all options. The location of the configuration file must be an absolute pathname. +The format of each line is: + +NAME:FLAGS:DEFAULT:ARGDEF + +NAME + +This field contains a name tag for the group or option. The name tag +is used to specify the group or option in all communication with +GPGConf. The name tag is to be used verbatim. It is not in any +escaped format. + +FLAGS + +The flags field contains an unsigned number. Its value is the +OR-wise combination of the following flag values: + + 16 default If this flag is set, a default value is available. + 32 default desc If this flag is set, a (runtime) default is available. + This and the "default" flag are mutually exclusive. + 64 no arg desc If this flag is set, and the "optional arg" flag + is set, then the option has a special meaning if no + argument is given. + +DEFAULT + +This field is defined only for options. Its format is that of an +option argument (see section Format Conventions for details). If the +default value is empty, then no default is known. Otherwise, the +value specifies the default value for this option. Note that this +field is also meaningful if the option itself does not take a real +argument. + +ARGDEF + +This field is defined only for options for which the "optional arg" +flag is set. If the "no arg desc" flag is not set, its format is that +of an option argument (see section Format Conventions for details). +If the default value is empty, then no default is known. Otherwise, +the value specifies the default value for this option. If the "no arg +desc" flag is set, the field is either empty or contains a description +of the effect of this option if no argument is given. Note that this +field is also meaningful if the option itself does not take a real +argument. + + Example: $ dirmngr --gpgconf-list gpgconf-config-file:/mnt/marcus/.gnupg/dirmngr.conf ldapservers-file:/mnt/marcus/.gnupg/dirmngr_ldapservers.conf add-servers:0 max-replies:10 + + +TODO +---- + +* Extend the backend interface to include gettext domain and +description, if available, to avoid repeating this information in +gpgconf. diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 2065a6587..4dc2fbbe8 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -176,20 +176,21 @@ typedef enum /* An unsigned integer argument. */ GC_ARG_TYPE_UINT32 = 3, + /* ADD NEW BASIC TYPE ENTRIES HERE. */ /* Complex argument types. */ /* A complete pathname. */ - GC_ARG_TYPE_PATHNAME = 4, + GC_ARG_TYPE_PATHNAME = 32, /* An LDAP server in the format HOSTNAME:PORT:USERNAME:PASSWORD:BASE_DN. */ - GC_ARG_TYPE_LDAP_SERVER = 5, + GC_ARG_TYPE_LDAP_SERVER = 33, /* A 40 character fingerprint. */ - GC_ARG_TYPE_KEY_FPR = 6, + GC_ARG_TYPE_KEY_FPR = 34, - /* ADD NEW ENTRIES HERE. */ + /* ADD NEW COMPLEX TYPE ENTRIES HERE. */ /* The number of the above entries. */ GC_ARG_TYPE_NR @@ -214,6 +215,22 @@ static struct { GC_ARG_TYPE_INT32, "int32" }, { GC_ARG_TYPE_UINT32, "uint32" }, + /* Reserved basic type entries for future extension. */ + { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, + { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, + { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, + { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, + { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, + { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, + { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, + { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, + { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, + { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, + { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, + { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, + { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, + { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, + /* The complex argument types have a basic type as fallback. */ { GC_ARG_TYPE_STRING, "pathname" }, { GC_ARG_TYPE_STRING, "ldap server" }, @@ -266,21 +283,32 @@ static struct /* Option flags. YOU MUST NOT CHANGE THE NUMBERS OF THE EXISTING FLAGS, AS THEY ARE PART OF THE EXTERNAL INTERFACE. */ -#define GC_OPT_FLAG_NONE 0 +#define GC_OPT_FLAG_NONE 0UL /* Some entries in the option list are not options, but mark the beginning of a new group of options. These entries have the GROUP flag set. */ -#define GC_OPT_FLAG_GROUP (1 << 0) +#define GC_OPT_FLAG_GROUP (1UL << 0) /* The ARG_OPT flag for an option indicates that the argument is optional. */ -#define GC_OPT_FLAG_ARG_OPT (1 << 1) +#define GC_OPT_FLAG_ARG_OPT (1UL << 1) /* The LIST flag for an option indicates that the option can occur several times. A comma separated list of arguments is used as the argument value. */ -#define GC_OPT_FLAG_LIST (1 << 2) +#define GC_OPT_FLAG_LIST (1UL << 2) /* The RUNTIME flag for an option indicates that the option can be changed at runtime. */ -#define GC_OPT_FLAG_RUNTIME (1 << 3) +#define GC_OPT_FLAG_RUNTIME (1UL << 3) + +/* The following flags are incorporated from the backend. */ +/* The DEFAULT flag for an option indicates that the option has a + default value. */ +#define GC_OPT_FLAG_DEFAULT (1UL << 4) +/* The DEF_DESC flag for an option indicates that the option has a + default, which is described by the value of the default field. */ +#define GC_OPT_FLAG_DEF_DESC (1UL << 5) +/* The NO_ARG_DESC flag for an option indicates that the argument has + a default, which is described by the value of the ARGDEF field. */ +#define GC_OPT_FLAG_NO_ARG_DESC (1UL << 6) /* A human-readable description for each flag. */ static struct @@ -311,7 +339,7 @@ struct gc_option group marker, not an option, and only the fields LEVEL, DESC_DOMAIN and DESC are valid. In all other cases, this entry describes a new option and all fields are valid. */ - unsigned int flags; + unsigned long flags; /* The expert level. This field is valid for options and groups. A group has the expert level of the lowest-level option in the @@ -350,6 +378,11 @@ struct gc_option available, and otherwise a quoted string. */ char *default_value; + /* The default argument is only valid if the "optional arg" flag is + set, and specifies the default argument (value) that is used if + the argument is omitted. */ + char *default_arg; + /* The current value of this option. */ char *value; @@ -744,7 +777,7 @@ gc_component_list_options (int component, FILE *out) fprintf (out, "%s", option->name); /* The flags field. */ - fprintf (out, ":%u", option->flags); + fprintf (out, ":%lu", option->flags); if (opt.verbose) { putc (' ', out); @@ -753,9 +786,9 @@ gc_component_list_options (int component, FILE *out) fprintf (out, "none"); else { - unsigned int flags = option->flags; - unsigned int flag = 0; - unsigned int first = 1; + unsigned long flags = option->flags; + unsigned long flag = 0; + unsigned long first = 1; while (flags) { @@ -800,6 +833,9 @@ gc_component_list_options (int component, FILE *out) /* The default value field. */ fprintf (out, ":%s", option->default_value ? option->default_value : ""); + /* The default argument field. */ + fprintf (out, ":%s", option->default_arg ? option->default_arg : ""); + /* The value field. */ fprintf (out, ":%s", option->value ? option->value : ""); @@ -884,26 +920,53 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend) while ((length = getline (&line, &line_len, config)) > 0) { gc_option_t *option; - char *value; - + char *linep; + unsigned long flags = 0; + char *default_value = NULL; + /* Strip newline and carriage return, if present. */ while (length > 0 && (line[length - 1] == '\n' || line[length - 1] == '\r')) line[--length] = '\0'; + linep = strchr (line, ':'); + if (linep) + *(linep++) = '\0'; + + /* Extract additional flags. Default to none. */ + if (linep) + { + char *end; + char *tail; + + end = strchr (linep, ':'); + if (end) + *(end++) = '\0'; + + errno = 0; + flags = strtoul (linep, &tail, 0); + if (errno) + gc_error (1, errno, "malformed flags in option %s from %s", line, cmd_line); + if (!(*tail == '\0' || *tail == ':' || *tail == ' ')) + gc_error (1, 0, "garbage after flags in option %s from %s", line, cmd_line); + + linep = end; + } + /* Extract default value, if present. Default to empty if not. */ - value = strchr (line, ':'); - if (!value) - value = ""; - else + if (linep) { char *end; - *(value++) = '\0'; - end = strchr (value, ':'); + end = strchr (linep, ':'); if (end) - *end = '\0'; + *(end++) = '\0'; + + if (flags & GC_OPT_FLAG_DEFAULT) + default_value = linep; + + linep = end; } /* Look up the option in the component and install the @@ -915,8 +978,10 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend) gc_error (1, errno, "option %s returned twice from %s", line, cmd_line); option->active = 1; - if (*value) - option->default_value = xstrdup (value); + + option->flags |= flags; + if (default_value && *default_value) + option->default_value = xstrdup (default_value); } } if (ferror (config)) @@ -981,7 +1046,7 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend) gc_error (0, 0, "warning: ignoring argument %s for option %s", value, name); - opt_value = xstrdup ("Y"); + opt_value = xstrdup ("1"); } else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_STRING) @@ -1011,6 +1076,8 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend) == GC_ARG_TYPE_STRING) opt_val++; + /* FIXME. For type none arguments, this is + wrong. */ option->value = xasprintf ("%s,%s", option->value, opt_val); xfree (opt_value); @@ -1411,32 +1478,66 @@ gc_component_change_options (int component, FILE *in) while ((length = getline (&line, &line_len, in)) > 0) { - char *value; + char *linep; + unsigned long flags = 0; + char *new_value = NULL; /* Strip newline and carriage return, if present. */ while (length > 0 && (line[length - 1] == '\n' || line[length - 1] == '\r')) line[--length] = '\0'; - value = strchr (line, ':'); - if (!value) - value = ""; - else + linep = strchr (line, ':'); + if (linep) + *(linep++) = '\0'; + + /* Extract additional flags. Default to none. */ + if (linep) + { + char *end; + char *tail; + + end = strchr (linep, ':'); + if (end) + *(end++) = '\0'; + + errno = 0; + flags = strtoul (linep, &tail, 0); + if (errno) + gc_error (1, errno, "malformed flags in option %s", line); + if (!(*tail == '\0' || *tail == ':' || *tail == ' ')) + gc_error (1, 0, "garbage after flags in option %s", line); + + linep = end; + } + + /* Extract default value, if present. Default to empty if + not. */ + if (linep) { char *end; - *(value++) = '\0'; - end = strchr (value, ':'); + end = strchr (linep, ':'); if (end) - *end = '\0'; + *(end++) = '\0'; + + if (!(flags & GC_OPT_FLAG_DEFAULT)) + new_value = linep; + + linep = end; } option = find_option (component, line, GC_BACKEND_ANY); if (!option) gc_error (1, 0, "unknown option %s", line); - option_check_validity (option, value); - option->new_value = xstrdup (value); + /* FIXME: This is not correct, as it ignores the optional arg + case. */ + if (flags & GC_OPT_FLAG_DEFAULT) + new_value = ""; + + option_check_validity (option, new_value); + option->new_value = xstrdup (new_value); } /* Now that we have collected and locally verified the changes,