aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/gpgconf-comp.c136
1 files changed, 108 insertions, 28 deletions
diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c
index 579161f8e..225c3e82c 100644
--- a/tools/gpgconf-comp.c
+++ b/tools/gpgconf-comp.c
@@ -421,13 +421,18 @@ static known_option_t known_options_gpg[] =
{ "use-keyboxd", 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 next is a pseudo option which we read via --gpgconf-list.
+ * The meta information is taken from the table below. */
+ { "default_pubkey_algo", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE },
{ NULL }
};
+static const char *known_pseudo_options_gpg[] =
+ {/* v-- ARGPARSE_TYPE_STRING */
+ "default_pubkey_algo:0:2:@:",
+ NULL
+ };
/* The known options of the GC_COMPONENT_GPGSM component. */
@@ -458,12 +463,16 @@ static known_option_t known_options_gpgsm[] =
{ "use-keyboxd", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE },
- /* Pseudo option follows. */
- { "default_pubkey_algo",
- (GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_NO_CHANGE), GC_LEVEL_INVISIBLE },
+ /* Pseudo option follows. See also table below. */
+ { "default_pubkey_algo", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE },
{ NULL }
};
+static const char *known_pseudo_options_gpgsm[] =
+ {/* v-- ARGPARSE_TYPE_STRING */
+ "default_pubkey_algo:0:2:@:",
+ NULL
+ };
/* The known options of the GC_COMPONENT_DIRMNGR component. */
@@ -604,6 +613,9 @@ static struct
/* The static table of known options for this component. */
known_option_t *known_options;
+ /* The static table of known pseudo options for this component or NULL. */
+ const char **known_pseudo_options;
+
/* The runtime change callback. If KILLFLAG is true the component
is killed and not just reloaded. */
void (*runtime_change) (int killflag);
@@ -629,31 +641,31 @@ static struct
{ GPG_NAME, GPG_DISP_NAME, "gnupg", N_("OpenPGP"),
GNUPG_MODULE_NAME_GPG, GPG_NAME ".conf",
- known_options_gpg },
+ known_options_gpg, known_pseudo_options_gpg },
{ GPGSM_NAME, GPGSM_DISP_NAME, "gnupg", N_("S/MIME"),
GNUPG_MODULE_NAME_GPGSM, GPGSM_NAME ".conf",
- known_options_gpgsm },
+ known_options_gpgsm, known_pseudo_options_gpgsm },
{ KEYBOXD_NAME, KEYBOXD_DISP_NAME, "gnupg", N_("Public Keys"),
GNUPG_MODULE_NAME_KEYBOXD, KEYBOXD_NAME ".conf",
- known_options_keyboxd, keyboxd_runtime_change },
+ known_options_keyboxd, NULL, keyboxd_runtime_change },
{ 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 },
+ known_options_gpg_agent, NULL, 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},
+ known_options_scdaemon, NULL, scdaemon_runtime_change},
{ TPM2DAEMON_NAME, TPM2DAEMON_DISP_NAME, "gnupg", N_("TPM"),
GNUPG_MODULE_NAME_TPM2DAEMON, TPM2DAEMON_NAME ".conf",
- known_options_tpm2daemon, tpm2daemon_runtime_change},
+ known_options_tpm2daemon, NULL, tpm2daemon_runtime_change},
{ DIRMNGR_NAME, DIRMNGR_DISP_NAME, "gnupg", N_("Network"),
GNUPG_MODULE_NAME_DIRMNGR, DIRMNGR_NAME ".conf",
- known_options_dirmngr, dirmngr_runtime_change },
+ known_options_dirmngr, NULL, dirmngr_runtime_change },
{ "pinentry", "Pinentry", "gnupg", N_("Passphrase Entry"),
GNUPG_MODULE_NAME_PINENTRY, NULL,
@@ -1612,7 +1624,49 @@ find_option (gc_component_id_t component, const char *name)
}
+
+struct read_line_wrapper_parm_s
+{
+ const char *pgmname;
+ estream_t fp;
+ char *line;
+ size_t line_len;
+ const char **extra_lines;
+ int extra_lines_idx;
+ char *extra_line_buffer;
+};
+
+
+/* Helper for retrieve_options_from_program. */
+static ssize_t
+read_line_wrapper (struct read_line_wrapper_parm_s *parm)
+{
+ ssize_t length;
+ const char *extra_line;
+
+ if (parm->fp)
+ {
+ length = es_read_line (parm->fp, &parm->line, &parm->line_len, NULL);
+ if (length > 0)
+ return length;
+ if (length < 0 || es_ferror (parm->fp))
+ gc_error (1, errno, "error reading from %s", parm->pgmname);
+ if (es_fclose (parm->fp))
+ gc_error (1, errno, "error closing %s", parm->pgmname);
+ /* EOF seen. */
+ parm->fp = NULL;
+ }
+ /* Return the made up lines. */
+ if (!parm->extra_lines
+ || !(extra_line = parm->extra_lines[parm->extra_lines_idx]))
+ return -1; /* This is really the EOF. */
+ parm->extra_lines_idx++;
+ xfree (parm->extra_line_buffer);
+ parm->extra_line_buffer = xstrdup (extra_line);
+ return strlen (parm->extra_line_buffer);
+}
+
/* Retrieve the options for the component COMPONENT. With
* ONLY_INSTALLED set components which are not installed are silently
* ignored. */
@@ -1628,7 +1682,7 @@ retrieve_options_from_program (gc_component_id_t component, int only_installed)
known_option_t *known_option;
gc_option_t *option;
char *line = NULL;
- size_t line_len = 0;
+ size_t line_len;
ssize_t length;
const char *config_name;
gpgrt_argparse_t pargs;
@@ -1641,6 +1695,8 @@ retrieve_options_from_program (gc_component_id_t component, int only_installed)
size_t opt_info_used = 0; /* Its current length. */
size_t opt_info_size = 0; /* Its allocated length. */
int i;
+ struct read_line_wrapper_parm_s read_line_parm;
+ int pseudo_count;
pgmname = (gc_component[component].module_name
? gnupg_module_name (gc_component[component].module_name)
@@ -1663,13 +1719,32 @@ retrieve_options_from_program (gc_component_id_t component, int only_installed)
pgmname, gpg_strerror (err));
}
- while ((length = es_read_line (outfp, &line, &line_len, NULL)) > 0)
+ read_line_parm.pgmname = pgmname;
+ read_line_parm.fp = outfp;
+ read_line_parm.line = line;
+ read_line_parm.line_len = line_len = 0;
+ read_line_parm.extra_line_buffer = NULL;
+ read_line_parm.extra_lines = gc_component[component].known_pseudo_options;
+ read_line_parm.extra_lines_idx = 0;
+ pseudo_count = 0;
+ while ((length = read_line_wrapper (&read_line_parm)) > 0)
{
const char *fields[4];
const char *optname, *optdesc;
unsigned int optflags;
int short_opt;
gc_arg_type_t arg_type;
+ int pseudo = 0;
+
+
+ if (read_line_parm.extra_line_buffer)
+ {
+ line = read_line_parm.extra_line_buffer;
+ pseudo = 1;
+ pseudo_count++;
+ }
+ else
+ line = read_line_parm.line;
/* Strip newline and carriage return, if present. */
while (length > 0
@@ -1685,14 +1760,13 @@ retrieve_options_from_program (gc_component_id_t component, int only_installed)
optname = fields[0];
short_opt = atoi (fields[1]);
- if (short_opt < 1)
+ if (short_opt < 1 && !pseudo)
{
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. */
@@ -1724,7 +1798,7 @@ retrieve_options_from_program (gc_component_id_t component, int only_installed)
sizeof *opt_info);
}
/* The +1 here accounts for the two items we are going to add to
- * the global string table. */
+ * the global string table. */
if (string_array_used + 1 >= string_array_size)
{
string_array_size += 256;
@@ -1745,11 +1819,14 @@ retrieve_options_from_program (gc_component_id_t component, int only_installed)
* 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 = short_opt;
- opt_table[opt_table_used].description = optdesc;
- opt_table[opt_table_used].flags = optflags;
- opt_table_used++;
+ if (!pseudo)
+ {
+ opt_table[opt_table_used].long_opt = optname;
+ opt_table[opt_table_used].short_opt = short_opt;
+ opt_table[opt_table_used].description = optdesc;
+ opt_table[opt_table_used].flags = optflags;
+ opt_table_used++;
+ }
/* Note that as per argparser specs the opt_table uses "@" to
* specifify an empty description. In the DESC script of
@@ -1770,6 +1847,9 @@ retrieve_options_from_program (gc_component_id_t component, int only_installed)
default: arg_type = GC_ARG_TYPE_NONE; break;
}
opt_info[opt_info_used].arg_type = arg_type;
+ if (pseudo) /* Pseudo options are always no_change. */
+ opt_info[opt_info_used].no_change = 1;
+
if ((optflags & ARGPARSE_OPT_HEADER))
opt_info[opt_info_used].is_header = 1;
@@ -1792,11 +1872,11 @@ retrieve_options_from_program (gc_component_id_t component, int only_installed)
}
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);
+ xfree (read_line_parm.extra_line_buffer);
+ line = read_line_parm.line;
+ line_len = read_line_parm.line_len;
+ log_assert (opt_table_used + pseudo_count == opt_info_used);
+
err = gnupg_wait_process (pgmname, pid, 1, &exitcode);
if (err)