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.
|
* Protocol Selection:: Selecting the protocol used by a context.
|
||||||
* Crypto Engine:: Configuring the crypto engine.
|
* Crypto Engine:: Configuring the crypto engine.
|
||||||
|
* Custom Engine Options:: Adding command line options to an engine.
|
||||||
* ASCII Armor:: Requesting @acronym{ASCII} armored output.
|
* ASCII Armor:: Requesting @acronym{ASCII} armored output.
|
||||||
* Text Mode:: Choosing canonical text mode.
|
* Text Mode:: Choosing canonical text mode.
|
||||||
* Included Certificates:: Including a number of certificates.
|
* Included Certificates:: Including a number of certificates.
|
||||||
@ -2283,6 +2284,7 @@ started. In fact, these references are accessed through the
|
|||||||
@menu
|
@menu
|
||||||
* Protocol Selection:: Selecting the protocol used by a context.
|
* Protocol Selection:: Selecting the protocol used by a context.
|
||||||
* Crypto Engine:: Configuring the crypto engine.
|
* Crypto Engine:: Configuring the crypto engine.
|
||||||
|
* Custom Engine Options:: Adding command line options to an engine.
|
||||||
* ASCII Armor:: Requesting @acronym{ASCII} armored output.
|
* ASCII Armor:: Requesting @acronym{ASCII} armored output.
|
||||||
* Text Mode:: Choosing canonical text mode.
|
* Text Mode:: Choosing canonical text mode.
|
||||||
* Included Certificates:: Including a number of certificates.
|
* Included Certificates:: Including a number of certificates.
|
||||||
@ -2362,6 +2364,29 @@ successful, or an eror code on failure.
|
|||||||
@end deftypefun
|
@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.
|
@c FIXME: Unfortunately, using @acronym here breaks texi2dvi.
|
||||||
@node ASCII Armor
|
@node ASCII Armor
|
||||||
@subsection @acronym{ASCII} Armor
|
@subsection @acronym{ASCII} Armor
|
||||||
|
@ -759,6 +759,8 @@ struct engine_ops _gpgme_engine_ops_assuan =
|
|||||||
NULL, /* set_colon_line_handler */
|
NULL, /* set_colon_line_handler */
|
||||||
llass_set_locale,
|
llass_set_locale,
|
||||||
NULL, /* set_protocol */
|
NULL, /* set_protocol */
|
||||||
|
NULL, /* set_options */
|
||||||
|
NULL, /* get_options */
|
||||||
NULL, /* decrypt */
|
NULL, /* decrypt */
|
||||||
NULL, /* decrypt_verify */
|
NULL, /* decrypt_verify */
|
||||||
NULL, /* delete */
|
NULL, /* delete */
|
||||||
|
@ -59,6 +59,8 @@ struct engine_ops
|
|||||||
void *fnc_value);
|
void *fnc_value);
|
||||||
gpgme_error_t (*set_locale) (void *engine, int category, const char *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_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_error_t (*decrypt) (void *engine, gpgme_data_t ciph,
|
||||||
gpgme_data_t plain);
|
gpgme_data_t plain);
|
||||||
gpgme_error_t (*decrypt_verify) (void *engine, gpgme_data_t ciph,
|
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 */
|
NULL, /* set_colon_line_handler */
|
||||||
g13_set_locale,
|
g13_set_locale,
|
||||||
NULL, /* set_protocol */
|
NULL, /* set_protocol */
|
||||||
|
NULL, /* set_options */
|
||||||
|
NULL, /* get_options */
|
||||||
NULL, /* decrypt */
|
NULL, /* decrypt */
|
||||||
NULL, /* decrypt_verify */
|
NULL, /* decrypt_verify */
|
||||||
NULL, /* delete */
|
NULL, /* delete */
|
||||||
|
@ -115,6 +115,7 @@ struct engine_gpg
|
|||||||
|
|
||||||
char **argv;
|
char **argv;
|
||||||
struct fd_data_map_s *fd_data_map;
|
struct fd_data_map_s *fd_data_map;
|
||||||
|
char *options; /* gpgme_ctx_set_engine_options() */
|
||||||
|
|
||||||
/* stuff needed for interactive (command) mode */
|
/* stuff needed for interactive (command) mode */
|
||||||
struct
|
struct
|
||||||
@ -404,6 +405,7 @@ gpg_release (void *engine)
|
|||||||
free (gpg->status.buffer);
|
free (gpg->status.buffer);
|
||||||
if (gpg->colon.buffer)
|
if (gpg->colon.buffer)
|
||||||
free (gpg->colon.buffer);
|
free (gpg->colon.buffer);
|
||||||
|
free (gpg->options);
|
||||||
if (gpg->argv)
|
if (gpg->argv)
|
||||||
free_argv (gpg->argv);
|
free_argv (gpg->argv);
|
||||||
if (gpg->cmd.keyword)
|
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
|
static gpgme_error_t
|
||||||
build_argv (engine_gpg_t gpg, const char *pgmname)
|
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 arg_and_data_s *a;
|
||||||
struct fd_data_map_s *fd_data_map;
|
struct fd_data_map_s *fd_data_map;
|
||||||
size_t datac=0, argc=0;
|
size_t datac=0, argc=0;
|
||||||
char **argv;
|
char **argv, **custom_argv = NULL, **pp;
|
||||||
int need_special = 0;
|
int need_special = 0;
|
||||||
int use_agent = 0;
|
int use_agent = 0;
|
||||||
char *p;
|
char *p;
|
||||||
@ -780,6 +819,10 @@ build_argv (engine_gpg_t gpg, const char *pgmname)
|
|||||||
argc++; /* --batch */
|
argc++; /* --batch */
|
||||||
argc += 1; /* --no-sk-comments */
|
argc += 1; /* --no-sk-comments */
|
||||||
|
|
||||||
|
err = build_custom_argv (gpg, &argc, &custom_argv);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
argv = calloc (argc + 1, sizeof *argv);
|
argv = calloc (argc + 1, sizeof *argv);
|
||||||
if (!argv)
|
if (!argv)
|
||||||
return gpg_error_from_syserror ();
|
return gpg_error_from_syserror ();
|
||||||
@ -801,6 +844,14 @@ build_argv (engine_gpg_t gpg, const char *pgmname)
|
|||||||
return saved_err;
|
return saved_err;
|
||||||
}
|
}
|
||||||
argc++;
|
argc++;
|
||||||
|
|
||||||
|
if (custom_argv)
|
||||||
|
{
|
||||||
|
for (pp = custom_argv; pp && *pp; pp++)
|
||||||
|
argv[argc++] = *pp;
|
||||||
|
free (custom_argv);
|
||||||
|
}
|
||||||
|
|
||||||
if (need_special)
|
if (need_special)
|
||||||
{
|
{
|
||||||
argv[argc] = strdup ("--enable-special-filenames");
|
argv[argc] = strdup ("--enable-special-filenames");
|
||||||
@ -2449,6 +2500,30 @@ gpg_set_pinentry_mode (void *engine, gpgme_pinentry_mode_t mode)
|
|||||||
return 0;
|
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 =
|
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_colon_line_handler,
|
||||||
gpg_set_locale,
|
gpg_set_locale,
|
||||||
NULL, /* set_protocol */
|
NULL, /* set_protocol */
|
||||||
|
gpg_set_options,
|
||||||
|
gpg_get_options,
|
||||||
gpg_decrypt,
|
gpg_decrypt,
|
||||||
gpg_decrypt, /* decrypt_verify */
|
gpg_decrypt, /* decrypt_verify */
|
||||||
gpg_delete,
|
gpg_delete,
|
||||||
|
@ -939,6 +939,8 @@ struct engine_ops _gpgme_engine_ops_gpgconf =
|
|||||||
NULL, /* set_colon_line_handler */
|
NULL, /* set_colon_line_handler */
|
||||||
NULL, /* set_locale */
|
NULL, /* set_locale */
|
||||||
NULL, /* set_protocol */
|
NULL, /* set_protocol */
|
||||||
|
NULL, /* set_options */
|
||||||
|
NULL, /* get_options */
|
||||||
NULL, /* decrypt */
|
NULL, /* decrypt */
|
||||||
NULL, /* decrypt_verify */
|
NULL, /* decrypt_verify */
|
||||||
NULL, /* delete */
|
NULL, /* delete */
|
||||||
|
@ -1988,6 +1988,8 @@ struct engine_ops _gpgme_engine_ops_gpgsm =
|
|||||||
gpgsm_set_colon_line_handler,
|
gpgsm_set_colon_line_handler,
|
||||||
gpgsm_set_locale,
|
gpgsm_set_locale,
|
||||||
NULL, /* set_protocol */
|
NULL, /* set_protocol */
|
||||||
|
NULL, /* set_options */
|
||||||
|
NULL, /* get_options */
|
||||||
gpgsm_decrypt,
|
gpgsm_decrypt,
|
||||||
gpgsm_decrypt,
|
gpgsm_decrypt,
|
||||||
gpgsm_delete, /* decrypt_verify */
|
gpgsm_delete, /* decrypt_verify */
|
||||||
|
@ -445,6 +445,8 @@ struct engine_ops _gpgme_engine_ops_spawn =
|
|||||||
NULL, /* set_colon_line_handler */
|
NULL, /* set_colon_line_handler */
|
||||||
NULL, /* set_locale */
|
NULL, /* set_locale */
|
||||||
NULL, /* set_protocol */
|
NULL, /* set_protocol */
|
||||||
|
NULL, /* set_options */
|
||||||
|
NULL, /* get_options */
|
||||||
NULL, /* decrypt */
|
NULL, /* decrypt */
|
||||||
NULL, /* decrypt_verify */
|
NULL, /* decrypt_verify */
|
||||||
NULL, /* delete */
|
NULL, /* delete */
|
||||||
|
@ -1316,6 +1316,8 @@ struct engine_ops _gpgme_engine_ops_uiserver =
|
|||||||
uiserver_set_colon_line_handler,
|
uiserver_set_colon_line_handler,
|
||||||
uiserver_set_locale,
|
uiserver_set_locale,
|
||||||
uiserver_set_protocol,
|
uiserver_set_protocol,
|
||||||
|
NULL, /* set_options */
|
||||||
|
NULL, /* get_options */
|
||||||
uiserver_decrypt,
|
uiserver_decrypt,
|
||||||
uiserver_decrypt_verify,
|
uiserver_decrypt_verify,
|
||||||
NULL, /* delete */
|
NULL, /* delete */
|
||||||
|
31
src/engine.c
31
src/engine.c
@ -445,6 +445,37 @@ gpgme_set_engine_info (gpgme_protocol_t proto,
|
|||||||
return err;
|
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_error_t
|
||||||
_gpgme_engine_new (gpgme_engine_info_t info, engine_t *r_engine)
|
_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_start @163
|
||||||
gpgme_op_spawn @164
|
gpgme_op_spawn @164
|
||||||
|
gpgme_ctx_set_engine_options @165
|
||||||
|
gpgme_ctx_get_engine_options @166
|
||||||
; END
|
; END
|
||||||
|
|
||||||
|
@ -947,6 +947,15 @@ gpgme_error_t gpgme_ctx_set_engine_info (gpgme_ctx_t ctx,
|
|||||||
const char *file_name,
|
const char *file_name,
|
||||||
const char *home_dir);
|
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
|
/* Return a statically allocated string with the name of the public
|
||||||
key algorithm ALGO, or NULL if that name is not known. */
|
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_start;
|
||||||
gpgme_op_spawn;
|
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;
|
struct gpgme_io_cbs io_cbs;
|
||||||
int no_reset = (type & 256);
|
int no_reset = (type & 256);
|
||||||
int reuse_engine = 0;
|
int reuse_engine = 0;
|
||||||
|
char *options = NULL;
|
||||||
|
const char *tmp = NULL;
|
||||||
|
|
||||||
type &= 255;
|
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);
|
_gpgme_release_result (ctx);
|
||||||
LOCK (ctx->lock);
|
LOCK (ctx->lock);
|
||||||
ctx->canceled = 0;
|
ctx->canceled = 0;
|
||||||
@ -119,7 +129,21 @@ _gpgme_op_reset (gpgme_ctx_t ctx, int type)
|
|||||||
err = _gpgme_engine_new (info, &ctx->engine);
|
err = _gpgme_engine_new (info, &ctx->engine);
|
||||||
if (err)
|
if (err)
|
||||||
return 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)
|
if (!reuse_engine)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user