[svn] gpgme - r1406 - in trunk: . src tests tests/opassuan

svn author marcus cvs at cvs.gnupg.org
Mon Oct 26 19:52:32 CET 2009


Author: marcus
Date: 2009-10-26 19:52:32 +0100 (Mon, 26 Oct 2009)
New Revision: 1406

Modified:
   trunk/ChangeLog
   trunk/configure.ac
   trunk/src/ChangeLog
   trunk/src/context.h
   trunk/src/data.c
   trunk/src/engine-assuan.c
   trunk/src/engine-backend.h
   trunk/src/engine-g13.c
   trunk/src/engine-gpg.c
   trunk/src/engine-gpgsm.c
   trunk/src/engine.c
   trunk/src/engine.h
   trunk/src/g13.c
   trunk/src/gpgme.c
   trunk/src/gpgme.def
   trunk/src/gpgme.h.in
   trunk/src/keylist.c
   trunk/src/libgpgme.vers
   trunk/src/opassuan.c
   trunk/src/ops.h
   trunk/src/trustlist.c
   trunk/src/wait-global.c
   trunk/src/wait-private.c
   trunk/src/wait-user.c
   trunk/src/wait.c
   trunk/src/wait.h
   trunk/tests/ChangeLog
   trunk/tests/opassuan/t-command.c
Log:
2009-10-26  Marcus Brinkmann  <marcus at g10code.de>

	* configure.ac (NEED_GPG_VERSION_DEFAULT): Bump to 1.4.0 as 1.3.0
	was development versions only.

tests/
2009-10-26  Marcus Brinkmann  <marcus at g10code.de>

	* opassuan/t-command.c: Update to new interface.

src/
2009-10-26  Marcus Brinkmann  <marcus at g10code.de>

	* gpgme.h.in (struct gpgme_io_event_done_data)
	(gpgme_io_event_done_data_t): New types.
	(struct _gpgme_op_assuan_result): Deprecate the err member.
	(gpgme_op_assuan_result): Deprecate (for now).
	(gpgme_op_assuan_transact_ext): New prototype.
	(gpgme_op_assuan_transact): Deprecate.
	(struct _gpgme_op_g13_result): Replace with ...
	(struct _gpgme_op_vfs_mount_result): ... this.
	(gpgme_op_g13_mount): Replace with ...
	(gpgme_op_vfs_mount): ... this.
	* gpgme.def (gpgme_op_assuan_transact_ext, gpgme_wait_ext)
	(gpgme_op_vfs_mount_result, gpgme_op_vfs_mount): New.
	(gpgme_op_g13_mount): Remove.
	* libgpgme.vers: Likewise.
	* engine-backend.h (struct engine_ops): Remove RESULT_CB and
	RESULT_CB_VALUE args in opassuan_transact member.  Add CANCEL_OP
	member.
	* ops.h (_gpgme_cancel_with_err, _gpgme_wait_on_condition): Add
	OP_ERR argument.
	(_gpgme_wait_one_ext): New prototype.
	* context.h (ctx_op_data_id_t): Add OPDATA_VFS_MOUNT.
	* engine-g13.c (g13_cancel_op): New function.
	(parse_status): Remove declaration.
	(g13_assuan_simple_command): Do nothing with status lines for now.
	(status_handler): Update opaque value access.
	(_gpgme_engine_ops_g13): Add new cancel_op member.
	* gpgme.c (_gpgme_cancel_with_err): Add new parameter OP_ERR.
	Handle operational errors.
	(gpgme_cancel, gpgme_io_read, gpgme_io_write): Add debug output.
	* data.c (_gpgme_data_inbound_handler)
	(_gpgme_data_outbound_handler): Adjust opaque value access.
	* engine-gpg.c (command_handler, status_handler)
	(colon_line_handler): Likewise.
	* engine-gpgsm.c (status_handler): Likewise.
	* engine-gpg.c (_gpgme_engine_ops_gpg): Add cancel_op member.
	* engine-gpgsm.c (_gpgme_engine_ops_gpgsm): Likewise.
	* g13.c: Rewritten (and will be rewritten again).
	* engine.h (_gpgme_engine_op_assuan_transact): Remove result_cb
	and result_cb_value parameters from prototype.
	(_gpgme_engine_cancel_op): New prototype.
	* engine.c (engine_ops) [! ENABLE_ASSUAN]: Add missing comma.
	(_gpgme_engine_op_assuan_transact): Remove result_cb and
	result_cb_value parameter.
	(_gpgme_engine_cancel_op): New function.
	* wait.h (_gpgme_run_io_cb): Add new argument OP_ERR.
	(struct io_cb_data): New struct to pass opaque data and get a
	op_err return value.  Needed because we can't modify I/O callback
	handler signature because it is exposed to the user.
	* wait.c (_gpgme_run_io_cb): Add OP_ERR parameter.  Handle
	operational errors.
	* wait-user.c (_gpgme_user_io_cb_handler): Handle operational
	errors.
	* wait-private.c (_gpgme_wait_on_condition): New argument to
	retrieve the operational result.  Handle operational errors in
	session based protocols.
	(_gpgme_wait_one_ext): New function.
	(_gpgme_wait_one): Pass argument in invocation of
	_gpgme_wait_on_condition.
	* wait-global.c (struct ctx_list_item): Add member OP_ERR.
	(ctx_done): New argument OP_ERR.
	(ctx_wait): New argument OP_ERR.
	(gpgme_wait_ext): New function based on gpgme_wait but handling
	operational errors.
	(gpgme_wait): Implement in term of gpgme_wait_ext.
	* keylist.c (gpgme_op_keylist_next): Pass argument in invocation
	of _gpgme_wait_on_condition.
	* trustlist.c (gpgme_op_trustlist_next): Pass argument in
	invocation of _gpgme_wait_on_condition.
	* engine-assuan.c (struct engine_llass): Replace members RESULT_CB
	and RESULT_CB_VALUE by LAST_OP_ERR.
	(_gpgme_engine_assuan_last_op_err): Add this hack function.
	(llass_cancel_op): New function.
	(_gpgme_engine_llass_ops): Add cancel_op member.
	(llass_status_handler): Update opaque value access.
	(llass_transact): Remove RESULT_CB and RESULT_CB_VALUE arguments.
	* opassuan.c: Move compat hacks to the end of file.
	(opassuan_start): Do not set OPD->result.err.
	Do not pass RESULT_Cb and CTX to _gpgme_engine_op_assuan_transact.
	(gpgme_op_assuan_transact_ext): New function.


[The diff below has been truncated]

Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2009-10-26 17:38:39 UTC (rev 1405)
+++ trunk/ChangeLog	2009-10-26 18:52:32 UTC (rev 1406)
@@ -1,3 +1,8 @@
+2009-10-26  Marcus Brinkmann  <marcus at g10code.de>
+
+	* configure.ac (NEED_GPG_VERSION_DEFAULT): Bump to 1.4.0 as 1.3.0
+	was development versions only.
+
 2009-10-22  Marcus Brinkmann  <marcus at g10code.de>
 
 	* configure.ac: Add support for G13.

Modified: trunk/src/ChangeLog
===================================================================
--- trunk/src/ChangeLog	2009-10-26 17:38:39 UTC (rev 1405)
+++ trunk/src/ChangeLog	2009-10-26 18:52:32 UTC (rev 1406)
@@ -1,5 +1,85 @@
 2009-10-26  Marcus Brinkmann  <marcus at g10code.de>
 
