doc: Fix documentation of struct data types
[gpgme.git] / src / wait-global.c
index ececc1b..f03775e 100644 (file)
@@ -1,19 +1,19 @@
-/* wait-global.c 
+/* wait-global.c
    Copyright (C) 2000 Werner Koch (dd9jn)
    Copyright (C) 2001, 2002, 2003, 2004, 2005 g10 Code GmbH
+
    This file is part of GPGME.
+
    GPGME is free software; you can redistribute it and/or modify it
    under the terms of the GNU Lesser General Public License as
    published by the Free Software Foundation; either version 2.1 of
    the License, or (at your option) any later version.
-   
+
    GPGME is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.
-   
+
    You should have received a copy of the GNU Lesser General Public
    License along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -34,6 +34,7 @@
 #include "wait.h"
 #include "priv-io.h"
 #include "ops.h"
+#include "debug.h"
 
 /* The global event loop is used for all asynchronous operations
    (except key listing) for which no user I/O callbacks are specified.
@@ -74,6 +75,7 @@ struct ctx_list_item
   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
@@ -95,7 +97,7 @@ ctx_active (gpgme_ctx_t ctx)
 {
   struct ctx_list_item *li = malloc (sizeof (struct ctx_list_item));
   if (!li)
-    return gpg_error_from_errno (errno);
+    return gpg_error_from_syserror ();
   li->ctx = ctx;
 
   LOCK (ctx_list_lock);
@@ -112,7 +114,7 @@ ctx_active (gpgme_ctx_t ctx)
 
 /* 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 +133,7 @@ ctx_done (gpgme_ctx_t ctx, gpgme_error_t status)
     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 +150,7 @@ ctx_done (gpgme_ctx_t ctx, gpgme_error_t status)
    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 +167,8 @@ ctx_wait (gpgme_ctx_t ctx, gpgme_error_t *status)
       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 +208,16 @@ _gpgme_wait_global_event_cb (void *data, gpgme_event_io_t type,
        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 +252,8 @@ _gpgme_wait_global_event_cb (void *data, gpgme_event_io_t type,
    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
     {
@@ -262,10 +269,12 @@ gpgme_wait (gpgme_ctx_t ctx, gpgme_error_t *status, int hang)
       fdt.fds = malloc (i * sizeof (struct io_select_fd_s));
       if (!fdt.fds)
        {
-         int saved_errno = errno;
+          int saved_err = gpg_error_from_syserror ();
          UNLOCK (ctx_list_lock);
          if (status)
-           *status = gpg_error_from_errno (saved_errno);
+           *status = saved_err;
+         if (op_err)
+           *op_err = 0;
          return NULL;
        }
       fdt.size = i;
@@ -281,10 +290,12 @@ gpgme_wait (gpgme_ctx_t ctx, gpgme_error_t *status, int hang)
       nr = _gpgme_io_select (fdt.fds, fdt.size, 0);
       if (nr < 0)
        {
-         int saved_errno = errno;
+          int saved_err = gpg_error_from_syserror ();
          free (fdt.fds);
          if (status)
-           *status = gpg_error_from_errno (saved_errno);
+           *status = saved_err;
+         if (op_err)
+           *op_err = 0;
          return NULL;
        }
 
@@ -294,11 +305,12 @@ gpgme_wait (gpgme_ctx_t ctx, gpgme_error_t *status, int hang)
            {
              gpgme_ctx_t ictx;
              gpgme_error_t err = 0;
+             gpgme_error_t local_op_err = 0;
              struct wait_item_s *item;
-             
+
              assert (nr);
              nr--;
-             
+
              item = (struct wait_item_s *) fdt.fds[i].opaque;
              assert (item);
              ictx = item->ctx;
@@ -310,12 +322,12 @@ gpgme_wait (gpgme_ctx_t ctx, gpgme_error_t *status, int hang)
              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,7 +350,9 @@ gpgme_wait (gpgme_ctx_t ctx, gpgme_error_t *status, int hang)
              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
@@ -349,7 +363,7 @@ gpgme_wait (gpgme_ctx_t ctx, gpgme_error_t *status, int hang)
                 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 +371,7 @@ gpgme_wait (gpgme_ctx_t ctx, gpgme_error_t *status, int hang)
       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 +383,8 @@ gpgme_wait (gpgme_ctx_t ctx, gpgme_error_t *status, int hang)
            ctx = NULL;
            if (status)
              *status = 0;
+           if (op_err)
+             *op_err = 0;
          }
       }
     }
@@ -376,3 +392,10 @@ gpgme_wait (gpgme_ctx_t ctx, gpgme_error_t *status, int hang)
 
   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);
+}