gpgme (14 files)

cvs user marcus cvs at cvs.gnupg.org
Tue Dec 7 19:17:49 CET 2004


    Date: Tuesday, December 7, 2004 @ 19:25:54
  Author: marcus
    Path: /cvs/gpgme/gpgme

Modified: NEWS gpgme/ChangeLog gpgme/context.h gpgme/engine-backend.h
          gpgme/engine-gpgsm.c gpgme/engine.c gpgme/engine.h gpgme/gpgme.c
          gpgme/gpgme.h gpgme/libgpgme.vers gpgme/op-support.c gpgme/ops.h
          gpgme/rungpg.c gpgme/version.c

2004-12-07  Marcus Brinkmann  <marcus at 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.


------------------------+
 NEWS                   |   13 ++
 gpgme/ChangeLog        |   54 +++++++++
 gpgme/context.h        |    3 
 gpgme/engine-backend.h |   15 ++
 gpgme/engine-gpgsm.c   |   36 +++---
 gpgme/engine.c         |  273 ++++++++++++++++++++++++++++++++++++++++-------
 gpgme/engine.h         |    9 +
 gpgme/gpgme.c          |   34 +++++
 gpgme/gpgme.h          |   33 ++++-
 gpgme/libgpgme.vers    |    9 +
 gpgme/op-support.c     |   15 ++
 gpgme/ops.h            |    6 -
 gpgme/rungpg.c         |   47 +++++---
 gpgme/version.c        |   18 +--
 14 files changed, 478 insertions(+), 87 deletions(-)


Index: gpgme/NEWS
diff -u gpgme/NEWS:1.136 gpgme/NEWS:1.137
--- gpgme/NEWS:1.136	Fri Oct 22 20:11:33 2004
+++ gpgme/NEWS	Tue Dec  7 19:25:54 2004
@@ -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)
 ------------------------------------------------
 
Index: gpgme/gpgme/ChangeLog
diff -u gpgme/gpgme/ChangeLog:1.386 gpgme/gpgme/ChangeLog:1.387
--- gpgme/gpgme/ChangeLog:1.386	Fri Oct 22 19:57:56 2004
+++ gpgme/gpgme/ChangeLog	Tue Dec  7 19:25:53 2004
@@ -1,3 +1,57 @@
+2004-12-07  Marcus Brinkmann  <marcus at 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 at g10code.de>
 
 	* verify.c (parse_trust): If no reason is provided, set
