2003-01-30 Marcus Brinkmann <marcus@g10code.de>
authorMarcus Brinkmann <mb@g10code.com>
Thu, 30 Jan 2003 22:40:05 +0000 (22:40 +0000)
committerMarcus Brinkmann <mb@g10code.com>
Thu, 30 Jan 2003 22:40:05 +0000 (22:40 +0000)
* engine-gpgsm.c (status_handler): Do not close status fd at end
of function.

* ops.h (_gpgme_op_data_lookup): Add prototype.
* op-support.c: Include <stdlib.h>.
(_gpgme_op_data_lookup): New function.
* decrypt.c (_gpgme_release_decrypt_result): Function removed.
(struct decrypt_result_s): Rename to ...
(struct decrypt_resul): ... this.
(DecryptResult): New type.
(_gpgme_decrypt_status_handler): Don't use
test_and_allocate_result, but use _gpgme_op_data_lookup to
retrieve result data object.
* sign.c (_gpgme_release_sign_result): Function removed.
(release_sign_result): New function.
(struct sign_result_s): Rename to ...
(struct sign_result): ... this.
(SignResult): New type.
(_gpgme_sign_status_handler): Don't use
test_and_allocate_result, but use _gpgme_op_data_lookup to
retrieve result data object.
* encrypt.c (struct encrypt_result_s): Rename to ...
(struct encrypt_result): ... this.
(_gpgme_release_encrypt_result): Function removed.
(release_encrypt_result): New function.
(_gpgme_encrypt_status_handler): Don't use
test_and_allocate_result, but use _gpgme_op_data_lookup to
retrieve result data object.
* verify.c (struct verify_result_s): Rename to ...
(struct verify_result): ... this.  Remove member next.
(VerifyResult): New type.
(_gpgme_release_verify_result): Function removed.
(release_verify_result): New function.
(finish_sig): Change first argument to type VerifyResult.  Diddle
the type of the op_data structure.
(add_notation): Change first argument to type VerifyResult.
(_gpgme_verify_status_handler): Don't use
test_and_allocate_result, but use _gpgme_op_data_lookup to
retrieve result data object.
* passphrase.c (struct passphrase_result_s): Rename to ...
(struct passphrase_result): ... this.  Remove member next.
(PassphraseResult): New type.
(_gpgme_release_passphrase_result): Function removed.
(release_passphrase_result): New function.
(_gpgme_passphrase_status_handler): Don't use
test_and_allocate_result, but use _gpgme_op_data_lookup to
retrieve result data object.
(_gpgme_passphrase_command_handler): Likewise.
* keylist.c (struct keylist_result_s): Rename to ...
(struct keylist_result): ... this.  Remove member next.
(KeylistResult): New type.
(_gpgme_release_keylist_result): Function removed.
(release_keylist_result): New function.
(keylist_status_handler): Don't use
test_and_allocate_result, but use _gpgme_op_data_lookup to
retrieve result data object.
* edit.c (struct edit_result_s): Rename to ...
(struct edit_result): ... this.  Remove member next.
(EditResult): New type.
(_gpgme_release_edit_result): Function removed.
(release_edit_result): New function.
(edit_status_handler): Don't use
test_and_allocate_result, but use _gpgme_op_data_lookup to
retrieve result data object.
(command_handler): Likewise.
* types.h (DecryptResult, SignResult, EncryptResult,
PassphraseResult, ImportResult, DeleteResult, GenKeyResult,
KeylistResult, EditResult): Types removed.
* ops.h: Don't include "types.h", but "gpgme.h" and "context.h".
(test_and_allocate_result): Remove macro.
(_gpgme_release_decrypt_result): Remove prototype.
(_gpgme_decrypt_result): Remove prototype.
(_gpgme_release_sign_result): Remove prototype.
(_gpgme_release_encrypt_result): Remove prototype.
(_gpgme_release_passphrase_result): Remove prototype.
(_gpgme_release_import_result): Remove prototype.
(_gpgme_release_delete_result): Remove prototype.
(_gpgme_release_genkey_result): Remove prototype.
(_gpgme_release_keylist_result): Remove prototype.
(_gpgme_release_edit_result): Remove prototype.
(_gpgme_release_verify_result): Remove prototype.
* gpgme.c (_gpgme_release_result): Rewritten.
* context.h (enum ctx_op_data_type): New enum.
(struct ctx_op_data): New structure.
(struct gpgme_context_s): Replace the member result with a member
op_data.
(fail_on_pending_request): Remove macro.
* op-support.c (_gpgme_op_reset): Expand macro
fail_on_pending_request.
* util.h: Don't include "types.h" or "debug.h", but include "gpgme.h".

22 files changed:
gpgme/ChangeLog
gpgme/context.h
gpgme/decrypt.c
gpgme/delete.c
gpgme/edit.c
gpgme/encrypt.c
gpgme/engine-gpgsm.c
gpgme/export.c
gpgme/genkey.c
gpgme/gpgme.c
gpgme/import.c
gpgme/keylist.c
gpgme/op-support.c
gpgme/ops.h
gpgme/passphrase.c
gpgme/posix-io.c
gpgme/rungpg.c
gpgme/sign.c
gpgme/types.h
gpgme/util.h
gpgme/verify.c
gpgme/wait.c

index e309509..2a7e61e 100644 (file)
@@ -1,5 +1,98 @@
 2003-01-30  Marcus Brinkmann  <marcus@g10code.de>
 
+       * engine-gpgsm.c (status_handler): Do not close status fd at end
+       of function.
+
+       * ops.h (_gpgme_op_data_lookup): Add prototype.
+       * op-support.c: Include <stdlib.h>.
+       (_gpgme_op_data_lookup): New function.
+       * decrypt.c (_gpgme_release_decrypt_result): Function removed.
+       (struct decrypt_result_s): Rename to ...
+       (struct decrypt_resul): ... this.
+       (DecryptResult): New type.
+       (_gpgme_decrypt_status_handler): Don't use
+       test_and_allocate_result, but use _gpgme_op_data_lookup to
+       retrieve result data object.
+       * sign.c (_gpgme_release_sign_result): Function removed.
+       (release_sign_result): New function.
+       (struct sign_result_s): Rename to ...
+       (struct sign_result): ... this.
+       (SignResult): New type.
+       (_gpgme_sign_status_handler): Don't use
+       test_and_allocate_result, but use _gpgme_op_data_lookup to
+       retrieve result data object.
+       * encrypt.c (struct encrypt_result_s): Rename to ...
+       (struct encrypt_result): ... this.
+       (_gpgme_release_encrypt_result): Function removed.
+       (release_encrypt_result): New function.
+       (_gpgme_encrypt_status_handler): Don't use
+       test_and_allocate_result, but use _gpgme_op_data_lookup to
+       retrieve result data object.
+       * verify.c (struct verify_result_s): Rename to ...
+       (struct verify_result): ... this.  Remove member next.
+       (VerifyResult): New type.
+       (_gpgme_release_verify_result): Function removed.
+       (release_verify_result): New function.
+       (finish_sig): Change first argument to type VerifyResult.  Diddle
+       the type of the op_data structure.
+       (add_notation): Change first argument to type VerifyResult.
+       (_gpgme_verify_status_handler): Don't use
+       test_and_allocate_result, but use _gpgme_op_data_lookup to
+       retrieve result data object.
+       * passphrase.c (struct passphrase_result_s): Rename to ...
+       (struct passphrase_result): ... this.  Remove member next.
+       (PassphraseResult): New type.
+       (_gpgme_release_passphrase_result): Function removed.
+       (release_passphrase_result): New function.
+       (_gpgme_passphrase_status_handler): Don't use
+       test_and_allocate_result, but use _gpgme_op_data_lookup to
+       retrieve result data object.
+       (_gpgme_passphrase_command_handler): Likewise.
+       * keylist.c (struct keylist_result_s): Rename to ...
+       (struct keylist_result): ... this.  Remove member next.
+       (KeylistResult): New type.
+       (_gpgme_release_keylist_result): Function removed.
+       (release_keylist_result): New function.
+       (keylist_status_handler): Don't use
+       test_and_allocate_result, but use _gpgme_op_data_lookup to
+       retrieve result data object.
+       * edit.c (struct edit_result_s): Rename to ...
+       (struct edit_result): ... this.  Remove member next.
+       (EditResult): New type.
+       (_gpgme_release_edit_result): Function removed.
+       (release_edit_result): New function.
+       (edit_status_handler): Don't use
+       test_and_allocate_result, but use _gpgme_op_data_lookup to
+       retrieve result data object.
+       (command_handler): Likewise.
+       * types.h (DecryptResult, SignResult, EncryptResult,
+       PassphraseResult, ImportResult, DeleteResult, GenKeyResult,
+       KeylistResult, EditResult): Types removed.
+       * ops.h: Don't include "types.h", but "gpgme.h" and "context.h".
+       (test_and_allocate_result): Remove macro.
+       (_gpgme_release_decrypt_result): Remove prototype.
+       (_gpgme_decrypt_result): Remove prototype.
+       (_gpgme_release_sign_result): Remove prototype.
+       (_gpgme_release_encrypt_result): Remove prototype.
+       (_gpgme_release_passphrase_result): Remove prototype.
+       (_gpgme_release_import_result): Remove prototype.
+       (_gpgme_release_delete_result): Remove prototype.
+       (_gpgme_release_genkey_result): Remove prototype.
+       (_gpgme_release_keylist_result): Remove prototype.
+       (_gpgme_release_edit_result): Remove prototype.
+       (_gpgme_release_verify_result): Remove prototype.
+       * gpgme.c (_gpgme_release_result): Rewritten.
+       * context.h (enum ctx_op_data_type): New enum.
+       (struct ctx_op_data): New structure.
+       (struct gpgme_context_s): Replace the member result with a member
+       op_data.
+       (fail_on_pending_request): Remove macro.
+       * op-support.c (_gpgme_op_reset): Expand macro
+       fail_on_pending_request.
+       * util.h: Don't include "types.h" or "debug.h", but include "gpgme.h".
+
+2003-01-30  Marcus Brinkmann  <marcus@g10code.de>
+
        * types.h (EngineObject): Move typedef to ...
        * engine.h: ... here.
        * types.h (GpgObject): Move typedef to ...
