2004-02-24 Marcus Brinkmann <marcus@g10code.de>
authorMarcus Brinkmann <mb@g10code.com>
Tue, 24 Feb 2004 14:31:59 +0000 (14:31 +0000)
committerMarcus Brinkmann <mb@g10code.com>
Tue, 24 Feb 2004 14:31:59 +0000 (14:31 +0000)
* 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
tools/README.gpgconf
tools/gpgconf-comp.c

index 1871f8b..efb3794 100644 (file)
@@ -1,3 +1,16 @@
+2004-02-24  Marcus Brinkmann  <marcus@g10code.de>
+
+       * 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  <marcus@g10code.de>
 
        * README.gpgconf: Change meaning of type 0 options value if it is
index 848e1c5..84fed51 100644 (file)
@@ -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.
index 2065a65..4dc2fbb 100644 (file)
@@ -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,