Index: gpgme/gpgme/context.h
diff -u gpgme/gpgme/context.h:1.56 gpgme/gpgme/context.h:1.57
--- gpgme/gpgme/context.h:1.56	Sun Sep 14 02:02:40 2003
+++ gpgme/gpgme/context.h	Tue Dec  7 19:25:53 2004
@@ -62,6 +62,9 @@
    be performed (sequentially).  */
 struct gpgme_context
 {
+  /* The engine info for this context.  */
+  gpgme_engine_info_t engine_info;
+
   /* The protocol used by this context.  */
   gpgme_protocol_t protocol;
 
Index: gpgme/gpgme/engine-backend.h
diff -u gpgme/gpgme/engine-backend.h:1.15 gpgme/gpgme/engine-backend.h:1.16
--- gpgme/gpgme/engine-backend.h:1.15	Wed Feb 25 00:08:46 2004
+++ gpgme/gpgme/engine-backend.h	Tue Dec  7 19:25:53 2004
@@ -30,10 +30,21 @@
 struct engine_ops
 {
   /* 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);
+
   gpgme_error_t (*new) (void **r_engine,
+			const char *file_name, const char *home_dir,
 			const char *lc_ctype, const char *lc_messages);
 
   /* Member functions.  */
Index: gpgme/gpgme/engine-gpgsm.c
diff -u gpgme/gpgme/engine-gpgsm.c:1.100 gpgme/gpgme/engine-gpgsm.c:1.101
--- gpgme/gpgme/engine-gpgsm.c:1.100	Fri Oct 22 18:55:16 2004
+++ gpgme/gpgme/engine-gpgsm.c	Tue Dec  7 19:25:53 2004
@@ -95,18 +95,11 @@
 typedef struct engine_gpgsm *engine_gpgsm_t;
 
 
-static const char *
-gpgsm_get_version (void)
+static char *
+gpgsm_get_version (const char *file_name)
 {
-  static const char *gpgsm_version;
-  DEFINE_STATIC_LOCK (gpgsm_version_lock);
-
-  LOCK (gpgsm_version_lock);
-  if (!gpgsm_version)
-    gpgsm_version = _gpgme_get_program_version (_gpgme_get_gpgsm_path ());
-  UNLOCK (gpgsm_version_lock);
-
-  return gpgsm_version;
+  return _gpgme_get_program_version (file_name ? file_name
+				     : _gpgme_get_gpgsm_path ());
 }
 
 
@@ -319,11 +312,13 @@
 
 
 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;
   engine_gpgsm_t gpgsm;
-  char *argv[3];
+  char *argv[5];
+  int argc;
   int fds[2];
   int child_fds[4];
   char *dft_display = NULL;
@@ -395,12 +390,19 @@
   child_fds[2] = gpgsm->message_fd_server;
   child_fds[3] = -1;
 
-  argv[0] = "gpgsm";
-  argv[1] = "--server";
-  argv[2] = NULL;
+  argc = 0;
+  argv[argc++] = "gpgsm";
+  if (home_dir)
+    {
+      argv[argc++] = "--homedir";
+      argv[argc++] = home_dir;
+    }
+  argv[argc++] = "--server";
+  argv[argc++] = NULL;
 
   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.  */
 
   /* We need to know the fd used by assuan for reads.  We do this by
Index: gpgme/gpgme/engine.c
diff -u gpgme/gpgme/engine.c:1.44 gpgme/gpgme/engine.c:1.45
--- gpgme/gpgme/engine.c:1.44	Wed Feb 25 00:08:46 2004
+++ gpgme/gpgme/engine.c	Tue Dec  7 19:25:53 2004
@@ -24,6 +24,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+#include <assert.h>
 
 #include "gpgme.h"
 #include "util.h"
@@ -51,9 +52,14 @@
 #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.  */
-static const char *
+static char *
 engine_get_file_name (gpgme_protocol_t proto)
 {
   if (proto > DIM (engine_ops))
@@ -66,15 +72,16 @@
 }
 
 
-/* Get the version number of the engine for PROTOCOL.  */
-static const char *
-engine_get_version (gpgme_protocol_t proto)
+/* Get a malloced string containing the version number of the engine
+   for PROTOCOL.  */
+static char *
+engine_get_version (gpgme_protocol_t proto, const char *file_name)
 {
   if (proto > DIM (engine_ops))
     return NULL;
 
   if (engine_ops[proto] && engine_ops[proto]->get_version)
-    return (*engine_ops[proto]->get_version) ();
+    return (*engine_ops[proto]->get_version) (file_name);
   else
     return NULL;
 }
@@ -98,21 +105,45 @@
 gpgme_error_t
 gpgme_engine_check_version (gpgme_protocol_t proto)
 {
-  return _gpgme_compare_versions (engine_get_version (proto),
-				  engine_get_req_version (proto))
-    ? 0 : gpg_error (GPG_ERR_INV_ENGINE);
+  int result;
+  char *engine_version = engine_get_version (proto, NULL);
+
+  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
    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_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);
   if (!engine_info)
     {
@@ -123,70 +154,238 @@
 
       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)
 	    continue;
 
+	  file_name = strdup (file_name);
+
 	  *lastp = malloc (sizeof (*engine_info));
-	  if (!*lastp)
+	  if (!*lastp || !file_name)
 	    {
 	      int saved_errno = errno;
 
-	      while (engine_info)
-		{
-		  gpgme_engine_info_t next_info = engine_info->next;
-		  free (engine_info);
-		  engine_info = next_info;
-		}
+	      _gpgme_engine_info_release (engine_info);
+	      engine_info = NULL;
+
+	      if (file_name)
+		free (file_name);
+
 	      UNLOCK (engine_info_lock);
 	      return gpg_error_from_errno (saved_errno);
 	    }
 
 	  (*lastp)->protocol = proto_list[proto];
 	  (*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)->next = NULL;
 	  lastp = &(*lastp)->next;
 	}
     }