+	* gpgme.h.in (struct gpgme_io_event_done_data)
+	(gpgme_io_event_done_data_t): New types.
+	(struct _gpgme_op_assuan_result): Deprecate the err member.
+	(gpgme_op_assuan_result): Deprecate (for now).
+	(gpgme_op_assuan_transact_ext): New prototype.
+	(gpgme_op_assuan_transact): Deprecate.
+	(struct _gpgme_op_g13_result): Replace with ...
+	(struct _gpgme_op_vfs_mount_result): ... this.
+	(gpgme_op_g13_mount): Replace with ...
+	(gpgme_op_vfs_mount): ... this.
+	* gpgme.def (gpgme_op_assuan_transact_ext, gpgme_wait_ext)
+	(gpgme_op_vfs_mount_result, gpgme_op_vfs_mount): New.
+	(gpgme_op_g13_mount): Remove.
+	* libgpgme.vers: Likewise.
+	* engine-backend.h (struct engine_ops): Remove RESULT_CB and
+	RESULT_CB_VALUE args in opassuan_transact member.  Add CANCEL_OP
+	member.
+	* ops.h (_gpgme_cancel_with_err, _gpgme_wait_on_condition): Add
+	OP_ERR argument.
+	(_gpgme_wait_one_ext): New prototype.
+	* context.h (ctx_op_data_id_t): Add OPDATA_VFS_MOUNT.
+	* engine-g13.c (g13_cancel_op): New function.
+	(parse_status): Remove declaration.
+	(g13_assuan_simple_command): Do nothing with status lines for now.
+	(status_handler): Update opaque value access.
+	(_gpgme_engine_ops_g13): Add new cancel_op member.
+	* gpgme.c (_gpgme_cancel_with_err): Add new parameter OP_ERR.
+	Handle operational errors.
+	(gpgme_cancel, gpgme_io_read, gpgme_io_write): Add debug output.
+	* data.c (_gpgme_data_inbound_handler)
+	(_gpgme_data_outbound_handler): Adjust opaque value access.
+	* engine-gpg.c (command_handler, status_handler)
+	(colon_line_handler): Likewise.
+	* engine-gpgsm.c (status_handler): Likewise.
+	* engine-gpg.c (_gpgme_engine_ops_gpg): Add cancel_op member.
+	* engine-gpgsm.c (_gpgme_engine_ops_gpgsm): Likewise.
+	* g13.c: Rewritten (and will be rewritten again).
+	* engine.h (_gpgme_engine_op_assuan_transact): Remove result_cb
+	and result_cb_value parameters from prototype.
+	(_gpgme_engine_cancel_op): New prototype.
+	* engine.c (engine_ops) [! ENABLE_ASSUAN]: Add missing comma.
+	(_gpgme_engine_op_assuan_transact): Remove result_cb and
+	result_cb_value parameter.
+	(_gpgme_engine_cancel_op): New function.
+	* wait.h (_gpgme_run_io_cb): Add new argument OP_ERR.
+	(struct io_cb_data): New struct to pass opaque data and get a
+	op_err return value.  Needed because we can't modify I/O callback
+	handler signature because it is exposed to the user.
+	* wait.c (_gpgme_run_io_cb): Add OP_ERR parameter.  Handle
+	operational errors.
+	* wait-user.c (_gpgme_user_io_cb_handler): Handle operational
+	errors.
+	* wait-private.c (_gpgme_wait_on_condition): New argument to
+	retrieve the operational result.  Handle operational errors in
+	session based protocols.
+	(_gpgme_wait_one_ext): New function.
+	(_gpgme_wait_one): Pass argument in invocation of
+	_gpgme_wait_on_condition.
+	* wait-global.c (struct ctx_list_item): Add member OP_ERR.
+	(ctx_done): New argument OP_ERR.
+	(ctx_wait): New argument OP_ERR.
+	(gpgme_wait_ext): New function based on gpgme_wait but handling
+	operational errors.
+	(gpgme_wait): Implement in term of gpgme_wait_ext.
+	* keylist.c (gpgme_op_keylist_next): Pass argument in invocation
+	of _gpgme_wait_on_condition.
+	* trustlist.c (gpgme_op_trustlist_next): Pass argument in
+	invocation of _gpgme_wait_on_condition.
+	* engine-assuan.c (struct engine_llass): Replace members RESULT_CB
+	and RESULT_CB_VALUE by LAST_OP_ERR.
+	(_gpgme_engine_assuan_last_op_err): Add this hack function.
+	(llass_cancel_op): New function.
+	(_gpgme_engine_llass_ops): Add cancel_op member.
+	(llass_status_handler): Update opaque value access.
+	(llass_transact): Remove RESULT_CB and RESULT_CB_VALUE arguments.
+	* opassuan.c: Move compat hacks to the end of file.
+	(opassuan_start): Do not set OPD->result.err.
+	Do not pass RESULT_Cb and CTX to _gpgme_engine_op_assuan_transact.
+	(gpgme_op_assuan_transact_ext): New function.
+
 	* debug.h (DEBUG_GLOBAL): New debug level.
 	* conversion.c (gnupg_errors, _gpgme_map_gnupg_error): Removed.
 	* data-user.c (gpgme_data_new_from_cbs): Add debug output.

Modified: trunk/tests/ChangeLog
===================================================================
--- trunk/tests/ChangeLog	2009-10-26 17:38:39 UTC (rev 1405)
+++ trunk/tests/ChangeLog	2009-10-26 18:52:32 UTC (rev 1406)
@@ -1,3 +1,7 @@
+2009-10-26  Marcus Brinkmann  <marcus at g10code.de>
+
+	* opassuan/t-command.c: Update to new interface.
+
 2009-10-15  Werner Koch  <wk at g10code.com>
 
 	* run-verify.c: New.

Modified: trunk/configure.ac
===================================================================
--- trunk/configure.ac	2009-10-26 17:38:39 UTC (rev 1405)
+++ trunk/configure.ac	2009-10-26 18:52:32 UTC (rev 1406)
@@ -286,7 +286,7 @@
 fi
 
 # Checks for system services
-NEED_GPG_VERSION_DEFAULT=1.3.0
+NEED_GPG_VERSION_DEFAULT=1.4.0
 NEED_GPGSM_VERSION_DEFAULT=1.9.6
 NEED_GPGCONF_VERSION_DEFAULT=2.0.4
 NEED_G13_VERSION_DEFAULT=2.1.0

Modified: trunk/src/context.h
===================================================================
--- trunk/src/context.h	2009-10-26 17:38:39 UTC (rev 1405)
+++ trunk/src/context.h	2009-10-26 18:52:32 UTC (rev 1406)
@@ -38,7 +38,7 @@
   {
     OPDATA_DECRYPT, OPDATA_SIGN, OPDATA_ENCRYPT, OPDATA_PASSPHRASE,
     OPDATA_IMPORT, OPDATA_GENKEY, OPDATA_KEYLIST, OPDATA_EDIT,
-    OPDATA_VERIFY, OPDATA_TRUSTLIST, OPDATA_ASSUAN
+    OPDATA_VERIFY, OPDATA_TRUSTLIST, OPDATA_ASSUAN, OPDATA_VFS_MOUNT
   } ctx_op_data_id_t;
 
 

