Add per-ctx 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.
This commit is contained in:
parent
a5d9e018b8
commit
259b61f73c
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
31
src/engine.c
31
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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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. */
|
||||
|
@ -92,6 +92,9 @@ GPGME_1.1 {
|
||||
|
||||
gpgme_op_spawn_start;
|
||||
gpgme_op_spawn;
|
||||
|
||||
gpgme_ctx_set_engine_options;
|
||||
gpgme_ctx_get_engine_options;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user