-  UNLOCK (engine_info_lock);
+
   *info = engine_info;
+  UNLOCK (engine_info_lock);
   return 0;
 }
 
-
+
+/* Get a deep copy of the engine info and return it in INFO.  */
 gpgme_error_t
-_gpgme_engine_new (gpgme_protocol_t proto, engine_t *r_engine,
-		   const char *lc_ctype, const char *lc_messages)
+_gpgme_engine_info_copy (gpgme_engine_info_t *r_info)
 {
-  engine_t engine;
+  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;
+}
+
 
-  const char *file_name;
-  const char *version;
+/* 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);
 
-  if (!engine_ops[proto])
+  while (info && info->protocol != proto)
+    info = info->next;
+
+  if (!info)
     return gpg_error (GPG_ERR_INV_ENGINE);
 
-  file_name = engine_get_file_name (proto);
-  version = engine_get_version (proto);
-  if (!file_name || !version)
+  /* 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_engine_new (gpgme_engine_info_t info, engine_t *r_engine,
+		   const char *lc_ctype, const char *lc_messages)
+{
+  engine_t engine;
+
+  if (!info->file_name || !info->version)
     return gpg_error (GPG_ERR_INV_ENGINE);
 
   engine = calloc (1, sizeof *engine);
   if (!engine)
     return gpg_error_from_errno (errno);
 
-  engine->ops = engine_ops[proto];
-  if (engine_ops[proto]->new)
+  engine->ops = engine_ops[info->protocol];
+  if (engine->ops->new)
     {
-      gpgme_error_t err = (*engine_ops[proto]->new) (&engine->engine,
-						     lc_ctype,
-						     lc_messages);
+      gpgme_error_t err = (*engine->ops->new) (&engine->engine,
+					       info->file_name, info->home_dir,
+					       lc_ctype, lc_messages);
       if (err)
 	{
 	  free (engine);
Index: gpgme/gpgme/engine.h
diff -u gpgme/gpgme/engine.h:1.34 gpgme/gpgme/engine.h:1.35
--- gpgme/gpgme/engine.h:1.34	Wed Feb 25 00:08:46 2004
+++ gpgme/gpgme/engine.h	Tue Dec  7 19:25:53 2004
@@ -35,7 +35,14 @@
 						   const char *keyword,
 						   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,
 				 const char *lc_ctype,
 				 const char *lc_messages);
Index: gpgme/gpgme/gpgme.c
diff -u gpgme/gpgme/gpgme.c:1.76 gpgme/gpgme/gpgme.c:1.77
--- gpgme/gpgme/gpgme.c:1.76	Wed Feb 25 00:08:46 2004
+++ gpgme/gpgme/gpgme.c	Tue Dec  7 19:25:53 2004
@@ -50,6 +50,14 @@
   ctx = calloc (1, sizeof *ctx);
   if (!ctx)
     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->include_certs = 1;
   ctx->protocol = GPGME_PROTOCOL_OpenPGP;
@@ -62,6 +70,7 @@
       if (!ctx->lc_ctype)
 	{
 	  UNLOCK (def_lc_lock);
+	  _gpgme_engine_info_release (ctx->engine_info);
 	  free (ctx);
 	  return gpg_error_from_errno (errno);
 	}
@@ -77,6 +86,7 @@
 	  UNLOCK (def_lc_lock);
 	  if (ctx->lc_ctype)
 	    free (ctx->lc_ctype);
+	  _gpgme_engine_info_release (ctx->engine_info);
 	  free (ctx);
 	  return gpg_error_from_errno (errno);
 	}
@@ -120,6 +130,7 @@
     free (ctx->lc_ctype);
   if (ctx->lc_messages)
     free (ctx->lc_messages);
+  _gpgme_engine_info_release (ctx->engine_info);
   free (ctx);
 }
 
@@ -390,6 +401,29 @@
 }
 
 
+/* 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 *
 gpgme_pubkey_algo_name (gpgme_pubkey_algo_t algo)
 {
Index: gpgme/gpgme/gpgme.h
diff -u gpgme/gpgme/gpgme.h:1.149 gpgme/gpgme/gpgme.h:1.150
--- gpgme/gpgme/gpgme.h:1.149	Tue Dec  7 16:27:11 2004
+++ gpgme/gpgme/gpgme.h	Tue Dec  7 19:25:53 2004
@@ -412,13 +412,16 @@
   gpgme_protocol_t protocol;
 
   /* The file name of the engine binary.  */
