2004-12-07 Marcus Brinkmann <marcus@g10code.de>

* libgpgme.vers (GPGME_1.1): New version.
	* engine-backend.h (struct engine_ops): Add argument FILE_NAME to
	member get_version().  Add arguments FILE_NAME and HOME_DIR to
	member new().  Change return type of get_file_name and get_version
	to char *.
	* engine-gpgsm.c (gpgsm_get_version): Change return type to char
	pointer.  Do not cache result.
	(gpgsm_new): Add file_name and home_dir argument, and use them
	instead of the defaults, if set.
	* rungpg.c (struct engine_gpg): New member file_name.
	(gpg_get_version): Change return type to char pointer, and do not
	cache result.
	(gpg_release): Free gpg->file_name.
	(gpg_new): Take new arguments file_name and home_dir.  Set the
	--homedir argument if HOME_DIR is not NULL.  Set gpg->file_name.
	(start): Use gpg->file_name instead _gpgme_get_gpg_path, if set.
	* engine.h (_gpgme_engine_info_copy, _gpgme_engine_info_release):
	New prototypes.
	(_gpgme_engine_new): Change first argument to gpgme_engine_info_t
	info.
	* engine.c: Include <assert.h>.
	(gpgme_get_engine_info): Set *INFO within the lock.  Move
	ENGINE_INFO and ENGINE_INFO_LOCK to ....
	(engine_info, engine_info_lock): ... here.  New static variables.
	(engine_get_version): Add file_name argument to
	get_version invocation.  Change return type to char pointer.
	(gpgme_engine_check_version): Rewritten to free() the return value
	of engine_get_version after using it.
	(_gpgme_engine_info_release): New function.
	(gpgme_get_engine_info): Rewritten.
	(_gpgme_engine_info_copy): New function.
	(_gpgme_set_engine_info): New function.
	(gpgme_set_engine_info): New function.
	(_gpgme_engine_new): Change first argument to gpgme_engine_info_t
	info, and use that.
	* gpgme.h (struct _gpgme_engine_info): Change type of file_name
	and version to char * (remove the const).  New member home_dir.
	(gpgme_set_engine_info, gpgme_ctx_get_engine_info,
	gpgme_ctx_set_engine_info): New prototypes.
	* context.h (struct gpgme_context): New member engine_info.
	* gpgme.c (gpgme_new): Allocate CTX->engine_info.
	(gpgme_release): Deallocate CTX->engine_info.
	(gpgme_ctx_get_engine_info, gpgme_ctx_set_engine_info): New
	functions.
	* op-support.c (_gpgme_op_reset): Look for correct engine info and
	pass it to _gpgme_engine_new.
	* version.c (gpgme_check_version): Adjust to
	_gpgme_compare_versions returning an int.
	(_gpgme_compare_versions): Return an int value, not a const char
	pointer.
	* ops.h (_gpgme_compare_versions): Same for prototype.
This commit is contained in:
Marcus Brinkmann 2004-12-07 18:25:54 +00:00
parent e8e4400785
commit 0ebb858f1e
14 changed files with 481 additions and 90 deletions

13
NEWS
View File

@ -1,3 +1,16 @@
Noteworthy changes in version 1.1.0 (unreleased)
------------------------------------------------
* You can now configure the backend engine file name and home
directory to be used, as default and per context.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gpgme_set_engine_info NEW
gpgme_ctx_get_engine_info NEW
gpgme_ctx_set_engine_info NEW
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Noteworthy changes in version 1.0.1 (2004-10-22) Noteworthy changes in version 1.0.1 (2004-10-22)
------------------------------------------------ ------------------------------------------------

View File