Modified: trunk/src/data.c
===================================================================
--- trunk/src/data.c	2009-10-26 17:38:39 UTC (rev 1405)
+++ trunk/src/data.c	2009-10-26 18:52:32 UTC (rev 1406)
@@ -247,7 +247,8 @@
 gpgme_error_t
 _gpgme_data_inbound_handler (void *opaque, int fd)
 {
-  gpgme_data_t dh = (gpgme_data_t) opaque;
+  struct io_cb_data *data = (struct io_cb_data *) opaque;
+  gpgme_data_t dh = (gpgme_data_t) data->handler_value;
   char buffer[BUFFER_SIZE];
   char *bufp = buffer;
   ssize_t buflen;
@@ -279,7 +280,8 @@
 gpgme_error_t
 _gpgme_data_outbound_handler (void *opaque, int fd)
 {
-  gpgme_data_t dh = (gpgme_data_t) opaque;
+  struct io_cb_data *data = (struct io_cb_data *) opaque;
+  gpgme_data_t dh = (gpgme_data_t) data->handler_value;
   ssize_t nwritten;
   TRACE_BEG1 (DEBUG_CTX, "_gpgme_data_outbound_handler", dh,
 	      "fd=0x%x", fd);

Modified: trunk/src/engine-assuan.c
===================================================================
--- trunk/src/engine-assuan.c	2009-10-26 17:38:39 UTC (rev 1405)
+++ trunk/src/engine-assuan.c	2009-10-26 18:52:32 UTC (rev 1406)
@@ -70,9 +70,8 @@
 
   struct gpgme_io_cbs io_cbs;
 
-  /* Internal callbacks.  */
-  engine_assuan_result_cb_t result_cb;
-  void *result_cb_value; 
+  /* Hack for old opassuan.c interface, see there the result struct.  */
+  gpg_error_t last_op_err;
 
   /* User provided callbacks.  */
   struct {
@@ -95,7 +94,13 @@
 typedef struct engine_llass *engine_llass_t;
 
 
+gpg_error_t _gpgme_engine_assuan_last_op_err (void *engine)
+{
+  engine_llass_t llass = engine;
+  return llass->last_op_err;
+}
 
+
 /* Prototypes.  */
 static void llass_io_event (void *engine,
                             gpgme_event_io_t type, void *type_data);
@@ -169,6 +174,21 @@
 }
 
 
+static gpgme_error_t
+llass_cancel_op (void *engine)
+{
+  engine_llass_t llass = engine;
+
+  if (!llass)
+    return gpg_error (GPG_ERR_INV_VALUE);
+
+  if (llass->status_cb.fd != -1)
+    _gpgme_io_close (llass->status_cb.fd);
+
+  return 0;
+}
+
+
 static void
 llass_release (void *engine)
 {
@@ -408,8 +428,9 @@
 static gpgme_error_t
 llass_status_handler (void *opaque, int fd)
 {
+  struct io_cb_data *data = (struct io_cb_data *) opaque;
+  engine_llass_t llass = (engine_llass_t) data->handler_value;
   gpgme_error_t err = 0;
-  engine_llass_t llass = opaque;
   char *line;
   size_t linelen;
 
@@ -459,8 +480,6 @@
           if (linelen && llass->user.data_cb)
             err = llass->user.data_cb (llass->user.data_cb_value,
                                        src, linelen);
-          else
-            err = 0;
 
           TRACE2 (DEBUG_CTX, "gpgme:llass_status_handler", llass,
 		  "fd 0x%x: D inlinedata; status from cb: %s",
@@ -474,8 +493,6 @@
           /* END received.  Tell the data callback.  */
           if (llass->user.data_cb)
             err = llass->user.data_cb (llass->user.data_cb_value, NULL, 0);
-          else
-            err = 0;
 
           TRACE2 (DEBUG_CTX, "gpgme:llass_status_handler", llass,
 		  "fd 0x%x: END line; status from cb: %s",
@@ -502,8 +519,6 @@
           if (llass->user.status_cb)
             err = llass->user.status_cb (llass->user.status_cb_value,
                                          src, args);
-          else
-            err = 0;
 
           TRACE3 (DEBUG_CTX, "gpgme:llass_status_handler", llass,
 		  "fd 0x%x: S line (%s) - status from cb: %s",
@@ -554,17 +569,15 @@
           TRACE2 (DEBUG_CTX, "gpgme:llass_status_handler", llass,
 		  "fd 0x%x: ERR line: %s",
                   fd, err ? gpg_strerror (err) : "ok");
+
 	  /* Command execution errors are not fatal, as we use
 	     a session based protocol.  */
-          if (llass->result_cb)
-            err = llass->result_cb (llass->result_cb_value, err);
-          else
-            err = 0;
-          if (!err)
-            {
-              _gpgme_io_close (llass->status_cb.fd);
-              return 0;
-            }
+	  data->op_err = err;
+	  llass->last_op_err = err;
+
+	  /* The caller will do the rest (namely, call cancel_op,
+	     which closes status_fd).  */
+	  return 0;
 	}
       else if (linelen >= 2
 	       && line[0] == 'O' && line[1] == 'K'
@@ -572,15 +585,11 @@
 	{
           TRACE1 (DEBUG_CTX, "gpgme:llass_status_handler", llass,
 		  "fd 0x%x: OK line", fd);
-          if (llass->result_cb)
-            err = llass->result_cb (llass->result_cb_value, 0);
-          else
-            err = 0;
-          if (!err)
-            {
-              _gpgme_io_close (llass->status_cb.fd);
-              return 0;
-            }
+
+	  llass->last_op_err = 0;
+
+	  _gpgme_io_close (llass->status_cb.fd);
+	  return 0;
 	}
       else
         {
@@ -667,8 +676,6 @@
 static gpgme_error_t
 llass_transact (void *engine,
                 const char *command,
-                engine_assuan_result_cb_t result_cb,
-                void *result_cb_value,
                 gpgme_assuan_data_cb_t data_cb,
                 void *data_cb_value,
                 gpgme_assuan_inquire_cb_t inq_cb,
@@ -682,8 +689,6 @@
   if (!llass || !command || !*command)
     return gpg_error (GPG_ERR_INV_VALUE);
 
-  llass->result_cb = result_cb;
-  llass->result_cb_value = result_cb_value;
   llass->user.data_cb = data_cb;
   llass->user.data_cb_value = data_cb_value;
   llass->user.inq_cb = inq_cb;
@@ -754,5 +759,6 @@
     NULL,		/* conf_save */
     llass_set_io_cbs,
     llass_io_event,
-    llass_cancel
+    llass_cancel,
+    llass_cancel_op
   };

Modified: trunk/src/engine-backend.h
===================================================================
--- trunk/src/engine-backend.h	2009-10-26 17:38:39 UTC (rev 1405)
+++ trunk/src/engine-backend.h	2009-10-26 18:52:32 UTC (rev 1406)
@@ -98,8 +98,6 @@
                                  unsigned int flags);
   gpgme_error_t  (*opassuan_transact) (void *engine, 
                                        const char *command,
-                                       engine_assuan_result_cb_t result_cb,
-                                       void *result_cb_value,
                                        gpgme_assuan_data_cb_t data_cb,
                                        void *data_cb_value,
                                        gpgme_assuan_inquire_cb_t inq_cb,
@@ -113,7 +111,11 @@
   void (*set_io_cbs) (void *engine, gpgme_io_cbs_t io_cbs);
   void (*io_event) (void *engine, gpgme_event_io_t type, void *type_data);
 
+  /* Cancel the whole engine session.  */
   gpgme_error_t (*cancel) (void *engine);
+
+  /* Cancel only the current operation, not the whole session.  */
+  gpgme_error_t (*cancel_op) (void *engine);
 };
 
 

Modified: trunk/src/engine-g13.c
===================================================================
--- trunk/src/engine-g13.c	2009-10-26 17:38:39 UTC (rev 1405)
+++ trunk/src/engine-g13.c	2009-10-26 18:52:32 UTC (rev 1406)
@@ -180,6 +180,21 @@
 }
 
 
+static gpgme_error_t
+g13_cancel_op (void *engine)
+{
+  engine_g13_t g13 = engine;
+
+  if (!g13)
+    return gpg_error (GPG_ERR_INV_VALUE);
+
+  if (g13->status_cb.fd != -1)
+    _gpgme_io_close (g13->status_cb.fd);
+
+  return 0;
+}
+
+
 static void
 g13_release (void *engine)
 {
@@ -385,9 +400,6 @@
 }
 
 
-/* Forward declaration.  */
-static gpgme_status_code_t parse_status (const char *name);
-
 static gpgme_error_t
 g13_assuan_simple_command (assuan_context_t ctx, char *cmd,
 			     engine_status_handler_t status_fnc,
@@ -422,7 +434,6 @@
 	       && line[0] == 'S' && line[1] == ' ')
 	{
 	  char *rest;
-	  gpgme_status_code_t r;
 
 	  rest = strchr (line + 2, ' ');
 	  if (!rest)
@@ -430,12 +441,7 @@
 	  else
 	    *(rest++) = 0;
 
-	  r = parse_status (line + 2);
-
-	  if (r >= 0 && status_fnc)
-	    err = status_fnc (status_fnc_value, r, rest);
-	  else
-	    err = gpg_error (GPG_ERR_GENERAL);
+	  /* Nothing to do with status lines.  */
 	}
       else
 	err = gpg_error (GPG_ERR_GENERAL);
@@ -449,8 +455,9 @@
 static gpgme_error_t
 status_handler (void *opaque, int fd)
 {
+  struct io_cb_data *data = (struct io_cb_data *) opaque;
+  engine_g13_t g13 = (engine_g13_t) data->handler_value;
   gpgme_error_t err = 0;
-  engine_g13_t g13 = opaque;
   char *line;
   size_t linelen;
 
@@ -792,5 +799,6 @@
     NULL,		/* conf_save */
     g13_set_io_cbs,
     g13_io_event,
-    g13_cancel
+    g13_cancel,
+    g13_cancel_op,
   };

Modified: trunk/src/engine-gpg.c
===================================================================
--- trunk/src/engine-gpg.c	2009-10-26 17:38:39 UTC (rev 1405)
+++ trunk/src/engine-gpg.c	2009-10-26 18:52:32 UTC (rev 1406)
@@ -646,10 +646,10 @@
 static gpgme_error_t
 command_handler (void *opaque, int fd)
 {
+  struct io_cb_data *data = (struct io_cb_data *) opaque;
+  engine_gpg_t gpg = (engine_gpg_t) data->handler_value;
   gpgme_error_t err;
-  engine_gpg_t gpg = (engine_gpg_t) opaque;
   int processed = 0;
-
   assert (gpg->cmd.used);
   assert (gpg->cmd.code);
   assert (gpg->cmd.fnc);
@@ -1139,7 +1139,8 @@
 static gpgme_error_t
 status_handler (void *opaque, int fd)
 {
-  engine_gpg_t gpg = opaque;
+  struct io_cb_data *data = (struct io_cb_data *) opaque;
+  engine_gpg_t gpg = (engine_gpg_t) data->handler_value;
   int err;
 
   assert (fd == gpg->status.fd[0]);
@@ -1246,7 +1247,8 @@
 static gpgme_error_t
 colon_line_handler (void *opaque, int fd)
 {
-  engine_gpg_t gpg = opaque;
+  struct io_cb_data *data = (struct io_cb_data *) opaque;
+  engine_gpg_t gpg = (engine_gpg_t) data->handler_value;
   gpgme_error_t rc = 0;
 
   assert (fd == gpg->colon.fd[0]);
@@ -2365,5 +2367,6 @@
     NULL,		/* conf_save */
     gpg_set_io_cbs,
     gpg_io_event,
-    gpg_cancel
+    gpg_cancel,
+    NULL		/* cancel_op */
   };

Modified: trunk/src/engine-gpgsm.c
===================================================================
--- trunk/src/engine-gpgsm.c	2009-10-26 17:38:39 UTC (rev 1405)
+++ trunk/src/engine-gpgsm.c	2009-10-26 18:52:32 UTC (rev 1406)
@@ -761,8 +761,9 @@
 static gpgme_error_t
 status_handler (void *opaque, int fd)
 {
+  struct io_cb_data *data = (struct io_cb_data *) opaque;
+  engine_gpgsm_t gpgsm = (engine_gpgsm_t) data->handler_value;
   gpgme_error_t err = 0;
-  engine_gpgsm_t gpgsm = opaque;
   char *line;
   size_t linelen;
 
@@ -799,7 +800,7 @@
 	    err = gpgsm->status.fnc (gpgsm->status.fnc_value,
 				     GPGME_STATUS_EOF, "");
 	  
-	  if (!err && gpgsm->colon.fnc && gpgsm->colon.any )
+	  if (!err && gpgsm->colon.fnc && gpgsm->colon.any)
             {
               /* We must tell a colon function about the EOF. We do
                  this only when we have seen any data lines.  Note
@@ -1939,5 +1940,6 @@
     NULL,		/* conf_save */
     gpgsm_set_io_cbs,
     gpgsm_io_event,
-    gpgsm_cancel
+    gpgsm_cancel,
+    NULL		/* cancel_op */
   };

Modified: trunk/src/engine.c
===================================================================
--- trunk/src/engine.c	2009-10-26 17:38:39 UTC (rev 1405)
+++ trunk/src/engine.c	2009-10-26 18:52:32 UTC (rev 1406)
@@ -58,7 +58,7 @@
 #ifdef ENABLE_ASSUAN
     &_gpgme_engine_ops_assuan,		/* Low-Level Assuan.  */
 #else
-    NULL
+    NULL,
 #endif
 #ifdef ENABLE_G13
     &_gpgme_engine_ops_g13		/* Crypto VFS.  */
@@ -777,8 +777,6 @@
 gpgme_error_t
 _gpgme_engine_op_assuan_transact (engine_t engine, 
                                   const char *command,
-                                  engine_assuan_result_cb_t result_cb,
-                                  void *result_cb_value,
                                   gpgme_assuan_data_cb_t data_cb,
                                   void *data_cb_value,
                                   gpgme_assuan_inquire_cb_t inq_cb,
@@ -794,7 +792,6 @@
 
   return (*engine->ops->opassuan_transact) (engine->engine, 
                                             command,
-                                            result_cb, result_cb_value,
                                             data_cb, data_cb_value,
                                             inq_cb, inq_cb_value,
                                             status_cb, status_cb_value);
@@ -848,6 +845,7 @@
 }
 
 
+/* Cancel the session and the pending operation if any.  */
 gpgme_error_t
 _gpgme_engine_cancel (engine_t engine)
 {
@@ -859,3 +857,17 @@
 
   return (*engine->ops->cancel) (engine->engine);
 }
+
+
+/* Cancel the pending operation, but not the complete session.  */
+gpgme_error_t
+_gpgme_engine_cancel_op (engine_t engine)
+{
+  if (!engine)
+    return gpg_error (GPG_ERR_INV_VALUE);
+
+  if (!engine->ops->cancel_op)
+    return 0;
+
+  return (*engine->ops->cancel_op) (engine->engine);
+}

Modified: trunk/src/engine.h
===================================================================
--- trunk/src/engine.h	2009-10-26 17:38:39 UTC (rev 1405)
+++ trunk/src/engine.h	2009-10-26 18:52:32 UTC (rev 1406)
@@ -133,8 +133,6 @@
 gpgme_error_t _gpgme_engine_op_assuan_transact 
                 (engine_t engine, 
                  const char *command,
-                 engine_assuan_result_cb_t result_cb,
-                 void *result_cb_value,
                  gpgme_assuan_data_cb_t data_cb,
                  void *data_cb_value,
                  gpgme_assuan_inquire_cb_t inq_cb,
@@ -154,4 +152,6 @@
 
 gpgme_error_t _gpgme_engine_cancel (engine_t engine);
 
+gpgme_error_t _gpgme_engine_cancel_op (engine_t engine);
+
 #endif /* ENGINE_H */

Modified: trunk/src/g13.c
===================================================================
--- trunk/src/g13.c	2009-10-26 17:38:39 UTC (rev 1405)
+++ trunk/src/g13.c	2009-10-26 18:52:32 UTC (rev 1406)
@@ -31,42 +31,20 @@
 
 typedef struct
 {
-  struct _gpgme_op_g13_result result;
+  struct _gpgme_op_vfs_mount_result result;
 } *op_data_t;
 
 
 
-/* This callback is used to return the status of the assuan command
-   back rather than transmission errors.  */
-static gpgme_error_t
-result_cb (void *priv, gpgme_error_t result)
+gpgme_vfs_mount_result_t
+gpgme_op_vfs_mount_result (gpgme_ctx_t ctx)
 {
-  gpgme_ctx_t ctx = (gpgme_ctx_t)priv;
   gpgme_error_t err;
   void *hook;
   op_data_t opd;
 
-  err = _gpgme_op_data_lookup (ctx, OPDATA_ASSUAN, &hook, -1, NULL);
+  err = _gpgme_op_data_lookup (ctx, OPDATA_VFS_MOUNT, &hook, -1, NULL);
   opd = hook;
-  if (err)
-    return err;
-  if (!opd)
-    return gpg_error (GPG_ERR_INTERNAL);
-
-  opd->result.err = result;
-  return 0;
-}
-
-
-gpgme_g13_result_t
-gpgme_op_g13_result (gpgme_ctx_t ctx)
-{
-  gpgme_error_t err;
-  void *hook;
-  op_data_t opd;
-
-  err = _gpgme_op_data_lookup (ctx, OPDATA_ASSUAN, &hook, -1, NULL);
-  opd = hook;
   /* Check in case this function is used without having run a command
      before.  */
   if (err || !opd)
@@ -77,14 +55,14 @@
 
 
 static gpgme_error_t
-opg13_start (gpgme_ctx_t ctx, int synchronous,
-                const char *command,
-                gpgme_assuan_data_cb_t data_cb,
-                void *data_cb_value,
-                gpgme_assuan_inquire_cb_t inq_cb,
-                void *inq_cb_value,
-                gpgme_assuan_status_cb_t status_cb,
-                void *status_cb_value)
+vfs_start (gpgme_ctx_t ctx, int synchronous,
+	   const char *command,
+	   gpgme_assuan_data_cb_t data_cb,
+	   void *data_cb_value,
+	   gpgme_assuan_inquire_cb_t inq_cb,
+	   void *inq_cb_value,
+	   gpgme_assuan_status_cb_t status_cb,
+	   void *status_cb_value)
 {
   gpgme_error_t err;
   void *hook;
@@ -99,14 +77,13 @@
   if (err)
     return err;
 
-  err = _gpgme_op_data_lookup (ctx, OPDATA_ASSUAN, &hook, sizeof (*opd), NULL);
+  err = _gpgme_op_data_lookup (ctx, OPDATA_VFS_MOUNT, &hook, sizeof (*opd),
+			       NULL);
   opd = hook;
   if (err)
     return err;
-  opd->result.err = gpg_error (GPG_ERR_UNFINISHED);
 
   return _gpgme_engine_op_assuan_transact (ctx->engine, command,
-					   result_cb, ctx,
 					   data_cb, data_cb_value,
 					   inq_cb, inq_cb_value,
 					   status_cb, status_cb_value);
@@ -116,7 +93,7 @@
 
 /* XXXX.  This is the asynchronous variant. */
 static gpgme_error_t
-gpgme_op_g13_transact_start (gpgme_ctx_t ctx, 
+gpgme_op_vfs_transact_start (gpgme_ctx_t ctx, 
 			     const char *command,
 			     gpgme_assuan_data_cb_t data_cb,
 			     void *data_cb_value,
@@ -125,59 +102,52 @@
 			     gpgme_assuan_status_cb_t status_cb,
 			     void *status_cb_value)
 {
-  return opg13_start (ctx, 0, command, data_cb, data_cb_value,
-		      inq_cb, inq_cb_value, status_cb, status_cb_value);
+  return vfs_start (ctx, 0, command, data_cb, data_cb_value,
+		    inq_cb, inq_cb_value, status_cb, status_cb_value);
 }
 
 
 /* XXXX.  This is the synchronous variant. */
 static gpgme_error_t
-gpgme_op_g13_transact (gpgme_ctx_t ctx,
+gpgme_op_vfs_transact (gpgme_ctx_t ctx,
 		       const char *command,
 		       gpgme_assuan_data_cb_t data_cb,
 		       void *data_cb_value,
 		       gpgme_assuan_inquire_cb_t inq_cb,
 		       void *inq_cb_value,
 		       gpgme_assuan_status_cb_t status_cb,
-		       void *status_cb_value)
+		       void *status_cb_value,
+		       gpgme_error_t *op_err)
 {
   gpgme_error_t err;
   
-  err = opg13_start (ctx, 1, command, data_cb, data_cb_value,
-		     inq_cb, inq_cb_value, status_cb, status_cb_value);
+  err = vfs_start (ctx, 1, command, data_cb, data_cb_value,
+		   inq_cb, inq_cb_value, status_cb, status_cb_value);
   if (!err)
-    err = _gpgme_wait_one (ctx);
+    err = _gpgme_wait_one_ext (ctx, op_err);
   return err;
 }
 
 
 /* The actual exported interface follows.  */
 
-static gpg_error_t
-get_err (gpgme_ctx_t ctx)
-{
-  gpgme_g13_result_t res;
-
-  res = gpgme_op_g13_result (ctx);
-  if (! res)
-    return gpg_error (GPG_ERR_GENERAL);
-
-  return res->err;
-}
-
-
 /* The container is automatically unmounted when the context is reset
    or destroyed.  This is a synchronous convenience interface, which
    automatically returns an operation error if there is no
    transmission error.  */
 gpgme_error_t
-gpgme_op_g13_mount (gpgme_ctx_t ctx, const char *container_file,
-		    const char *mount_dir, int flags)
+gpgme_op_vfs_mount (gpgme_ctx_t ctx, const char *container_file,
+		    const char *mount_dir, int flags, gpgme_error_t *op_err)
 {
   gpg_error_t err;
   char *cmd;
   char *container_file_esc = NULL;
-  
+
+  /* We want to encourage people to check error values, so not getting
+     them is discouraged here.  Also makes our code easier.  */
+  if (! op_err)
+    return gpg_error (GPG_ERR_INV_VALUE);
+
   err = _gpgme_encode_percent_string (container_file, &container_file_esc, 0);
   if (err)
     return err;
@@ -190,11 +160,10 @@
     }
   free (container_file_esc);
 
-  err = gpgme_op_g13_transact (ctx, cmd, NULL, NULL, NULL, NULL,
-			       NULL, NULL);
+  err = gpgme_op_vfs_transact (ctx, cmd, NULL, NULL, NULL, NULL,
+			       NULL, NULL, op_err);
   free (cmd);
-  err = err || get_err (ctx);
-  if (err)
+  if (err || *op_err)
     return err;
 
   if (mount_dir)
@@ -219,11 +188,9 @@
 	return gpg_error_from_syserror ();
     }
     
-  err = gpgme_op_g13_transact (ctx, cmd, NULL, NULL, NULL, NULL,
-			       NULL, NULL);
+  err = gpgme_op_vfs_transact (ctx, cmd, NULL, NULL, NULL, NULL,
+			       NULL, NULL, op_err);
   free (cmd);
 
-  /* Note: in symmetry with the asynchronous variant, we don't return 
-     the error in the result structure here, if any.  */
   return err;
 }

Modified: trunk/src/gpgme.c
===================================================================
--- trunk/src/gpgme.c	2009-10-26 17:38:39 UTC (rev 1405)
+++ trunk/src/gpgme.c	2009-10-26 18:52:32 UTC (rev 1406)
@@ -46,7 +46,7 @@
 gpgme_error_t _gpgme_selftest = GPG_ERR_NOT_OPERATIONAL;
 
 /* Protects all reference counters in result structures.  All other
-   accesses to a key are read only.  */
+   accesses to a result structure are read only.  */
 DEFINE_STATIC_LOCK (result_ref_lock);
 
 
@@ -118,18 +118,33 @@
 
 
 gpgme_error_t
-_gpgme_cancel_with_err (gpgme_ctx_t ctx, gpg_error_t ctx_err)
+_gpgme_cancel_with_err (gpgme_ctx_t ctx, gpg_error_t ctx_err,
+			gpg_error_t op_err)
 {
   gpgme_error_t err;
-  TRACE_BEG1 (DEBUG_CTX, "_gpgme_cancel_with_err", ctx, "ctx_err=%i",
-	      ctx_err);
+  struct gpgme_io_event_done_data data;
 
-  err = _gpgme_engine_cancel (ctx->engine);
-  if (err)
-    return TRACE_ERR (err);
+  TRACE_BEG2 (DEBUG_CTX, "_gpgme_cancel_with_err", ctx, "ctx_err=%i, op_err=%i",
+	      ctx_err, op_err);
 
-  _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_DONE, &ctx_err);
+  if (ctx_err)
+    {
+      err = _gpgme_engine_cancel (ctx->engine);
+      if (err)
+	return TRACE_ERR (err);
+    }
+  else
+    {
+      err = _gpgme_engine_cancel_op (ctx->engine);
+      if (err)
+	return TRACE_ERR (err);
+    }
 
+  data.err = ctx_err;
+  data.op_err = op_err;
+
+  _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_DONE, &data);
+
   return TRACE_ERR (0);
 }
 
@@ -138,7 +153,13 @@
 gpgme_error_t
 gpgme_cancel (gpgme_ctx_t ctx)
 {
-  return _gpgme_cancel_with_err (ctx, gpg_error (GPG_ERR_CANCELED));
+  gpg_error_t err;
+
+  TRACE_BEG (DEBUG_CTX, "gpgme_cancel", ctx);
+
+  err = _gpgme_cancel_with_err (ctx, gpg_error (GPG_ERR_CANCELED), 0);
+
+  return TRACE_ERR (err);
 }
 
 
@@ -486,10 +507,12 @@
 gpgme_io_read (int fd, void *buffer, size_t count)
 {
   int ret;
+  TRACE_BEG2 (DEBUG_GLOBAL, "gpgme_io_read", fd,
+	      "buffer=%p, count=%u", buffer, count);
 
   ret = _gpgme_io_read (fd, buffer, count);
 
-  return ret;
+  return TRACE_SYSRES (ret);
 }
 
 
@@ -500,10 +523,12 @@
 gpgme_io_write (int fd, const void *buffer, size_t count)
 {
   int ret;
+  TRACE_BEG2 (DEBUG_GLOBAL, "gpgme_io_write", fd,
+	      "buffer=%p, count=%u", buffer, count);
 
   ret = _gpgme_io_write (fd, buffer, count);
 
-  return ret;
+  return TRACE_SYSRES (ret);
 }
 
 

Modified: trunk/src/gpgme.def
===================================================================
--- trunk/src/gpgme.def	2009-10-26 17:38:39 UTC (rev 1405)
+++ trunk/src/gpgme.def	2009-10-26 18:52:32 UTC (rev 1406)
@@ -185,7 +185,11 @@
     gpgme_op_export_keys                  @142
     gpgme_op_export_keys_start            @143
 
-    gpgme_op_g13_mount			  @144
+    gpgme_op_assuan_transact_ext	  @144
 
+    gpgme_wait_ext			  @145
+    gpgme_op_vfs_mount_result		  @146
+    gpgme_op_vfs_mount			  @147
+
 ; END
 

Modified: trunk/src/gpgme.h.in
===================================================================
--- trunk/src/gpgme.h.in	2009-10-26 17:38:39 UTC (rev 1405)
+++ trunk/src/gpgme.h.in	2009-10-26 18:52:32 UTC (rev 1406)
@@ -960,6 +960,17 @@
   }
 gpgme_event_io_t;
 
+struct gpgme_io_event_done_data
+{
+  /* A fatal IPC error or an operational error in state-less
+     protocols.  */
+  gpgme_error_t err;
+
+  /* An operational errors in session-based protocols.  */
+  gpgme_error_t op_err;
+};
+typedef struct gpgme_io_event_done_data *gpgme_io_event_done_data_t;
+
 /* The type of a function that is called when a context finished an
    operation.  */
 typedef void (*gpgme_event_io_cb_t) (void *data, gpgme_event_io_t type,
@@ -990,6 +1001,9 @@
    the pending operation to finish.  */
 gpgme_ctx_t gpgme_wait (gpgme_ctx_t ctx, gpgme_error_t *status, int hang);
 
+gpgme_ctx_t gpgme_wait_ext (gpgme_ctx_t ctx, gpgme_error_t *status,
+			    gpgme_error_t *op_err, int hang);
+
 
 /* Functions to handle data objects.  */
 
@@ -1733,21 +1747,6 @@
 typedef gpgme_error_t (*gpgme_assuan_status_cb_t)
      (void *opaque, const char *status, const char *args);
 
-struct _gpgme_op_assuan_result
-{
-  /* The result of the actual assuan command.  An OK is indicated by a
-     value of 0 and an ERR by the respective error error value.  This
-     is required because assuan operations use a session-based
-     interface.  The error code of the GPGME function calls just
-     reflects transmission errors.  */
-  gpgme_error_t err;
-};
-typedef struct _gpgme_op_assuan_result *gpgme_assuan_result_t;
-
-
-/* Return the result of the last Assuan command. */
-gpgme_assuan_result_t gpgme_op_assuan_result (gpgme_ctx_t ctx);
-
 /* Send the Assuan COMMAND and return results via the callbacks.
    Asynchronous variant. */
 gpgme_error_t gpgme_op_assuan_transact_start (gpgme_ctx_t ctx, 
@@ -1761,35 +1760,56 @@
 
 /* Send the Assuan COMMAND and return results via the callbacks.
    Synchronous variant. */
-gpgme_error_t gpgme_op_assuan_transact (gpgme_ctx_t ctx, 
-                                        const char *command,
-                                        gpgme_assuan_data_cb_t data_cb,
-                                        void *data_cb_value,
-                                        gpgme_assuan_inquire_cb_t inq_cb,
-                                        void *inq_cb_value,
-                                        gpgme_assuan_status_cb_t stat_cb,
-                                        void *stat_cb_value);
+gpgme_error_t gpgme_op_assuan_transact_ext (gpgme_ctx_t ctx, 
+					    const char *command,
+					    gpgme_assuan_data_cb_t data_cb,
+					    void *data_cb_value,
+					    gpgme_assuan_inquire_cb_t inq_cb,
+					    void *inq_cb_value,
+					    gpgme_assuan_status_cb_t stat_cb,
+					    void *stat_cb_value,
+					    gpgme_error_t *op_err);
 
+/* Compat.  */
+struct _gpgme_op_assuan_result
+{
+  /* Deprecated.  Use the second value in a DONE event or the
+     synchronous variant gpgme_op_assuan_transact_ext.  */
+  gpgme_error_t err _GPGME_DEPRECATED_OUTSIDE_GPGME;
+};
+typedef struct _gpgme_op_assuan_result *gpgme_assuan_result_t;
 
+
+/* Return the result of the last Assuan command. */
+gpgme_assuan_result_t gpgme_op_assuan_result (gpgme_ctx_t ctx)
+  _GPGME_DEPRECATED;
+
+gpgme_error_t
+gpgme_op_assuan_transact (gpgme_ctx_t ctx,
+			      const char *command,
+			      gpgme_assuan_data_cb_t data_cb,
+			      void *data_cb_value,
+			      gpgme_assuan_inquire_cb_t inq_cb,
+			      void *inq_cb_value,
+			      gpgme_assuan_status_cb_t status_cb,
+			      void *status_cb_value) _GPGME_DEPRECATED;
+
 
 /* Crypto container support.  */
-struct _gpgme_op_g13_result
+struct _gpgme_op_vfs_mount_result
 {
-  /* The result of the actual assuan command.  An OK is indicated by a
-     value of 0 and an ERR by the respective error error value.  This
-     is required because assuan operations use a session-based
-     interface.  The error code of the GPGME function calls just
-     reflects transmission errors.  */
-  gpgme_error_t err;
+  char *mount_dir;
 };
-typedef struct _gpgme_op_g13_result *gpgme_g13_result_t;
+typedef struct _gpgme_op_vfs_mount_result *gpgme_vfs_mount_result_t;
 
+gpgme_vfs_mount_result_t gpgme_op_vfs_mount_result (gpgme_ctx_t ctx);
+
 /* The container is automatically unmounted when the context is reset
-   or destroyed.  This is a synchronous convenience interface, which
-   automatically returns an operation error if there is no
-   transmission error.  */
-gpgme_error_t gpgme_op_g13_mount (gpgme_ctx_t ctx, const char *container_file,
-				  const char *mount_dir, int flags);
+   or destroyed.  Transmission errors are returned directly,
+   operational errors are returned in OP_ERR.  */
+gpgme_error_t gpgme_op_vfs_mount (gpgme_ctx_t ctx, const char *container_file,
+				  const char *mount_dir, int flags,
+				  gpgme_error_t *op_err);
 
 
 /* Interface to gpgconf(1).  */

Modified: trunk/src/keylist.c
===================================================================
--- trunk/src/keylist.c	2009-10-26 17:38:39 UTC (rev 1405)
+++ trunk/src/keylist.c	2009-10-26 18:52:32 UTC (rev 1406)
@@ -928,7 +928,7 @@
 
   if (!opd->key_queue)
     {
-      err = _gpgme_wait_on_condition (ctx, &opd->key_cond);
+      err = _gpgme_wait_on_condition (ctx, &opd->key_cond, NULL);
       if (err)
 	return err;
 

Modified: trunk/src/libgpgme.vers
===================================================================
--- trunk/src/libgpgme.vers	2009-10-26 17:38:39 UTC (rev 1405)
+++ trunk/src/libgpgme.vers	2009-10-26 18:52:32 UTC (rev 1406)
@@ -65,7 +65,12 @@
     gpgme_op_export_keys;
     gpgme_op_export_keys_start;
 
-    gpgme_op_g13_mount;
+    gpgme_op_assuan_transact_ext;
+
+    gpgme_wait_ext;
+
+    gpgme_op_vfs_mount_result;
+    gpgme_op_vfs_mount;
 };
 
 

Modified: trunk/src/opassuan.c
===================================================================
--- trunk/src/opassuan.c	2009-10-26 17:38:39 UTC (rev 1405)
+++ trunk/src/opassuan.c	2009-10-26 18:52:32 UTC (rev 1406)
@@ -26,59 +26,7 @@
 #include "ops.h"
 #include "util.h"
 
-
-typedef struct
-{
-  struct _gpgme_op_assuan_result result;
-
-} *op_data_t;
-
-
-
-
-/* This callback is used to return the status of the assuan command
-   back.  Note that this is different from the error code returned
-   from gpgme_op_assuan_transact because the later only reflects error
-   with the connection.  */
 static gpgme_error_t
-result_cb (void *priv, gpgme_error_t result)
-{
-  gpgme_ctx_t ctx = (gpgme_ctx_t)priv;
-  gpgme_error_t err;
-  void *hook;
-  op_data_t opd;
-
-  err = _gpgme_op_data_lookup (ctx, OPDATA_ASSUAN, &hook, -1, NULL);
-  opd = hook;
-  if (err)
-    return err;
-  if (!opd)
-    return gpg_error (GPG_ERR_INTERNAL);
-
-  opd->result.err = result;
-  return 0;
-}
-
-
-gpgme_assuan_result_t
-gpgme_op_assuan_result (gpgme_ctx_t ctx)
-{
-  gpgme_error_t err;
-  void *hook;
-  op_data_t opd;
-
-  err = _gpgme_op_data_lookup (ctx, OPDATA_ASSUAN, &hook, -1, NULL);
-  opd = hook;
-  /* Check in case this function is used without having run a command
-     before.  */
-  if (err || !opd)
-    return NULL;
-
-  return &opd->result;
-}
-
-
-static gpgme_error_t
 opassuan_start (gpgme_ctx_t ctx, int synchronous,
                 const char *command,
                 gpgme_assuan_data_cb_t data_cb,
@@ -89,8 +37,6 @@
                 void *status_cb_value)
 {
   gpgme_error_t err;
-  void *hook;
-  op_data_t opd;
 
   if (!command || !*command)
     return gpg_error (GPG_ERR_INV_VALUE);
@@ -101,14 +47,7 @@
   if (err)
     return err;
 
-  err = _gpgme_op_data_lookup (ctx, OPDATA_ASSUAN, &hook, sizeof (*opd), NULL);
-  opd = hook;
-  if (err)
-    return err;
-  opd->result.err = gpg_error (GPG_ERR_UNFINISHED);
-
   return _gpgme_engine_op_assuan_transact (ctx->engine, command,
-                                           result_cb, ctx,
                                            data_cb, data_cb_value,
                                            inq_cb, inq_cb_value,
                                            status_cb, status_cb_value);
@@ -119,13 +58,13 @@
 /* XXXX.  This is the asynchronous variant. */
 gpgme_error_t
 gpgme_op_assuan_transact_start (gpgme_ctx_t ctx, 
-                                const char *command,
-                                gpgme_assuan_data_cb_t data_cb,
-                                void *data_cb_value,
-                                gpgme_assuan_inquire_cb_t inq_cb,
-                                void *inq_cb_value,
-                                gpgme_assuan_status_cb_t status_cb,
-                                void *status_cb_value)
+				const char *command,
+				gpgme_assuan_data_cb_t data_cb,
+				void *data_cb_value,
+				gpgme_assuan_inquire_cb_t inq_cb,
+				void *inq_cb_value,
+				gpgme_assuan_status_cb_t status_cb,
+				void *status_cb_value)
 {
   return opassuan_start (ctx, 0, command, 
                          data_cb, data_cb_value,
@@ -136,14 +75,15 @@
 
 /* XXXX.  This is the synchronous variant. */
 gpgme_error_t
-gpgme_op_assuan_transact (gpgme_ctx_t ctx,
-                          const char *command,
-                          gpgme_assuan_data_cb_t data_cb,
-                          void *data_cb_value,
-                          gpgme_assuan_inquire_cb_t inq_cb,
-                          void *inq_cb_value,
-                          gpgme_assuan_status_cb_t status_cb,
-                          void *status_cb_value)
+gpgme_op_assuan_transact_ext (gpgme_ctx_t ctx,
+			      const char *command,
+			      gpgme_assuan_data_cb_t data_cb,
+			      void *data_cb_value,
+			      gpgme_assuan_inquire_cb_t inq_cb,
+			      void *inq_cb_value,
+			      gpgme_assuan_status_cb_t status_cb,
+			      void *status_cb_value,
+			      gpgme_error_t *op_err)
 {
   gpgme_error_t err;
 
@@ -152,7 +92,70 @@
                         inq_cb, inq_cb_value,
                         status_cb, status_cb_value);
   if (!err)
-    err = _gpgme_wait_one (ctx);
+    err = _gpgme_wait_one_ext (ctx, op_err);
   return err;
 }
 
+
+
+
+/* Compatibility code for old interface.  */
+
+/* Evil hack breaking abstractions for the purpose of localizing our
+   other hack.  This is copied from engine.c.  */
+struct engine
+{
+  struct engine_ops *ops;
+  void *engine;
+};
+
+typedef struct
+{
+  struct _gpgme_op_assuan_result result;
+} *op_data_t;
+
+gpg_error_t _gpgme_engine_assuan_last_op_err (void *engine);
+
+gpgme_assuan_result_t
+gpgme_op_assuan_result (gpgme_ctx_t ctx)
+{
+  gpgme_error_t err;
+  void *hook;
+  op_data_t opd;
+
+  err = _gpgme_op_data_lookup (ctx, OPDATA_ASSUAN, &hook, -1, NULL);
+  opd = hook;
+  /* Check in case this function is used without having run a command
+     before.  */
+  if (err || !opd)
+    return NULL;
+
+  /* All of this is a hack for the old style interface.  The new style
+     interface returns op errors directly.  */
+  opd->result.err = _gpgme_engine_assuan_last_op_err (ctx->engine->engine);
+
+  return &opd->result;
+}
+
+
+gpgme_error_t
+gpgme_op_assuan_transact (gpgme_ctx_t ctx,
+			  const char *command,
+			  gpgme_assuan_data_cb_t data_cb,
+			  void *data_cb_value,
+			  gpgme_assuan_inquire_cb_t inq_cb,
+			  void *inq_cb_value,
+			  gpgme_assuan_status_cb_t status_cb,
+			  void *status_cb_value)
+{
+  gpgme_error_t op_err;
+  gpgme_error_t err;
+
+  /* Users of the old-style session based interfaces need to look at
+     the result structure.  */
+  gpgme_op_assuan_transact_ext (ctx, command, data_cb, data_cb_value,
+				inq_cb, inq_cb_value,
+				status_cb, status_cb_value, &op_err);
+
+  return err;
+}

Modified: trunk/src/ops.h
===================================================================
--- trunk/src/ops.h	2009-10-26 17:38:39 UTC (rev 1405)
+++ trunk/src/ops.h	2009-10-26 18:52:32 UTC (rev 1406)
@@ -27,14 +27,17 @@
 
 
 /* From gpgme.c.  */
-gpgme_error_t _gpgme_cancel_with_err (gpgme_ctx_t ctx, gpg_error_t ctx_err);
+gpgme_error_t _gpgme_cancel_with_err (gpgme_ctx_t ctx, gpg_error_t ctx_err,
+				      gpg_error_t op_err);
 
 void _gpgme_release_result (gpgme_ctx_t ctx);
 
 
 /* From wait.c.  */
 gpgme_error_t _gpgme_wait_one (gpgme_ctx_t ctx);
-gpgme_error_t _gpgme_wait_on_condition (gpgme_ctx_t ctx, volatile int *cond);
+gpgme_error_t _gpgme_wait_one_ext (gpgme_ctx_t ctx, gpgme_error_t *op_err);
+gpgme_error_t _gpgme_wait_on_condition (gpgme_ctx_t ctx, volatile int *cond,
+					gpgme_error_t *op_err);
 
 
 /* From data.c.  */

Modified: trunk/src/trustlist.c
===================================================================
--- trunk/src/trustlist.c	2009-10-26 17:38:39 UTC (rev 1405)
+++ trunk/src/trustlist.c	2009-10-26 18:52:32 UTC (rev 1406)
@@ -220,7 +220,7 @@
 
   if (!opd->trust_queue)
     {
-      err = _gpgme_wait_on_condition (ctx, &opd->trust_cond);
+      err = _gpgme_wait_on_condition (ctx, &opd->trust_cond, NULL);
       if (err)
 	return err;
       if (!opd->trust_cond)

Modified: trunk/src/wait-global.c
===================================================================
--- trunk/src/wait-global.c	2009-10-26 17:38:39 UTC (rev 1405)
+++ trunk/src/wait-global.c	2009-10-26 18:52:32 UTC (rev 1406)
@@ -74,6 +74,7 @@
   gpgme_ctx_t ctx;
   /* The status is set when the ctx is moved to the done list.  */
   gpgme_error_t status;
+  gpgme_error_t op_err;
 };
 
 /* The active list contains all contexts that are in the global event
@@ -112,7 +113,7 @@
 
 /* Enter the context CTX into the done list with status STATUS.  */
 static void
-ctx_done (gpgme_ctx_t ctx, gpgme_error_t status)
+ctx_done (gpgme_ctx_t ctx, gpgme_error_t status, gpgme_error_t op_err)
 {
   struct ctx_list_item *li;
 
@@ -131,6 +132,7 @@
     ctx_active_list = li->next;
 
   li->status = status;
+  li->op_err = op_err;
 
   /* Add LI to done list.  */
   li->next = ctx_done_list;
@@ -147,7 +149,7 @@
    If a matching context could be found, return it.  Return NULL if no
    context could be found.  */
 static gpgme_ctx_t
-ctx_wait (gpgme_ctx_t ctx, gpgme_error_t *status)
+ctx_wait (gpgme_ctx_t ctx, gpgme_error_t *status, gpgme_error_t *op_err)
 {
   struct ctx_list_item *li;
 
@@ -164,6 +166,8 @@
       ctx = li->ctx;
       if (status)
 	*status = li->status;
+      if (op_err)
+	*op_err = li->op_err;
 
       /* Remove LI from done list.  */
       if (li->next)
@@ -203,15 +207,16 @@
 	if (err)
 	  /* An error occured.  Close all fds in this context, and
 	     send the error in a done event.  */
-	  _gpgme_cancel_with_err (ctx, err);
+	  _gpgme_cancel_with_err (ctx, err, 0);
       }
       break;
 
     case GPGME_EVENT_DONE:
       {
-	gpgme_error_t *errp = (gpgme_error_t *) type_data;
-	assert (errp);
-	ctx_done (ctx, *errp);
+	gpgme_io_event_done_data_t done_data =
+	  (gpgme_io_event_done_data_t) type_data;
+
+	ctx_done (ctx, done_data->err, done_data->op_err);
       }
       break;
 
@@ -246,7 +251,8 @@
    error occurs, NULL is returned and *STATUS is set to the error
    value.  */
 gpgme_ctx_t
-gpgme_wait (gpgme_ctx_t ctx, gpgme_error_t *status, int hang)
+gpgme_wait_ext (gpgme_ctx_t ctx, gpgme_error_t *status,
+		gpgme_error_t *op_err, int hang)
 {
   do
     {
@@ -266,6 +272,8 @@
 	  UNLOCK (ctx_list_lock);
 	  if (status)
 	    *status = gpg_error_from_errno (saved_errno);
+	  if (op_err)
+	    *op_err = 0;
 	  return NULL;
 	}
       fdt.size = i;
@@ -285,6 +293,8 @@
 	  free (fdt.fds);
 	  if (status)
 	    *status = gpg_error_from_errno (saved_errno);
+	  if (op_err)
+	    *op_err = 0;
 	  return NULL;
 	}
 
@@ -294,6 +304,7 @@
 	    {
 	      gpgme_ctx_t ictx;
 	      gpgme_error_t err = 0;
+	      gpgme_error_t local_op_err = 0;
 	      struct wait_item_s *item;
 	      
 	      assert (nr);
@@ -310,12 +321,12 @@
 	      UNLOCK (ctx->lock);
 
 	      if (!err)
-		err = _gpgme_run_io_cb (&fdt.fds[i], 0);
-	      if (err)
+		err = _gpgme_run_io_cb (&fdt.fds[i], 0, &local_op_err);
+	      if (err || local_op_err)
 		{
 		  /* An error occured.  Close all fds in this context,
 		     and signal it.  */
-		  _gpgme_cancel_with_err (ictx, err);
+		  _gpgme_cancel_with_err (ictx, err, local_op_err);
 
 		  /* Break out of the loop, and retry the select()
 		     from scratch, because now all fds should be
@@ -338,8 +349,10 @@
 	      break;
 	  if (i == actx->fdt.size)
 	    {
-	      gpgme_error_t err = 0;
-
+	      struct gpgme_io_event_done_data data;
+	      data.err = 0;
+	      data.op_err = 0;
+	      
 	      /* FIXME: This does not perform too well.  We have to
 		 release the lock because the I/O event handler
 		 acquires it to remove the context from the active
@@ -349,7 +362,7 @@
 		 contexts to be released and call the DONE events
 		 afterwards.  */
 	      UNLOCK (ctx_list_lock);
-	      _gpgme_engine_io_event (actx->engine, GPGME_EVENT_DONE, &err);
+	      _gpgme_engine_io_event (actx->engine, GPGME_EVENT_DONE, &data);
 	      LOCK (ctx_list_lock);
 	      goto retry;
 	    }
@@ -357,7 +370,7 @@
       UNLOCK (ctx_list_lock);
 
       {
-	gpgme_ctx_t dctx = ctx_wait (ctx, status);
+	gpgme_ctx_t dctx = ctx_wait (ctx, status, op_err);
 
 	if (dctx)
 	  {
@@ -369,6 +382,8 @@
 	    ctx = NULL;
 	    if (status)
 	      *status = 0;
+	    if (op_err)
+	      *op_err = 0;
 	  }
       }
     }
@@ -376,3 +391,10 @@
 
   return ctx;
 }
+
+
+gpgme_ctx_t
+gpgme_wait (gpgme_ctx_t ctx, gpgme_error_t *status, int hang)
+{
+  return gpgme_wait_ext (ctx, status, NULL, hang);
+}

Modified: trunk/src/wait-private.c
===================================================================
--- trunk/src/wait-private.c	2009-10-26 17:38:39 UTC (rev 1405)
+++ trunk/src/wait-private.c	2009-10-26 18:52:32 UTC (rev 1406)
@@ -72,7 +72,8 @@
    finished and return its error value.  Otherwise, wait until COND is
    satisfied or the operation finished.  */
 gpgme_error_t
-_gpgme_wait_on_condition (gpgme_ctx_t ctx, volatile int *cond)
+_gpgme_wait_on_condition (gpgme_ctx_t ctx, volatile int *cond,
+			  gpgme_error_t *op_err_p)
 {
   gpgme_error_t err = 0;
   int hang = 1;
@@ -87,8 +88,10 @@
 	  /* An error occured.  Close all fds in this context, and
 	     signal it.  */
 	  err = gpg_error_from_errno (errno);
-          _gpgme_cancel_with_err (ctx, err);
+          _gpgme_cancel_with_err (ctx, err, 0);
 
+	  if (op_err_p)
+	    *op_err_p = 0;
 	  return err;
 	}
       
@@ -96,6 +99,8 @@
 	{
 	  if (ctx->fdt.fds[i].fd != -1 && ctx->fdt.fds[i].signaled)
 	    {
+	      gpgme_error_t op_err = 0;
+
 	      ctx->fdt.fds[i].signaled = 0;
 	      assert (nr);
 	      nr--;
@@ -106,15 +111,33 @@
 	      UNLOCK (ctx->lock);
 	      
 	      if (!err)
-		err = _gpgme_run_io_cb (&ctx->fdt.fds[i], 0);
+		err = _gpgme_run_io_cb (&ctx->fdt.fds[i], 0, &op_err);  
 	      if (err)
 		{
 		  /* An error occured.  Close all fds in this context,
 		     and signal it.  */
-		  _gpgme_cancel_with_err (ctx, err);
+		  _gpgme_cancel_with_err (ctx, err, 0);
 
+		  if (op_err_p)
+		    *op_err_p = 0;
 		  return err;
 		}
+	      else if (op_err)
+		{
+		  /* An operational error occured.  Cancel the current
+		     operation but not the session, and signal it.  */
+		  _gpgme_cancel_with_err (ctx, 0, op_err);
+
+		  /* NOTE: This relies on the operational error being
+		     generated after the operation really has
+		     completed, for example after no further status
+		     line output is generated.  Otherwise the
+		     following I/O will spill over into the next
+		     operation.  */
+		  if (op_err_p)
+		    *op_err_p = op_err;
+		  return 0;
+		}
 	    }
 	}
 
@@ -123,7 +146,10 @@
 	  break;
       if (i == ctx->fdt.size)
 	{
-	  _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_DONE, &err);
+	  struct gpgme_io_event_done_data data;
+	  data.err = 0;
+	  data.op_err = 0;
+	  _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_DONE, &data);
 	  hang = 0;
 	}
       if (cond && *cond)
@@ -131,14 +157,26 @@
     }
   while (hang);
 
+  if (op_err_p)
+    *op_err_p = 0;
   return 0;
 }
 
 
 /* Wait until the blocking operation in context CTX has finished and
-   return the error value.  */
+   return the error value.  This variant can not be used for
+   session-based protocols.  */
 gpgme_error_t
 _gpgme_wait_one (gpgme_ctx_t ctx)
 {
-  return _gpgme_wait_on_condition (ctx, NULL);
+  return _gpgme_wait_on_condition (ctx, NULL, NULL);
 }
+
+/* Wait until the blocking operation in context CTX has finished and
+   return the error value.  This is the right variant to use for
+   sesion-based protocols.  */
+gpgme_error_t
+_gpgme_wait_one_ext (gpgme_ctx_t ctx, gpgme_error_t *op_err)
+{
+  return _gpgme_wait_on_condition (ctx, NULL, op_err);
+}

Modified: trunk/src/wait-user.c
===================================================================
--- trunk/src/wait-user.c	2009-10-26 17:38:39 UTC (rev 1405)
+++ trunk/src/wait-user.c	2009-10-26 18:52:32 UTC (rev 1406)
@@ -41,6 +41,7 @@




More information about the Gnupg-commits mailing list