-  const char *file_name;
-
+  char *file_name;
+  
   /* The version string of the installed engine.  */
-  const char *version;
+  char *version;
 
   /* The minimum version required for GPGME.  */
   const char *req_version;
+
+  /* The home directory used, or NULL if default.  */
+  char *home_dir;
 };
 typedef struct _gpgme_engine_info *gpgme_engine_info_t;
 
@@ -741,6 +744,19 @@
    locale if CTX is a null pointer.  */
 gpgme_error_t gpgme_set_locale (gpgme_ctx_t ctx, int category,
 				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
    key algorithm ALGO, or NULL if that name is not known.  */
@@ -1501,9 +1517,18 @@
 /* Check that the library fulfills the version requirement.  */
 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);
 
+/* 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.  */
 
Index: gpgme/gpgme/libgpgme.vers
diff -u gpgme/gpgme/libgpgme.vers:1.3 gpgme/gpgme/libgpgme.vers:1.4
--- gpgme/gpgme/libgpgme.vers:1.3	Wed Jun  2 16:18:03 2004
+++ gpgme/gpgme/libgpgme.vers	Tue Dec  7 19:25:53 2004
@@ -18,6 +18,15 @@
 # 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 {
   global:
     gpgme_check_version;
Index: gpgme/gpgme/op-support.c
diff -u gpgme/gpgme/op-support.c:1.15 gpgme/gpgme/op-support.c:1.16
--- gpgme/gpgme/op-support.c:1.15	Tue Oct  5 17:08:45 2004
+++ gpgme/gpgme/op-support.c	Tue Dec  7 19:25:53 2004
@@ -66,17 +66,26 @@
 _gpgme_op_reset (gpgme_ctx_t ctx, int type)
 {
   gpgme_error_t err = 0;
+  gpgme_engine_info_t info;
   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);
 
-  /* Create an engine object.  */
-  if  (ctx->engine)
+  if (ctx->engine)
     {
       _gpgme_engine_release (ctx->engine);
       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);
   if (err)
     return err;
Index: gpgme/gpgme/ops.h
diff -u gpgme/gpgme/ops.h:1.55 gpgme/gpgme/ops.h:1.56
--- gpgme/gpgme/ops.h:1.55	Fri Jun  6 02:55:42 2003
+++ gpgme/gpgme/ops.h	Tue Dec  7 19:25:53 2004
@@ -136,8 +136,10 @@
 
 
 /*-- version.c --*/
-const char *_gpgme_compare_versions (const char *my_version,
-				     const char *req_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);
 char *_gpgme_get_program_version (const char *const path);
 
 #endif /* OPS_H */