index fa6a3dc..26467ca 100644 (file)
 #include "engine.h"
 #include "wait.h"
 
+\f
+/* Operations might require to remember arbitrary information and data
+   objects during invocations of the status handler.  The
+   ctx_op_data structure provides a generic framework to hook in
+   such additional data.  */
+typedef enum
+  {
+    OPDATA_DECRYPT, OPDATA_SIGN, OPDATA_ENCRYPT, OPDATA_PASSPHRASE,
+    OPDATA_IMPORT, OPDATA_GENKEY, OPDATA_KEYLIST, OPDATA_EDIT,
+    OPDATA_VERIFY_COLLECTING, OPDATA_VERIFY
+  } ctx_op_data_type;
+
+struct ctx_op_data
+{
+  /* The next element in the linked list, or NULL if this is the last
+     element.  */
+  struct ctx_op_data *next;
+
+  /* The type of the hook data, which can be used by a routine to
+     lookup the hook data.  */
+  ctx_op_data_type type;
+
+  /* The function to release HOOK and all its associated resources.
+     Can be NULL if no special dealllocation routine is necessary.  */
+  void (*cleanup) (void *hook);
+
+  /* The hook that points to the operation data.  */
+  void *hook;
+};
+
+\f
 struct key_queue_item_s
 {
   struct key_queue_item_s *next;
   GpgmeKey key;
 };
 
+
 struct trust_queue_item_s
 {
   struct trust_queue_item_s *next;
@@ -68,19 +100,8 @@ struct gpgme_context_s
   int signers_size;
   GpgmeKey *signers;
 
-  struct
-  {
-    VerifyResult verify;
-    DecryptResult decrypt;
-    SignResult sign;
-    EncryptResult encrypt;
-    PassphraseResult passphrase;
-    ImportResult import;
-    DeleteResult delete;
-    GenKeyResult genkey;
-    KeylistResult keylist;
-    EditResult edit;
-  } result;
+  /* The operation data hooked into the context.  */
+  struct ctx_op_data *op_data;
 
   /* Last signature notation.  */
   GpgmeData notation;
@@ -132,14 +153,8 @@ struct user_id_s
 struct gpgme_recipients_s
 {
   struct user_id_s *list;
-  int checked; /* Wether the recipients are all valid.  */
+  int checked; /* Whether the recipients are all valid.  */
 };
 
 
-#define fail_on_pending_request(c)                            \
-          do {                                                \
-                if (!(c))         return GPGME_Invalid_Value; \
-                if ((c)->pending) return GPGME_Busy;          \
-             } while (0)
-
 #endif /* CONTEXT_H */
index e7f3914..6855563 100644 (file)
 #endif
 #include <stdlib.h>
 
-#include "util.h"
 #include "context.h"
 #include "ops.h"
 
 
-struct decrypt_result_s
+struct decrypt_result
 {
   int okay;
   int failed;
 };
+typedef struct decrypt_result *DecryptResult;
 
 
-void
-_gpgme_release_decrypt_result (DecryptResult result)
-{
-  if (!result)
-    return;
-  free (result);
-}
-
 /* Check whether STRING starts with TOKEN and return true in this
    case.  This is case insensitive.  If NEXT is not NULL return the
    number of bytes to be added to STRING to get to the next token; a
@@ -87,30 +79,40 @@ skip_token (const char *string, size_t *next)
 GpgmeError
 _gpgme_decrypt_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
 {
-  GpgmeError err;
+  DecryptResult result;
+  GpgmeError err = 0;
   size_t n;
 
   err = _gpgme_passphrase_status_handler (ctx, code, args);
   if (err)
     return err;
 
-  test_and_allocate_result (ctx, decrypt);
-
   switch (code)
     {
     case GPGME_STATUS_EOF:
-      if (ctx->result.decrypt->failed)
-       return GPGME_Decryption_Failed;
-      else if (!ctx->result.decrypt->okay)
-       return GPGME_No_Data;
+      err = _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, (void **) &result,
+                                  -1, NULL);
+      if (!err)
+       {
+         if (result && result->failed)
+           err = GPGME_Decryption_Failed;
+         else if (!result || !result->okay)
+           err = GPGME_No_Data;
+       }
       break;
 
     case GPGME_STATUS_DECRYPTION_OKAY:
-      ctx->result.decrypt->okay = 1;
+      err = _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, (void **) &result,
+                                  sizeof (*result), NULL);
+      if (!err)
+       result->okay = 1;
       break;
 
     case GPGME_STATUS_DECRYPTION_FAILED:
-      ctx->result.decrypt->failed = 1;
+      err = _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, (void **) &result,
+                                  sizeof (*result), NULL);
+      if (!err)
+       result->failed = 1;
       break;
 
     case GPGME_STATUS_ERROR:
@@ -155,7 +157,7 @@ _gpgme_decrypt_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
       break;
     }
 
-  return 0;
+  return err;
 }
 
 
index 2fe3386..e711b30 100644 (file)
@@ -37,53 +37,28 @@ enum delete_problem
   };
 
 
-struct delete_result_s
-{
-  enum delete_problem problem;
-};
-
-
-void
-_gpgme_release_delete_result (DeleteResult result)
-{
-  if (!result)
-    return;
-  free (result);
-}
-
-
 static GpgmeError
 delete_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
 {
-  test_and_allocate_result (ctx, delete);
-
-  switch (code)
+  if (code == GPGME_STATUS_DELETE_PROBLEM)
     {
-    case GPGME_STATUS_EOF:
-      switch (ctx->result.delete->problem)
+      enum delete_problem problem = atoi (args);
+      switch (problem)
        {
        case DELETE_No_Problem:
          break;
+
        case DELETE_No_Such_Key:
          return GPGME_Invalid_Key;
-         break;
+
        case DELETE_Must_Delete_Secret_Key:
          return GPGME_Conflict;
-         break;
+
        case DELETE_Ambiguous_Specification:
          /* XXX Need better error value.  Fall through.  */
        default:
          return GPGME_General_Error;
-         break;
        }
-      break;
-
-    case GPGME_STATUS_DELETE_PROBLEM:
-      ctx->result.delete->problem = atoi (args);
-      break;
-
-    default:
-      break;
     }
   return 0;
 }
index ec898dc..b624516 100644 (file)
 #include "ops.h"
 
 
-struct edit_result_s
+struct edit_result
 {
   GpgmeEditCb fnc;
   void *fnc_value;
 };
