diff options
author | Marcus Brinkmann <mb@g10code.com> | 2008-05-20 00:46:41 +0200 |
---|---|---|
committer | Marcus Brinkmann <mb@g10code.com> | 2008-05-20 00:46:41 +0200 |
commit | 7d714a378864eef96cb6f4b4bc3cd2833149f42a (patch) | |
tree | ad9a5a2c37dc82761ee204b143fa7d6fea27c6b5 /tools | |
parent | 2008-05-15 Marcus Brinkmann <marcus@g10code.de> (diff) | |
download | gnupg2-7d714a378864eef96cb6f4b4bc3cd2833149f42a.tar.xz gnupg2-7d714a378864eef96cb6f4b4bc3cd2833149f42a.zip |
doc/
2008-05-20 Marcus Brinkmann <marcus@g10code.de>
* tools.texi (Invoking gpgconf): Add --dry-run and --check-options.
(Checking programs): Document --check-options.
tools/
2008-05-20 Marcus Brinkmann <marcus@g10code.de>
* gpgconf.h (gc_component_check_programs): Rename to ...
(gc_check_programs): ... this.
(gc_component_change_options): Add argument OUT.
(gc_component_check_options): New function.
* gpgconf.c (enum cmd_and_opt_values): New option aCheckOptions.
(opts): Add new option aCheckOptions (aka --check-options).
(main): Handle new option aCheckOptions.
* gpgconf-comp.c (gc_component_check_programs): Rename to ...
(gc_check_programs): ... this. Refactor core of it to ...
(gc_component_check_options): ... this new function.
(gc_component_change_options): Add new argument OUT. Externally
verify all changes. Implement option --dry-run.
Diffstat (limited to 'tools')
-rw-r--r-- | tools/ChangeLog | 15 | ||||
-rw-r--r-- | tools/gpgconf-comp.c | 251 | ||||
-rw-r--r-- | tools/gpgconf.c | 10 | ||||
-rw-r--r-- | tools/gpgconf.h | 9 |
4 files changed, 177 insertions, 108 deletions
diff --git a/tools/ChangeLog b/tools/ChangeLog index 6638be57a..a28b774da 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,18 @@ +2008-05-20 Marcus Brinkmann <marcus@g10code.de> + + * gpgconf.h (gc_component_check_programs): Rename to ... + (gc_check_programs): ... this. + (gc_component_change_options): Add argument OUT. + (gc_component_check_options): New function. + * gpgconf.c (enum cmd_and_opt_values): New option aCheckOptions. + (opts): Add new option aCheckOptions (aka --check-options). + (main): Handle new option aCheckOptions. + * gpgconf-comp.c (gc_component_check_programs): Rename to ... + (gc_check_programs): ... this. Refactor core of it to ... + (gc_component_check_options): ... this new function. + (gc_component_change_options): Add new argument OUT. Externally + verify all changes. Implement option --dry-run. + 2008-05-09 Werner Koch <wk@g10code.com> * gpgconf-comp.c (my_dgettext) [USE_SIMPLE_GETTEXT]: Hack to diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 664589b9c..5dc32d6eb 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -1317,118 +1317,140 @@ collect_error_output (int fd, const char *tag) } - -/* Check all components that are available. */ -void -gc_component_check_programs (FILE *out) +/* Check the options of a single component. Returns 0 if everything + is OK. */ +int +gc_component_check_options (int component, FILE *out, const char *conf_file) { gpg_error_t err; - gc_component_t component; unsigned int result; int backend_seen[GC_BACKEND_NR]; gc_backend_t backend; gc_option_t *option; - const char *desc; const char *pgmname; - const char *argv[2]; + const char *argv[4]; + int i; pid_t pid; int exitcode; int filedes[2]; - error_line_t errlines, errptr; + error_line_t errlines; /* We use a temporary file to collect the error output. It would be better to use a pipe here but as of now we have no suitable fucntion to create a portable pipe outside of exechelp. Thus it is easier to use the tempfile approach. */ - for (component = 0; component < GC_COMPONENT_NR; component++) + + for (backend = 0; backend < GC_BACKEND_NR; backend++) + backend_seen[backend] = 0; + + option = gc_component[component].options; + for (; option && option->name; option++) { - if (!gc_component[component].options) - continue; + if ((option->flags & GC_OPT_FLAG_GROUP)) + continue; + backend = option->backend; + if (backend_seen[backend]) + continue; + backend_seen[backend] = 1; + assert (backend != GC_BACKEND_ANY); + if (!gc_backend[backend].program) + continue; + if (!gc_backend[backend].module_name) + continue; + + break; + } + if (! option || ! option->name) + return 0; - for (backend = 0; backend < GC_BACKEND_NR; backend++) - backend_seen[backend] = 0; + pgmname = gnupg_module_name (gc_backend[backend].module_name); + i = 0; + if (conf_file) + { + argv[i++] = "--options"; + argv[i++] = conf_file; + } + argv[i++] = "--gpgconf-test"; + argv[i++] = NULL; + + err = gnupg_create_inbound_pipe (filedes); + if (err) + gc_error (1, 0, _("error creating a pipe: %s\n"), + gpg_strerror (err)); + + result = 0; + errlines = NULL; + if (gnupg_spawn_process_fd (pgmname, argv, -1, -1, filedes[1], &pid)) + { + close (filedes[0]); + close (filedes[1]); + result |= 1; /* Program could not be run. */ + } + else + { + close (filedes[1]); + errlines = collect_error_output (filedes[0], + gc_component[component].name); + if (gnupg_wait_process (pgmname, pid, &exitcode)) + { + if (exitcode == -1) + result |= 1; /* Program could not be run or it + terminated abnormally. */ + result |= 2; /* Program returned an error. */ + } + } + + /* If the program could not be run, we can't tell whether + the config file is good. */ + if (result & 1) + result |= 2; + + if (out) + { + const char *desc; + error_line_t errptr; + + desc = gc_component[component].desc; + desc = my_dgettext (gc_component[component].desc_domain, desc); + fprintf (out, "%s:%s:", + gc_component[component].name, my_percent_escape (desc)); + fputs (my_percent_escape (pgmname), out); + fprintf (out, ":%d:%d:", !(result & 1), !(result & 2)); + for (errptr = errlines; errptr; errptr = errptr->next) + { + if (errptr != errlines) + fputs ("\n:::::", out); /* Continuation line. */ + if (errptr->fname) + fputs (my_percent_escape (errptr->fname), out); + putc (':', out); + if (errptr->fname) + fprintf (out, "%u", errptr->lineno); + putc (':', out); + fputs (my_percent_escape (errptr->errtext), out); + putc (':', out); + } + putc ('\n', out); + } - 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; - assert (backend != GC_BACKEND_ANY); - if (!gc_backend[backend].program) - continue; - if (!gc_backend[backend].module_name) - continue; - - pgmname = gnupg_module_name (gc_backend[backend].module_name); - argv[0] = "--gpgconf-test"; - argv[1] = NULL; - - err = gnupg_create_inbound_pipe (filedes); - if (err) - gc_error (1, 0, _("error creating a pipe: %s\n"), - gpg_strerror (err)); - - result = 0; - errlines = NULL; - if (gnupg_spawn_process_fd (pgmname, argv, -1, -1, filedes[1], &pid)) - { - close (filedes[0]); - close (filedes[1]); - result |= 1; /* Program could not be run. */ - } - else - { - close (filedes[1]); - errlines = collect_error_output (filedes[0], - gc_component[component].name); - if (gnupg_wait_process (pgmname, pid, &exitcode)) - { - if (exitcode == -1) - result |= 1; /* Program could not be run or it - terminated abnormally. */ - result |= 2; /* Program returned an error. */ - } - } - - /* If the program could not be run, we can't tell whether - the config file is good. */ - if ((result&1)) - result |= 2; - - desc = gc_component[component].desc; - desc = my_dgettext (gc_component[component].desc_domain, desc); - fprintf (out, "%s:%s:", - gc_component[component].name, my_percent_escape (desc)); - fputs (my_percent_escape (pgmname), out); - fprintf (out, ":%d:%d:", !(result & 1), !(result & 2)); - for (errptr = errlines; errptr; errptr = errptr->next) - { - if (errptr != errlines) - fputs ("\n:::::", out); /* Continuation line. */ - if (errptr->fname) - fputs (my_percent_escape (errptr->fname), out); - putc (':', out); - if (errptr->fname) - fprintf (out, "%u", errptr->lineno); - putc (':', out); - fputs (my_percent_escape (errptr->errtext), out); - putc (':', out); - } - putc ('\n', out); - - while (errlines) - { - error_line_t tmp = errlines->next; - xfree (errlines); - errlines = tmp; - } - break; /* Loop over options of this component */ - } - } + while (errlines) + { + error_line_t tmp = errlines->next; + xfree (errlines); + errlines = tmp; + } + + return result; +} + + +/* Check all components that are available. */ +void +gc_check_programs (FILE *out) +{ + gc_component_t component; + + for (component = 0; component < GC_COMPONENT_NR; component++) + gc_component_check_options (component, out, NULL); } @@ -2831,7 +2853,7 @@ change_one_value (gc_option_t *option, int *runtime, modifications are expected to already have been set to the global table. */ void -gc_component_change_options (int component, FILE *in) +gc_component_change_options (int component, FILE *in, FILE *out) { int err = 0; int runtime[GC_BACKEND_NR]; @@ -2935,10 +2957,26 @@ gc_component_change_options (int component, FILE *in) } if (gc_backend[option->backend].program) - err = change_options_program (component, option->backend, - &src_pathname[option->backend], - &dest_pathname[option->backend], - &orig_pathname[option->backend]); + { + err = change_options_program (component, option->backend, + &src_pathname[option->backend], + &dest_pathname[option->backend], + &orig_pathname[option->backend]); + if (! err) + { + /* External verification. */ + err = gc_component_check_options (component, out, + src_pathname[option->backend]); + if (err) + { + gc_error (0, 0, + _("External verification of component %s failed"), + gc_component[component].name); + errno = EINVAL; + } + } + + } else err = change_options_file (component, option->backend, &src_pathname[option->backend], @@ -2951,7 +2989,7 @@ gc_component_change_options (int component, FILE *in) option++; } - if (!err) + if (! err && ! opt.dry_run) { int i; @@ -2994,12 +3032,12 @@ gc_component_change_options (int component, FILE *in) } } - if (err) + if (err || opt.dry_run) { int i; int saved_errno = errno; - /* An error occured. */ + /* An error occured or a dry-run is requested. */ for (i = 0; i < GC_BACKEND_NR; i++) { if (src_pathname[i]) @@ -3027,7 +3065,11 @@ gc_component_change_options (int component, FILE *in) unlink (dest_pathname[i]); } } - gc_error (1, saved_errno, "could not commit changes"); + if (err) + gc_error (1, saved_errno, "could not commit changes"); + + /* Fall-through for dry run. */ + goto leave; } /* If it all worked, notify the daemons of the changes. */ @@ -3055,6 +3097,7 @@ gc_component_change_options (int component, FILE *in) rename (orig_pathname[backend], backup_pathname); } + leave: xfree (line); } @@ -3463,7 +3506,7 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults, for (component_id = 0; component_id < GC_COMPONENT_NR; component_id++) { - gc_component_change_options (component_id, NULL); + gc_component_change_options (component_id, NULL, NULL); } opt.runtime = save_opt_runtime; diff --git a/tools/gpgconf.c b/tools/gpgconf.c index 9c1c77a2d..8813d545b 100644 --- a/tools/gpgconf.c +++ b/tools/gpgconf.c @@ -43,6 +43,7 @@ enum cmd_and_opt_values aCheckPrograms, aListOptions, aChangeOptions, + aCheckOptions, aApplyDefaults, aListConfig, aCheckConfig @@ -59,6 +60,7 @@ static ARGPARSE_OPTS opts[] = { aCheckPrograms, "check-programs", 256, N_("check all programs") }, { aListOptions, "list-options", 256, N_("|COMPONENT|list options") }, { aChangeOptions, "change-options", 256, N_("|COMPONENT|change options") }, + { aCheckOptions, "check-options", 256, N_("|COMPONENT|check options") }, { aApplyDefaults, "apply-defaults", 256, N_("apply global default values") }, { aListConfig, "list-config", 256, @@ -167,6 +169,7 @@ main (int argc, char **argv) case aCheckPrograms: case aListOptions: case aChangeOptions: + case aCheckOptions: case aApplyDefaults: case aListConfig: case aCheckConfig: @@ -192,11 +195,12 @@ main (int argc, char **argv) case aCheckPrograms: /* Check all programs. */ - gc_component_check_programs (get_outfp (&outfp)); + gc_check_programs (get_outfp (&outfp)); break; case aListOptions: case aChangeOptions: + case aCheckOptions: if (!fname) { fputs (_("usage: gpgconf [options] "), stderr); @@ -219,8 +223,10 @@ main (int argc, char **argv) exit (1); if (cmd == aListOptions) gc_component_list_options (idx, get_outfp (&outfp)); + else if (cmd == aChangeOptions) + gc_component_change_options (idx, stdin, get_outfp (&outfp)); else - gc_component_change_options (idx, stdin); + gc_component_check_options (idx, get_outfp (&outfp), NULL); } break; diff --git a/tools/gpgconf.h b/tools/gpgconf.h index 2f4bd5216..0a27dd9c3 100644 --- a/tools/gpgconf.h +++ b/tools/gpgconf.h @@ -43,7 +43,7 @@ void gc_error (int status, int errnum, const char *fmt, ...); void gc_component_list_components (FILE *out); /* List all programs along with their status. */ -void gc_component_check_programs (FILE *out); +void gc_check_programs (FILE *out); /* Find the component with the name NAME. Returns -1 if not found. */ @@ -57,7 +57,12 @@ void gc_component_retrieve_options (int component); void gc_component_list_options (int component, FILE *out); /* Read the modifications from IN and apply them. */ -void gc_component_change_options (int component, FILE *in); +void gc_component_change_options (int component, FILE *in, FILE *out); + +/* Check the options of a single component. Returns 0 if everything + is OK. */ +int gc_component_check_options (int component, FILE *out, + const char *conf_file); /* Process global configuration file. */ int gc_process_gpgconf_conf (const char *fname, int update, int defaults, |