From 9f24e6c9010e171fd11c5cdac797cb8ce2e501dd Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann Date: Tue, 15 Aug 2017 19:40:12 +0200 Subject: [PATCH] gpgconf: Add access to --list-dirs for non-default engine. * src/engine-assuan.c (_gpgme_engine_ops_assuan): Add conf_dir. * src/engine-g13.c (_gpgme_engine_ops_g13): Likewise. * src/engine-gpg.c (_gpgme_engine_ops_gpg): Likewise. * src/engine-gpgsm.c (_gpgme_engine_ops_gpgsm): Likewise. * src/engine-spawn.c (_gpgme_engine_ops_spawn): Likewise. * src/engine-uiserver.c (_gpgme_engine_ops_uiserver): Likewise. * src/engine-backend.h (struct engine_ops): Likewise. * src/engine-gpgconf.c (gpgconf_config_dir_cb, gpgconf_conf_dir): New functions. (struct engine_ops): Add gpgconf_conf_dir. * src/engine.c (_gpgme_engine_op_conf_dir): New function. * src/engine.h (_gpgme_engine_op_conf_dir): New prototype. * src/gpgconf.c (gpgme_op_conf_dir): New function. * src/gpgme.def (gpgme_op_conf_save): New symbol. * src/gpgme.h.in (gpgme_op_conf_dir): New prototype. * src/libgpgme.vers (gpgme_op_conf_dir): New symbol. * tests/gpg/t-gpgconf.c (main): Test gpgme_op_conf_dir. Signed-off-by: Marcus Brinkmann GnuPG-bug-id: 3018 --- src/engine-assuan.c | 1 + src/engine-backend.h | 1 + src/engine-g13.c | 1 + src/engine-gpg.c | 1 + src/engine-gpgconf.c | 43 +++++++++++++++++++++++++++++++++++++++++++ src/engine-gpgsm.c | 1 + src/engine-spawn.c | 1 + src/engine-uiserver.c | 1 + src/engine.c | 13 +++++++++++++ src/engine.h | 3 +++ src/gpgconf.c | 21 +++++++++++++++++++++ src/gpgme.def | 2 ++ src/gpgme.h.in | 4 ++++ src/libgpgme.vers | 1 + tests/gpg/t-gpgconf.c | 17 +++++++++++++++++ 15 files changed, 111 insertions(+) diff --git a/src/engine-assuan.c b/src/engine-assuan.c index 68bdaa6a..bb2290ac 100644 --- a/src/engine-assuan.c +++ b/src/engine-assuan.c @@ -796,6 +796,7 @@ struct engine_ops _gpgme_engine_ops_assuan = llass_transact, /* opassuan_transact */ NULL, /* conf_load */ NULL, /* conf_save */ + NULL, /* conf_dir */ NULL, /* query_swdb */ llass_set_io_cbs, llass_io_event, diff --git a/src/engine-backend.h b/src/engine-backend.h index 90328ecb..f41aaeb6 100644 --- a/src/engine-backend.h +++ b/src/engine-backend.h @@ -128,6 +128,7 @@ struct engine_ops gpgme_error_t (*conf_load) (void *engine, gpgme_conf_comp_t *conf_p); gpgme_error_t (*conf_save) (void *engine, gpgme_conf_comp_t conf); + gpgme_error_t (*conf_dir) (void *engine, const char *what, char **result); gpgme_error_t (*query_swdb) (void *engine, const char *name, const char *iversion, diff --git a/src/engine-g13.c b/src/engine-g13.c index 02951e83..f8f31780 100644 --- a/src/engine-g13.c +++ b/src/engine-g13.c @@ -811,6 +811,7 @@ struct engine_ops _gpgme_engine_ops_g13 = g13_transact, NULL, /* conf_load */ NULL, /* conf_save */ + NULL, /* conf_dir */ NULL, /* query_swdb */ g13_set_io_cbs, g13_io_event, diff --git a/src/engine-gpg.c b/src/engine-gpg.c index c749c972..bc60d82d 100644 --- a/src/engine-gpg.c +++ b/src/engine-gpg.c @@ -3093,6 +3093,7 @@ struct engine_ops _gpgme_engine_ops_gpg = NULL, /* opassuan_transact */ NULL, /* conf_load */ NULL, /* conf_save */ + NULL, /* conf_dir */ NULL, /* query_swdb */ gpg_set_io_cbs, gpg_io_event, diff --git a/src/engine-gpgconf.c b/src/engine-gpgconf.c index af5f1103..2b0f448a 100644 --- a/src/engine-gpgconf.c +++ b/src/engine-gpgconf.c @@ -986,6 +986,48 @@ gpgconf_conf_save (void *engine, gpgme_conf_comp_t comp) } +static gpgme_error_t +gpgconf_config_dir_cb (void *hook, char *line) +{ + /* This is an input- and output-parameter. */ + char **str_p = (char **) hook; + char *what = *str_p; + int len = strlen(what); + + if (!strncmp(line, what, len) && line[len] == ':') + { + char *result = strdup(&line[len + 1]); + if (!result) + return gpg_error_from_syserror (); + *str_p = result; + return gpg_error(GPG_ERR_USER_1); + } + return 0; +} + + +static gpgme_error_t +gpgconf_conf_dir (void *engine, const char *what, char **result) +{ + gpgme_error_t err; + char *res = what; + + *result = NULL; + err = gpgconf_read (engine, "--list-dirs", NULL, + gpgconf_config_dir_cb, &res); + if (gpg_err_code (err) == GPG_ERR_USER_1) + { + /* This signals to use that a result was found. */ + *result = res; + return 0; + } + + if (!err) + err = gpg_error(GPG_ERR_NOT_FOUND); + return 0; +} + + /* Parse a line received from gpgconf --query-swdb. This function may * modify LINE. The result is stored at RESUL. */ static gpg_error_t @@ -1254,6 +1296,7 @@ struct engine_ops _gpgme_engine_ops_gpgconf = NULL, /* opassuan_transact */ gpgconf_conf_load, gpgconf_conf_save, + gpgconf_conf_dir, gpgconf_query_swdb, gpgconf_set_io_cbs, NULL, /* io_event */ diff --git a/src/engine-gpgsm.c b/src/engine-gpgsm.c index a0fcb1f4..f23b0bfd 100644 --- a/src/engine-gpgsm.c +++ b/src/engine-gpgsm.c @@ -2119,6 +2119,7 @@ struct engine_ops _gpgme_engine_ops_gpgsm = NULL, /* opassuan_transact */ NULL, /* conf_load */ NULL, /* conf_save */ + NULL, /* conf_dir */ NULL, /* query_swdb */ gpgsm_set_io_cbs, gpgsm_io_event, diff --git a/src/engine-spawn.c b/src/engine-spawn.c index 9d587cc5..7044781b 100644 --- a/src/engine-spawn.c +++ b/src/engine-spawn.c @@ -469,6 +469,7 @@ struct engine_ops _gpgme_engine_ops_spawn = NULL, /* opassuan_transact */ NULL, /* conf_load */ NULL, /* conf_save */ + NULL, /* conf_dir */ NULL, /* query_swdb */ engspawn_set_io_cbs, engspawn_io_event, /* io_event */ diff --git a/src/engine-uiserver.c b/src/engine-uiserver.c index 20a8abf2..3db705d8 100644 --- a/src/engine-uiserver.c +++ b/src/engine-uiserver.c @@ -1386,6 +1386,7 @@ struct engine_ops _gpgme_engine_ops_uiserver = NULL, /* opassuan_transact */ NULL, /* conf_load */ NULL, /* conf_save */ + NULL, /* conf_dir */ NULL, /* query_swdb */ uiserver_set_io_cbs, uiserver_io_event, diff --git a/src/engine.c b/src/engine.c index 89a8552c..2c7e625f 100644 --- a/src/engine.c +++ b/src/engine.c @@ -983,6 +983,19 @@ _gpgme_engine_op_conf_save (engine_t engine, gpgme_conf_comp_t conf) } +gpgme_error_t +_gpgme_engine_op_conf_dir (engine_t engine, const char *what, char **result) +{ + if (!engine) + return gpg_error (GPG_ERR_INV_VALUE); + + if (!engine->ops->conf_dir) + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + + return (*engine->ops->conf_dir) (engine->engine, what, result); +} + + gpgme_error_t _gpgme_engine_op_query_swdb (engine_t engine, const char *name, const char *iversion, diff --git a/src/engine.h b/src/engine.h index d25c1fa6..b71b7e2d 100644 --- a/src/engine.h +++ b/src/engine.h @@ -176,6 +176,9 @@ gpgme_error_t _gpgme_engine_op_conf_load (engine_t engine, gpgme_conf_comp_t *conf_p); gpgme_error_t _gpgme_engine_op_conf_save (engine_t engine, gpgme_conf_comp_t conf); +gpgme_error_t _gpgme_engine_op_conf_dir (engine_t engine, + const char *what, + char **result); gpgme_error_t _gpgme_engine_op_query_swdb (engine_t engine, const char *name, diff --git a/src/gpgconf.c b/src/gpgconf.c index b1b84a62..ce6ace41 100644 --- a/src/gpgconf.c +++ b/src/gpgconf.c @@ -108,3 +108,24 @@ gpgme_op_conf_save (gpgme_ctx_t ctx, gpgme_conf_comp_t comp) ctx->protocol = proto; return err; } + + +gpgme_error_t +gpgme_op_conf_dir (gpgme_ctx_t ctx, const char *what, char **result) +{ + gpgme_error_t err; + gpgme_protocol_t proto; + + if (!ctx) + return gpg_error (GPG_ERR_INV_VALUE); + + proto = ctx->protocol; + ctx->protocol = GPGME_PROTOCOL_GPGCONF; + err = _gpgme_op_reset (ctx, 1); + if (err) + return err; + + err = _gpgme_engine_op_conf_dir (ctx->engine, what, result); + ctx->protocol = proto; + return err; +} diff --git a/src/gpgme.def b/src/gpgme.def index a8918122..dd8e532a 100644 --- a/src/gpgme.def +++ b/src/gpgme.def @@ -265,5 +265,7 @@ EXPORTS gpgme_op_delete_ext @197 gpgme_op_delete_ext_start @198 + gpgme_op_conf_save @199 + ; END diff --git a/src/gpgme.h.in b/src/gpgme.h.in index 29cda2c6..8afc276e 100644 --- a/src/gpgme.h.in +++ b/src/gpgme.h.in @@ -2240,6 +2240,10 @@ gpgme_error_t gpgme_op_conf_load (gpgme_ctx_t ctx, gpgme_conf_comp_t *conf_p); follow chained components! */ gpgme_error_t gpgme_op_conf_save (gpgme_ctx_t ctx, gpgme_conf_comp_t comp); +/* Retrieve the configured directory. */ +gpgme_error_t gpgme_op_conf_dir(gpgme_ctx_t ctx, const char *what, + char **result); + /* Information about software versions. * This structure shall be considered read-only and an application diff --git a/src/libgpgme.vers b/src/libgpgme.vers index 9a74b76f..a95befba 100644 --- a/src/libgpgme.vers +++ b/src/libgpgme.vers @@ -46,6 +46,7 @@ GPGME_1.1 { gpgme_conf_opt_change; gpgme_op_conf_load; gpgme_op_conf_save; + gpgme_op_conf_dir; gpgme_cancel_async; diff --git a/tests/gpg/t-gpgconf.c b/tests/gpg/t-gpgconf.c index 67bb8861..8c81de69 100644 --- a/tests/gpg/t-gpgconf.c +++ b/tests/gpg/t-gpgconf.c @@ -263,6 +263,23 @@ main (void) err = gpgme_new (&ctx); fail_if_err (err); + /* Let's check getting the agent-socket directory for different homedirs. */ + char *result1 = NULL; + err = gpgme_ctx_set_engine_info (ctx, GPGME_PROTOCOL_GPGCONF, NULL, "/tmp/foo"); + fail_if_err (err); + err = gpgme_op_conf_dir (ctx, "agent-socket", &result1); + fail_if_err (err); + + char *result2 = NULL; + err = gpgme_ctx_set_engine_info (ctx, GPGME_PROTOCOL_GPGCONF, NULL, NULL); + fail_if_err (err); + err = gpgme_op_conf_dir (ctx, "agent-socket", &result2); + fail_if_err (err); + + /* They have to be different. */ + test (strcmp(result1, result2)); + + err = gpgme_op_conf_load (ctx, &conf); fail_if_err (err);