@ -1,3 +1,57 @@
2004-12-07 Marcus Brinkmann <marcus@g10code.de>
* libgpgme.vers (GPGME_1.1): New version.
* engine-backend.h (struct engine_ops): Add argument FILE_NAME to
member get_version(). Add arguments FILE_NAME and HOME_DIR to
member new(). Change return type of get_file_name and get_version
to char *.
* engine-gpgsm.c (gpgsm_get_version): Change return type to char
pointer. Do not cache result.
(gpgsm_new): Add file_name and home_dir argument, and use them
instead of the defaults, if set.
* rungpg.c (struct engine_gpg): New member file_name.
(gpg_get_version): Change return type to char pointer, and do not
cache result.
(gpg_release): Free gpg->file_name.
(gpg_new): Take new arguments file_name and home_dir. Set the
--homedir argument if HOME_DIR is not NULL. Set gpg->file_name.
(start): Use gpg->file_name instead _gpgme_get_gpg_path, if set.
* engine.h (_gpgme_engine_info_copy, _gpgme_engine_info_release):
New prototypes.
(_gpgme_engine_new): Change first argument to gpgme_engine_info_t
info.
* engine.c: Include <assert.h>.
(gpgme_get_engine_info): Set *INFO within the lock. Move
ENGINE_INFO and ENGINE_INFO_LOCK to ....
(engine_info, engine_info_lock): ... here. New static variables.
(engine_get_version): Add file_name argument to
get_version invocation. Change return type to char pointer.
(gpgme_engine_check_version): Rewritten to free() the return value
of engine_get_version after using it.
(_gpgme_engine_info_release): New function.
(gpgme_get_engine_info): Rewritten.
(_gpgme_engine_info_copy): New function.
(_gpgme_set_engine_info): New function.
(gpgme_set_engine_info): New function.
(_gpgme_engine_new): Change first argument to gpgme_engine_info_t
info, and use that.
* gpgme.h (struct _gpgme_engine_info): Change type of file_name
and version to char * (remove the const). New member home_dir.
(gpgme_set_engine_info, gpgme_ctx_get_engine_info,
gpgme_ctx_set_engine_info): New prototypes.
* context.h (struct gpgme_context): New member engine_info.
* gpgme.c (gpgme_new): Allocate CTX->engine_info.
(gpgme_release): Deallocate CTX->engine_info.
(gpgme_ctx_get_engine_info, gpgme_ctx_set_engine_info): New
functions.
* op-support.c (_gpgme_op_reset): Look for correct engine info and
pass it to _gpgme_engine_new.
* version.c (gpgme_check_version): Adjust to
_gpgme_compare_versions returning an int.
(_gpgme_compare_versions): Return an int value, not a const char
pointer.
* ops.h (_gpgme_compare_versions): Same for prototype.
2004-10-03 Marcus Brinkmann <marcus@g10code.de> 2004-10-03 Marcus Brinkmann <marcus@g10code.de>
* verify.c (parse_trust): If no reason is provided, set * verify.c (parse_trust): If no reason is provided, set

View File

