summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Kibbey <bjk@luxsci.net>2015-07-15 21:41:15 -0400
committerBen Kibbey <bjk@luxsci.net>2015-07-16 21:10:48 -0400
commit259b61f73cb40fd3cb7da21cba4b1a69bfa2da78 (patch)
tree046ca71e0b6d5ab0834407875175ed587a23bdab
parenta5d9e018b8826e97c9fcc548c8e9e797bbc8d6db (diff)
downloadgpgme-bjk/custom-engine-options.tar.gz
Add per-ctx custom engine options.bjk/custom-engine-options
* src/gpgme.h.in (gpgme_ctx_set_engine_options): New prototype. (gpgme_ctx_get_engine_options): Ditto. * src/engine-backend.h (engine_ops): Add set_options and get_options. * src/engine.c (gpgme_ctx_set_engine_options): New. (gpgme_ctx_get_engine_options): Ditto. * src/engine-gpg.c (gpg_set_options): New. (gpg_get_options): Ditto. * src/op-support.c (_gpgme_op_reset): Keep custom options. * src/engine-gpg.c (_gpgme_engine_ops_gpg): Adjust for new members. * src/engine-assuan.c (_gpgme_engine_ops_assuan): Ditto. * src/engine-g13.c (_gpgme_engine_ops_g13): Ditto. * src/engine-gpgconf.c (_gpgme_engine_ops_gpgconf): Ditto. * src/engine-gpgsm.c (_gpgme_engine_ops_gpgsm): Ditto. * src/engine-spawn.c (_gpgme_engine_ops_spawn): Ditto. * src/engine-uiserver.c (_gpgme_engine_ops_uiserver): Ditto. * src/gpgme.def: Export new symbols. * src/libgpgme.vers: Ditto. * doc/gpgme.texi: Document these new functions. -- Not all of gpg2's features are exposed to libgpgme and adding these functions makes it possible to do things like specify an --s2k-count, etc.
-rw-r--r--doc/gpgme.texi25
-rw-r--r--src/engine-assuan.c2
-rw-r--r--src/engine-backend.h2
-rw-r--r--src/engine-g13.c2
-rw-r--r--src/engine-gpg.c79
-rw-r--r--src/engine-gpgconf.c2
-rw-r--r--src/engine-gpgsm.c2
-rw-r--r--src/engine-spawn.c2
-rw-r--r--src/engine-uiserver.c2
-rw-r--r--src/engine.c31
-rw-r--r--src/gpgme.def2
-rw-r--r--src/gpgme.h.in9
-rw-r--r--src/libgpgme.vers3
-rw-r--r--src/op-support.c24
14 files changed, 186 insertions, 1 deletions
diff --git a/doc/gpgme.texi b/doc/gpgme.texi
index 45c359d0..b3aa369f 100644
--- a/doc/gpgme.texi
+++ b/doc/gpgme.texi
@@ -187,6 +187,7 @@ Context Attributes
* Protocol Selection:: Selecting the protocol used by a context.
* Crypto Engine:: Configuring the crypto engine.
+* Custom Engine Options:: Adding command line options to an engine.
* ASCII Armor:: Requesting @acronym{ASCII} armored output.
* Text Mode:: Choosing canonical text mode.
* Included Certificates:: Including a number of certificates.
@@ -2283,6 +2284,7 @@ started. In fact, these references are accessed through the
@menu
* Protocol Selection:: Selecting the protocol used by a context.
* Crypto Engine:: Configuring the crypto engine.
+* Custom Engine Options:: Adding command line options to an engine.
* ASCII Armor:: Requesting @acronym{ASCII} armored output.
* Text Mode:: Choosing canonical text mode.
* Included Certificates:: Including a number of certificates.
@@ -2362,6 +2364,29 @@ successful, or an eror code on failure.
@end deftypefun
+@node Custom Engine Options
+@subsection Custom Engine Options
+@cindex context, configuring engine
+@cindex engine, configuration per context
+
+Since not all features of all engines may be exposed by @acronym{GPGME},
+additional command line arguments may be needed to allow the wanted
+functionality.
+
+@deftypefun gpgme_error_t gpgme_ctx_set_engine_options (@w{gpgme_ctx_t @var{ctx}}, @w{const char *@var{options}})
+The function @code{gpgme_ctx_set_engine_options} sets command line options for
+the configured engine in context @var{ctx} to @var{options}. The options are
+passed upon each op call and may be reset by setting @var{options} to
+@code{NULL}. This function returns @code{0} on success or an error on failure.
+@end deftypefun
+
+@deftypefun gpgme_error_t gpgme_ctx_get_engine_options (@w{gpgme_ctx_t @var{ctx}}, @w{char ** @var{result}})
+The function @code{gpgme_ctx_get_engine_options} returns the previously set
+engine options in @var{result}. This function returns @code{0} on success or
+an error on failure.
+@end deftypefun
+
+
@c FIXME: Unfortunately, using @acronym here breaks texi2dvi.
@node ASCII Armor
@subsection @acronym{ASCII} Armor
diff --git a/src/engine-assuan.c b/src/engine-assuan.c
index 663b2eab..99cd9a6c 100644
--- a/src/engine-assuan.c
+++ b/src/engine-assuan.c
@@ -759,6 +759,8 @@ struct engine_ops _gpgme_engine_ops_assuan =
NULL, /* set_colon_line_handler */
llass_set_locale,
NULL, /* set_protocol */
+ NULL, /* set_options */
+ NULL, /* get_options */
NULL, /* decrypt */
NULL, /* decrypt_verify */
NULL, /* delete */
diff --git a/src/engine-backend.h b/src/engine-backend.h
index b3cc412a..1079f5f8 100644
--- a/src/engine-backend.h
+++ b/src/engine-backend.h
@@ -59,6 +59,8 @@ struct engine_ops
void *fnc_value);
gpgme_error_t (*set_locale) (void *engine, int category, const char *value);
gpgme_error_t (*set_protocol) (void *engine, gpgme_protocol_t protocol);
+ gpgme_error_t (*set_options) (void *engine, const char *options);
+ const char *(*get_options) (void *engine);
gpgme_error_t (*decrypt) (void *engine, gpgme_data_t ciph,
gpgme_data_t plain);
gpgme_error_t (*decrypt_verify) (void *engine, gpgme_data_t ciph,
diff --git a/src/engine-g13.c b/src/engine-g13.c
index a9717eec..6cc91008 100644
--- a/src/engine-g13.c
+++ b/src/engine-g13.c
@@ -775,6 +775,8 @@ struct engine_ops _gpgme_engine_ops_g13 =
NULL, /* set_colon_line_handler */
g13_set_locale,
NULL, /* set_protocol */
+ NULL, /* set_options */
+ NULL, /* get_options */
NULL, /* decrypt */
NULL, /* decrypt_verify */
NULL, /* delete */
diff --git a/src/engine-gpg.c b/src/engine-gpg.c
index e14fd8dd..0be970a6 100644
--- a/src/engine-gpg.c
+++ b/src/engine-gpg.c
@@ -115,6 +115,7 @@ struct engine_gpg
char **argv;
struct fd_data_map_s *fd_data_map;
+ char *options; /* gpgme_ctx_set_engine_options() */
/* stuff needed for interactive (command) mode */
struct
@@ -404,6 +405,7 @@ gpg_release (void *engine)
free (gpg->status.buffer);
if (gpg->colon.buffer)
free (gpg->colon.buffer);
+ free (gpg->options);
if (gpg->argv)
free_argv (gpg->argv);
if (gpg->cmd.keyword)
@@ -716,6 +718,43 @@ gpg_set_command_handler (void *engine, engine_command_handler_t fnc,
}
+/* Custom command line options set with gpgme_ctx_set_engine_options() */
+static gpgme_error_t
+build_custom_argv (engine_gpg_t gpg, size_t *argc, char ***result)
+{
+ char *s, *options = gpg->options;
+ char **argv = NULL;
+ int total = 0;
+
+ if (!options)
+ return 0;
+
+ while ((s = strsep (&options, " ")))
+ {
+ char **tmp = realloc (argv, (total+2) * sizeof (char *));
+
+ if (!tmp)
+ {
+ free_argv (argv);
+ return GPG_ERR_ENOMEM;
+ }
+
+ argv = tmp;
+ argv[total] = strdup (s);
+ if (!argv[total++])
+ {
+ free_argv (argv);
+ return GPG_ERR_ENOMEM;
+ }
+
+ argv[total] = NULL;
+ (*argc)++;
+ }
+
+ *result = argv;
+ return 0;
+}
+
static gpgme_error_t
build_argv (engine_gpg_t gpg, const char *pgmname)
{
@@ -723,7 +762,7 @@ build_argv (engine_gpg_t gpg, const char *pgmname)
struct arg_and_data_s *a;
struct fd_data_map_s *fd_data_map;
size_t datac=0, argc=0;
- char **argv;
+ char **argv, **custom_argv = NULL, **pp;
int need_special = 0;
int use_agent = 0;
char *p;
@@ -780,6 +819,10 @@ build_argv (engine_gpg_t gpg, const char *pgmname)
argc++; /* --batch */
argc += 1; /* --no-sk-comments */
+ err = build_custom_argv (gpg, &argc, &custom_argv);
+ if (err)
+ return err;
+
argv = calloc (argc + 1, sizeof *argv);
if (!argv)
return gpg_error_from_syserror ();
@@ -801,6 +844,14 @@ build_argv (engine_gpg_t gpg, const char *pgmname)
return saved_err;
}
argc++;
+
+ if (custom_argv)
+ {
+ for (pp = custom_argv; pp && *pp; pp++)
+ argv[argc++] = *pp;
+ free (custom_argv);
+ }
+
if (need_special)
{
argv[argc] = strdup ("--enable-special-filenames");
@@ -2449,6 +2500,30 @@ gpg_set_pinentry_mode (void *engine, gpgme_pinentry_mode_t mode)
return 0;
}
+static gpgme_error_t
+gpg_set_options (void *engine, const char *options)
+{
+ engine_gpg_t gpg = engine;
+
+ free (gpg->options);
+ gpg->options = NULL;
+ if (options)
+ {
+ gpg->options = strdup (options);
+ if (!gpg->options)
+ return GPG_ERR_ENOMEM;
+ }
+
+ return 0;
+}
+
+static const char *
+gpg_get_options (void *engine)
+{
+ engine_gpg_t gpg = engine;
+
+ return gpg->options;
+}
struct engine_ops _gpgme_engine_ops_gpg =
@@ -2468,6 +2543,8 @@ struct engine_ops _gpgme_engine_ops_gpg =
gpg_set_colon_line_handler,
gpg_set_locale,
NULL, /* set_protocol */
+ gpg_set_options,
+ gpg_get_options,
gpg_decrypt,
gpg_decrypt, /* decrypt_verify */
gpg_delete,
diff --git a/src/engine-gpgconf.c b/src/engine-gpgconf.c
index a2407ac7..1033adbd 100644
--- a/src/engine-gpgconf.c
+++ b/src/engine-gpgconf.c
@@ -939,6 +939,8 @@ struct engine_ops _gpgme_engine_ops_gpgconf =
NULL, /* set_colon_line_handler */
NULL, /* set_locale */
NULL, /* set_protocol */
+ NULL, /* set_options */
+ NULL, /* get_options */
NULL, /* decrypt */
NULL, /* decrypt_verify */
NULL, /* delete */
diff --git a/src/engine-gpgsm.c b/src/engine-gpgsm.c
index ac6c5fc6..1c27898c 100644
--- a/src/engine-gpgsm.c
+++ b/src/engine-gpgsm.c
@@ -1988,6 +1988,8 @@ struct engine_ops _gpgme_engine_ops_gpgsm =
gpgsm_set_colon_line_handler,
gpgsm_set_locale,
NULL, /* set_protocol */
+ NULL, /* set_options */
+ NULL, /* get_options */
gpgsm_decrypt,
gpgsm_decrypt,
gpgsm_delete, /* decrypt_verify */
diff --git a/src/engine-spawn.c b/src/engine-spawn.c
index eb4e0385..93850217 100644
--- a/src/engine-spawn.c
+++ b/src/engine-spawn.c
@@ -445,6 +445,8 @@ struct engine_ops _gpgme_engine_ops_spawn =
NULL, /* set_colon_line_handler */
NULL, /* set_locale */
NULL, /* set_protocol */
+ NULL, /* set_options */
+ NULL, /* get_options */
NULL, /* decrypt */
NULL, /* decrypt_verify */
NULL, /* delete */
diff --git a/src/engine-uiserver.c b/src/engine-uiserver.c
index a7184b7a..4bfb8852 100644
--- a/src/engine-uiserver.c
+++ b/src/engine-uiserver.c
@@ -1316,6 +1316,8 @@ struct engine_ops _gpgme_engine_ops_uiserver =
uiserver_set_colon_line_handler,
uiserver_set_locale,
uiserver_set_protocol,
+ NULL, /* set_options */
+ NULL, /* get_options */
uiserver_decrypt,
uiserver_decrypt_verify,
NULL, /* delete */
diff --git a/src/engine.c b/src/engine.c
index ff015c00..cbd34575 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -445,6 +445,37 @@ gpgme_set_engine_info (gpgme_protocol_t proto,
return err;
}
+/* Set custom command line options for the engine associated with a
+ context. */
+gpgme_error_t
+gpgme_ctx_set_engine_options (gpgme_ctx_t ctx, const char *options)
+{
+ if (!ctx || !ctx->engine)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (!ctx->engine->ops->set_options)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+ return (*ctx->engine->ops->set_options) (ctx->engine->engine, options);
+}
+
+/* Return previously set custom engine command line options. */
+gpgme_error_t
+gpgme_ctx_get_engine_options (gpgme_ctx_t ctx, const char **result)
+{
+ if (!ctx || !ctx->engine)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (!result)
+ return gpg_error (GPG_ERR_INV_ARG);
+
+ if (!ctx->engine->ops->get_options)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+ *result = (*ctx->engine->ops->get_options) (ctx->engine->engine);
+ return 0;
+}
+
gpgme_error_t
_gpgme_engine_new (gpgme_engine_info_t info, engine_t *r_engine)
diff --git a/src/gpgme.def b/src/gpgme.def
index dc189484..754cb57d 100644
--- a/src/gpgme.def
+++ b/src/gpgme.def
@@ -217,5 +217,7 @@ EXPORTS
gpgme_op_spawn_start @163
gpgme_op_spawn @164
+ gpgme_ctx_set_engine_options @165
+ gpgme_ctx_get_engine_options @166
; END
diff --git a/src/gpgme.h.in b/src/gpgme.h.in
index 15ed8037..ffa58c57 100644
--- a/src/gpgme.h.in
+++ b/src/gpgme.h.in
@@ -947,6 +947,15 @@ gpgme_error_t gpgme_ctx_set_engine_info (gpgme_ctx_t ctx,
const char *file_name,
const char *home_dir);
+/* Set custom command line options for the engine associated with a
+ context. */
+gpgme_error_t gpgme_ctx_set_engine_options (gpgme_ctx_t ctx,
+ const char *options);
+
+/* Return previously set custom engine command line options. */
+gpgme_error_t gpgme_ctx_get_engine_options (gpgme_ctx_t ctx,
+ const char **result);
+
/* Return a statically allocated string with the name of the public
key algorithm ALGO, or NULL if that name is not known. */
diff --git a/src/libgpgme.vers b/src/libgpgme.vers
index 39663c1c..d7c97c8f 100644
--- a/src/libgpgme.vers
+++ b/src/libgpgme.vers
@@ -92,6 +92,9 @@ GPGME_1.1 {
gpgme_op_spawn_start;
gpgme_op_spawn;
+
+ gpgme_ctx_set_engine_options;
+ gpgme_ctx_get_engine_options;
};
diff --git a/src/op-support.c b/src/op-support.c
index 2bcb3a35..87a9b8d2 100644
--- a/src/op-support.c
+++ b/src/op-support.c
@@ -83,9 +83,19 @@ _gpgme_op_reset (gpgme_ctx_t ctx, int type)
struct gpgme_io_cbs io_cbs;
int no_reset = (type & 256);
int reuse_engine = 0;
+ char *options = NULL;
+ const char *tmp = NULL;
type &= 255;
+ err = gpgme_ctx_get_engine_options (ctx, &tmp);
+ if (tmp)
+ {
+ options = strdup (tmp);
+ if (!options)
+ return GPG_ERR_ENOMEM;
+ }
+
_gpgme_release_result (ctx);
LOCK (ctx->lock);
ctx->canceled = 0;
@@ -119,8 +129,22 @@ _gpgme_op_reset (gpgme_ctx_t ctx, int type)
err = _gpgme_engine_new (info, &ctx->engine);
if (err)
return err;
+
+ if (options)
+ {
+ err = gpgme_ctx_set_engine_options (ctx, options);
+ if (err && gpg_err_code (err) != GPG_ERR_NOT_IMPLEMENTED)
+ {
+ free (options);
+ _gpgme_engine_release (ctx->engine);
+ ctx->engine = NULL;
+ return err;
+ }
+ }
}
+ free (options);
+
if (!reuse_engine)
{
err = 0;