-
-void
-_gpgme_release_edit_result (EditResult result)
-{
-  if (!result)
-    return;
-  free (result);
-}
-
+typedef struct edit_result *EditResult;
 
 static GpgmeError
 edit_status_handler (GpgmeCtx ctx, GpgmeStatusCode status, char *args)
 {
+  EditResult result;
   GpgmeError err = _gpgme_passphrase_status_handler (ctx, status, args);
   if (err)
     return err;
 
-  return (*ctx->result.edit->fnc) (ctx->result.edit->fnc_value, status,
-                                  args, NULL);
+  err = _gpgme_op_data_lookup (ctx, OPDATA_EDIT, (void **) &result,
+                              -1, NULL);
+  if (err)
+    return err;
+  assert (result);
+
+  return (*result->fnc) (result->fnc_value, status, args, NULL);
 }
 
 
 static GpgmeError
 command_handler (void *opaque, GpgmeStatusCode status, const char *args,
-                const char **result)
+                const char **result_r)
 {
+  EditResult result;
   GpgmeError err;
   GpgmeCtx ctx = opaque;
 
-  err = _gpgme_passphrase_command_handler (ctx, status, args, result);
+  *result_r = NULL;
+  err = _gpgme_passphrase_command_handler (ctx, status, args, result_r);
+  if (err)
+    return err;
+
+  err = _gpgme_op_data_lookup (ctx, OPDATA_EDIT, (void **) &result,
+                              -1, NULL);
   if (err)
     return err;
+  assert (result);
 
-  if (!result)
-    err = (*ctx->result.edit->fnc) (ctx->result.edit->fnc_value, status,
-                                   args, result);
+  if (!*result_r)
+    err = (*result->fnc) (result->fnc_value, status, args, result_r);
 
   return err;
 }
@@ -80,6 +85,7 @@ _gpgme_op_edit_start (GpgmeCtx ctx, int synchronous,
                      GpgmeEditCb fnc, void *fnc_value,
                      GpgmeData out)
 {
+  EditResult result;
   GpgmeError err = 0;
 
   if (!fnc)
@@ -89,15 +95,13 @@ _gpgme_op_edit_start (GpgmeCtx ctx, int synchronous,
   if (err)
     goto leave;
 
-  assert (!ctx->result.edit);
-  ctx->result.edit = malloc (sizeof *ctx->result.edit);
-  if (!ctx->result.edit)
-    {
-      err = GPGME_Out_Of_Core;
-      goto leave;
-    }
-  ctx->result.edit->fnc = fnc;
-  ctx->result.edit->fnc_value = fnc_value;
+  err = _gpgme_op_data_lookup (ctx, OPDATA_EDIT, (void **) &result,
+                              sizeof (*result), NULL);
+  if (err)
+    goto leave;
+
+  result->fnc = fnc;
+  result->fnc_value = fnc_value;
 
   /* Check the supplied data.  */
   if (!out)
index 3b36d76..5f95151 100644 (file)
         return; /* oops */ \
 } while (0)
 
-struct encrypt_result_s
+struct encrypt_result
 {
   int no_valid_recipients;
   int invalid_recipients;
   GpgmeData xmlinfo;
 };
+typedef struct encrypt_result *EncryptResult;
 
-void
-_gpgme_release_encrypt_result (EncryptResult result)
+static void
+release_encrypt_result (void *hook)
 {
-  if (!result)
-    return;
+  EncryptResult result = (EncryptResult) hook;
+
   gpgme_data_release (result->xmlinfo);
-  free (result);
 }
 
+
 /* Parse the args and save the information in an XML structure.  With
    args of NULL the xml structure is closed.  */
 static void
@@ -100,36 +101,50 @@ append_xml_encinfo (GpgmeData *rdh, char *args)
 GpgmeError
 _gpgme_encrypt_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
 {
-  test_and_allocate_result (ctx, encrypt);
+  GpgmeError err = 0;
+  EncryptResult result;
 
   switch (code)
     {
     case GPGME_STATUS_EOF:
-      if (ctx->result.encrypt->xmlinfo)
+      err = _gpgme_op_data_lookup (ctx, OPDATA_ENCRYPT, (void **) &result,
+                                  -1, NULL);
+      if (!err)
        {
-         append_xml_encinfo (&ctx->result.encrypt->xmlinfo, NULL);
-         _gpgme_set_op_info (ctx, ctx->result.encrypt->xmlinfo);
-         ctx->result.encrypt->xmlinfo = NULL;
+         if (result && result->xmlinfo)
+           {
+             append_xml_encinfo (&result->xmlinfo, NULL);
+             _gpgme_set_op_info (ctx, result->xmlinfo);
+             result->xmlinfo = NULL;
+           }
+         if (result && result->no_valid_recipients) 
+           return GPGME_No_Recipients;
+         if (result && result->invalid_recipients) 
+           return GPGME_Invalid_Recipients;
        }
-      if (ctx->result.encrypt->no_valid_recipients) 
-       return GPGME_No_Recipients;
-      else if (ctx->result.encrypt->invalid_recipients) 
-       return GPGME_Invalid_Recipients;
       break;
 
     case GPGME_STATUS_INV_RECP:
-      ctx->result.encrypt->invalid_recipients++;
-      append_xml_encinfo (&ctx->result.encrypt->xmlinfo, args);
+      err = _gpgme_op_data_lookup (ctx, OPDATA_ENCRYPT, (void **) &result,
+                                  sizeof (*result), release_encrypt_result);
+      if (!err)
+       {
+         result->invalid_recipients++;
+         append_xml_encinfo (&result->xmlinfo, args);
+       }
       break;
 
     case GPGME_STATUS_NO_RECP:
-      ctx->result.encrypt->no_valid_recipients = 1;
+      err = _gpgme_op_data_lookup (ctx, OPDATA_ENCRYPT, (void **) &result,
+                                  sizeof (*result), release_encrypt_result);
+      if (!err)
+       result->no_valid_recipients = 1;
       break;
 
     default:
       break;
     }
-  return 0;
+  return err;
 }
 
 
index 82d719a..586bc2c 100644 (file)
@@ -806,7 +806,6 @@ status_handler (void *opaque, int fd)
     }
   while (!err && assuan_pending_line (gpgsm->assuan_ctx));
          
-  _gpgme_io_close (gpgsm->status_cb.fd);
   return err;
 }
 
index 9fefee8..2cf9169 100644 (file)
@@ -26,7 +26,7 @@
 #include "util.h"
 #include "context.h"
 #include "ops.h"
-
+#include "debug.h"
 
 static GpgmeError
 export_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
index 427365e..2636c0f 100644 (file)
 #include "ops.h"
 
 
-struct genkey_result_s
+struct genkey_result
 {
   int created_primary : 1;
   int created_sub : 1;
   char *fpr;
 };
+typedef struct genkey_result *GenKeyResult;
 