@ -62,6 +62,9 @@ typedef struct ctx_op_data *ctx_op_data_t;
be performed (sequentially). */ be performed (sequentially). */
struct gpgme_context struct gpgme_context
{ {
/* The engine info for this context. */
gpgme_engine_info_t engine_info;
/* The protocol used by this context. */ /* The protocol used by this context. */
gpgme_protocol_t protocol; gpgme_protocol_t protocol;

View File

@ -30,10 +30,21 @@
struct engine_ops struct engine_ops
{ {
/* Static functions. */ /* Static functions. */
const char *(*get_file_name) (void);
const char *(*get_version) (void); /* Return the default file name for the binary of this engine. */
char *(*get_file_name) (void);
/* Returns a malloced string containing the version of the engine
with the given binary file name (or the default if FILE_NAME is
NULL. */
char *(*get_version) (const char *file_name);
/* Returns a statically allocated string containing the required
version. */
const char *(*get_req_version) (void); const char *(*get_req_version) (void);
gpgme_error_t (*new) (void **r_engine, gpgme_error_t (*new) (void **r_engine,
const char *file_name, const char *home_dir,
const char *lc_ctype, const char *lc_messages); const char *lc_ctype, const char *lc_messages);
/* Member functions. */ /* Member functions. */

View File

@ -95,18 +95,11 @@ struct engine_gpgsm
typedef struct engine_gpgsm *engine_gpgsm_t; typedef struct engine_gpgsm *engine_gpgsm_t;
static const char * static char *
gpgsm_get_version (void) gpgsm_get_version (const char *file_name)
{ {
static const char *gpgsm_version; return _gpgme_get_program_version (file_name ? file_name
DEFINE_STATIC_LOCK (gpgsm_version_lock); : _gpgme_get_gpgsm_path ());
LOCK (gpgsm_version_lock);
if (!gpgsm_version)
gpgsm_version = _gpgme_get_program_version (_gpgme_get_gpgsm_path ());
UNLOCK (gpgsm_version_lock);
return gpgsm_version;
} }
@ -319,11 +312,13 @@ gpgsm_release (void *engine)
static gpgme_error_t static gpgme_error_t
gpgsm_new (void **engine, const char *lc_ctype, const char *lc_messages) gpgsm_new (void **engine, const char *file_name, const char *home_dir,
const char *lc_ctype, const char *lc_messages)
{ {
gpgme_error_t err = 0; gpgme_error_t err = 0;
engine_gpgsm_t gpgsm; engine_gpgsm_t gpgsm;
char *argv[3]; char *argv[5];
int argc;
int fds[2]; int fds[2];
int child_fds[4]; int child_fds[4];
char *dft_display = NULL; char *dft_display = NULL;
@ -395,12 +390,19 @@ gpgsm_new (void **engine, const char *lc_ctype, const char *lc_messages)
child_fds[2] = gpgsm->message_fd_server; child_fds[2] = gpgsm->message_fd_server;
child_fds[3] = -1; child_fds[3] = -1;
argv[0] = "gpgsm"; argc = 0;
argv[1] = "--server"; argv[argc++] = "gpgsm";
argv[2] = NULL; if (home_dir)
{
argv[argc++] = "--homedir";
argv[argc++] = home_dir;
}
argv[argc++] = "--server";
argv[argc++] = NULL;
err = assuan_pipe_connect (&gpgsm->assuan_ctx, err = assuan_pipe_connect (&gpgsm->assuan_ctx,
_gpgme_get_gpgsm_path (), argv, child_fds); file_name ? file_name : _gpgme_get_gpgsm_path (),
argv, child_fds);
/* FIXME: Check error. */ /* FIXME: Check error. */
/* We need to know the fd used by assuan for reads. We do this by /* We need to know the fd used by assuan for reads. We do this by

View File

@ -24,6 +24,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <assert.h>
#include "gpgme.h" #include "gpgme.h"
#include "util.h" #include "util.h"
@ -51,9 +52,14 @@ static struct engine_ops *engine_ops[] =
#endif #endif
}; };
/* The engine info. */
static gpgme_engine_info_t engine_info;
DEFINE_STATIC_LOCK (engine_info_lock);
/* Get the file name of the engine for PROTOCOL. */ /* Get the file name of the engine for PROTOCOL. */
static const char * static char *
engine_get_file_name (gpgme_protocol_t proto) engine_get_file_name (gpgme_protocol_t proto)
{ {
if (proto > DIM (engine_ops)) if (proto > DIM (engine_ops))
@ -66,15 +72,16 @@ engine_get_file_name (gpgme_protocol_t proto)
} }
/* Get the version number of the engine for PROTOCOL. */ /* Get a malloced string containing the version number of the engine
static const char * for PROTOCOL. */
engine_get_version (gpgme_protocol_t proto) static char *
engine_get_version (gpgme_protocol_t proto, const char *file_name)
{ {
if (proto > DIM (engine_ops)) if (proto > DIM (engine_ops))
return NULL; return NULL;
if (engine_ops[proto] && engine_ops[proto]->get_version) if (engine_ops[proto] && engine_ops[proto]->get_version)
return (*engine_ops[proto]->get_version) (); return (*engine_ops[proto]->get_version) (file_name);
else else
return NULL; return NULL;
} }
@ -98,21 +105,45 @@ engine_get_req_version (gpgme_protocol_t proto)
gpgme_error_t gpgme_error_t
gpgme_engine_check_version (gpgme_protocol_t proto) gpgme_engine_check_version (gpgme_protocol_t proto)
{ {
return _gpgme_compare_versions (engine_get_version (proto), int result;
engine_get_req_version (proto)) char *engine_version = engine_get_version (proto, NULL);
? 0 : gpg_error (GPG_ERR_INV_ENGINE);
result = _gpgme_compare_versions (engine_version,
engine_get_req_version (proto));
if (engine_version)
free (engine_version);
return result ? 0 : gpg_error (GPG_ERR_INV_ENGINE);
}
/* Release the engine info INFO. */
void
_gpgme_engine_info_release (gpgme_engine_info_t info)
{
while (info)
{
gpgme_engine_info_t next_info = info->next;
assert (info->file_name);
free (info->file_name);
if (info->home_dir)
free (info->home_dir);
if (info->version)
free (info->version);
free (info);
info = next_info;
}
} }
/* Get the information about the configured and installed engines. A /* Get the information about the configured and installed engines. A
pointer to the first engine in the statically allocated linked list pointer to the first engine in the statically allocated linked list
is returned in *INFO. If an error occurs, it is returned. */ is returned in *INFO. If an error occurs, it is returned. The
returned data is valid until the next gpgme_set_engine_info. */
gpgme_error_t gpgme_error_t
gpgme_get_engine_info (gpgme_engine_info_t *info) gpgme_get_engine_info (gpgme_engine_info_t *info)
{ {
static gpgme_engine_info_t engine_info;
DEFINE_STATIC_LOCK (engine_info_lock);
LOCK (engine_info_lock); LOCK (engine_info_lock);
if (!engine_info) if (!engine_info)
{ {
@ -123,70 +154,238 @@ gpgme_get_engine_info (gpgme_engine_info_t *info)
for (proto = 0; proto < DIM (proto_list); proto++) for (proto = 0; proto < DIM (proto_list); proto++)
{ {
const char *file_name = engine_get_file_name (proto_list[proto]); char *file_name = engine_get_file_name (proto_list[proto]);
if (!file_name) if (!file_name)
continue; continue;
file_name = strdup (file_name);
*lastp = malloc (sizeof (*engine_info)); *lastp = malloc (sizeof (*engine_info));
if (!*lastp) if (!*lastp || !file_name)
{ {
int saved_errno = errno; int saved_errno = errno;
while (engine_info) _gpgme_engine_info_release (engine_info);
{ engine_info = NULL;
gpgme_engine_info_t next_info = engine_info->next;
free (engine_info); if (file_name)
engine_info = next_info; free (file_name);
}
UNLOCK (engine_info_lock); UNLOCK (engine_info_lock);
return gpg_error_from_errno (saved_errno); return gpg_error_from_errno (saved_errno);
} }
(*lastp)->protocol = proto_list[proto]; (*lastp)->protocol = proto_list[proto];
(*lastp)->file_name = file_name; (*lastp)->file_name = file_name;
(*lastp)->version = engine_get_version (proto_list[proto]); (*lastp)->home_dir = NULL;
(*lastp)->version = engine_get_version (proto_list[proto], NULL);
(*lastp)->req_version = engine_get_req_version (proto_list[proto]); (*lastp)->req_version = engine_get_req_version (proto_list[proto]);
(*lastp)->next = NULL; (*lastp)->next = NULL;
lastp = &(*lastp)->next; lastp = &(*lastp)->next;
} }
} }
UNLOCK (engine_info_lock);
*info = engine_info; *info = engine_info;
UNLOCK (engine_info_lock);
return 0; return 0;
} }
/* Get a deep copy of the engine info and return it in INFO. */
gpgme_error_t
_gpgme_engine_info_copy (gpgme_engine_info_t *r_info)
{
gpgme_error_t err = 0;
gpgme_engine_info_t info;
gpgme_engine_info_t new_info;
gpgme_engine_info_t *lastp;
LOCK (engine_info_lock);
info = engine_info;
if (!info)
{
/* Make sure it is initialized. */
UNLOCK (engine_info_lock);
err = gpgme_get_engine_info (&info);
if (err)
return err;
LOCK (engine_info_lock);
}
new_info = NULL;
lastp = &new_info;
while (info)
{
char *file_name;
char *home_dir;
char *version;
assert (info->file_name);
file_name = strdup (info->file_name);
if (info->home_dir)
{
home_dir = strdup (info->home_dir);
if (!home_dir)
err = gpg_error_from_errno (errno);
}
else
home_dir = NULL;
if (info->version)
{
version = strdup (info->version);
if (!version)
err = gpg_error_from_errno (errno);
}
else
version = NULL;
*lastp = malloc (sizeof (*engine_info));
if (!*lastp || !file_name || err)
{
int saved_errno = errno;
_gpgme_engine_info_release (new_info);
if (file_name)
free (file_name);
if (home_dir)
free (home_dir);
if (version)
free (version);
UNLOCK (engine_info_lock);
return gpg_error_from_errno (saved_errno);
}
(*lastp)->protocol = info->protocol;
(*lastp)->file_name = file_name;
(*lastp)->home_dir = home_dir;
(*lastp)->version = version;
(*lastp)->req_version = info->req_version;
(*lastp)->next = NULL;
lastp = &(*lastp)->next;
info = info->next;
}
*r_info = new_info;
UNLOCK (engine_info_lock);
return 0;
}
/* Set the engine info for the info list INFO, protocol PROTO, to the
file name FILE_NAME and the home directory HOME_DIR. */
gpgme_error_t
_gpgme_set_engine_info (gpgme_engine_info_t info, gpgme_protocol_t proto,
const char *file_name, const char *home_dir)
{
char *new_file_name;
char *new_home_dir;
/* FIXME: Use some PROTO_MAX definition. */
if (proto > DIM (engine_ops))
return gpg_error (GPG_ERR_INV_VALUE);
while (info && info->protocol != proto)
info = info->next;
if (!info)
return gpg_error (GPG_ERR_INV_ENGINE);
/* Prepare new members. */
if (file_name)
new_file_name = strdup (file_name);
else
{
new_file_name = engine_get_file_name (proto);
assert (file_name);
new_file_name = strdup (new_file_name);
}
if (!new_file_name)
return gpg_error_from_errno (errno);
if (home_dir)
{
new_home_dir = strdup (home_dir);
if (!new_home_dir)
{
free (new_file_name);
return gpg_error_from_errno (errno);
}
}
else
new_home_dir = NULL;
/* Remove the old members. */
assert (info->file_name);
free (info->file_name);
if (info->home_dir)
free (info->home_dir);
if (info->version)
free (info->version);
/* Install the new members. */
info->file_name = new_file_name;
info->home_dir = new_home_dir;
info->version = engine_get_version (proto, file_name);
return 0;
}
/* Set the default engine info for the protocol PROTO to the file name
FILE_NAME and the home directory HOME_DIR. */
gpgme_error_t
gpgme_set_engine_info (gpgme_protocol_t proto,
const char *file_name, const char *home_dir)
{
gpgme_error_t err;
gpgme_engine_info_t info;
LOCK (engine_info_lock);
info = engine_info;
if (!info)
{
/* Make sure it is initialized. */
UNLOCK (engine_info_lock);
err = gpgme_get_engine_info (&info);
if (err)
return err;
LOCK (engine_info_lock);
}
err = _gpgme_set_engine_info (info, proto, file_name, home_dir);
UNLOCK (engine_info_lock);
return err;
}
gpgme_error_t gpgme_error_t
_gpgme_engine_new (gpgme_protocol_t proto, engine_t *r_engine, _gpgme_engine_new (gpgme_engine_info_t info, engine_t *r_engine,
const char *lc_ctype, const char *lc_messages) const char *lc_ctype, const char *lc_messages)
{ {
engine_t engine; engine_t engine;
const char *file_name; if (!info->file_name || !info->version)
const char *version;
if (proto > DIM (engine_ops))
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine_ops[proto])
return gpg_error (GPG_ERR_INV_ENGINE);
file_name = engine_get_file_name (proto);
version = engine_get_version (proto);
if (!file_name || !version)
return gpg_error (GPG_ERR_INV_ENGINE); return gpg_error (GPG_ERR_INV_ENGINE);
engine = calloc (1, sizeof *engine); engine = calloc (1, sizeof *engine);
if (!engine) if (!engine)
return gpg_error_from_errno (errno); return gpg_error_from_errno (errno);
engine->ops = engine_ops[proto]; engine->ops = engine_ops[info->protocol];
if (engine_ops[proto]->new) if (engine->ops->new)
{ {
gpgme_error_t err = (*engine_ops[proto]->new) (&engine->engine, gpgme_error_t err = (*engine->ops->new) (&engine->engine,
lc_ctype, info->file_name, info->home_dir,
lc_messages); lc_ctype, lc_messages);
if (err) if (err)
{ {
free (engine); free (engine);

View File

@ -35,7 +35,14 @@ typedef gpgme_error_t (*engine_command_handler_t) (void *priv,
const char *keyword, const char *keyword,
int fd); int fd);
gpgme_error_t _gpgme_engine_new (gpgme_protocol_t proto, /* Get a deep copy of the engine info and return it in INFO. */
gpgme_error_t _gpgme_engine_info_copy (gpgme_engine_info_t *r_info);
/* Release the engine info INFO. */
void _gpgme_engine_info_release (gpgme_engine_info_t info);
gpgme_error_t _gpgme_engine_new (gpgme_engine_info_t info,
engine_t *r_engine, engine_t *r_engine,
const char *lc_ctype, const char *lc_ctype,
const char *lc_messages); const char *lc_messages);

View File

@ -50,6 +50,14 @@ gpgme_new (gpgme_ctx_t *r_ctx)
ctx = calloc (1, sizeof *ctx); ctx = calloc (1, sizeof *ctx);
if (!ctx) if (!ctx)
return gpg_error_from_errno (errno); return gpg_error_from_errno (errno);
_gpgme_engine_info_copy (&ctx->engine_info);
if (!ctx->engine_info)
{
free (ctx);
return gpg_error_from_errno (errno);
}
ctx->keylist_mode = GPGME_KEYLIST_MODE_LOCAL; ctx->keylist_mode = GPGME_KEYLIST_MODE_LOCAL;
ctx->include_certs = 1; ctx->include_certs = 1;
ctx->protocol = GPGME_PROTOCOL_OpenPGP; ctx->protocol = GPGME_PROTOCOL_OpenPGP;
@ -62,6 +70,7 @@ gpgme_new (gpgme_ctx_t *r_ctx)
if (!ctx->lc_ctype) if (!ctx->lc_ctype)
{ {
UNLOCK (def_lc_lock); UNLOCK (def_lc_lock);
_gpgme_engine_info_release (ctx->engine_info);
free (ctx); free (ctx);
return gpg_error_from_errno (errno); return gpg_error_from_errno (errno);
} }
@ -77,6 +86,7 @@ gpgme_new (gpgme_ctx_t *r_ctx)
UNLOCK (def_lc_lock); UNLOCK (def_lc_lock);
if (ctx->lc_ctype) if (ctx->lc_ctype)
free (ctx->lc_ctype); free (ctx->lc_ctype);
_gpgme_engine_info_release (ctx->engine_info);
free (ctx); free (ctx);
return gpg_error_from_errno (errno); return gpg_error_from_errno (errno);
} }
@ -120,6 +130,7 @@ gpgme_release (gpgme_ctx_t ctx)
free (ctx->lc_ctype); free (ctx->lc_ctype);
if (ctx->lc_messages) if (ctx->lc_messages)
free (ctx->lc_messages); free (ctx->lc_messages);
_gpgme_engine_info_release (ctx->engine_info);
free (ctx); free (ctx);
} }
@ -389,6 +400,29 @@ gpgme_set_locale (gpgme_ctx_t ctx, int category, const char *value)
return 0; return 0;
} }
/* Get the information about the configured engines. A pointer to the
first engine in the statically allocated linked list is returned.
The returned data is valid until the next gpgme_ctx_set_engine_info. */
gpgme_engine_info_t
gpgme_ctx_get_engine_info (gpgme_ctx_t ctx)
{
return ctx->engine_info;
}
/* Set the engine info for the context CTX, protocol PROTO, to the
file name FILE_NAME and the home directory HOME_DIR. */
gpgme_error_t
gpgme_ctx_set_engine_info (gpgme_ctx_t ctx, gpgme_protocol_t proto,
const char *file_name, const char *home_dir)
{
/* FIXME: Make sure to reset the context if we are running in daemon
mode. */
return _gpgme_set_engine_info (ctx->engine_info, proto,
file_name, home_dir);
}
const char * const char *
gpgme_pubkey_algo_name (gpgme_pubkey_algo_t algo) gpgme_pubkey_algo_name (gpgme_pubkey_algo_t algo)

View File

@ -412,13 +412,16 @@ struct _gpgme_engine_info
gpgme_protocol_t protocol; gpgme_protocol_t protocol;
/* The file name of the engine binary. */ /* The file name of the engine binary. */
const char *file_name; char *file_name;
/* The version string of the installed engine. */ /* The version string of the installed engine. */
const char *version; char *version;
/* The minimum version required for GPGME. */ /* The minimum version required for GPGME. */
const char *req_version; const char *req_version;
/* The home directory used, or NULL if default. */
char *home_dir;
}; };
typedef struct _gpgme_engine_info *gpgme_engine_info_t; typedef struct _gpgme_engine_info *gpgme_engine_info_t;
@ -741,6 +744,19 @@ void gpgme_get_progress_cb (gpgme_ctx_t ctx, gpgme_progress_cb_t *cb,
locale if CTX is a null pointer. */ locale if CTX is a null pointer. */
gpgme_error_t gpgme_set_locale (gpgme_ctx_t ctx, int category, gpgme_error_t gpgme_set_locale (gpgme_ctx_t ctx, int category,
const char *value); const char *value);
/* Get the information about the configured engines. A pointer to the
first engine in the statically allocated linked list is returned.
The returned data is valid until the next gpgme_ctx_set_engine_info. */
gpgme_engine_info_t gpgme_ctx_get_engine_info (gpgme_ctx_t ctx);
/* Set the engine info for the context CTX, protocol PROTO, to the
file name FILE_NAME and the home directory HOME_DIR. */
gpgme_error_t gpgme_ctx_set_engine_info (gpgme_ctx_t ctx,
gpgme_protocol_t proto,
const char *file_name,
const char *home_dir);
/* 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. */
@ -1501,9 +1517,18 @@ int gpgme_trust_item_get_int_attr (gpgme_trust_item_t item, _gpgme_attr_t what,
/* Check that the library fulfills the version requirement. */ /* Check that the library fulfills the version requirement. */
const char *gpgme_check_version (const char *req_version); const char *gpgme_check_version (const char *req_version);
/* Retrieve information about the backend engines. */ /* Get the information about the configured and installed engines. A
pointer to the first engine in the statically allocated linked list
is returned in *INFO. If an error occurs, it is returned. The
returned data is valid until the next gpgme_set_engine_info. */
gpgme_error_t gpgme_get_engine_info (gpgme_engine_info_t *engine_info); gpgme_error_t gpgme_get_engine_info (gpgme_engine_info_t *engine_info);
/* Set the default engine info for the protocol PROTO to the file name
FILE_NAME and the home directory HOME_DIR. */
gpgme_error_t gpgme_set_engine_info (gpgme_protocol_t proto,
const char *file_name,
const char *home_dir);
/* Engine support functions. */ /* Engine support functions. */

View File

@ -18,6 +18,15 @@
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
GPGME_1.1 {
global:
gpgme_set_engine_info;
gpgme_ctx_get_engine_info;
gpgme_ctx_set_engine_info;
};
GPGME_1.0 { GPGME_1.0 {
global: global:
gpgme_check_version; gpgme_check_version;

View File

@ -66,17 +66,26 @@ gpgme_error_t
_gpgme_op_reset (gpgme_ctx_t ctx, int type) _gpgme_op_reset (gpgme_ctx_t ctx, int type)
{ {
gpgme_error_t err = 0; gpgme_error_t err = 0;
gpgme_engine_info_t info;
struct gpgme_io_cbs io_cbs; struct gpgme_io_cbs io_cbs;
info = ctx->engine_info;
while (info && info->protocol != ctx->protocol)
info = info->next;
if (!info)
return gpg_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
_gpgme_release_result (ctx); _gpgme_release_result (ctx);
/* Create an engine object. */
if (ctx->engine) if (ctx->engine)
{ {
_gpgme_engine_release (ctx->engine); _gpgme_engine_release (ctx->engine);
ctx->engine = NULL; ctx->engine = NULL;
} }
err = _gpgme_engine_new (ctx->protocol, &ctx->engine,
/* Create an engine object. */
err = _gpgme_engine_new (info, &ctx->engine,
ctx->lc_ctype, ctx->lc_messages); ctx->lc_ctype, ctx->lc_messages);
if (err) if (err)
return err; return err;

View File

@ -136,7 +136,9 @@ void _gpgme_op_trustlist_event_cb (void *data, gpgme_event_io_t type,
/*-- version.c --*/ /*-- version.c --*/
const char *_gpgme_compare_versions (const char *my_version, /* Return true if MY_VERSION is at least REQ_VERSION, and false
otherwise. */
int _gpgme_compare_versions (const char *my_version,
const char *req_version); const char *req_version);
char *_gpgme_get_program_version (const char *const path); char *_gpgme_get_program_version (const char *const path);

View File

@ -66,6 +66,8 @@ struct fd_data_map_s
struct engine_gpg struct engine_gpg
{ {
char *file_name;
struct arg_and_data_s *arglist; struct arg_and_data_s *arglist;
struct arg_and_data_s **argtail; struct arg_and_data_s **argtail;
@ -224,17 +226,11 @@ add_data (engine_gpg_t gpg, gpgme_data_t data, int dup_to, int inbound)
} }
static const char * static char *
gpg_get_version (void) gpg_get_version (const char *file_name)
{ {
static const char *gpg_version; return _gpgme_get_program_version (file_name ? file_name
DEFINE_STATIC_LOCK (gpg_version_lock); : _gpgme_get_gpg_path ());
LOCK (gpg_version_lock);
if (!gpg_version)
gpg_version = _gpgme_get_program_version (_gpgme_get_gpg_path ());
UNLOCK (gpg_version_lock);
return gpg_version;
} }
@ -313,6 +309,9 @@ gpg_release (void *engine)
gpg_cancel (engine); gpg_cancel (engine);
if (gpg->file_name)
free (gpg->file_name);
while (gpg->arglist) while (gpg->arglist)
{ {
struct arg_and_data_s *next = gpg->arglist->next; struct arg_and_data_s *next = gpg->arglist->next;
@ -336,7 +335,8 @@ gpg_release (void *engine)
static gpgme_error_t static gpgme_error_t
gpg_new (void **engine, const char *lc_ctype, const char *lc_messages) gpg_new (void **engine, const char *file_name, const char *home_dir,
const char *lc_ctype, const char *lc_messages)
{ {
engine_gpg_t gpg; engine_gpg_t gpg;
gpgme_error_t rc = 0; gpgme_error_t rc = 0;
@ -345,6 +345,16 @@ gpg_new (void **engine, const char *lc_ctype, const char *lc_messages)
if (!gpg) if (!gpg)
return gpg_error_from_errno (errno); return gpg_error_from_errno (errno);
if (file_name)
{
gpg->file_name = strdup (file_name);
if (!gpg->file_name)
{
rc = gpg_error_from_errno (errno);
goto leave;
}
}
gpg->argtail = &gpg->arglist; gpg->argtail = &gpg->arglist;
gpg->status.fd[0] = -1; gpg->status.fd[0] = -1;
gpg->status.fd[1] = -1; gpg->status.fd[1] = -1;
@ -380,6 +390,16 @@ gpg_new (void **engine, const char *lc_ctype, const char *lc_messages)
goto leave; goto leave;
} }
gpg->status.eof = 0; gpg->status.eof = 0;
if (home_dir)
{
rc = add_arg (gpg, "--homedir");
if (!rc)
rc = add_arg (gpg, home_dir);
if (rc)
goto leave;
}
rc = add_arg (gpg, "--status-fd"); rc = add_arg (gpg, "--status-fd");
if (rc) if (rc)
goto leave; goto leave;
@ -1043,7 +1063,7 @@ start (engine_gpg_t gpg)
if (!gpg) if (!gpg)
return gpg_error (GPG_ERR_INV_VALUE); return gpg_error (GPG_ERR_INV_VALUE);
if (! _gpgme_get_gpg_path ()) if (!gpg->file_name && !_gpgme_get_gpg_path ())
return gpg_error (GPG_ERR_INV_ENGINE); return gpg_error (GPG_ERR_INV_ENGINE);
rc = build_argv (gpg); rc = build_argv (gpg);
@ -1101,7 +1121,8 @@ start (engine_gpg_t gpg)
fd_parent_list[n].fd = -1; fd_parent_list[n].fd = -1;
fd_parent_list[n].dup_to = -1; fd_parent_list[n].dup_to = -1;
status = _gpgme_io_spawn (_gpgme_get_gpg_path (), status = _gpgme_io_spawn (gpg->file_name ? gpg->file_name :
_gpgme_get_gpg_path (),
gpg->argv, fd_child_list, fd_parent_list); gpg->argv, fd_child_list, fd_parent_list);
saved_errno = errno; saved_errno = errno;
free (fd_child_list); free (fd_child_list);

View File

@ -103,7 +103,9 @@ parse_version_string (const char *str, int *major, int *minor, int *micro)
} }
const char * /* Return true if MY_VERSION is at least REQ_VERSION, and false
otherwise. */
int
_gpgme_compare_versions (const char *my_version, _gpgme_compare_versions (const char *my_version,
const char *rq_version) const char *rq_version)
{ {
@ -112,17 +114,17 @@ _gpgme_compare_versions (const char *my_version,
const char *my_plvl, *rq_plvl; const char *my_plvl, *rq_plvl;
if (!rq_version) if (!rq_version)
return my_version; return 1;
if (!my_version) if (!my_version)
return NULL; return 0;
my_plvl = parse_version_string (my_version, &my_major, &my_minor, &my_micro); my_plvl = parse_version_string (my_version, &my_major, &my_minor, &my_micro);
if (!my_plvl) if (!my_plvl)
return NULL; return 0;
rq_plvl = parse_version_string (rq_version, &rq_major, &rq_minor, &rq_micro); rq_plvl = parse_version_string (rq_version, &rq_major, &rq_minor, &rq_micro);
if (!rq_plvl) if (!rq_plvl)
return NULL; return 0;
if (my_major > rq_major if (my_major > rq_major
|| (my_major == rq_major && my_minor > rq_minor) || (my_major == rq_major && my_minor > rq_minor)
@ -130,9 +132,9 @@ _gpgme_compare_versions (const char *my_version,
&& my_micro > rq_micro) && my_micro > rq_micro)
|| (my_major == rq_major && my_minor == rq_minor || (my_major == rq_major && my_minor == rq_minor
&& my_micro == rq_micro && strcmp (my_plvl, rq_plvl) >= 0)) && my_micro == rq_micro && strcmp (my_plvl, rq_plvl) >= 0))
return my_version; return 1;
return NULL; return 0;
} }
@ -149,7 +151,7 @@ const char *
gpgme_check_version (const char *req_version) gpgme_check_version (const char *req_version)
{ {
do_subsystem_inits (); do_subsystem_inits ();
return _gpgme_compare_versions (VERSION, req_version); return _gpgme_compare_versions (VERSION, req_version) ? VERSION : NULL;
} }