Index: gpgme/gpgme/rungpg.c
diff -u gpgme/gpgme/rungpg.c:1.101 gpgme/gpgme/rungpg.c:1.102
--- gpgme/gpgme/rungpg.c:1.101	Thu Sep 30 02:24:58 2004
+++ gpgme/gpgme/rungpg.c	Tue Dec  7 19:25:53 2004
@@ -66,6 +66,8 @@
 
 struct engine_gpg
 {
+  char *file_name;
+
   struct arg_and_data_s *arglist;
   struct arg_and_data_s **argtail;
 
@@ -224,17 +226,11 @@
 }
 
 
-static const char *
-gpg_get_version (void)
+static char *
+gpg_get_version (const char *file_name)
 {
-  static const char *gpg_version;
-  DEFINE_STATIC_LOCK (gpg_version_lock);
-
-  LOCK (gpg_version_lock);
-  if (!gpg_version)
-    gpg_version = _gpgme_get_program_version (_gpgme_get_gpg_path ());
-  UNLOCK (gpg_version_lock);
-  return gpg_version;
+  return _gpgme_get_program_version (file_name ? file_name
+				     : _gpgme_get_gpg_path ());
 }
 
 
@@ -313,6 +309,9 @@
 
   gpg_cancel (engine);
 
+  if (gpg->file_name)
+    free (gpg->file_name);
+
   while (gpg->arglist)
     {
       struct arg_and_data_s *next = gpg->arglist->next;
@@ -336,7 +335,8 @@
 
 
 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;
   gpgme_error_t rc = 0;
@@ -345,6 +345,16 @@
   if (!gpg)
     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->status.fd[0] = -1;
   gpg->status.fd[1] = -1;
@@ -380,6 +390,16 @@
       goto leave;
     }
   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");
   if (rc)
     goto leave;
@@ -1043,7 +1063,7 @@
   if (!gpg)
     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);
 
   rc = build_argv (gpg);
@@ -1101,7 +1121,8 @@
   fd_parent_list[n].fd = -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);
   saved_errno = errno;
   free (fd_child_list);
Index: gpgme/gpgme/version.c
diff -u gpgme/gpgme/version.c:1.25 gpgme/gpgme/version.c:1.26
--- gpgme/gpgme/version.c:1.25	Mon Oct  6 18:17:13 2003
+++ gpgme/gpgme/version.c	Tue Dec  7 19:25:53 2004
@@ -103,7 +103,9 @@
 }
 
 
-const char *
+/* Return true if MY_VERSION is at least REQ_VERSION, and false
+   otherwise.  */
+int
 _gpgme_compare_versions (const char *my_version,
 			 const char *rq_version)
 {
@@ -112,17 +114,17 @@
   const char *my_plvl, *rq_plvl;
 
   if (!rq_version)
-    return my_version;
+    return 1;
   if (!my_version)
-    return NULL;
+    return 0;
 
   my_plvl = parse_version_string (my_version, &my_major, &my_minor, &my_micro);
   if (!my_plvl)
-    return NULL;
+    return 0;
 
   rq_plvl = parse_version_string (rq_version, &rq_major, &rq_minor, &rq_micro);
   if (!rq_plvl)
-    return NULL;
+    return 0;
 
   if (my_major > rq_major
       || (my_major == rq_major && my_minor > rq_minor)
@@ -130,9 +132,9 @@
 	  && my_micro > rq_micro)
       || (my_major == rq_major && my_minor == rq_minor
 	  && my_micro == rq_micro && strcmp (my_plvl, rq_plvl) >= 0))
-    return my_version;
+    return 1;
 
-  return NULL;
+  return 0;
 }
 
 
@@ -149,7 +151,7 @@
 gpgme_check_version (const char *req_version)
 {
   do_subsystem_inits ();
-  return _gpgme_compare_versions (VERSION, req_version);
+  return _gpgme_compare_versions (VERSION, req_version) ? VERSION : NULL;
 }
 
 




More information about the Gnupg-commits mailing list