-
-void
-_gpgme_release_genkey_result (GenKeyResult result)
+static void
+release_genkey_result (void *hook)
 {
-  if (!result)
-    return;
+  GenKeyResult result = (GenKeyResult) hook;
+  
   if (result->fpr)
     free (result->fpr);
-  free (result);
 }
 
 
 static GpgmeError
 genkey_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
 {
+  GenKeyResult result;
   GpgmeError err = _gpgme_progress_status_handler (ctx, code, args);
   if (err)
     return err;
 
-  test_and_allocate_result (ctx, genkey);
+  err = _gpgme_op_data_lookup (ctx, OPDATA_GENKEY, (void **) &result,
+                              sizeof (*result), release_genkey_result);
+  if (err)
+    return err;
 
   switch (code)
     {
@@ -63,15 +66,15 @@ genkey_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
       if (args && *args)
        {
          if (*args == 'B' || *args == 'P')
-           ctx->result.genkey->created_primary = 1;
+           result->created_primary = 1;
          if (*args == 'B' || *args == 'S')
-           ctx->result.genkey->created_sub = 1;
+           result->created_sub = 1;
          if (args[1] == ' ')
            {
-             if (ctx->result.genkey->fpr)
-               free (ctx->result.genkey->fpr);
-             ctx->result.genkey->fpr = strdup (&args[2]);
-             if (!ctx->result.genkey->fpr)
+             if (result->fpr)
+               free (result->fpr);
+             result->fpr = strdup (&args[2]);
+             if (!result->fpr)
                return GPGME_Out_Of_Core;
            }
        }
@@ -79,8 +82,8 @@ genkey_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
 
     case GPGME_STATUS_EOF:
       /* FIXME: Should return some more useful error value.  */
-      if (!ctx->result.genkey->created_primary
-         && !ctx->result.genkey->created_sub)
+      if (!result->created_primary
+         && !result->created_sub)
        return GPGME_General_Error;
       break;
 
@@ -212,9 +215,16 @@ gpgme_op_genkey (GpgmeCtx ctx, const char *parms,
     err = _gpgme_wait_one (ctx);
   if (!err && fpr)
     {
-      if (ctx->result.genkey->fpr)
+      GenKeyResult result;
+
+      err = _gpgme_op_data_lookup (ctx, OPDATA_GENKEY, (void **) &result,
+                                  -1, NULL);
+      if (err)
+       return err;
+
+      if (result && result->fpr)
        {
-         *fpr = strdup (ctx->result.genkey->fpr);
+         *fpr = strdup (result->fpr);
          if (!*fpr)
            return GPGME_Out_Of_Core;
        }
index 134089b..02bc908 100644 (file)
@@ -87,17 +87,17 @@ gpgme_release (GpgmeCtx ctx)
 void
 _gpgme_release_result (GpgmeCtx ctx)
 {
-  _gpgme_release_verify_result (ctx->result.verify);
-  _gpgme_release_decrypt_result (ctx->result.decrypt);
-  _gpgme_release_sign_result (ctx->result.sign);
-  _gpgme_release_encrypt_result (ctx->result.encrypt);
-  _gpgme_release_passphrase_result (ctx->result.passphrase);
-  _gpgme_release_import_result (ctx->result.import);
-  _gpgme_release_delete_result (ctx->result.delete);
-  _gpgme_release_genkey_result (ctx->result.genkey);
-  _gpgme_release_keylist_result (ctx->result.keylist);
-  _gpgme_release_edit_result (ctx->result.edit);
-  memset (&ctx->result, 0, sizeof (ctx->result));
+  struct ctx_op_data *data = ctx->op_data;
+
+  while (data)
+    {
+      struct ctx_op_data *next_data = data->next;
+      if (data->cleanup)
+       (*data->cleanup) (data->hook);
+      free (data);
+      data = next_data;
+    }
+  ctx->op_data = NULL;
   _gpgme_set_op_info (ctx, NULL);
 }
 
index 46c696b..ada3dd8 100644 (file)
 #include "context.h"
 #include "ops.h"
 
-
-struct import_result_s
+\f
+struct import_result
 {
   int nr_imported;
   int nr_considered;
   GpgmeData xmlinfo;
 };
+typedef struct import_result *ImportResult;
 
-
-void
-_gpgme_release_import_result (ImportResult result)
+static void
+release_import_result (void *hook)
 {
-  if (!result)
-    return;
-  gpgme_data_release (result->xmlinfo);
-  free (result);
+  ImportResult result = (ImportResult) hook;
+
+  if (result->xmlinfo)
+    gpgme_data_release (result->xmlinfo);
 }
 
 
@@ -143,28 +143,34 @@ append_xml_impinfo (GpgmeData *rdh, GpgmeStatusCode code, char *args)
 static GpgmeError
 import_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
 {
-  test_and_allocate_result (ctx, import);
+  GpgmeError err;
+  ImportResult result;
+
+  err = _gpgme_op_data_lookup (ctx, OPDATA_IMPORT, (void **) &result,
+                              sizeof (*result), release_import_result);
+  if (err)
+    return err;
 
   switch (code)
     {
     case GPGME_STATUS_EOF:
-      if (ctx->result.import->xmlinfo)
+      if (result->xmlinfo)
         {
-          append_xml_impinfo (&ctx->result.import->xmlinfo, code, NULL);
-          _gpgme_set_op_info (ctx, ctx->result.import->xmlinfo);
-          ctx->result.import->xmlinfo = NULL;
+          append_xml_impinfo (&result->xmlinfo, code, NULL);
+          _gpgme_set_op_info (ctx, result->xmlinfo);
+          result->xmlinfo = NULL;
         }
       /* XXX Calculate error value.  */
       break;
 
     case GPGME_STATUS_IMPORTED:
-      ctx->result.import->nr_imported++;
-      append_xml_impinfo (&ctx->result.import->xmlinfo, code, args);
+      result->nr_imported++;
+      append_xml_impinfo (&result->xmlinfo, code, args);
       break;
 
     case GPGME_STATUS_IMPORT_RES:
-      ctx->result.import->nr_considered = strtol (args, 0, 0);
-      append_xml_impinfo (&ctx->result.import->xmlinfo, code, args);
+      result->nr_considered = strtol (args, 0, 0);
+      append_xml_impinfo (&result->xmlinfo, code, args);
       break;
 
     default:
@@ -230,8 +236,12 @@ gpgme_op_import_ext (GpgmeCtx ctx, GpgmeData keydata, int *nr)
     err = _gpgme_wait_one (ctx);
   if (!err && nr)
     {
-      if (ctx->result.import)
-       *nr = ctx->result.import->nr_considered;
+      ImportResult result;
+
+      err = _gpgme_op_data_lookup (ctx, OPDATA_IMPORT, (void **) &result,
+                                  -1, NULL);
+      if (result)
+       *nr = result->nr_considered;
       else
        *nr = 0;
     }
@@ -243,4 +253,3 @@ gpgme_op_import (GpgmeCtx ctx, GpgmeData keydata)
 {
   return gpgme_op_import_ext (ctx, keydata, 0);
 }
-
index c2b3c99..e6cc5ce 100644 (file)
 #include "context.h"
 #include "ops.h"
 #include "key.h"
+#include "debug.h"
 
 \f
-struct keylist_result_s
+struct keylist_result
 {
   int truncated;
   GpgmeData xmlinfo;
 };
+typedef struct keylist_result *KeylistResult;
 
-
-void
-_gpgme_release_keylist_result (KeylistResult result)
+static void
+release_keylist_result (void *hook)
 {
-  if (!result)
-    return;
-  free (result);
+  KeylistResult result = (KeylistResult) hook;
+
+  if (result->xmlinfo)
+    gpgme_data_release (result->xmlinfo);
 }
 
 
@@ -86,22 +88,28 @@ append_xml_keylistinfo (GpgmeData *rdh, char *args)
 static GpgmeError
 keylist_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
 {
-  test_and_allocate_result (ctx, keylist);
+  GpgmeError err;
+  KeylistResult result;
+
+  err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, (void **) &result,
+                              sizeof (*result), release_keylist_result);
+  if (err)
+    return err;
 
   switch (code)
     {
     case GPGME_STATUS_TRUNCATED:
-      ctx->result.keylist->truncated = 1;
+      result->truncated = 1;
       break;
 
     case GPGME_STATUS_EOF:
-      if (ctx->result.keylist->truncated)
-        append_xml_keylistinfo (&ctx->result.keylist->xmlinfo, "1");
-      if (ctx->result.keylist->xmlinfo)
+      if (result->truncated)
+        append_xml_keylistinfo (&result->xmlinfo, "1");
+      if (result->xmlinfo)
        {
-         append_xml_keylistinfo (&ctx->result.keylist->xmlinfo, NULL);
-         _gpgme_set_op_info (ctx, ctx->result.keylist->xmlinfo);
-         ctx->result.keylist->xmlinfo = NULL;
+         append_xml_keylistinfo (&result->xmlinfo, NULL);
+         _gpgme_set_op_info (ctx, result->xmlinfo);
+         result->xmlinfo = NULL;
         }
       break;
 
index 14fb6c8..909b75d 100644 (file)
 #if HAVE_CONFIG_H
 #include <config.h>
 #endif
+#include <stdlib.h>
 
 #include "gpgme.h"
 #include "context.h"
 #include "ops.h"
 
+\f
+GpgmeError
+_gpgme_op_data_lookup (GpgmeCtx ctx, ctx_op_data_type type, void **hook,
+                      int size, void (*cleanup) (void *))
+{
+  struct ctx_op_data *data = ctx->op_data;
+  while (data && data->type != type)
+    data = data->next;
+  if (!data)
+    {
+      if (size < 0)
+       {
+         *hook = NULL;
+         return 0;
+       }
+
+      data = calloc (1, sizeof (struct ctx_op_data) + size);
+      if (!data)
+       return GPGME_Out_Of_Core;
+      data->next = ctx->op_data;
+      data->type = type;
+      data->cleanup = cleanup;
+      data->hook = ((void *) data) + sizeof (struct ctx_op_data);
+      ctx->op_data = data;
+    }
+  *hook = data->hook;
+  return 0;
+}
+
+
 /* type is: 0: asynchronous operation (use global or user event loop).
             1: synchronous operation (always use private event loop).
             2: asynchronous private operation (use private or user
@@ -35,7 +66,9 @@ _gpgme_op_reset (GpgmeCtx ctx, int type)
   GpgmeError err = 0;
   struct GpgmeIOCbs io_cbs;
 
-  fail_on_pending_request (ctx);
+  if (ctx->pending)
+    return GPGME_Busy;
+
   _gpgme_release_result (ctx);
 
   /* Create an engine object.  */
index b382ec2..49e1afe 100644 (file)
 #ifndef OPS_H
 #define OPS_H
 
-#include "types.h"
-
-/* Support macros.  */
-
-#define test_and_allocate_result(ctx,field)                            \
-  do                                                                   \
-    {                                                                  \
-      if (!ctx->result.field)                                          \
-        {                                                              \
-          ctx->result.field = calloc (1, sizeof *ctx->result.field);   \
-          if (!ctx->result.field)                                      \
-            return GPGME_Out_Of_Core;                                  \
-        }                                                              \
-    }                                                                  \
-  while (0)
+#include "gpgme.h"
+#include "context.h"
 
 /*-- gpgme.c --*/
 void _gpgme_release_result (GpgmeCtx ctx);
@@ -77,34 +64,31 @@ GpgmeError _gpgme_key_new ( GpgmeKey *r_key );
 GpgmeError _gpgme_key_new_secret ( GpgmeKey *r_key );
 
 /*-- op-support.c --*/
+GpgmeError _gpgme_op_data_lookup (GpgmeCtx ctx, ctx_op_data_type type,
+                                 void **hook, int size,
+                                 void (*cleanup) (void *));
 GpgmeError _gpgme_op_reset (GpgmeCtx ctx, int synchronous);
 
 /*-- verify.c --*/
-void _gpgme_release_verify_result (VerifyResult result);
 GpgmeError _gpgme_verify_status_handler (GpgmeCtx ctx, GpgmeStatusCode code,
                                         char *args);
 
 /*-- decrypt.c --*/
-void _gpgme_release_decrypt_result (DecryptResult result);
 GpgmeError _gpgme_decrypt_status_handler (GpgmeCtx ctx, GpgmeStatusCode code,
                                          char *args);
 GpgmeError _gpgme_decrypt_start (GpgmeCtx ctx, int synchronous,
                                 GpgmeData ciph, GpgmeData plain,
                                 void *status_handler);
-GpgmeError _gpgme_decrypt_result (GpgmeCtx ctx);
 
 /*-- sign.c --*/
-void _gpgme_release_sign_result ( SignResult res );
 GpgmeError _gpgme_sign_status_handler (GpgmeCtx ctx, GpgmeStatusCode code,
                                       char *args);
 
 /*-- encrypt.c --*/
-void _gpgme_release_encrypt_result ( EncryptResult res );
 GpgmeError _gpgme_encrypt_status_handler (GpgmeCtx ctx, GpgmeStatusCode code,
                                          char *args);
 
 /*-- passphrase.c --*/
-void _gpgme_release_passphrase_result (PassphraseResult result);
 GpgmeError _gpgme_passphrase_status_handler (GpgmeCtx ctx, GpgmeStatusCode code,
                                             char *args);
 GpgmeError _gpgme_passphrase_command_handler (void *opaque,
@@ -116,25 +100,12 @@ GpgmeError _gpgme_passphrase_start (GpgmeCtx ctx);
 GpgmeError _gpgme_progress_status_handler (GpgmeCtx ctx, GpgmeStatusCode code,
                                           char *args);
 
-/*-- import.c --*/
-void _gpgme_release_import_result (ImportResult res);
-
-/*-- delete.c --*/
-void _gpgme_release_delete_result (DeleteResult res);
-
-/*-- genkey.c --*/
-void _gpgme_release_genkey_result (GenKeyResult res);
-
 /*-- keylist.c --*/
-void _gpgme_release_keylist_result (KeylistResult res);
 void _gpgme_op_keylist_event_cb (void *data, GpgmeEventIO type, void *type_data);
 
 /*-- trustlist.c --*/
 void _gpgme_op_trustlist_event_cb (void *data, GpgmeEventIO type, void *type_data);
 
-/*-- edit.c --*/
-void _gpgme_release_edit_result (EditResult res);
-
 /*-- version.c --*/
 const char *_gpgme_compare_versions (const char *my_version,
                                     const char *req_version);
index 43f2b7b..67fb43b 100644 (file)
 #include "util.h"
 #include "context.h"
 #include "ops.h"
+#include "debug.h"
 
-
-struct passphrase_result_s
+\f
+struct passphrase_result
 {
   int no_passphrase;
   void *last_pw_handle;
@@ -39,58 +40,63 @@ struct passphrase_result_s
   char *passphrase_info;
   int bad_passphrase;
 };
+typedef struct passphrase_result *PassphraseResult;
 
-
-void
-_gpgme_release_passphrase_result (PassphraseResult result)
+static void
+release_passphrase_result (void *hook)
 {
-  if (!result)
-    return;
+  PassphraseResult result = (PassphraseResult) hook;
+
   free (result->passphrase_info);
   free (result->userid_hint);
-  free (result);
 }
 
-
+\f
 GpgmeError
 _gpgme_passphrase_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
 {
-  test_and_allocate_result (ctx, passphrase);
+  GpgmeError err;
+  PassphraseResult result;
+
+  err = _gpgme_op_data_lookup (ctx, OPDATA_PASSPHRASE, (void **) &result,
+                              sizeof (*result), release_passphrase_result);
+  if (err)
+    return err;
 
   switch (code)
     {
     case GPGME_STATUS_USERID_HINT:
-      free (ctx->result.passphrase->userid_hint);
-      if (!(ctx->result.passphrase->userid_hint = strdup (args)))
+      free (result->userid_hint);
+      if (!(result->userid_hint = strdup (args)))
        return GPGME_Out_Of_Core;
       break;
 
     case GPGME_STATUS_BAD_PASSPHRASE:
-      ctx->result.passphrase->bad_passphrase++;
-      ctx->result.passphrase->no_passphrase = 0;
+      result->bad_passphrase++;
+      result->no_passphrase = 0;
       break;
 
     case GPGME_STATUS_GOOD_PASSPHRASE:
-      ctx->result.passphrase->bad_passphrase = 0;
-      ctx->result.passphrase->no_passphrase = 0;
+      result->bad_passphrase = 0;
+      result->no_passphrase = 0;
       break;
 
     case GPGME_STATUS_NEED_PASSPHRASE:
     case GPGME_STATUS_NEED_PASSPHRASE_SYM:
-      free (ctx->result.passphrase->passphrase_info);
-      ctx->result.passphrase->passphrase_info = strdup (args);
-      if (!ctx->result.passphrase->passphrase_info)
+      free (result->passphrase_info);
+      result->passphrase_info = strdup (args);
+      if (!result->passphrase_info)
        return GPGME_Out_Of_Core;
       break;
 
     case GPGME_STATUS_MISSING_PASSPHRASE:
       DEBUG0 ("missing passphrase - stop\n");;
-      ctx->result.passphrase->no_passphrase = 1;
+      result->no_passphrase = 1;
       break;
 
     case GPGME_STATUS_EOF:
-      if (ctx->result.passphrase->no_passphrase
-         || ctx->result.passphrase->bad_passphrase)
+      if (result->no_passphrase
+         || result->bad_passphrase)
        return GPGME_No_Passphrase;
       break;
 
@@ -104,16 +110,16 @@ _gpgme_passphrase_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args
 
 GpgmeError
 _gpgme_passphrase_command_handler (void *opaque, GpgmeStatusCode code,
-                                  const char *key, const char **result)
+                                  const char *key, const char **result_r)
 {
   GpgmeCtx ctx = opaque;
+  GpgmeError err;
+  PassphraseResult result;
 
-  if (!ctx->result.passphrase)
-    {
-      ctx->result.passphrase = calloc (1, sizeof *ctx->result.passphrase);
-      if (!ctx->result.passphrase)
-       return GPGME_Out_Of_Core;
-    }
+  err = _gpgme_op_data_lookup (ctx, OPDATA_PASSPHRASE, (void **) &result,
+                              sizeof (*result), release_passphrase_result);
+  if (err)
+    return err;
 
   if (!code)
     {
@@ -122,26 +128,26 @@ _gpgme_passphrase_command_handler (void *opaque, GpgmeStatusCode code,
        { 
          /* Fixme: Take the key in account.  */
          ctx->passphrase_cb (ctx->passphrase_cb_value, NULL, 
-                             &ctx->result.passphrase->last_pw_handle);
+                             &result->last_pw_handle);
         }
-      *result = NULL;
+      *result_r = NULL;
       return 0;
     }
 
   if (!key || !ctx->passphrase_cb)
     {
-      *result = NULL;
+      *result_r = NULL;
       return 0;
     }
     
   if (code == GPGME_STATUS_GET_HIDDEN && !strcmp (key, "passphrase.enter"))
     {
-      const char *userid_hint = ctx->result.passphrase->userid_hint;
-      const char *passphrase_info = ctx->result.passphrase->passphrase_info;
-      int bad_passphrase = ctx->result.passphrase->bad_passphrase;
+      const char *userid_hint = result->userid_hint;
+      const char *passphrase_info = result->passphrase_info;
+      int bad_passphrase = result->bad_passphrase;
       char *buf;
 
-      ctx->result.passphrase->bad_passphrase = 0;
+      result->bad_passphrase = 0;
       if (!userid_hint)
        userid_hint = "[User ID hint missing]";
       if (!passphrase_info)
@@ -154,13 +160,13 @@ _gpgme_passphrase_command_handler (void *opaque, GpgmeStatusCode code,
               bad_passphrase ? "TRY_AGAIN":"ENTER",
               userid_hint, passphrase_info);
 
-      *result = ctx->passphrase_cb (ctx->passphrase_cb_value, buf,
-                                   &ctx->result.passphrase->last_pw_handle);
+      *result_r = ctx->passphrase_cb (ctx->passphrase_cb_value, buf,
+                                     &result->last_pw_handle);
       free (buf);
       return 0;
     }
 
-  *result = NULL;
+  *result_r = NULL;
   return 0;
 }
 
index 49bca0f..9c571b0 100644 (file)
@@ -37,6 +37,7 @@
 #include "io.h"
 #include "sema.h"
 #include "ath.h"
+#include "debug.h"
 
 static struct
 {
index 2b0e4d3..2d5a1a7 100644 (file)
@@ -40,6 +40,7 @@
 #include "context.h"  /*temp hack until we have GpmeData methods to do I/O */
 #include "io.h"
 #include "sema.h"
+#include "debug.h"
 
 #include "status-table.h"
 #include "engine-backend.h"
index d8431cb..eeebe7a 100644 (file)
         return; /* oops */ \
 } while (0)
 
-struct sign_result_s
+struct sign_result
 {
   int okay;
   GpgmeData xmlinfo;
 };
+typedef struct sign_result *SignResult;
 
-void
-_gpgme_release_sign_result (SignResult result)
+
+static void
+release_sign_result (void *hook)
 {
-  if (!result)
-    return;
+  SignResult result = (SignResult) hook;
+
   gpgme_data_release (result->xmlinfo);
-  free (result);
 }
 
 /* Parse the args and save the information 
@@ -139,35 +140,44 @@ append_xml_siginfo (GpgmeData *rdh, char *args)
 GpgmeError
 _gpgme_sign_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
 {
-  GpgmeError err = _gpgme_passphrase_status_handler (ctx, code, args);
+  SignResult result;
+  GpgmeError err;
+
+  err = _gpgme_passphrase_status_handler (ctx, code, args);
   if (err)
     return err;
 
-  test_and_allocate_result (ctx, sign);
-
   switch (code)
     {
     case GPGME_STATUS_EOF:
-      if (ctx->result.sign->okay)
+      err = _gpgme_op_data_lookup (ctx, OPDATA_SIGN, (void **) &result,
+                                  -1, NULL);
+      if (!err)
        {
-         append_xml_siginfo (&ctx->result.sign->xmlinfo, NULL);
-         _gpgme_set_op_info (ctx, ctx->result.sign->xmlinfo);
-         ctx->result.sign->xmlinfo = NULL;
-        }
-      if (!ctx->result.sign->okay)
-       return GPGME_No_Data; /* Hmmm: choose a better error? */
+         if (result && result->okay)
+           {
+             append_xml_siginfo (&result->xmlinfo, NULL);
+             _gpgme_set_op_info (ctx, result->xmlinfo);
+             result->xmlinfo = NULL;
+           }
+         else if (!result || !result->okay)
+           /* FIXME: choose a better error code?  */
+           err = GPGME_No_Data;
+       }
       break;
 
     case GPGME_STATUS_SIG_CREATED: 
       /* FIXME: We have no error return for multiple signatures.  */
-      append_xml_siginfo (&ctx->result.sign->xmlinfo, args);
-      ctx->result.sign->okay = 1;
+      err = _gpgme_op_data_lookup (ctx, OPDATA_SIGN, (void **) &result,
+                                  sizeof (*result), release_sign_result);
+      append_xml_siginfo (&result->xmlinfo, args);
+      result->okay = 1;
       break;
 
     default:
       break;
     }
-  return 0;
+  return err;
 }
 
 static GpgmeError
index 90d7129..8a36c47 100644 (file)
@@ -32,44 +32,4 @@ typedef GpgmeError (*GpgmeCommandHandler) (void*, GpgmeStatusCode code,
                                           const char *keyword, const char **result);
 
 
-/*-- verify.c --*/
-struct verify_result_s;
-typedef struct verify_result_s *VerifyResult;
-
-/*-- decrypt.c --*/
-struct decrypt_result_s;
-typedef struct decrypt_result_s *DecryptResult;
-
-/*-- sign.c --*/
-struct sign_result_s;
-typedef struct sign_result_s *SignResult;
-
-/*-- encrypt.c --*/
-struct encrypt_result_s;
-typedef struct encrypt_result_s *EncryptResult;
-
-/*-- passphrase.c --*/
-struct passphrase_result_s;
-typedef struct passphrase_result_s *PassphraseResult;
-
-/*-- import.c --*/
-struct import_result_s;
-typedef struct import_result_s *ImportResult;
-
-/*-- delete.c --*/
-struct delete_result_s;
-typedef struct delete_result_s *DeleteResult;
-
-/*-- genkey.c --*/
-struct genkey_result_s;
-typedef struct genkey_result_s *GenKeyResult;
-
-/*-- keylist.c --*/
-struct keylist_result_s;
-typedef struct keylist_result_s *KeylistResult;
-
-/*-- edit.c --*/
-struct edit_result_s;
-typedef struct edit_result_s *EditResult;
-
 #endif /* TYPES_H */
index 8f697de..a280587 100644 (file)
 #ifndef UTIL_H
 #define UTIL_H
 
-#include "types.h"
-#include "debug.h"
-
+#include "gpgme.h"
 
+\f
 #define DIM(v) (sizeof(v)/sizeof((v)[0]))
 #define DIMof(type,member)   DIM(((type *)0)->member)
 
+\f
 /*-- {posix,w32}-util.c --*/
 const char *_gpgme_get_gpg_path (void);
 const char *_gpgme_get_gpgsm_path (void);
 
+\f
 /*-- replacement functions in <funcname>.c --*/
 #ifdef HAVE_CONFIG_H
 #ifndef HAVE_STPCPY
@@ -59,7 +60,7 @@ FILE *fopencookie (void *cookie, const char *opentype,
 #endif /*!HAVE_FOPENCOOKIE*/
 #endif /*HAVE_CONFIG_H*/
 
-
+\f
 /*-- conversion.c --*/
 /* Convert two hexadecimal digits from STR to the value they
    represent.  Returns -1 if one of the characters is not a
index f678dc0..7817668 100644 (file)
@@ -32,9 +32,8 @@
 #include "key.h"
 
 
-struct verify_result_s
+struct verify_result
 {
-  struct verify_result_s *next;
   GpgmeSigStat status;
   GpgmeSigStat expstatus;      /* Only used by finish_sig.  */
   GpgmeData notation;          /* We store an XML fragment here.  */
@@ -48,20 +47,18 @@ struct verify_result_s
   int wrong_key_usage;  
   char trust_errtok[31];       /* Error token send with the trust status.  */
 };
+typedef struct verify_result *VerifyResult;
 
 
-void
-_gpgme_release_verify_result (VerifyResult result)
+static void
+release_verify_result (void *hook)
 {
-  while (result)
-    {
-      VerifyResult next_result = result->next;
-      gpgme_data_release (result->notation);
-      free (result);
-      result = next_result;
-    }
+  VerifyResult result = (VerifyResult) hook;
+
+  gpgme_data_release (result->notation);
 }
 
+
 /* Check whether STRING starts with TOKEN and return true in this
    case.  This is case insensitive.  If NEXT is not NULL return the
    number of bytes to be added to STRING to get to the next token; a
@@ -120,43 +117,43 @@ copy_token (const char *string, char *buffer, size_t length)
 
 /* FIXME: Check that we are adding this to the correct signature.  */
 static GpgmeError
-add_notation (GpgmeCtx ctx, GpgmeStatusCode code, const char *data)
+add_notation (VerifyResult result, GpgmeStatusCode code, const char *notation)
 {
-  GpgmeData dh = ctx->result.verify->notation;
+  GpgmeData dh = result->notation;
 
   if (!dh)
     {
       if (gpgme_data_new (&dh))
        return GPGME_Out_Of_Core;
-      ctx->result.verify->notation = dh;
+      result->notation = dh;
       _gpgme_data_append_string (dh, "  <notation>\n");
     }
 
   if (code == GPGME_STATUS_NOTATION_DATA)
     {
-      if (!ctx->result.verify->notation_in_data)
+      if (!result->notation_in_data)
        _gpgme_data_append_string (dh, "  <data>");
-      _gpgme_data_append_percentstring_for_xml (dh, data);
-      ctx->result.verify->notation_in_data = 1;
+      _gpgme_data_append_percentstring_for_xml (dh, notation);
+      result->notation_in_data = 1;
       return 0;
     }
 
-  if (ctx->result.verify->notation_in_data)
+  if (result->notation_in_data)
     {
       _gpgme_data_append_string (dh, "</data>\n");
-      ctx->result.verify->notation_in_data = 0;
+      result->notation_in_data = 0;
     }
 
   if (code == GPGME_STATUS_NOTATION_NAME)
     {
       _gpgme_data_append_string (dh, "  <name>");
-      _gpgme_data_append_percentstring_for_xml (dh, data);
+      _gpgme_data_append_percentstring_for_xml (dh, notation);
       _gpgme_data_append_string (dh, "</name>\n");
     }
   else if (code == GPGME_STATUS_POLICY_URL)
     {
       _gpgme_data_append_string (dh, "  <policy>");
-      _gpgme_data_append_percentstring_for_xml (dh, data);
+      _gpgme_data_append_percentstring_for_xml (dh, notation);
       _gpgme_data_append_string (dh, "</policy>\n");
     }
   else
@@ -165,53 +162,44 @@ add_notation (GpgmeCtx ctx, GpgmeStatusCode code, const char *data)
 }
 
 
-/* Finish a pending signature info collection and prepare for a new
-   signature info collection.  */
-static GpgmeError
-finish_sig (GpgmeCtx ctx, int stop)
+/* Finish a pending signature info collection.  */
+static void
+finish_sig (VerifyResult result)
 {
-  if (ctx->result.verify->status == GPGME_SIG_STAT_GOOD)
-    ctx->result.verify->status = ctx->result.verify->expstatus;
-
-  if (stop)
-    return 0; /* nothing to do */
-
-  if (ctx->result.verify->collecting)
-    {
-      VerifyResult res2;
-
-      ctx->result.verify->collecting = 0;
-      /* Create a new result structure.  */
-      res2 = calloc (1, sizeof *res2);
-      if (!res2)
-       return GPGME_Out_Of_Core;
-
-      res2->next = ctx->result.verify;
-      ctx->result.verify = res2;
-    }
-    
-  ctx->result.verify->collecting = 1;
-  return 0;
+  struct ctx_op_data *op_data;
+
+  /* We intimately know that gpgme_op_data_lookup appends the data to
+     the op_data structure.  We can use this here to change the type
+     knowing only the hook value.  */
+  op_data = (struct ctx_op_data *) ((void *) result
+                                   - sizeof (struct ctx_op_data));
+  op_data->type = OPDATA_VERIFY;
 }
 
 
 GpgmeError
 _gpgme_verify_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
 {
+  VerifyResult result;
   GpgmeError err;
   char *p;
   size_t n;
   int i;
 
-  test_and_allocate_result (ctx, verify);
+  err = _gpgme_op_data_lookup (ctx, OPDATA_VERIFY_COLLECTING, (void **) &result,
+                              -1, NULL);
+  if (err)
+    return err;
 
-  if (code == GPGME_STATUS_GOODSIG
-      || code == GPGME_STATUS_EXPSIG
-      || code == GPGME_STATUS_EXPKEYSIG
-      || code == GPGME_STATUS_BADSIG
+  if (code == GPGME_STATUS_GOODSIG || code == GPGME_STATUS_EXPSIG
+      || code == GPGME_STATUS_EXPKEYSIG || code == GPGME_STATUS_BADSIG
       || code == GPGME_STATUS_ERRSIG)
     {
-      err = finish_sig (ctx,0);
+      /* A new signature starts.  */
+      if (result)
+       finish_sig (result);
+      err = _gpgme_op_data_lookup (ctx, OPDATA_VERIFY_COLLECTING, (void **) &result,
+                                  sizeof (*result), release_verify_result);
       if (err)
        return err;
     }
@@ -220,44 +208,56 @@ _gpgme_verify_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
     {
     case GPGME_STATUS_NODATA:
     case GPGME_STATUS_UNEXPECTED:
-      ctx->result.verify->status = GPGME_SIG_STAT_NOSIG;
+      if (!result)
+       return GPGME_General_Error;
+      result->status = GPGME_SIG_STAT_NOSIG;
       break;
 
     case GPGME_STATUS_GOODSIG:
-      ctx->result.verify->expstatus = GPGME_SIG_STAT_GOOD;
+      if (!result)
+       return GPGME_General_Error;
+      result->expstatus = GPGME_SIG_STAT_GOOD;
       break;
-    
+
     case GPGME_STATUS_EXPSIG:
-      ctx->result.verify->expstatus = GPGME_SIG_STAT_GOOD_EXP;
+      if (!result)
+       return GPGME_General_Error;
+      result->expstatus = GPGME_SIG_STAT_GOOD_EXP;
       break;
 
     case GPGME_STATUS_EXPKEYSIG:
-      ctx->result.verify->expstatus = GPGME_SIG_STAT_GOOD_EXPKEY;
+      if (!result)
+       return GPGME_General_Error;
+      result->expstatus = GPGME_SIG_STAT_GOOD_EXPKEY;
       break;
 
     case GPGME_STATUS_VALIDSIG:
-      ctx->result.verify->status = GPGME_SIG_STAT_GOOD;
-      i = copy_token (args, ctx->result.verify->fpr,
-                      DIM(ctx->result.verify->fpr));
+      if (!result)
+       return GPGME_General_Error;
+      result->status = GPGME_SIG_STAT_GOOD;
+      i = copy_token (args, result->fpr, DIM (result->fpr));
       /* Skip the formatted date.  */
       while (args[i] && args[i] == ' ')
        i++;
       while (args[i] && args[i] != ' ')
        i++;
       /* And get the timestamp.  */
-      ctx->result.verify->timestamp = strtoul (args+i, &p, 10);
+      result->timestamp = strtoul (args + i, &p, 10);
       if (args[i])
-        ctx->result.verify->exptimestamp = strtoul (p, NULL, 10);
+        result->exptimestamp = strtoul (p, NULL, 10);
       break;
 
     case GPGME_STATUS_BADSIG:
-      ctx->result.verify->status = GPGME_SIG_STAT_BAD;
+      if (!result)
+       return GPGME_General_Error;
+      result->status = GPGME_SIG_STAT_BAD;
       /* Store the keyID in the fpr field.  */
-      copy_token (args, ctx->result.verify->fpr,
-                  DIM(ctx->result.verify->fpr));
+      copy_token (args, result->fpr, DIM (result->fpr));
       break;
 
     case GPGME_STATUS_ERRSIG:
+      if (!result)
+       return GPGME_General_Error;
       /* The return code is the 6th argument, if it is 9, the problem
         is a missing key.  Note that this is not emitted by gpgsm */
       for (p = args, i = 0; p && *p && i < 5; i++)
@@ -268,85 +268,97 @@ _gpgme_verify_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
               p++;
         }
       if (p && *(p++) == '9' && (*p == '\0' || *p == ' '))
-       ctx->result.verify->status = GPGME_SIG_STAT_NOKEY;
+       result->status = GPGME_SIG_STAT_NOKEY;
       else
-       ctx->result.verify->status = GPGME_SIG_STAT_ERROR;
+       result->status = GPGME_SIG_STAT_ERROR;
       /* Store the keyID in the fpr field.  */
-      copy_token (args, ctx->result.verify->fpr,
-                  DIM(ctx->result.verify->fpr));
+      copy_token (args, result->fpr, DIM (result->fpr));
       break;
 
     case GPGME_STATUS_NOTATION_NAME:
     case GPGME_STATUS_NOTATION_DATA:
     case GPGME_STATUS_POLICY_URL:
-      err = add_notation (ctx, code, args);
+      if (!result)
+       return GPGME_General_Error;
+      err = add_notation (result, code, args);
       if (err)
        return err;
       break;
 
     case GPGME_STATUS_TRUST_UNDEFINED:
-      ctx->result.verify->validity = GPGME_VALIDITY_UNKNOWN;
-      copy_token (args, ctx->result.verify->trust_errtok,
-                  DIM(ctx->result.verify->trust_errtok));
+      if (!result)
+       return GPGME_General_Error;
+      result->validity = GPGME_VALIDITY_UNKNOWN;
+      copy_token (args, result->trust_errtok,
+                  DIM(result->trust_errtok));
       break;
     case GPGME_STATUS_TRUST_NEVER:
-      ctx->result.verify->validity = GPGME_VALIDITY_NEVER;
-      copy_token (args, ctx->result.verify->trust_errtok,
-                  DIM(ctx->result.verify->trust_errtok));
+      if (!result)
+       return GPGME_General_Error;
+      result->validity = GPGME_VALIDITY_NEVER;
+      copy_token (args, result->trust_errtok,
+                  DIM(result->trust_errtok));
       break;
     case GPGME_STATUS_TRUST_MARGINAL:
-      if (ctx->result.verify->status == GPGME_SIG_STAT_GOOD)
-        ctx->result.verify->validity = GPGME_VALIDITY_MARGINAL;
-      copy_token (args, ctx->result.verify->trust_errtok,
-                  DIM(ctx->result.verify->trust_errtok));
+      if (!result)
+       return GPGME_General_Error;
+      if (result->status == GPGME_SIG_STAT_GOOD)
+        result->validity = GPGME_VALIDITY_MARGINAL;
+      copy_token (args, result->trust_errtok,
+                  DIM(result->trust_errtok));
       break;
     case GPGME_STATUS_TRUST_FULLY:
     case GPGME_STATUS_TRUST_ULTIMATE:
-      if (ctx->result.verify->status == GPGME_SIG_STAT_GOOD)
-        ctx->result.verify->validity = GPGME_VALIDITY_FULL;
+      if (!result)
+       return GPGME_General_Error;
+      if (result->status == GPGME_SIG_STAT_GOOD)
+        result->validity = GPGME_VALIDITY_FULL;
       break;
 
     case GPGME_STATUS_END_STREAM:
       break;
 
     case GPGME_STATUS_ERROR:
+      if (!result)
+       return GPGME_General_Error;
       /* Generic error, we need this for gpgsm (and maybe for gpg in future)
          to get error descriptions. */
       if (is_token (args, "verify.findkey", &n) && n)
         {
           args += n;
           if (is_token (args, "No_Public_Key", NULL))
-            ctx->result.verify->status = GPGME_SIG_STAT_NOKEY;
+            result->status = GPGME_SIG_STAT_NOKEY;
           else
-            ctx->result.verify->status = GPGME_SIG_STAT_ERROR;
+            result->status = GPGME_SIG_STAT_ERROR;
 
         }
       else if (skip_token (args, &n) && n)
         {
           args += n;
           if (is_token (args, "Wrong_Key_Usage", NULL))
-            ctx->result.verify->wrong_key_usage = 1;
+            result->wrong_key_usage = 1;
         }
       break;
 
     case GPGME_STATUS_EOF:
-      err = finish_sig (ctx,1);
-      if (err)
-       return err;
-
-      /* FIXME: Put all notation data into one XML fragment.  */
-      if (ctx->result.verify->notation)
+      if (result)
        {
-         GpgmeData dh = ctx->result.verify->notation;
+         finish_sig (result);
 
-         if (ctx->result.verify->notation_in_data)
+         /* FIXME: Put all notation data into one XML fragment.  */
+         if (result->notation)
            {
-             _gpgme_data_append_string (dh, "</data>\n");
-             ctx->result.verify->notation_in_data = 0;
+             GpgmeData dh = result->notation;
+             
+             if (result->notation_in_data)
+               {
+                 _gpgme_data_append_string (dh, "</data>\n");
+                 result->notation_in_data = 0;
+               }
+             _gpgme_data_append_string (dh, "</notation>\n");
+             ctx->notation = dh;
+             result->notation = NULL;
            }
-         _gpgme_data_append_string (dh, "</notation>\n");
-         ctx->notation = dh;
-         ctx->result.verify->notation = NULL;
        }
       break;
  
@@ -465,20 +477,28 @@ gpgme_op_verify (GpgmeCtx ctx, GpgmeData sig, GpgmeData signed_text,
  *               when there are no more signatures.
  **/
 const char *
-gpgme_get_sig_status (GpgmeCtx c, int idx,
+gpgme_get_sig_status (GpgmeCtx ctx, int idx,
                       GpgmeSigStat *r_stat, time_t *r_created)
 {
+  struct ctx_op_data *op_data;
   VerifyResult result;
 
-  if (!c || c->pending || !c->result.verify)
+  if (!ctx || ctx->pending)
     return NULL;       /* No results yet or verification error.  */
 
-  for (result = c->result.verify;
-       result && idx > 0; result = result->next, idx--)
-    ;
-  if (!result)
+  op_data = ctx->op_data;
+  while (op_data)
+    {
+      while (op_data && op_data->type != OPDATA_VERIFY)
+       op_data = op_data->next;
+      if (idx-- == 0)
+       break;
+      op_data = op_data->next; 
+    }
+  if (!op_data)
     return NULL;       /* No more signatures.  */
 
+  result = (VerifyResult) op_data->hook;
   if (r_stat)
     *r_stat = result->status;
   if (r_created)
@@ -545,19 +565,27 @@ calc_sig_summary (VerifyResult result)
 
 
 const char *
-gpgme_get_sig_string_attr (GpgmeCtx c, int idx, GpgmeAttr what, int whatidx)
+gpgme_get_sig_string_attr (GpgmeCtx ctx, int idx, GpgmeAttr what, int whatidx)
 {
+  struct ctx_op_data *op_data;
   VerifyResult result;
 
-  if (!c || c->pending || !c->result.verify)
+  if (!ctx || ctx->pending)
     return NULL;       /* No results yet or verification error.  */
 
-  for (result = c->result.verify;
-       result && idx > 0; result = result->next, idx--)
-    ;
-  if (!result)
+  op_data = ctx->op_data;
+  while (op_data)
+    {
+      while (op_data && op_data->type != OPDATA_VERIFY)
+       op_data = op_data->next;
+      if (idx-- == 0)
+       break;
+      op_data = op_data->next; 
+    }
+  if (!op_data)
     return NULL;       /* No more signatures.  */
 
+  result = (VerifyResult) op_data->hook;
   switch (what)
     {
     case GPGME_ATTR_FPR:
@@ -575,19 +603,27 @@ gpgme_get_sig_string_attr (GpgmeCtx c, int idx, GpgmeAttr what, int whatidx)
 
 
 unsigned long
-gpgme_get_sig_ulong_attr (GpgmeCtx c, int idx, GpgmeAttr what, int reserved)
+gpgme_get_sig_ulong_attr (GpgmeCtx ctx, int idx, GpgmeAttr what, int reserved)
 {
+  struct ctx_op_data *op_data;
   VerifyResult result;
 
-  if (!c || c->pending || !c->result.verify)
+  if (!ctx || ctx->pending)
     return 0;  /* No results yet or verification error.  */
 
-  for (result = c->result.verify;
-       result && idx > 0; result = result->next, idx--)
-    ;
-  if (!result)
+  op_data = ctx->op_data;
+  while (op_data)
+    {
+      while (op_data && op_data->type != OPDATA_VERIFY)
+       op_data = op_data->next;
+      if (idx-- == 0)
+       break;
+      op_data = op_data->next; 
+    }
+  if (!op_data)
     return 0;  /* No more signatures.  */
 
+  result = (VerifyResult) op_data->hook;
   switch (what)
     {
     case GPGME_ATTR_CREATED:
@@ -595,9 +631,9 @@ gpgme_get_sig_ulong_attr (GpgmeCtx c, int idx, GpgmeAttr what, int reserved)
     case GPGME_ATTR_EXPIRE:
       return result->exptimestamp;
     case GPGME_ATTR_VALIDITY:
-      return (unsigned long)result->validity;
+      return (unsigned long) result->validity;
     case GPGME_ATTR_SIG_STATUS:
-      return (unsigned long)result->status;
+      return (unsigned long) result->status;
     case GPGME_ATTR_SIG_SUMMARY:
       return calc_sig_summary (result);
     default:
@@ -621,18 +657,28 @@ gpgme_get_sig_ulong_attr (GpgmeCtx c, int idx, GpgmeAttr what, int reserved)
 GpgmeError
 gpgme_get_sig_key (GpgmeCtx ctx, int idx, GpgmeKey *r_key)
 {
+  struct ctx_op_data *op_data;
   VerifyResult result;
 
   if (!ctx || !r_key)
     return GPGME_Invalid_Value;
-  if (ctx->pending || !ctx->result.verify)
+
+  if (ctx->pending)
     return GPGME_Busy;
-  
-  for (result = ctx->result.verify;
-       result && idx > 0; result = result->next, idx--)
-    ;
-  if (!result)
+
+  op_data = ctx->op_data;
+  while (op_data)
+    {
+      while (op_data && op_data->type != OPDATA_VERIFY)
+       op_data = op_data->next;
+      if (idx-- == 0)
+       break;
+      op_data = op_data->next; 
+    }
+  if (!op_data)
     return GPGME_EOF;
 
+  result = (VerifyResult) op_data->hook;
+
   return gpgme_get_key (ctx, result->fpr, r_key, 0, 0);
 }
index 6d5f272..c70efa1 100644 (file)
@@ -34,6 +34,7 @@
 #include "sema.h"
 #include "io.h"
 #include "engine.h"
+#include "debug.h"
 
 \f
 void