aboutsummaryrefslogtreecommitdiffstats
path: root/tools/gpgconf-comp.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/gpgconf-comp.c')
-rw-r--r--tools/gpgconf-comp.c2237
1 files changed, 656 insertions, 1581 deletions
diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c
index ddedd6a21..f6d9c10b1 100644
--- a/tools/gpgconf-comp.c
+++ b/tools/gpgconf-comp.c
@@ -1,7 +1,7 @@
/* gpgconf-comp.c - Configuration utility for GnuPG.
* Copyright (C) 2004, 2007-2011 Free Software Foundation, Inc.
* Copyright (C) 2016 Werner Koch
- * Copyright (C) 2030 g10 Code GmbH
+ * Copyright (C) 2020 g10 Code GmbH
*
* This file is part of GnuPG.
*
@@ -43,7 +43,6 @@
# include <grp.h>
#endif
-/* For log_logv(), asctimestamp(), gnupg_get_time (). */
#include "../common/util.h"
#include "../common/i18n.h"
#include "../common/exechelp.h"
@@ -62,13 +61,6 @@
#define GPGNAME GPG_NAME
#endif
-
-/* TODO:
- Components: Add more components and their options.
- Robustness: Do more validation. Call programs to do validation for us.
- Add options to change backend binary path.
- Extract binary path for some backends from gpgsm/gpg config.
-*/
#if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ))
@@ -110,90 +102,19 @@ static void gpg_agent_runtime_change (int killflag);
static void scdaemon_runtime_change (int killflag);
static void dirmngr_runtime_change (int killflag);
-/* Backend configuration. Backends are used to decide how the default
- and current value of an option can be determined, and how the
- option can be changed. To every option in every component belongs
- exactly one backend that controls and determines the option. Some
- backends are programs from the GPG system. Others might be
- implemented by GPGConf itself. If you change this enum, don't
- forget to update GC_BACKEND below. */
-typedef enum
- {
- /* Any backend, used for find_option (). */
- GC_BACKEND_ANY,
-
- /* The Gnu Privacy Guard. */
- GC_BACKEND_GPG,
-
- /* The Gnu Privacy Guard for S/MIME. */
- GC_BACKEND_GPGSM,
-
- /* The GPG Agent. */
- GC_BACKEND_GPG_AGENT,
-
- /* The GnuPG SCDaemon. */
- GC_BACKEND_SCDAEMON,
-
- /* The GnuPG directory manager. */
- GC_BACKEND_DIRMNGR,
-
- /* The LDAP server list file for the director manager. */
- GC_BACKEND_DIRMNGR_LDAP_SERVER_LIST,
-
- /* The Pinentry (not a part of GnuPG, proper). */
- GC_BACKEND_PINENTRY,
-
- /* The number of the above entries. */
- GC_BACKEND_NR
- } gc_backend_t;
-
-
-/* To be able to implement generic algorithms for the various
- backends, we collect all information about them in this struct. */
-static const struct
-{
- /* The name of the backend. */
- const char *name;
-
- /* The name of the program that acts as the backend. Some backends
- don't have an associated program, but are implemented directly by
- GPGConf. In this case, PROGRAM is NULL. */
- char *program;
- /* The module name (GNUPG_MODULE_NAME_foo) as defined by
- ../common/util.h. This value is used to get the actual installed
- path of the program. 0 is used if no backend program is
- available. */
- char module_name;
- /* The runtime change callback. If KILLFLAG is true the component
- is killed and not just reloaded. */
- void (*runtime_change) (int killflag);
-
- /* The name for the configuration filename of this backend. */
- const char *option_config_filename;
+
+/* STRING_ARRAY is a malloced array with malloced strings. It is used
+ * a space to store strings so that other objects may point to these
+ * strings. It shall never be shrinked or any items changes.
+ * STRING_ARRAY itself may be reallocated to increase the size of the
+ * table. STRING_ARRAY_USED is the number of items currently used,
+ * STRING_ARRAY_SIZE is the number of calloced slots. */
+static char **string_array;
+static size_t string_array_used;
+static size_t string_array_size;
- /* If this is a file backend rather than a program backend, then
- this is the name of the option associated with the file. */
- const char *option_name;
-} gc_backend[GC_BACKEND_NR] =
- {
- { NULL }, /* GC_BACKEND_ANY dummy entry. */
- { GPG_DISP_NAME, GPGNAME, GNUPG_MODULE_NAME_GPG,
- NULL, GPG_NAME ".conf" },
- { GPGSM_DISP_NAME, GPGSM_NAME, GNUPG_MODULE_NAME_GPGSM,
- NULL, GPGSM_NAME ".conf" },
- { GPG_AGENT_DISP_NAME, GPG_AGENT_NAME, GNUPG_MODULE_NAME_AGENT,
- gpg_agent_runtime_change, GPG_AGENT_NAME ".conf" },
- { SCDAEMON_DISP_NAME, SCDAEMON_NAME, GNUPG_MODULE_NAME_SCDAEMON,
- scdaemon_runtime_change, SCDAEMON_NAME ".conf" },
- { DIRMNGR_DISP_NAME, DIRMNGR_NAME, GNUPG_MODULE_NAME_DIRMNGR,
- dirmngr_runtime_change, DIRMNGR_NAME ".conf" },
- { DIRMNGR_DISP_NAME " LDAP Server List", NULL, 0,
- NULL, "ldapserverlist-file", "LDAP Server" },
- { "Pinentry", "pinentry", GNUPG_MODULE_NAME_PINENTRY,
- NULL, "pinentry.conf" },
- };
/* Option configuration. */
@@ -339,15 +260,16 @@ static const struct
};
-/* Option flags. The flags which are used by the backends are defined
+/* Option flags. The flags which are used by the components are defined
by gc-opt-flags.h, included above.
YOU MUST NOT CHANGE THE NUMBERS OF THE EXISTING FLAGS, AS THEY ARE
PART OF THE EXTERNAL INTERFACE. */
-/* 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. */
+/* Some entries in the emitted option list are not options, but mark
+ the beginning of a new group of options. These entries have the
+ GROUP flag set. Note that this is internally also known as a
+ header line. */
#define GC_OPT_FLAG_GROUP (1UL << 0)
/* The ARG_OPT flag for an option indicates that the argument is
optional. This is never set for GC_ARG_TYPE_NONE options. */
@@ -375,715 +297,339 @@ static const struct
};
-/* To each option, or group marker, the information in the GC_OPTION
- struct is provided. If you change this, don't forget to update the
- option list of each component. */
-struct gc_option
+
+/* Each option we want to support in gpgconf has the needed
+ * information in a static list per componenet. This struct describes
+ * the info for a single option. */
+struct known_option_s
{
/* If this is NULL, then this is a terminator in an array of unknown
- length. Otherwise, if this entry is a group marker (see FLAGS),
- then this is the name of the group described by this entry.
- Otherwise it is the name of the option described by this
- entry. The name must not contain a colon. */
+ * length. Otherwise it is the name of the option described by this
+ * entry. The name must not contain a colon. */
const char *name;
- /* The option flags. If the GROUP flag is set, then this entry is a
- 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. */
+ /* The option 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
- group. */
+ /* The expert level. */
gc_expert_level_t level;
- /* A gettext domain in which the following description can be found.
- If this is NULL, then DESC is not translated. Valid for groups
- and options.
-
- Note that we try to keep the description of groups within the
- gnupg domain.
+ /* The complex type of the option argument; the default of 0 is used
+ * for a standard type as returned by --dump-option-table. */
+ gc_arg_type_t arg_type;
+};
+typedef struct known_option_s known_option_t;
- IMPORTANT: If you add a new domain please make sure to add a code
- set switching call to the function my_dgettext further below. */
- const char *desc_domain;
- /* A gettext description for this group or option. If it starts
- with a '|', then the string up to the next '|' describes the
- argument, and the description follows the second '|'.
+/* The known options of the GC_COMPONENT_GPG_AGENT component. */
+static known_option_t known_options_gpg_agent[] =
+ {
+ { "verbose", GC_OPT_FLAG_LIST|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC },
+ { "quiet", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC },
+ { "disable-scdaemon", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED },
+ { "enable-ssh-support", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC },
+ { "ssh-fingerprint-digest", GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT },
+ { "enable-putty-support", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC },
+ { "enable-extended-key-format", GC_OPT_FLAG_RUNTIME, GC_LEVEL_INVISIBLE },
+ { "debug-level", GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED},
+ { "log-file", GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED,
+ /**/ GC_ARG_TYPE_FILENAME },
+ { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE },
+
+ { "default-cache-ttl", GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC },
+ { "default-cache-ttl-ssh", GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED },
+ { "max-cache-ttl", GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT },
+ { "max-cache-ttl-ssh", GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT },
+ { "ignore-cache-for-signing", GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC },
+ { "allow-emacs-pinentry", GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED },
+ { "grab", GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT },
+ { "no-allow-external-cache", GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC },
+ { "no-allow-mark-trusted", GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED },
+ { "no-allow-loopback-pinentry", GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT },
+
+ { "enforce-passphrase-constraints", GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT },
+ { "min-passphrase-len", GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED },
+ { "min-passphrase-nonalpha", GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT },
+ { "check-passphrase-pattern", GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT,
+ /**/ GC_ARG_TYPE_FILENAME },
+ { "max-passphrase-days", GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT },
+ { "enable-passphrase-history", GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT },
+ { "pinentry-timeout", GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED },
+
+ { NULL }
+ };
- In general enclosing these description in N_() is not required
- because the description should be identical to the one in the
- help menu of the respective program. */
- const char *desc;
- /* The following fields are only valid for options. */
+/* The known options of the GC_COMPONENT_SCDAEMON component. */
+static known_option_t known_options_scdaemon[] =
+ {
+ { "verbose", GC_OPT_FLAG_LIST|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC },
+ { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC },
+ { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE },
+ { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
+ GC_ARG_TYPE_FILENAME },
+ { "reader-port", GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC },
+ { "ctapi-driver", GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED },
+ { "pcsc-driver", GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED },
+ { "disable-ccid", GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT },
+ { "disable-pinpad", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC },
+ { "enable-pinpad-varlen", GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC },
+ { "card-timeout", GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC },
+ { "application-priority", GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED },
+ { "debug-level", GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED},
+ { "log-file", GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED,
+ GC_ARG_TYPE_FILENAME },
+ { "deny-admin", GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC },
+
+ { NULL }
+ };
- /* The type of the option argument. */
- gc_arg_type_t arg_type;
- /* The backend that implements this option. */
- gc_backend_t backend;
+/* The known options of the GC_COMPONENT_GPG component. */
+static known_option_t known_options_gpg[] =
+ {
+ { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC },
+ { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC },
+ { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE },
+ { "default-key", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC },
+ { "encrypt-to", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC },
+ { "group", GC_OPT_FLAG_LIST, GC_LEVEL_ADVANCED,
+ GC_ARG_TYPE_ALIAS_LIST},
+ { "options", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
+ GC_ARG_TYPE_FILENAME },
+ { "compliance", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT },
+ { "default-new-key-algo", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE },
+ { "trust-model", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE },
+ { "debug-level", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED },
+ { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
+ GC_ARG_TYPE_FILENAME },
+ { "auto-key-locate", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED },
+ { "auto-key-retrieve", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT },
+ { "no-auto-key-retrieve", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE },
+ { "disable-dirmngr", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT },
+ { "max-cert-depth", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE },
+ { "completes-needed", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE },
+ { "marginals-needed", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE },
+
+ /* The next is a pseudo option which we read via --gpgconf-list */
+ { "default_pubkey_algo",
+ (GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_NO_CHANGE), GC_LEVEL_INVISIBLE },
- /* The following fields are set to NULL at startup (because all
- option's are declared as static variables). They are at the end
- of the list so that they can be omitted from the option
- declarations. */
+ { NULL }
+ };
- struct {
- unsigned int ignore:1; /* The ARGPARSE_ATTR_IGNORE. */
- unsigned int force:1; /* The ARGPARSE_ATTR_FORCE. */
- } attr;
- /* This is true if the option is supported by this version of the
- backend. */
- int active;
+/* The known options of the GC_COMPONENT_GPGSM component. */
+static known_option_t known_options_gpgsm[] =
+ {
+ { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC },
+ { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC },
+ { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE },
+ { "default-key", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC },
+ { "encrypt-to", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC },
+ { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
+ GC_ARG_TYPE_FILENAME },
+ { "disable-dirmngr", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT },
+ { "p12-charset", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED },
+ { "keyserver", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC,
+ GC_ARG_TYPE_LDAP_SERVER },
+ { "compliance", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT },
+ { "debug-level", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED },
+ { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
+ GC_ARG_TYPE_FILENAME },
+ { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE },
+ { "disable-crl-checks", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC },
+ { "enable-crl-checks", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE },
+ { "enable-ocsp", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED },
+ { "include-certs", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT },
+ { "disable-policy-checks", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED },
+ { "auto-issuer-key-retrieve", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC },
+ { "cipher-algo", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED },
+ { "disable-trusted-cert-crl-check", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT },
+
+ /* Pseudo option follows. */
+ { "default_pubkey_algo",
+ (GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_NO_CHANGE), GC_LEVEL_INVISIBLE },
- /* The default value for this option. This is NULL if the option is
- not present in the backend, the empty string if no default is
- available, and otherwise a quoted string. */
- char *default_value;
+ { NULL }
+ };
- /* 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;
+/* The known options of the GC_COMPONENT_DIRMNGR component. */
+static known_option_t known_options_dirmngr[] =
+ {
+ { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC },
+ { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC },
+ { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE },
+ { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
+ GC_ARG_TYPE_FILENAME },
+ { "resolver-timeout", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE },
+ { "nameserver", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE },
+ { "debug-level", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED },
+ { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
+ GC_ARG_TYPE_FILENAME },
+ { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE },
+ { "batch", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC },
+ { "force", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC },
+ { "use-tor", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC },
+ { "keyserver", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC },
+ { "disable-http", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED },
+ { "ignore-http-dp", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED },
+ { "http-proxy", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED },
+ { "honor-http-proxy", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED },
+ { "disable-ldap", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED },
+ { "ignore-ldap-dp", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED },
+ { "ldap-proxy", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC },
+ { "only-ldap-proxy", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED },
+ { "add-servers", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED },
+ { "ldaptimeout", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC },
+ { "max-replies", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC },
+ { "allow-ocsp", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC },
+ { "ocsp-responder", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED },
+ { "ocsp-signer", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED },
+ { "allow-version-check", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC },
+ { "ignore-ocsp-service-url", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED },
+
+
+ { NULL }
+ };
- /* The new flags for this option. The only defined flag is actually
- GC_OPT_FLAG_DEFAULT, and it means that the option should be
- deleted. In this case, NEW_VALUE is NULL. */
- unsigned long new_flags;
- /* The new value of this option. */
- char *new_value;
-};
-typedef struct gc_option gc_option_t;
+/* The known options of the GC_COMPONENT_PINENTRY component. */
+static known_option_t known_options_pinentry[] =
+ {
+ { NULL }
+ };
-/* Use this macro to terminate an option list. */
-#define GC_OPTION_NULL { NULL }
-#ifndef BUILD_WITH_AGENT
-#define gc_options_gpg_agent NULL
-#else
-/* The options of the GC_COMPONENT_GPG_AGENT component. */
-static gc_option_t gc_options_gpg_agent[] =
- {
- /* The configuration file to which we write the changes. */
- { GPGCONF_NAME"-" GPG_AGENT_NAME ".conf",
- GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
- NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG_AGENT },
-
- { "Monitor",
- GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
- "gnupg", N_("Options controlling the diagnostic output") },
- { "verbose", GC_OPT_FLAG_LIST|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
- "gnupg", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
- { "quiet", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
- "gnupg", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
- { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
- NULL, NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
-
- { "Configuration",
- GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
- "gnupg", N_("Options controlling the configuration") },
- { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
- "gnupg", NULL,
- GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG_AGENT },
- { "disable-scdaemon", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
- "gnupg", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
- { "enable-ssh-support", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "gnupg", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
- { "ssh-fingerprint-digest",
- GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT,
- "gnupg", NULL,
- GC_ARG_TYPE_STRING, GC_BACKEND_GPG_AGENT },
- { "enable-putty-support", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "gnupg", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
- { "enable-extended-key-format", GC_OPT_FLAG_RUNTIME, GC_LEVEL_INVISIBLE,
- NULL, NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
-
- { "Debug",
- GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
- "gnupg", N_("Options useful for debugging") },
- { "debug-level", GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED,
- "gnupg", NULL,
- GC_ARG_TYPE_STRING, GC_BACKEND_GPG_AGENT },
- { "log-file", GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED,
- "gnupg", NULL,
- GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG_AGENT },
- { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
- NULL, NULL,
- GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
-
- { "Security",
- GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
- "gnupg", N_("Options controlling the security") },
- { "default-cache-ttl", GC_OPT_FLAG_RUNTIME,
- GC_LEVEL_BASIC, "gnupg", NULL,
- GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
- { "default-cache-ttl-ssh", GC_OPT_FLAG_RUNTIME,
- GC_LEVEL_ADVANCED, "gnupg", NULL,
- GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
- { "max-cache-ttl", GC_OPT_FLAG_RUNTIME,
- GC_LEVEL_EXPERT, "gnupg", NULL,
- GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
- { "max-cache-ttl-ssh", GC_OPT_FLAG_RUNTIME,
- GC_LEVEL_EXPERT, "gnupg", NULL,
- GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
- { "ignore-cache-for-signing", GC_OPT_FLAG_RUNTIME,
- GC_LEVEL_BASIC, "gnupg", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
- { "allow-emacs-pinentry", GC_OPT_FLAG_RUNTIME,
- GC_LEVEL_ADVANCED,
- "gnupg", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
- { "grab", GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT,
- "gnupg", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
- { "no-allow-external-cache", GC_OPT_FLAG_RUNTIME,
- GC_LEVEL_BASIC, "gnupg", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
- { "no-allow-mark-trusted", GC_OPT_FLAG_RUNTIME,
- GC_LEVEL_ADVANCED, "gnupg", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
- { "no-allow-loopback-pinentry", GC_OPT_FLAG_RUNTIME,
- GC_LEVEL_EXPERT, "gnupg", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
-
- { "Passphrase policy",
- GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
- "gnupg", N_("Options enforcing a passphrase policy") },
- { "enforce-passphrase-constraints", GC_OPT_FLAG_RUNTIME,
- GC_LEVEL_EXPERT, "gnupg", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
- { "min-passphrase-len", GC_OPT_FLAG_RUNTIME,
- GC_LEVEL_ADVANCED, "gnupg", NULL,
- GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
- { "min-passphrase-nonalpha", GC_OPT_FLAG_RUNTIME,
- GC_LEVEL_EXPERT, "gnupg", NULL,
- GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
- { "check-passphrase-pattern", GC_OPT_FLAG_RUNTIME,
- GC_LEVEL_EXPERT,
- "gnupg", NULL,
- GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG_AGENT },
- { "max-passphrase-days", GC_OPT_FLAG_RUNTIME,
- GC_LEVEL_EXPERT, "gnupg", NULL,
- GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
- { "enable-passphrase-history", GC_OPT_FLAG_RUNTIME,
- GC_LEVEL_EXPERT, "gnupg", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
- { "pinentry-timeout", GC_OPT_FLAG_RUNTIME,
- GC_LEVEL_ADVANCED, "gnupg", NULL,
- GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
-
- GC_OPTION_NULL
- };
-#endif /*BUILD_WITH_AGENT*/
+/* Our main option info object. We copy all required information from the
+ * gpgrt_opt_t items but convert the flags value to bit flags. */
+struct gc_option_s
+{
+ const char *name; /* The same as gpgrt_opt_t.long_opt. */
+ const char *desc; /* The same as gpgrt_opt_t.description. */
+ unsigned int is_header:1; /* This is a header item. */
+ unsigned int is_list:1; /* This is a list style option. */
+ unsigned int opt_arg:1; /* The option's argument is optional. */
+ unsigned int runtime:1; /* The option is runtime changeable. */
-#ifndef BUILD_WITH_SCDAEMON
-#define gc_options_scdaemon NULL
-#else
-/* The options of the GC_COMPONENT_SCDAEMON component. */
-static gc_option_t gc_options_scdaemon[] =
- {
- /* The configuration file to which we write the changes. */
- { GPGCONF_NAME"-"SCDAEMON_NAME".conf",
- GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
- NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_SCDAEMON },
-
- { "Monitor",
- GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
- "gnupg", N_("Options controlling the diagnostic output") },
- { "verbose", GC_OPT_FLAG_LIST|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
- "gnupg", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
- { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "gnupg", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
- { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
- NULL, NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
-
- { "Configuration",
- GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT,
- "gnupg", N_("Options controlling the configuration") },
- { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
- "gnupg", NULL,
- GC_ARG_TYPE_FILENAME, GC_BACKEND_SCDAEMON },
- { "reader-port", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
- "gnupg", NULL,
- GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON },
- { "ctapi-driver", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED,
- "gnupg", NULL,
- GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON },
- { "pcsc-driver", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED,
- "gnupg", NULL,
- GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON },
- { "disable-ccid", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT,
- "gnupg", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
- { "disable-pinpad", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
- "gnupg", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
- { "enable-pinpad-varlen",
- GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
- "gnupg", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
- { "card-timeout", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
- "gnupg", NULL,
- GC_ARG_TYPE_UINT32, GC_BACKEND_SCDAEMON },
- { "application-priority",
- GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED,
- "gnupg", NULL,
- GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON },
-
- { "Debug",
- GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
- "gnupg", N_("Options useful for debugging") },
- { "debug-level", GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED,
- "gnupg", NULL,
- GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON },
- { "log-file", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED,
- "gnupg", NULL,
- GC_ARG_TYPE_FILENAME, GC_BACKEND_SCDAEMON },
-
- { "Security",
- GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
- "gnupg", N_("Options controlling the security") },
- { "deny-admin", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
- "gnupg", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
-
-
- GC_OPTION_NULL
- };
-#endif /*BUILD_WITH_SCDAEMON*/
+ unsigned int active:1; /* Has been announced in gpgconf-list. */
-#ifndef BUILD_WITH_GPG
-#define gc_options_gpg NULL
-#else
-/* The options of the GC_COMPONENT_GPG component. */
-static gc_option_t gc_options_gpg[] =
- {
- /* The configuration file to which we write the changes. */
- { GPGCONF_NAME"-"GPG_NAME".conf",
- GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
- NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG },
-
- { "Monitor",
- GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
- "gnupg", N_("Options controlling the diagnostic output") },
- { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC,
- "gnupg", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_GPG },
- { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "gnupg", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_GPG },
- { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
- NULL, NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_GPG },
-
- { "Configuration",
- GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT,
- "gnupg", N_("Options controlling the configuration") },
- { "default-key", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "gnupg", NULL,
- GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
- { "encrypt-to", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "gnupg", NULL,
- GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
- { "group", GC_OPT_FLAG_LIST, GC_LEVEL_ADVANCED,
- "gnupg", NULL,
- GC_ARG_TYPE_ALIAS_LIST, GC_BACKEND_GPG },
- { "options", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
- NULL, NULL,
- GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG },
- { "compliance", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
- NULL, NULL,
- GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
- { "default-new-key-algo", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
- NULL, NULL,
- GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
- { "default_pubkey_algo", /*FIXME: This is a pseudo option which we
- * read using --gpgconf-list */
- (GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_NO_CHANGE), GC_LEVEL_INVISIBLE,
- NULL, NULL,
- GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
- { "trust-model",
- GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
- NULL, NULL,
- GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
-
-
- { "Debug",
- GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
- "gnupg", N_("Options useful for debugging") },
- { "debug-level", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED,
- "gnupg", NULL,
- GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
- { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
- "gnupg", NULL,
- GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG },
-/* { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE, */
-/* NULL, NULL, */
-/* GC_ARG_TYPE_UINT32, GC_BACKEND_GPG }, */
-
- { "Keyserver",
- GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
- "gnupg", N_("Configuration for Keyservers") },
- { "auto-key-locate", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
- "gnupg", NULL,
- GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
- { "auto-key-retrieve", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
- NULL, NULL, GC_ARG_TYPE_NONE, GC_BACKEND_GPG },
- { "no-auto-key-retrieve", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
- NULL, NULL, GC_ARG_TYPE_NONE, GC_BACKEND_GPG },
- { "disable-dirmngr", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
- "gnupg", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_GPG },
- { "max-cert-depth",
- GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
- NULL, NULL,
- GC_ARG_TYPE_UINT32, GC_BACKEND_GPG },
- { "completes-needed",
- GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
- NULL, NULL,
- GC_ARG_TYPE_UINT32, GC_BACKEND_GPG },
- { "marginals-needed",
- GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
- NULL, NULL,
- GC_ARG_TYPE_UINT32, GC_BACKEND_GPG },
-
-
- GC_OPTION_NULL
- };
-#endif /*BUILD_WITH_GPG*/
+ unsigned int has_default:1; /* The option has a default value. */
+ unsigned int def_in_desc:1; /* The default is in the descrition. */
+ unsigned int no_arg_desc:1; /* The argument has a default ???. */
+ unsigned int no_change:1; /* User shall not change the option. */
+ unsigned int attr_ignore:1; /* The ARGPARSE_ATTR_IGNORE. */
+ unsigned int attr_force:1; /* The ARGPARSE_ATTR_FORCE. */
-#ifndef BUILD_WITH_GPGSM
-#define gc_options_gpgsm NULL
-#else
-/* The options of the GC_COMPONENT_GPGSM component. */
-static gc_option_t gc_options_gpgsm[] =
- {
- /* The configuration file to which we write the changes. */
- { GPGCONF_NAME"-"GPGSM_NAME".conf",
- GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
- NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_GPGSM },
-
- { "Monitor",
- GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
- "gnupg", N_("Options controlling the diagnostic output") },
- { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC,
- "gnupg", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
- { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "gnupg", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
- { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
- NULL, NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
-
- { "Configuration",
- GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT,
- "gnupg", N_("Options controlling the configuration") },
- { "default-key", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "gnupg", NULL,
- GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM },
- { "encrypt-to", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "gnupg", NULL,
- GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM },
- { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
- "gnupg", NULL,
- GC_ARG_TYPE_FILENAME, GC_BACKEND_GPGSM },
- { "disable-dirmngr", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
- "gnupg", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
- { "p12-charset", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
- "gnupg", NULL,
- GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM },
- { "keyserver", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC,
- "gnupg", NULL,
- GC_ARG_TYPE_LDAP_SERVER, GC_BACKEND_GPGSM },
- { "default_pubkey_algo",
- (GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_NO_CHANGE), GC_LEVEL_INVISIBLE,
- NULL, NULL,
- GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM },
- { "compliance", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
- NULL, NULL,
- GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM },
-
- { "Debug",
- GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
- "gnupg", N_("Options useful for debugging") },
- { "debug-level", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED,
- "gnupg", NULL,
- GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM },
- { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
- "gnupg", NULL,
- GC_ARG_TYPE_FILENAME, GC_BACKEND_GPGSM },
- { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
- NULL, NULL,
- GC_ARG_TYPE_UINT32, GC_BACKEND_GPGSM },
-
- { "Security",
- GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
- "gnupg", N_("Options controlling the security") },
- { "disable-crl-checks", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "gnupg", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
- { "enable-crl-checks", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
- NULL, NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
- { "disable-trusted-cert-crl-check", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
- "gnupg", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
- { "enable-ocsp", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
- "gnupg", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
- { "include-certs", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
- "gnupg", NULL,
- GC_ARG_TYPE_INT32, GC_BACKEND_GPGSM },
- { "disable-policy-checks", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
- "gnupg", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
- { "auto-issuer-key-retrieve", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "gnupg", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
- { "cipher-algo", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
- "gnupg", NULL,
- GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM },
-
- GC_OPTION_NULL
- };
-#endif /*BUILD_WITH_GPGSM*/
+ /* The expert level - copied from known_options. */
+ gc_expert_level_t level;
+ /* The complex type - copied from known_options. */
+ gc_arg_type_t arg_type;
-#ifndef BUILD_WITH_DIRMNGR
-#define gc_options_dirmngr NULL
-#else
-/* The options of the GC_COMPONENT_DIRMNGR component. */
-static gc_option_t gc_options_dirmngr[] =
- {
- /* The configuration file to which we write the changes. */
- { GPGCONF_NAME"-"DIRMNGR_NAME".conf",
- GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
- NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_DIRMNGR },
-
- { "Monitor",
- GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
- "gnupg", N_("Options controlling the diagnostic output") },
- { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC,
- "dirmngr", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
- { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "dirmngr", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
- { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
- NULL, NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
-
- { "Format",
- GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
- "gnupg", N_("Options controlling the format of the output") },
- { "sh", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "dirmngr", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
- { "csh", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "dirmngr", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
-
- { "Configuration",
- GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT,
- "gnupg", N_("Options controlling the configuration") },
- { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
- "dirmngr", NULL,
- GC_ARG_TYPE_FILENAME, GC_BACKEND_DIRMNGR },
- { "resolver-timeout", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
- NULL, NULL,
- GC_ARG_TYPE_INT32, GC_BACKEND_DIRMNGR },
- { "nameserver", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
- NULL, NULL,
- GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR },
-
- { "Debug",
- GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
- "gnupg", N_("Options useful for debugging") },
- { "debug-level", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED,
- "dirmngr", NULL,
- GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR },
- { "no-detach", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
- "dirmngr", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
- { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
- "dirmngr", NULL,
- GC_ARG_TYPE_FILENAME, GC_BACKEND_DIRMNGR },
- { "debug-wait", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
- NULL, NULL,
- GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
- { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
- NULL, NULL,
- GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
-
- { "Enforcement",
- GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
- "gnupg", N_("Options controlling the interactivity and enforcement") },
- { "batch", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "dirmngr", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
- { "force", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "dirmngr", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
- { "allow-version-check", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "dirmngr", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
-
- { "Tor",
- GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
- "gnupg", N_("Options controlling the use of Tor") },
- { "use-tor", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "dirmngr", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
-
- { "Keyserver",
- GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
- "gnupg", N_("Configuration for Keyservers") },
- { "keyserver", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "gnupg", NULL,
- GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR },
-
- { "HTTP",
- GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
- "gnupg", N_("Configuration for HTTP servers") },
- { "disable-http", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
- "dirmngr", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
- { "ignore-http-dp", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
- "dirmngr", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
- { "http-proxy", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
- "dirmngr", NULL,
- GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR },
- { "honor-http-proxy", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
- "gnupg", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
-
- { "LDAP",
- GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
- "gnupg", N_("Configuration of LDAP servers to use") },
- { "disable-ldap", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
- "dirmngr", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
- { "ignore-ldap-dp", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
- "dirmngr", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
- { "ldap-proxy", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "dirmngr", NULL,
- GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR },
- { "only-ldap-proxy", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
- "dirmngr", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
- { "add-servers", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
- "dirmngr", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
- { "ldaptimeout", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "dirmngr", NULL,
- GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
- /* The following entry must not be removed, as it is required for
- the GC_BACKEND_DIRMNGR_LDAP_SERVER_LIST. */
- { "ldapserverlist-file",
- GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
- "dirmngr", NULL,
- GC_ARG_TYPE_FILENAME, GC_BACKEND_DIRMNGR },
- /* This entry must come after at least one entry for
- GC_BACKEND_DIRMNGR in this component, so that the entry for
- "ldapserverlist-file will be initialized before this one. */
- { "LDAP Server", GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_LIST, GC_LEVEL_BASIC,
- "gnupg", NULL, /* FIXME: Need desc N_("LDAP server list") */
- GC_ARG_TYPE_LDAP_SERVER, GC_BACKEND_DIRMNGR_LDAP_SERVER_LIST },
- { "max-replies", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "dirmngr", NULL,
- GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
-
- { "OCSP",
- GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
- "gnupg", N_("Configuration for OCSP") },
- { "allow-ocsp", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "dirmngr", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
- { "ignore-ocsp-service-url", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
- "dirmngr", NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
- { "ocsp-responder", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
- "dirmngr", NULL,
- GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR },
- { "ocsp-signer", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
- "dirmngr", NULL,
- GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR },
-
-
- GC_OPTION_NULL
- };
-#endif /*BUILD_WITH_DIRMNGR*/
+ /* The default value for this option. This is NULL if the option is
+ not present in the component, the empty string if no default is
+ available, and otherwise a quoted string. This is currently
+ malloced.*/
+ char *default_value;
+ /* The current value of this option. */
+ char *value;
-/* The options of the GC_COMPONENT_PINENTRY component. */
-static gc_option_t gc_options_pinentry[] =
- {
- /* A dummy option to allow gc_component_list_components to find the
- pinentry backend. Needs to be a conf file. */
- { GPGCONF_NAME"-pinentry.conf",
- GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
- NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_PINENTRY },
+ /* The new flags for this option. The only defined flag is actually
+ GC_OPT_FLAG_DEFAULT, and it means that the option should be
+ deleted. In this case, NEW_VALUE is NULL. */
+ unsigned long new_flags;
- GC_OPTION_NULL
- };
+ /* The new value of this option. */
+ char *new_value;
+};
+typedef struct gc_option_s gc_option_t;
/* The information associated with each component. */
-static const struct
+static struct
{
- /* The name of this component. Must not contain a colon (':')
- character. */
+ /* The name of the component. Some components don't have an
+ * associated program, but are implemented directly by GPGConf. In
+ * this case, PROGRAM is NULL. */
+ char *program;
+
+ /* The displayed name of this component. Must not contain a colon
+ * (':') character. */
const char *name;
/* The gettext domain for the description DESC. If this is NULL,
then the description is not translated. */
const char *desc_domain;
- /* The description for this domain. */
+ /* The description of this component. */
const char *desc;
- /* The list of options for this component, terminated by
- GC_OPTION_NULL. */
+ /* The module name (GNUPG_MODULE_NAME_foo) as defined by
+ * ../common/util.h. This value is used to get the actual installed
+ * path of the program. 0 is used if no program for the component
+ * is available. */
+ char module_name;
+
+ /* The name for the configuration filename of this component. */
+ const char *option_config_filename;
+
+ /* The static table of known options for this component. */
+ known_option_t *known_options;
+
+ /* The runtime change callback. If KILLFLAG is true the component
+ is killed and not just reloaded. */
+ void (*runtime_change) (int killflag);
+
+ /* The table of known options as read from the component including
+ * header lines and such. This is suitable to be passed to
+ * gpgrt_argparser. Will be filled in by
+ * retrieve_options_from_program. */
+ gpgrt_opt_t *opt_table;
+
+ /* The full table including data from OPT_TABLE. The end of the
+ * table is marked by NULL entry for NAME. Will be filled in by
+ * retrieve_options_from_program. */
gc_option_t *options;
-} gc_component[] =
+
+} gc_component[GC_COMPONENT_NR] =
{
- { "gpg", "gnupg", N_("OpenPGP"), gc_options_gpg },
- { "gpg-agent","gnupg", N_("Private Keys"), gc_options_gpg_agent },
- { "scdaemon", "gnupg", N_("Smartcards"), gc_options_scdaemon },
- { "gpgsm", "gnupg", N_("S/MIME"), gc_options_gpgsm },
- { "dirmngr", "gnupg", N_("Network"), gc_options_dirmngr },
- { "pinentry", "gnupg", N_("Passphrase Entry"), gc_options_pinentry }
+ { NULL }, /* DUMMY for GC_COMPONENT_ANY */
+
+ { GPG_NAME, GPG_DISP_NAME, "gnupg", N_("OpenPGP"),
+ GNUPG_MODULE_NAME_GPG, GPG_NAME ".conf",
+ known_options_gpg },
+
+ { GPGSM_NAME, GPGSM_DISP_NAME, "gnupg", N_("S/MIME"),
+ GNUPG_MODULE_NAME_GPGSM, GPGSM_NAME ".conf",
+ known_options_gpgsm },
+
+ { GPG_AGENT_NAME, GPG_AGENT_DISP_NAME, "gnupg", N_("Private Keys"),
+ GNUPG_MODULE_NAME_AGENT, GPG_AGENT_NAME ".conf",
+ known_options_gpg_agent, gpg_agent_runtime_change },
+
+ { SCDAEMON_NAME, SCDAEMON_DISP_NAME, "gnupg", N_("Smartcards"),
+ GNUPG_MODULE_NAME_SCDAEMON, SCDAEMON_NAME ".conf",
+ known_options_scdaemon, scdaemon_runtime_change},
+
+ { DIRMNGR_NAME, DIRMNGR_DISP_NAME, "gnupg", N_("Network"),
+ GNUPG_MODULE_NAME_DIRMNGR, DIRMNGR_NAME ".conf",
+ known_options_dirmngr, dirmngr_runtime_change },
+
+ { "pinentry", "Pinentry", "gnupg", N_("Passphrase Entry"),
+ GNUPG_MODULE_NAME_PINENTRY, NULL,
+ known_options_pinentry }
};
-/* Structure used to collect error output of the backend programs. */
+/* Structure used to collect error output of the component programs. */
struct error_line_s;
typedef struct error_line_s *error_line_t;
struct error_line_s
@@ -1297,79 +843,44 @@ gc_component_launch (int component)
}
-/* Unconditionally restart COMPONENT. */
-void
-gc_component_kill (int component)
+static void
+do_runtime_change (int component, int killflag)
{
- int runtime[GC_BACKEND_NR];
- gc_option_t *option;
- gc_backend_t backend;
-
- /* Set a flag for the backends to be reloaded. */
- for (backend = 0; backend < GC_BACKEND_NR; backend++)
- runtime[backend] = 0;
+ int runtime[GC_COMPONENT_NR] = { 0 };
if (component < 0)
{
for (component = 0; component < GC_COMPONENT_NR; component++)
- {
- option = gc_component[component].options;
- for (; option && option->name; option++)
- runtime[option->backend] = 1;
- }
+ runtime [component] = 1;
}
else
{
- log_assert (component < GC_COMPONENT_NR);
- option = gc_component[component].options;
- for (; option && option->name; option++)
- runtime[option->backend] = 1;
+ log_assert (component >= 0 && component < GC_COMPONENT_NR);
+ runtime [component] = 1;
}
- /* Do the restart for the selected backends. */
- for (backend = GC_BACKEND_NR-1; backend; backend--)
+ /* Do the restart for the selected components. */
+ for (component = GC_COMPONENT_NR-1; component >= 0; component--)
{
- if (runtime[backend] && gc_backend[backend].runtime_change)
- (*gc_backend[backend].runtime_change) (1);
+ if (runtime[component] && gc_component[component].runtime_change)
+ (*gc_component[component].runtime_change) (killflag);
}
}
-/* Unconditionally reload COMPONENT or all components if COMPONENT is -1. */
+/* Unconditionally restart COMPONENT. */
void
-gc_component_reload (int component)
+gc_component_kill (int component)
{
- int runtime[GC_BACKEND_NR];
- gc_option_t *option;
- gc_backend_t backend;
-
- /* Set a flag for the backends to be reloaded. */
- for (backend = 0; backend < GC_BACKEND_NR; backend++)
- runtime[backend] = 0;
+ do_runtime_change (component, 1);
+}
- if (component < 0)
- {
- for (component = 0; component < GC_COMPONENT_NR; component++)
- {
- option = gc_component[component].options;
- for (; option && option->name; option++)
- runtime[option->backend] = 1;
- }
- }
- else
- {
- log_assert (component < GC_COMPONENT_NR);
- option = gc_component[component].options;
- for (; option && option->name; option++)
- runtime[option->backend] = 1;
- }
- /* Do the reload for all selected backends. */
- for (backend = 0; backend < GC_BACKEND_NR; backend++)
- {
- if (runtime[backend] && gc_backend[backend].runtime_change)
- (*gc_backend[backend].runtime_change) (0);
- }
+/* Unconditionally reload COMPONENT or all components if COMPONENT is -1. */
+void
+gc_component_reload (int component)
+{
+ do_runtime_change (component, 0);
}
@@ -1538,44 +1049,24 @@ percent_deescape (const char *src)
void
gc_component_list_components (estream_t out)
{
- gc_component_t component;
- gc_option_t *option;
- gc_backend_t backend;
- int backend_seen[GC_BACKEND_NR];
+ gc_component_id_t component;
const char *desc;
const char *pgmname;
for (component = 0; component < GC_COMPONENT_NR; component++)
{
- option = gc_component[component].options;
- if (option)
- {
- for (backend = 0; backend < GC_BACKEND_NR; backend++)
- backend_seen[backend] = 0;
-
- pgmname = "";
- for (; option && option->name; option++)
- {
- if ((option->flags & GC_OPT_FLAG_GROUP))
- continue;
- backend = option->backend;
- if (backend_seen[backend])
- continue;
- backend_seen[backend] = 1;
- log_assert (backend != GC_BACKEND_ANY);
- if (gc_backend[backend].program
- && !gc_backend[backend].module_name)
- continue;
- pgmname = gnupg_module_name (gc_backend[backend].module_name);
- break;
- }
+ if (!gc_component[component].program)
+ continue;
+ if (gc_component[component].module_name)
+ pgmname = gnupg_module_name (gc_component[component].module_name);
+ else
+ pgmname = "";
- desc = gc_component[component].desc;
- desc = my_dgettext (gc_component[component].desc_domain, desc);
- es_fprintf (out, "%s:%s:",
- gc_component[component].name, gc_percent_escape (desc));
- es_fprintf (out, "%s\n", gc_percent_escape (pgmname));
- }
+ desc = gc_component[component].desc;
+ desc = my_dgettext (gc_component[component].desc_domain, desc);
+ es_fprintf (out, "%s:%s:",
+ gc_component[component].program, gc_percent_escape (desc));
+ es_fprintf (out, "%s\n", gc_percent_escape (pgmname));
}
}
@@ -1682,9 +1173,6 @@ gc_component_check_options (int component, estream_t out, const char *conf_file)
{
gpg_error_t err;
unsigned int result;
- int backend_seen[GC_BACKEND_NR];
- gc_backend_t backend;
- gc_option_t *option;
const char *pgmname;
const char *argv[4];
int i;
@@ -1693,30 +1181,14 @@ gc_component_check_options (int component, estream_t out, const char *conf_file)
estream_t errfp;
error_line_t errlines;
- for (backend = 0; backend < GC_BACKEND_NR; backend++)
- backend_seen[backend] = 0;
+ log_assert (component >= 0 && component < GC_COMPONENT_NR);
- option = gc_component[component].options;
- for (; option && option->name; option++)
- {
- if ((option->flags & GC_OPT_FLAG_GROUP))
- continue;
- backend = option->backend;
- if (backend_seen[backend])
- continue;
- backend_seen[backend] = 1;
- log_assert (backend != GC_BACKEND_ANY);
- if (!gc_backend[backend].program)
- continue;
- if (!gc_backend[backend].module_name)
- continue;
-
- break;
- }
- if (! option || ! option->name)
+ if (!gc_component[component].program)
+ return 0;
+ if (!gc_component[component].module_name)
return 0;
- pgmname = gnupg_module_name (gc_backend[backend].module_name);
+ pgmname = gnupg_module_name (gc_component[component].module_name);
i = 0;
if (conf_file)
{
@@ -1763,7 +1235,7 @@ gc_component_check_options (int component, estream_t out, const char *conf_file)
desc = gc_component[component].desc;
desc = my_dgettext (gc_component[component].desc_domain, desc);
es_fprintf (out, "%s:%s:",
- gc_component[component].name, gc_percent_escape (desc));
+ gc_component[component].program, gc_percent_escape (desc));
es_fputs (gc_percent_escape (pgmname), out);
es_fprintf (out, ":%d:%d:", !(result & 1), !(result & 2));
for (errptr = errlines; errptr; errptr = errptr->next)
@@ -1798,7 +1270,7 @@ gc_component_check_options (int component, estream_t out, const char *conf_file)
void
gc_check_programs (estream_t out)
{
- gc_component_t component;
+ gc_component_id_t component;
for (component = 0; component < GC_COMPONENT_NR; component++)
gc_component_check_options (component, out, NULL);
@@ -1811,12 +1283,12 @@ gc_check_programs (estream_t out)
int
gc_component_find (const char *name)
{
- gc_component_t idx;
+ gc_component_id_t idx;
for (idx = 0; idx < GC_COMPONENT_NR; idx++)
{
- if (gc_component[idx].options
- && !strcmp (name, gc_component[idx].name))
+ if (gc_component[idx].program
+ && !strcmp (name, gc_component[idx].program))
return idx;
}
return -1;
@@ -1825,14 +1297,17 @@ gc_component_find (const char *name)
/* List the option OPTION. */
static void
-list_one_option (const gc_option_t *option, estream_t out)
+list_one_option (gc_component_id_t component,
+ const gc_option_t *option, estream_t out)
{
const char *desc = NULL;
char *arg_name = NULL;
+ unsigned long flags;
+ const char *desc_domain = gc_component[component].desc_domain;
if (option->desc)
{
- desc = my_dgettext (option->desc_domain, option->desc);
+ desc = my_dgettext (desc_domain, option->desc);
if (*desc == '|')
{
@@ -1858,16 +1333,23 @@ list_one_option (const gc_option_t *option, estream_t out)
es_fprintf (out, "%s", option->name);
/* The flags field. */
- es_fprintf (out, ":%lu", option->flags);
+ flags = 0;
+ if (option->is_header) flags |= GC_OPT_FLAG_GROUP;
+ if (option->is_list) flags |= GC_OPT_FLAG_LIST;
+ if (option->runtime) flags |= GC_OPT_FLAG_RUNTIME;
+ if (option->has_default) flags |= GC_OPT_FLAG_DEFAULT;
+ if (option->def_in_desc) flags |= GC_OPT_FLAG_DEF_DESC;
+ if (option->no_arg_desc) flags |= GC_OPT_FLAG_NO_ARG_DESC;
+ if (option->no_change) flags |= GC_OPT_FLAG_NO_CHANGE;
+ es_fprintf (out, ":%lu", flags);
if (opt.verbose)
{
es_putc (' ', out);
- if (!option->flags)
+ if (!flags)
es_fprintf (out, "none");
else
{
- unsigned long flags = option->flags;
unsigned long flag = 0;
unsigned long first = 1;
@@ -1913,16 +1395,17 @@ list_one_option (const gc_option_t *option, estream_t out)
/* The default value field. */
es_fprintf (out, ":%s", option->default_value ? option->default_value : "");
- /* The default argument field. */
- es_fprintf (out, ":%s", option->default_arg ? option->default_arg : "");
+ /* The default argument field. This was never used and is thus empty. */
+ es_fprintf (out, ":");
/* The value field. */
if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE
- && (option->flags & GC_OPT_FLAG_LIST)
- && option->value)
- /* The special format "1,1,1,1,...,1" is converted to a number
- here. */
- es_fprintf (out, ":%u", (unsigned int)((strlen (option->value) + 1) / 2));
+ && option->is_list && option->value)
+ {
+ /* The special format "1,1,1,1,...,1" is converted to a number
+ here. */
+ es_fprintf (out, ":%u", (unsigned int)((strlen (option->value) + 1) / 2));
+ }
else
es_fprintf (out, ":%s", option->value ? option->value : "");
@@ -1938,17 +1421,14 @@ gc_component_list_options (int component, estream_t out)
{
const gc_option_t *option = gc_component[component].options;
- while (option && option->name)
+ for ( ; option && option->name; option++)
{
/* Do not output unknown or internal options. */
- if (!(option->flags & GC_OPT_FLAG_GROUP)
+ if (!option->is_header
&& (!option->active || option->level == GC_LEVEL_INTERNAL))
- {
- option++;
continue;
- }
- if (option->flags & GC_OPT_FLAG_GROUP)
+ if (option->is_header)
{
const gc_option_t *group_option = option + 1;
gc_expert_level_t level = GC_LEVEL_NR;
@@ -1959,13 +1439,12 @@ gc_component_list_options (int component, estream_t out)
maintain manually, we calculate it here. The value in
the global static table is ignored. */
- while (group_option->name)
+ for ( ; group_option->name; group_option++)
{
- if (group_option->flags & GC_OPT_FLAG_GROUP)
+ if (group_option->is_header)
break;
if (group_option->level < level)
level = group_option->level;
- group_option++;
}
/* Check if group is empty. */
@@ -1974,88 +1453,59 @@ gc_component_list_options (int component, estream_t out)
gc_option_t opt_copy;
/* Fix up the group level. */
- memcpy (&opt_copy, option, sizeof (opt_copy));
+ opt_copy = *option;
opt_copy.level = level;
- list_one_option (&opt_copy, out);
+ list_one_option (component, &opt_copy, out);
}
}
else
- list_one_option (option, out);
-
- option++;
+ list_one_option (component, option, out);
}
}
-/* Find the option NAME in component COMPONENT, for the backend
- BACKEND. If BACKEND is GC_BACKEND_ANY, any backend will match. */
-static gc_option_t *
-find_option (gc_component_t component, const char *name,
- gc_backend_t backend)
+/* Return true if the option NAME is known and that we want it as
+ * gpgconf managed option. */
+static known_option_t *
+is_known_option (gc_component_id_t component, const char *name)
{
- gc_option_t *option = gc_component[component].options;
- while (option->name)
+ known_option_t *option = gc_component[component].known_options;
+ if (option)
{
- if (!(option->flags & GC_OPT_FLAG_GROUP)
- && !strcmp (option->name, name)
- && (backend == GC_BACKEND_ANY || option->backend == backend))
- break;
- option++;
+ for (; option->name; option++)
+ if (!strcmp (option->name, name))
+ break;
}
- return option->name ? option : NULL;
+ return option;
}
-
-/* Determine the configuration filename for the component COMPONENT
- and backend BACKEND. */
-static char *
-get_config_filename (gc_component_t component, gc_backend_t backend)
+
+/* Find the option NAME in component COMPONENT. Returns pointer to
+ * the option descriptor or NULL if not found. */
+static gc_option_t *
+find_option (gc_component_id_t component, const char *name)
{
- char *filename = NULL;
- gc_option_t *option = find_option
- (component, gc_backend[backend].option_config_filename, GC_BACKEND_ANY);
- log_assert (option);
- log_assert (option->arg_type == GC_ARG_TYPE_FILENAME);
- log_assert (!(option->flags & GC_OPT_FLAG_LIST));
-
- if (!option->active || !option->default_value)
- gc_error (1, 0, "Option %s, needed by backend %s, was not initialized",
- gc_backend[backend].option_config_filename,
- gc_backend[backend].name);
-
- if (option->value && *option->value)
- filename = percent_deescape (&option->value[1]);
- else if (option->default_value && *option->default_value)
- filename = percent_deescape (&option->default_value[1]);
- else
- filename = "";
-
-#if HAVE_W32CE_SYSTEM
- if (!(filename[0] == '/' || filename[0] == '\\'))
-#elif defined(HAVE_DOSISH_SYSTEM)
- if (!(filename[0]
- && filename[1] == ':'
- && (filename[2] == '/' || filename[2] == '\\')) /* x:\ or x:/ */
- && !((filename[0] == '\\' && filename[1] == '\\')
- || (filename[0] == '/' && filename[1] == '/'))) /* \\server */
-#else
- if (filename[0] != '/')
-#endif
- gc_error (1, 0, "Option %s, needed by backend %s, is not absolute",
- gc_backend[backend].option_config_filename,
- gc_backend[backend].name);
+ gc_option_t *option = gc_component[component].options;
- return filename;
+ if (option)
+ {
+ for (; option->name; option++)
+ {
+ if (!option->is_header
+ && !strcmp (option->name, name))
+ return option;
+ }
+ }
+ return NULL;
}
+
-/* Retrieve the options for the component COMPONENT from backend
- * BACKEND, which we already know is a program-type backend. With
+/* Retrieve the options for the component COMPONENT. With
* ONLY_INSTALLED set components which are not installed are silently
* ignored. */
static void
-retrieve_options_from_program (gc_component_t component, gc_backend_t backend,
- int only_installed)
+retrieve_options_from_program (gc_component_id_t component, int only_installed)
{
gpg_error_t err;
const char *pgmname;
@@ -2063,6 +1513,7 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend,
estream_t outfp;
int exitcode;
pid_t pid;
+ known_option_t *known_option;
gc_option_t *option;
char *line = NULL;
size_t line_len = 0;
@@ -2070,21 +1521,17 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend,
const char *config_name;
gpgrt_argparse_t pargs;
int dummy_argc;
- gpgrt_opt_t *opt_table = NULL; /* A malloced option table. */
- size_t opt_table_used = 0; /* Its current length. */
- size_t opt_table_size = 0; /* Its allocated length. */
- char **string_array = NULL; /* An allocated array with
- * malloced strings. */
- size_t string_array_used = 0; /* Current number of items in
- * the array. */
- size_t string_array_size = 0; /* Allocated number of slots in
- * the array. */
- size_t n;
+ gpgrt_opt_t *opt_table = NULL; /* A malloced option table. */
+ size_t opt_table_used = 0; /* Its current length. */
+ size_t opt_table_size = 0; /* Its allocated length. */
+ gc_option_t *opt_info = NULL; /* A malloced options table. */
+ size_t opt_info_used = 0; /* Its current length. */
+ size_t opt_info_size = 0; /* Its allocated length. */
int i;
- pgmname = (gc_backend[backend].module_name
- ? gnupg_module_name (gc_backend[backend].module_name)
- : gc_backend[backend].program );
+ pgmname = (gc_component[component].module_name
+ ? gnupg_module_name (gc_component[component].module_name)
+ : gc_component[component].program );
if (only_installed && access (pgmname, X_OK))
{
@@ -2107,13 +1554,15 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend,
{
char *fields[4];
char *optname, *optdesc;
+ unsigned int optflags;
+ int short_opt;
+ gc_arg_type_t arg_type;
/* Strip newline and carriage return, if present. */
while (length > 0
&& (line[length - 1] == '\n' || line[length - 1] == '\r'))
line[--length] = '\0';
- log_debug ("line='%s'\n", line);
if (split_fields_colon (line, fields, DIM (fields)) < 4)
{
gc_error (0,0, "WARNING: invalid line in option table of '%s'\n",
@@ -2121,6 +1570,24 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend,
continue;
}
+ optname = fields[0];
+ short_opt = atoi (fields[1]);
+ if (short_opt < 1)
+ {
+ gc_error (0,0, "WARNING: bad short option in option table of '%s'\n",
+ pgmname);
+ continue;
+ }
+
+
+ optflags = strtoul (fields[2], NULL, 10);
+ if ((optflags & ARGPARSE_OPT_HEADER))
+ known_option = NULL; /* We want all header-only options. */
+ else if ((known_option = is_known_option (component, optname)))
+ ; /* Yes we want this one. */
+ else
+ continue; /* No need to store this option description. */
+
/* The +1 here is to make sure that we will have a zero item at
* the end of the table. */
if (opt_table_used + 1 >= opt_table_size)
@@ -2132,7 +1599,19 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend,
opt_table_size,
sizeof *opt_table);
}
- /* The +1 here accounts for the two items we add below. */
+ /* The +1 here is to make sure that we will have a zero item at
+ * the end of the table. */
+ if (opt_info_used + 1 >= opt_info_size)
+ {
+ /* Note that this also does the initial allocation. */
+ opt_info_size += 128;
+ opt_info = xreallocarray (opt_info,
+ opt_info_used,
+ opt_info_size,
+ sizeof *opt_info);
+ }
+ /* The +1 here accounts for the two items we are going to add to
+ * the global string table. */
if (string_array_used + 1 >= string_array_size)
{
string_array_size += 256;
@@ -2144,21 +1623,67 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend,
string_array[string_array_used++] = optname = xstrdup (fields[0]);
string_array[string_array_used++] = optdesc = xstrdup (fields[3]);
+ /* Create an option table which can then be supplied to
+ * gpgrt_parser. Unfortunately there is no private pointer in
+ * the public option table struct so that we can't add extra
+ * data we need here. Thus we need to build up another table
+ * for such info and for ease of use we also copy the tehre the
+ * data from the option table. It is not possible to use the
+ * known_option_s for this because that one does not carry
+ * header lines and it might also be problematic to use such
+ * static tables for caching options and default values. */
opt_table[opt_table_used].long_opt = optname;
- opt_table[opt_table_used].short_opt = atoi (fields[1]);
+ opt_table[opt_table_used].short_opt = short_opt;
opt_table[opt_table_used].description = optdesc;
- opt_table[opt_table_used].flags = strtoul (fields[2], NULL, 10);
+ opt_table[opt_table_used].flags = optflags;
opt_table_used++;
- /* Put the description into our table. */
- option = find_option (component, optname, backend);
- if (option && !option->desc)
- option->desc = xstrdup (optdesc);
+ /* Note that as per argparser specs the opt_table uses "@" to
+ * specifify an empty description. In the DESC script of
+ * options (opt_info_t) we want to have a real empty string. */
+ opt_info[opt_info_used].name = optname;
+ if (*optdesc == '@' && !optdesc[1])
+ opt_info[opt_info_used].desc = optdesc+1;
+ else
+ opt_info[opt_info_used].desc = optdesc;
+
+ /* Unfortunately we need to remap the types. */
+ switch ((optflags & ARGPARSE_TYPE_MASK))
+ {
+ case ARGPARSE_TYPE_INT: arg_type = GC_ARG_TYPE_INT32; break;
+ case ARGPARSE_TYPE_LONG: arg_type = GC_ARG_TYPE_INT32; break;
+ case ARGPARSE_TYPE_ULONG: arg_type = GC_ARG_TYPE_UINT32; break;
+ case ARGPARSE_TYPE_STRING: arg_type = GC_ARG_TYPE_STRING; break;
+ default: arg_type = GC_ARG_TYPE_NONE; break;
+ }
+ opt_info[opt_info_used].arg_type = arg_type;
+
+ if ((optflags & ARGPARSE_OPT_HEADER))
+ opt_info[opt_info_used].is_header = 1;
+ if (known_option)
+ {
+ if ((known_option->flags & GC_OPT_FLAG_LIST))
+ opt_info[opt_info_used].is_list = 1;
+ /* FIXME: The next can also be taken from opt_table->flags.
+ * We need to check the code whether both specifications match. */
+ if ((known_option->flags & GC_OPT_FLAG_ARG_OPT))
+ opt_info[opt_info_used].opt_arg = 1;
+ /* Same here. */
+ if ((known_option->flags & GC_OPT_FLAG_RUNTIME))
+ opt_info[opt_info_used].runtime = 1;
+
+ opt_info[opt_info_used].level = known_option->level;
+ /* Override the received argtype by a complex type. */
+ if (known_option->arg_type)
+ opt_info[opt_info_used].arg_type = known_option->arg_type;
+ }
+ opt_info_used++;
}
if (length < 0 || es_ferror (outfp))
gc_error (1, errno, "error reading from %s", pgmname);
if (es_fclose (outfp))
gc_error (1, errno, "error closing %s", pgmname);
+ log_assert (opt_table_used == opt_info_used);
err = gnupg_wait_process (pgmname, pid, 1, &exitcode);
if (err)
@@ -2166,6 +1691,10 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend,
pgmname, exitcode, gpg_strerror (err));
gnupg_release_process (pid);
+ /* Make the gpgrt option table and the internal option table available. */
+ gc_component[component].opt_table = opt_table;
+ gc_component[component].options = opt_info;
+
/* Now read the default options. */
argv[0] = "--gpgconf-list";
@@ -2225,7 +1754,7 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend,
if (end)
*(end++) = '\0';
- if (flags & GC_OPT_FLAG_DEFAULT)
+ if ((flags & GC_OPT_FLAG_DEFAULT))
default_value = linep;
linep = end;
@@ -2233,15 +1762,22 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend,
/* Look up the option in the component and install the
configuration data. */
- option = find_option (component, line, backend);
+ option = find_option (component, line);
if (option)
{
if (option->active)
- gc_error (1, errno, "option %s returned twice from %s",
+ gc_error (1, errno,
+ "option %s returned twice from \"%s --gpgconf-list\"",
line, pgmname);
option->active = 1;
- option->flags |= flags;
+ /* Runtime is duplicated - see above. */
+ option->runtime = !!(flags & GC_OPT_FLAG_RUNTIME);
+ option->has_default = !!(flags & GC_OPT_FLAG_DEFAULT);
+ option->def_in_desc = !!(flags & GC_OPT_FLAG_DEF_DESC);
+ option->no_arg_desc = !!(flags & GC_OPT_FLAG_NO_ARG_DESC);
+ option->no_change = !!(flags & GC_OPT_FLAG_NO_CHANGE);
+
if (default_value && *default_value)
option->default_value = xstrdup (default_value);
}
@@ -2259,7 +1795,7 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend,
/* At this point, we can parse the configuration file. */
- config_name = gc_backend[backend].option_config_filename;
+ config_name = gc_component[component].option_config_filename;
if (!config_name)
gc_error (1, 0, "name of config file for %s is not known\n", pgmname);
@@ -2278,13 +1814,13 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend,
if (pargs.r_type & ARGPARSE_OPT_IGNORE)
{
- log_debug ("ignored\n");
+ /* log_debug ("ignored\n"); */
continue;
}
if (pargs.r_opt == ARGPARSE_CONFFILE)
{
- log_debug ("current conffile='%s'\n",
- pargs.r_type? pargs.r.ret_str: "[cmdline]");
+ /* log_debug ("current conffile='%s'\n", */
+ /* pargs.r_type? pargs.r.ret_str: "[cmdline]"); */
continue;
}
@@ -2296,14 +1832,14 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend,
if (!opt_table[i].short_opt || !opt_table[i].long_opt)
continue; /* No or only a short option - ignore. */
- /* Look up the option from the config file in our fixed list of
- * options which are handled by us. */
- option = find_option (component, opt_table[i].long_opt, backend);
+ /* Look up the option from the config file in our list of
+ * supported options. */
+ option= find_option (component, opt_table[i].long_opt);
if (!option)
continue; /* We don't want to handle this option. */
- option->attr.ignore = !!(pargs.r_type & ARGPARSE_ATTR_IGNORE);
- option->attr.force = !!(pargs.r_type & ARGPARSE_ATTR_FORCE);
+ option->attr_ignore = !!(pargs.r_type & ARGPARSE_ATTR_IGNORE);
+ option->attr_force = !!(pargs.r_type & ARGPARSE_ATTR_FORCE);
switch ((pargs.r_type & ARGPARSE_TYPE_MASK))
{
@@ -2324,13 +1860,13 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend,
break;
}
- /* Now enter the value read form the config file into the table. */
- if (!(option->flags & GC_OPT_FLAG_LIST))
+ /* Now enter the value read from the config file into the table. */
+ if (!option->is_list)
{
xfree (option->value);
option->value = opt_value;
}
- else if (!option->value)
+ else if (!option->value) /* LIST but first item. */
option->value = opt_value;
else
{
@@ -2342,112 +1878,22 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend,
}
xfree (line);
- xfree (opt_table);
- /* Note that we release the string array after the option table
- * because the option table has pointers into tye string array. */
- for (n=0; n < string_array_used; n++)
- xfree (string_array[n]);
- xfree (string_array);
}
-/* Retrieve the options for the component COMPONENT from backend
- BACKEND, which we already know is of type file list. */
-static void
-retrieve_options_from_file (gc_component_t component, gc_backend_t backend)
-{
- gc_option_t *list_option;
- gc_option_t *config_option;
- char *list_filename;
- gpgrt_stream_t list_file;
- char *line = NULL;
- size_t line_len = 0;
- ssize_t length;
- char *list = NULL;
-
- list_option = find_option (component,
- gc_backend[backend].option_name, GC_BACKEND_ANY);
- log_assert (list_option);
- log_assert (!list_option->active);
-
- list_filename = get_config_filename (component, backend);
- list_file = gpgrt_fopen (list_filename, "r");
- if (!list_file)
- gc_error (0, errno, "warning: can't open list file %s", list_filename);
- else
- {
- while ((length = gpgrt_read_line (list_file, &line, &line_len, NULL)) > 0)
- {
- char *start;
- char *end;
- char *new_list;
-
- start = line;
- while (*start == ' ' || *start == '\t')
- start++;
- if (!*start || *start == '#' || *start == '\r' || *start == '\n')
- continue;
-
- end = start;
- while (*end && *end != '#' && *end != '\r' && *end != '\n')
- end++;
- /* Walk back to skip trailing white spaces. Looks evil, but
- works because of the conditions on START and END imposed
- at this point (END is at least START + 1, and START is
- not a whitespace character). */
- while (*(end - 1) == ' ' || *(end - 1) == '\t')
- end--;
- *end = '\0';
- /* FIXME: Oh, no! This is so lame! Should use realloc and
- really append. */
- if (list)
- {
- new_list = xasprintf ("%s,\"%s", list, gc_percent_escape (start));
- xfree (list);
- list = new_list;
- }
- else
- list = xasprintf ("\"%s", gc_percent_escape (start));
- }
- if (length < 0 || gpgrt_ferror (list_file))
- gc_error (1, errno, "can' read list file %s", list_filename);
- }
-
- list_option->active = 1;
- list_option->value = list;
-
- /* Fix up the read-only flag. */
- config_option = find_option
- (component, gc_backend[backend].option_config_filename, GC_BACKEND_ANY);
- if (config_option->flags & GC_OPT_FLAG_NO_CHANGE)
- list_option->flags |= GC_OPT_FLAG_NO_CHANGE;
-
- if (list_file && gpgrt_fclose (list_file))
- gc_error (1, errno, "error closing %s", list_filename);
- xfree (line);
-}
-
-
-/* Retrieve the currently active options and their defaults from all
- involved backends for this component. Using -1 for component will
- retrieve all options from all installed components. */
+/* Retrieve the currently active options and their defaults for this
+ component. Using -1 for component will retrieve all options from
+ all installed components. */
void
gc_component_retrieve_options (int component)
{
int process_all = 0;
- int backend_seen[GC_BACKEND_NR];
- gc_backend_t backend;
- gc_option_t *option;
-
- for (backend = 0; backend < GC_BACKEND_NR; backend++)
- backend_seen[backend] = 0;
if (component == -1)
{
process_all = 1;
component = 0;
- log_assert (component < GC_COMPONENT_NR);
}
do
@@ -2455,31 +1901,8 @@ gc_component_retrieve_options (int component)
if (component == GC_COMPONENT_PINENTRY)
continue; /* Skip this dummy component. */
- option = gc_component[component].options;
-
- while (option && option->name)
- {
- if (!(option->flags & GC_OPT_FLAG_GROUP))
- {
- backend = option->backend;
-
- if (backend_seen[backend])
- {
- option++;
- continue;
- }
- backend_seen[backend] = 1;
-
- log_assert (backend != GC_BACKEND_ANY);
-
- if (gc_backend[backend].program)
- retrieve_options_from_program (component, backend,
- process_all);
- else
- retrieve_options_from_file (component, backend);
- }
- option++;
- }
+ if (gc_component[component].program)
+ retrieve_options_from_program (component, process_all);
}
while (process_all && ++component < GC_COMPONENT_NR);
@@ -2492,15 +1915,16 @@ gc_component_retrieve_options (int component)
* type GC_ARG_TYPE_NONE. If VERBATIM is set the profile parsing mode
* is used. */
static void
-option_check_validity (gc_option_t *option, unsigned long flags,
+option_check_validity (gc_component_id_t component,
+ gc_option_t *option, unsigned long flags,
char *new_value, unsigned long *new_value_nr,
int verbatim)
{
char *arg;
if (!option->active)
- gc_error (1, 0, "option %s not supported by backend %s",
- option->name, gc_backend[option->backend].name);
+ gc_error (1, 0, "option %s not supported by component %s",
+ option->name, gc_component[component].name);
if (option->new_flags || option->new_value)
gc_error (1, 0, "option %s already changed", option->name);
@@ -2529,7 +1953,7 @@ option_check_validity (gc_option_t *option, unsigned long flags,
gc_error (1, 0, "garbage after argument for option %s",
option->name);
- if (!(option->flags & GC_OPT_FLAG_LIST))
+ if (!option->is_list)
{
if (*new_value_nr != 1)
gc_error (1, 0, "argument for non-list option %s of type 0 "
@@ -2550,10 +1974,10 @@ option_check_validity (gc_option_t *option, unsigned long flags,
{
if (*arg == '\0' || (*arg == ',' && !verbatim))
{
- if (!(option->flags & GC_OPT_FLAG_ARG_OPT))
+ if (!option->opt_arg)
gc_error (1, 0, "argument required for option %s", option->name);
- if (*arg == ',' && !verbatim && !(option->flags & GC_OPT_FLAG_LIST))
+ if (*arg == ',' && !verbatim && !option->is_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)
@@ -2667,328 +2091,7 @@ copy_file (const char *src_name, const char *dst_name)
/* Create and verify the new configuration file for the specified
- * backend and component. Returns 0 on success and -1 on error. This
- * function may store pointers to malloced strings in SRC_FILENAMEP,
- * DEST_FILENAMEP, and ORIG_FILENAMEP. Those must be freed by the
- * caller. The strings refer to three versions of the configuration
- * file:
- *
- * SRC_FILENAME: The updated configuration is written to this file.
- * DEST_FILENAME: Name of the configuration file read by the
- * component.
- * ORIG_FILENAME: A backup of the previous configuration file.
- *
- * To apply the configuration change, rename SRC_FILENAME to
- * DEST_FILENAME. To revert to the previous configuration, rename
- * ORIG_FILENAME to DEST_FILENAME. */
-static int
-change_options_file (gc_component_t component, gc_backend_t backend,
- char **src_filenamep, char **dest_filenamep,
- char **orig_filenamep)
-{
- static const char marker[] = "###+++--- " GPGCONF_DISP_NAME " ---+++###";
- /* True if we are within the marker in the config file. */
- int in_marker = 0;
- gc_option_t *option;
- char *line = NULL;
- size_t line_len;
- ssize_t length;
- int res;
- int fd;
- gpgrt_stream_t src_file = NULL;
- gpgrt_stream_t dest_file = NULL;
- char *src_filename;
- char *dest_filename;
- char *orig_filename;
- char *arg;
- char *cur_arg = NULL;
-
- option = find_option (component,
- gc_backend[backend].option_name, GC_BACKEND_ANY);
- log_assert (option);
- log_assert (option->active);
- log_assert (gc_arg_type[option->arg_type].fallback != GC_ARG_TYPE_NONE);
-
- /* FIXME. Throughout the function, do better error reporting. */
- /* Note that get_config_filename() calls percent_deescape(), so we
- call this before processing the arguments. */
- dest_filename = xstrdup (get_config_filename (component, backend));
- src_filename = xasprintf ("%s.%s.%i.new",
- dest_filename, GPGCONF_NAME, (int)getpid ());
- orig_filename = xasprintf ("%s.%s.%i.bak",
- dest_filename, GPGCONF_NAME, (int)getpid ());
-
- arg = option->new_value;
- if (arg && arg[0] == '\0')
- arg = NULL;
- else if (arg)
- {
- char *end;
-
- arg++;
- end = strchr (arg, ',');
- if (end)
- *end = '\0';
-
- cur_arg = percent_deescape (arg);
- if (end)
- {
- *end = ',';
- arg = end + 1;
- }
- else
- arg = NULL;
- }
-
-#ifdef HAVE_W32_SYSTEM
- res = copy_file (dest_filename, orig_filename);
-#else
- res = link (dest_filename, orig_filename);
-#endif
- if (res < 0 && errno != ENOENT)
- {
- xfree (dest_filename);
- xfree (src_filename);
- xfree (orig_filename);
- return -1;
- }
- if (res < 0)
- {
- 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;
- *dest_filenamep = dest_filename;
- *orig_filenamep = orig_filename;
-
- /* Use open() so that we can use O_EXCL. */
- fd = open (src_filename, O_CREAT | O_EXCL | O_WRONLY, 0644);
- if (fd < 0)
- return -1;
- src_file = gpgrt_fdopen (fd, "w");
- res = errno;
- if (!src_file)
- {
- gpg_err_set_errno (res);
- return -1;
- }
-
- /* Only if ORIG_FILENAME is not NULL did the configuration file
- exist already. In this case, we will copy its content into the
- new configuration file, changing it to our liking in the
- process. */
- if (orig_filename)
- {
- dest_file = gpgrt_fopen (dest_filename, "r");
- if (!dest_file)
- goto change_file_one_err;
-
- while ((length = gpgrt_read_line (dest_file, &line, &line_len, NULL)) > 0)
- {
- int disable = 0;
- char *start;
-
- if (!strncmp (marker, line, sizeof (marker) - 1))
- {
- if (!in_marker)
- in_marker = 1;
- else
- break;
- }
-
- start = line;
- while (*start == ' ' || *start == '\t')
- start++;
- if (*start && *start != '\r' && *start != '\n' && *start != '#')
- {
- char *end;
- char *endp;
- char saved_end;
-
- endp = start;
- end = endp;
-
- /* Search for the end of the line. */
- while (*endp && *endp != '#' && *endp != '\r' && *endp != '\n')
- {
- endp++;
- if (*endp && *endp != ' ' && *endp != '\t'
- && *endp != '\r' && *endp != '\n' && *endp != '#')
- end = endp + 1;
- }
- saved_end = *end;
- *end = '\0';
-
- if ((option->new_flags & GC_OPT_FLAG_DEFAULT)
- || !cur_arg || strcmp (start, cur_arg))
- disable = 1;
- else
- {
- /* Find next argument. */
- if (arg)
- {
- char *arg_end;
-
- arg++;
- arg_end = strchr (arg, ',');
- if (arg_end)
- *arg_end = '\0';
-
- cur_arg = percent_deescape (arg);
- if (arg_end)
- {
- *arg_end = ',';
- arg = arg_end + 1;
- }
- else
- arg = NULL;
- }
- else
- cur_arg = NULL;
- }
-
- *end = saved_end;
- }
-
- if (disable)
- {
- if (!in_marker)
- {
- gpgrt_fprintf (src_file,
- "# %s disabled this option here at %s\n",
- GPGCONF_DISP_NAME, asctimestamp (gnupg_get_time ()));
- if (gpgrt_ferror (src_file))
- goto change_file_one_err;
- gpgrt_fprintf (src_file, "# %s", line);
- if (gpgrt_ferror (src_file))
- goto change_file_one_err;
- }
- }
- else
- {
- gpgrt_fprintf (src_file, "%s", line);
- if (gpgrt_ferror (src_file))
- goto change_file_one_err;
- }
- }
- if (length < 0 || gpgrt_ferror (dest_file))
- goto change_file_one_err;
- }
-
- if (!in_marker)
- {
- /* There was no marker. This is the first time we edit the
- file. We add our own marker at the end of the file and
- proceed. Note that we first write a newline, this guards us
- against files which lack the newline at the end of the last
- line, while it doesn't hurt us in all other cases. */
- gpgrt_fprintf (src_file, "\n%s\n", marker);
- if (gpgrt_ferror (src_file))
- goto change_file_one_err;
- }
-
- /* At this point, we have copied everything up to the end marker
- into the new file, except for the arguments we are going to add.
- Now, dump the new arguments and write the end marker, possibly
- followed by the rest of the original file. */
- while (cur_arg)
- {
- gpgrt_fprintf (src_file, "%s\n", cur_arg);
-
- /* Find next argument. */
- if (arg)
- {
- char *end;
-
- arg++;
- end = strchr (arg, ',');
- if (end)
- *end = '\0';
-
- cur_arg = percent_deescape (arg);
- if (end)
- {
- *end = ',';
- arg = end + 1;
- }
- else
- arg = NULL;
- }
- else
- cur_arg = NULL;
- }
-
- gpgrt_fprintf (src_file, "%s %s\n", marker, asctimestamp (gnupg_get_time ()));
- if (gpgrt_ferror (src_file))
- goto change_file_one_err;
-
- if (!in_marker)
- {
- gpgrt_fprintf (src_file, "# %s edited this configuration file.\n",
- GPGCONF_DISP_NAME);
- if (gpgrt_ferror (src_file))
- goto change_file_one_err;
- gpgrt_fprintf (src_file, "# It will disable options before this marked "
- "block, but it will\n");
- if (gpgrt_ferror (src_file))
- goto change_file_one_err;
- gpgrt_fprintf (src_file, "# never change anything below these lines.\n");
- if (gpgrt_ferror (src_file))
- goto change_file_one_err;
- }
- if (dest_file)
- {
- while ((length = gpgrt_read_line (dest_file, &line, &line_len, NULL)) > 0)
- {
- gpgrt_fprintf (src_file, "%s", line);
- if (gpgrt_ferror (src_file))
- goto change_file_one_err;
- }
- if (length < 0 || gpgrt_ferror (dest_file))
- goto change_file_one_err;
- }
- xfree (line);
- line = NULL;
-
- res = gpgrt_fclose (src_file);
- if (res)
- {
- res = errno;
- close (fd);
- if (dest_file)
- gpgrt_fclose (dest_file);
- gpg_err_set_errno (res);
- return -1;
- }
- close (fd);
- if (dest_file)
- {
- res = gpgrt_fclose (dest_file);
- if (res)
- return -1;
- }
- return 0;
-
- change_file_one_err:
- xfree (line);
- res = errno;
- if (src_file)
- {
- gpgrt_fclose (src_file);
- close (fd);
- }
- if (dest_file)
- gpgrt_fclose (dest_file);
- gpg_err_set_errno (res);
- return -1;
-}
-
-
-/* Create and verify the new configuration file for the specified
- * backend and component. Returns 0 on success and -1 on error. If
+ * component. Returns 0 on success and -1 on error. If
* VERBATIM is set the profile mode is used. This function may store
* pointers to malloced strings in SRC_FILENAMEP, DEST_FILENAMEP, and
* ORIG_FILENAMEP. Those must be freed by the caller. The strings
@@ -3003,7 +2106,7 @@ change_options_file (gc_component_t component, gc_backend_t backend,
* DEST_FILENAME. To revert to the previous configuration, rename
* ORIG_FILENAME to DEST_FILENAME. */
static int
-change_options_program (gc_component_t component, gc_backend_t backend,
+change_options_program (gc_component_id_t component,
char **src_filenamep, char **dest_filenamep,
char **orig_filenamep,
int verbatim)
@@ -3025,8 +2128,14 @@ change_options_program (gc_component_t component, gc_backend_t backend,
/* Special hack for gpg, see below. */
int utf8strings_seen = 0;
+
/* FIXME. Throughout the function, do better error reporting. */
- dest_filename = xstrdup (get_config_filename (component, backend));
+ if (!gc_component[component].option_config_filename)
+ gc_error (1, 0, "name of config file for %s is not known\n",
+ gc_component[component].name);
+
+ dest_filename = make_absfilename
+ (gnupg_homedir (), gc_component[component].option_config_filename, NULL);
src_filename = xasprintf ("%s.%s.%i.new",
dest_filename, GPGCONF_NAME, (int)getpid ());
orig_filename = xasprintf ("%s.%s.%i.bak",
@@ -3090,7 +2199,7 @@ change_options_program (gc_component_t component, gc_backend_t backend,
else
break;
}
- else if (backend == GC_BACKEND_GPG && in_marker
+ else if (component == GC_COMPONENT_GPG && in_marker
&& ! strcmp ("utf8-strings\n", line))
{
/* Strip duplicated entries. */
@@ -3115,7 +2224,7 @@ change_options_program (gc_component_t component, gc_backend_t backend,
saved_end = *end;
*end = '\0';
- option = find_option (component, start, backend);
+ option = find_option (component, start);
*end = saved_end;
if (option && ((option->new_flags & GC_OPT_FLAG_DEFAULT)
|| option->new_value))
@@ -3164,15 +2273,13 @@ change_options_program (gc_component_t component, gc_backend_t backend,
followed by the rest of the original file. */
/* We have to turn on UTF8 strings for GnuPG. */
- if (backend == GC_BACKEND_GPG && ! utf8strings_seen)
+ if (component == GC_COMPONENT_GPG && ! utf8strings_seen)
gpgrt_fprintf (src_file, "utf8-strings\n");
option = gc_component[component].options;
- while (option->name)
+ for ( ; option->name; option++)
{
- if (!(option->flags & GC_OPT_FLAG_GROUP)
- && option->backend == backend
- && option->new_value)
+ if (!option->is_header && option->new_value)
{
char *arg = option->new_value;
@@ -3243,7 +2350,6 @@ change_options_program (gc_component_t component, gc_backend_t backend,
}
while (arg && *arg);
}
- option++;
}
gpgrt_fprintf (src_file, "%s %s\n", marker, asctimestamp (gnupg_get_time ()));
@@ -3316,21 +2422,23 @@ change_options_program (gc_component_t component, gc_backend_t backend,
* gc_process_gpgconf_conf. If VERBATIM is set the profile parsing
* mode is used. */
static void
-change_one_value (gc_option_t *option, int *runtime,
+change_one_value (gc_component_id_t component,
+ gc_option_t *option, int *r_runtime,
unsigned long flags, char *new_value, int verbatim)
{
unsigned long new_value_nr = 0;
- option_check_validity (option, flags, new_value, &new_value_nr, verbatim);
+ option_check_validity (component, option,
+ flags, new_value, &new_value_nr, verbatim);
- if (option->flags & GC_OPT_FLAG_RUNTIME)
- runtime[option->backend] = 1;
+ if (option->runtime)
+ *r_runtime = 1;
option->new_flags = flags;
if (!(flags & GC_OPT_FLAG_DEFAULT))
{
if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE
- && (option->flags & GC_OPT_FLAG_LIST))
+ && option->is_list)
{
char *str;
@@ -3362,11 +2470,10 @@ gc_component_change_options (int component, estream_t in, estream_t out,
{
int err = 0;
int block = 0;
- int runtime[GC_BACKEND_NR];
- char *src_filename[GC_BACKEND_NR];
- char *dest_filename[GC_BACKEND_NR];
- char *orig_filename[GC_BACKEND_NR];
- gc_backend_t backend;
+ int runtime = 0;
+ char *src_filename = NULL;
+ char *dest_filename = NULL;
+ char *orig_filename = NULL;
gc_option_t *option;
char *line = NULL;
size_t line_len = 0;
@@ -3375,14 +2482,6 @@ gc_component_change_options (int component, estream_t in, estream_t out,
if (component == GC_COMPONENT_PINENTRY)
return; /* Dummy component for now. */
- for (backend = 0; backend < GC_BACKEND_NR; backend++)
- {
- runtime[backend] = 0;
- src_filename[backend] = NULL;
- dest_filename[backend] = NULL;
- orig_filename[backend] = NULL;
- }
-
if (in)
{
/* Read options from the file IN. */
@@ -3435,18 +2534,18 @@ gc_component_change_options (int component, estream_t in, estream_t out,
linep = end;
}
- option = find_option (component, line, GC_BACKEND_ANY);
+ option = find_option (component, line);
if (!option)
gc_error (1, 0, "unknown option %s", line);
- if ((option->flags & GC_OPT_FLAG_NO_CHANGE))
+ if (option->no_change)
{
gc_error (0, 0, "ignoring new value for option %s",
option->name);
continue;
}
- change_one_value (option, runtime, flags, new_value, 0);
+ change_one_value (component, option, &runtime, flags, new_value, 0);
}
if (length < 0 || gpgrt_ferror (in))
gc_error (1, errno, "error reading stream 'in'");
@@ -3458,27 +2557,24 @@ gc_component_change_options (int component, estream_t in, estream_t out,
option = gc_component[component].options;
while (option && option->name)
{
- /* Go on if we have already seen this backend, or if there is
- nothing to do. */
- if (src_filename[option->backend]
- || !(option->new_flags || option->new_value))
+ /* Go on if there is nothing to do. */
+ if (src_filename || !(option->new_flags || option->new_value))
{
option++;
continue;
}
- if (gc_backend[option->backend].program)
+ if (gc_component[component].program)
{
- err = change_options_program (component, option->backend,
- &src_filename[option->backend],
- &dest_filename[option->backend],
- &orig_filename[option->backend],
+ err = change_options_program (component,
+ &src_filename,
+ &dest_filename,
+ &orig_filename,
verbatim);
if (! err)
{
/* External verification. */
- err = gc_component_check_options (component, out,
- src_filename[option->backend]);
+ err = gc_component_check_options (component, out, src_filename);
if (err)
{
gc_error (0, 0,
@@ -3489,12 +2585,6 @@ gc_component_change_options (int component, estream_t in, estream_t out,
}
}
- else
- err = change_options_file (component, option->backend,
- &src_filename[option->backend],
- &dest_filename[option->backend],
- &orig_filename[option->backend]);
-
if (err)
break;
@@ -3509,70 +2599,62 @@ gc_component_change_options (int component, estream_t in, estream_t out,
block = 1;
gnupg_block_all_signals ();
- if (! err && ! opt.dry_run)
+ if (!err && !opt.dry_run)
{
- int i;
-
- for (i = 0; i < GC_BACKEND_NR; i++)
- {
- if (src_filename[i])
- {
- /* FIXME: Make a verification here. */
+ if (src_filename)
+ {
+ /* FIXME: Make a verification here. */
- log_assert (dest_filename[i]);
+ log_assert (dest_filename);
- if (orig_filename[i])
- err = gnupg_rename_file (src_filename[i], dest_filename[i], NULL);
- else
- {
+ if (orig_filename)
+ err = gnupg_rename_file (src_filename, dest_filename, NULL);
+ else
+ {
#ifdef HAVE_W32_SYSTEM
- /* We skip the unlink if we expect the file not to
- be there. */
- err = gnupg_rename_file (src_filename[i], dest_filename[i], NULL);
+ /* We skip the unlink if we expect the file not to be
+ * there. */
+ err = gnupg_rename_file (src_filename, dest_filename, NULL);
#else /* HAVE_W32_SYSTEM */
- /* This is a bit safer than rename() because we
- expect DEST_FILENAME not to be there. If it
- happens to be there, this will fail. */
- err = link (src_filename[i], dest_filename[i]);
- if (!err)
- err = unlink (src_filename[i]);
+ /* This is a bit safer than rename() because we expect
+ * DEST_FILENAME not to be there. If it happens to be
+ * there, this will fail. */
+ err = link (src_filename, dest_filename);
+ if (!err)
+ err = unlink (src_filename);
#endif /* !HAVE_W32_SYSTEM */
- }
- if (err)
- break;
- xfree (src_filename[i]);
- src_filename[i] = NULL;
- }
- }
+ }
+ if (!err)
+ {
+ xfree (src_filename);
+ src_filename = NULL;
+ }
+ }
}
if (err || opt.dry_run)
{
- int i;
int saved_errno = errno;
/* An error occurred or a dry-run is requested. */
- for (i = 0; i < GC_BACKEND_NR; i++)
- {
- if (src_filename[i])
- {
- /* The change was not yet committed. */
- unlink (src_filename[i]);
- if (orig_filename[i])
- unlink (orig_filename[i]);
- }
- else
- {
- /* The changes were already committed. FIXME: This is a
- tad dangerous, as we don't know if we don't overwrite
- a version of the file that is even newer than the one
- we just installed. */
- if (orig_filename[i])
- gnupg_rename_file (orig_filename[i], dest_filename[i], NULL);
- else
- unlink (dest_filename[i]);
- }
- }
+ if (src_filename)
+ {
+ /* The change was not yet committed. */
+ unlink (src_filename);
+ if (orig_filename)
+ unlink (orig_filename);
+ }
+ else
+ {
+ /* The changes were already committed. FIXME: This is a tad
+ dangerous, as we don't know if we don't overwrite a
+ version of the file that is even newer than the one we
+ just installed. */
+ if (orig_filename)
+ gnupg_rename_file (orig_filename, dest_filename, NULL);
+ else
+ unlink (dest_filename);
+ }
if (err)
gc_error (1, saved_errno, "could not commit changes");
@@ -3582,36 +2664,29 @@ gc_component_change_options (int component, estream_t in, estream_t out,
/* If it all worked, notify the daemons of the changes. */
if (opt.runtime)
- for (backend = 0; backend < GC_BACKEND_NR; backend++)
- {
- if (runtime[backend] && gc_backend[backend].runtime_change)
- (*gc_backend[backend].runtime_change) (0);
- }
+ do_runtime_change (component, 0);
+
/* Move the per-process backup file into its place. */
- for (backend = 0; backend < GC_BACKEND_NR; backend++)
- if (orig_filename[backend])
- {
- char *backup_filename;
+ if (orig_filename)
+ {
+ char *backup_filename;
- log_assert (dest_filename[backend]);
+ log_assert (dest_filename);
- backup_filename = xasprintf ("%s.%s.bak",
- dest_filename[backend], GPGCONF_NAME);
- gnupg_rename_file (orig_filename[backend], backup_filename, NULL);
- xfree (backup_filename);
- }
+ backup_filename = xasprintf ("%s.%s.bak",
+ dest_filename, GPGCONF_NAME);
+ gnupg_rename_file (orig_filename, backup_filename, NULL);
+ xfree (backup_filename);
+ }
leave:
if (block)
gnupg_unblock_all_signals ();
xfree (line);
- for (backend = 0; backend < GC_BACKEND_NR; backend++)
- {
- xfree (src_filename[backend]);
- xfree (dest_filename[backend]);
- xfree (orig_filename[backend]);
- }
+ xfree (src_filename);
+ xfree (dest_filename);
+ xfree (orig_filename);
}
@@ -3743,8 +2818,8 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults,
int lineno = 0;
int in_rule = 0;
int got_match = 0;
- int runtime[GC_BACKEND_NR];
- int backend_id, component_id;
+ int runtime[GC_COMPONENT_NR] = { 0 };
+ int component_id;
char *fname;
if (fname_arg)
@@ -3753,9 +2828,6 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults,
fname = make_filename (gnupg_sysconfdir (), GPGCONF_NAME EXTSEP_S "conf",
NULL);
- for (backend_id = 0; backend_id < GC_BACKEND_NR; backend_id++)
- runtime[backend_id] = 0;
-
config = gpgrt_fopen (fname, "r");
if (!config)
{
@@ -3772,7 +2844,7 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults,
while ((length = gpgrt_read_line (config, &line, &line_len, NULL)) > 0)
{
- char *key, *component, *option, *flags, *value;
+ char *key, *compname, *option, *flags, *value;
char *empty;
gc_option_t *option_info = NULL;
char *p;
@@ -3806,7 +2878,7 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults,
continue;
}
*p++ = 0;
- component = p;
+ compname = p;
}
else if (!in_rule)
{
@@ -3817,18 +2889,18 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults,
}
else
{
- component = key;
+ compname = key;
key = NULL;
}
in_rule = 1;
/* Parse the component. */
- while (*component == ' ' || *component == '\t')
- component++;
- for (p=component; *p && !strchr (" \t\r\n", *p); p++)
+ while (*compname == ' ' || *compname == '\t')
+ compname++;
+ for (p=compname; *p && !strchr (" \t\r\n", *p); p++)
;
- if (p == component)
+ if (p == compname)
{
gc_error (0, 0, "missing component at '%s', line %d",
fname, lineno);
@@ -3842,7 +2914,7 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults,
empty = p;
*p++ = 0;
option = p;
- component_id = gc_component_find (component);
+ component_id = gc_component_find (compname);
if (component_id < 0)
{
gc_error (0, 0, "unknown component at '%s', line %d",
@@ -3874,11 +2946,15 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults,
flags = p;
if ( component_id != -1)
{
- option_info = find_option (component_id, option, GC_BACKEND_ANY);
+ /* We need to make sure that we got the option list for the
+ * component. */
+ if (!gc_component[component_id].options)
+ gc_component_retrieve_options (component_id);
+ option_info = find_option (component_id, option);
if (!option_info)
{
- gc_error (0, 0, "unknown option at '%s', line %d",
- fname, lineno);
+ gc_error (0, 0, "unknown option '%s' at '%s', line %d",
+ option, fname, lineno);
gpgconf_write_status (STATUS_WARNING,
"gpgconf.conf %d file '%s' line %d "
"unknown option",
@@ -3999,9 +3075,9 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults,
else if (!strcmp (flags, "default"))
newflags |= GC_OPT_FLAG_DEFAULT;
else if (!strcmp (flags, "no-change"))
- option_info->flags |= GC_OPT_FLAG_NO_CHANGE;
+ option_info->no_change = 1;
else if (!strcmp (flags, "change"))
- option_info->flags &= ~GC_OPT_FLAG_NO_CHANGE;
+ option_info->no_change = 0;
if (defaults)
{
@@ -4015,7 +3091,8 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults,
xfree (option_info->new_value);
option_info->new_value = NULL;
}
- change_one_value (option_info, runtime, newflags, value, 0);
+ change_one_value (component_id, option_info,
+ runtime, newflags, value, 0);
}
}
}
@@ -4046,9 +3123,10 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults,
if (opt.runtime)
{
- for (backend_id = 0; backend_id < GC_BACKEND_NR; backend_id++)
- if (runtime[backend_id] && gc_backend[backend_id].runtime_change)
- (*gc_backend[backend_id].runtime_change) (0);
+ for (component_id = 0; component_id < GC_COMPONENT_NR; component_id++)
+ if (runtime[component_id]
+ && gc_component[component_id].runtime_change)
+ (*gc_component[component_id].runtime_change) (0);
}
}
@@ -4070,8 +3148,7 @@ gc_apply_profile (const char *fname)
ssize_t length;
estream_t fp;
int lineno = 0;
- int runtime[GC_BACKEND_NR];
- int backend_id;
+ int runtime[GC_COMPONENT_NR] = { 0 };
int component_id = -1;
int skip_section = 0;
int error_count = 0;
@@ -4080,9 +3157,6 @@ gc_apply_profile (const char *fname)
if (!fname)
fname = "-";
- for (backend_id = 0; backend_id < GC_BACKEND_NR; backend_id++)
- runtime[backend_id] = 0;
-
if (!(!strcmp (fname, "-")
|| strchr (fname, '/')
@@ -4173,7 +3247,7 @@ gc_apply_profile (const char *fname)
*p++ = 0;
value = p;
- option_info = find_option (component_id, name, GC_BACKEND_ANY);
+ option_info = find_option (component_id, name);
if (!option_info)
{
error_count++;
@@ -4220,7 +3294,7 @@ gc_apply_profile (const char *fname)
xfree (option_info->new_value);
option_info->new_value = NULL;
}
- change_one_value (option_info, runtime, newflags, value, 1);
+ change_one_value (component_id, option_info, runtime, newflags, value, 1);
}
if (length < 0 || es_ferror (fp))
@@ -4253,9 +3327,10 @@ gc_apply_profile (const char *fname)
if (opt.runtime)
{
- for (backend_id = 0; backend_id < GC_BACKEND_NR; backend_id++)
- if (runtime[backend_id] && gc_backend[backend_id].runtime_change)
- (*gc_backend[backend_id].runtime_change) (0);
+ for (component_id = 0; component_id < GC_COMPONENT_NR; component_id++)
+ if (runtime[component_id]
+ && gc_component[component_id].runtime_change)
+ (*gc_component[component_id].runtime_change) (0);
}
}