LCOV - code coverage report
Current view: top level - src - wait-private.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 49 55 89.1 %
Date: 2016-09-12 13:07:23 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /* wait-private.c
       2             :    Copyright (C) 2000 Werner Koch (dd9jn)
       3             :    Copyright (C) 2001, 2002, 2003, 2004, 2005 g10 Code GmbH
       4             : 
       5             :    This file is part of GPGME.
       6             : 
       7             :    GPGME is free software; you can redistribute it and/or modify it
       8             :    under the terms of the GNU Lesser General Public License as
       9             :    published by the Free Software Foundation; either version 2.1 of
      10             :    the License, or (at your option) any later version.
      11             : 
      12             :    GPGME is distributed in the hope that it will be useful, but
      13             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :    Lesser General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU Lesser General Public
      18             :    License along with this program; if not, write to the Free Software
      19             :    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
      20             :    02111-1307, USA.  */
      21             : 
      22             : #if HAVE_CONFIG_H
      23             : #include <config.h>
      24             : #endif
      25             : #include <assert.h>
      26             : #include <errno.h>
      27             : 
      28             : #include "gpgme.h"
      29             : #include "context.h"
      30             : #include "wait.h"
      31             : #include "ops.h"
      32             : #include "priv-io.h"
      33             : #include "util.h"
      34             : #include "debug.h"
      35             : 
      36             : 
      37             : /* The private event loops are used for all blocking operations, and
      38             :    for the key and trust item listing operations.  They are completely
      39             :    separated from each other.  */
      40             : 
      41             : 
      42             : /* Internal I/O callback functions.  */
      43             : 
      44             : /* The add_io_cb and remove_io_cb handlers are shared with the global
      45             :    event loops.  */
      46             : 
      47             : void
      48         852 : _gpgme_wait_private_event_cb (void *data, gpgme_event_io_t type,
      49             :                               void *type_data)
      50             : {
      51         852 :   switch (type)
      52             :     {
      53             :     case GPGME_EVENT_START:
      54             :       /* Nothing to do here, as the wait routine is called after the
      55             :          initialization is finished.  */
      56         288 :       break;
      57             : 
      58             :     case GPGME_EVENT_DONE:
      59         378 :       break;
      60             : 
      61             :     case GPGME_EVENT_NEXT_KEY:
      62         186 :       _gpgme_op_keylist_event_cb (data, type, type_data);
      63         186 :       break;
      64             : 
      65             :     case GPGME_EVENT_NEXT_TRUSTITEM:
      66           0 :       _gpgme_op_trustlist_event_cb (data, type, type_data);
      67           0 :       break;
      68             :     }
      69         852 : }
      70             : 
      71             : 
      72             : /* If COND is a null pointer, wait until the blocking operation in CTX
      73             :    finished and return its error value.  Otherwise, wait until COND is
      74             :    satisfied or the operation finished.  */
      75             : gpgme_error_t
      76         415 : _gpgme_wait_on_condition (gpgme_ctx_t ctx, volatile int *cond,
      77             :                           gpgme_error_t *op_err_p)
      78             : {
      79         415 :   gpgme_error_t err = 0;
      80         415 :   int hang = 1;
      81             : 
      82         415 :   if (op_err_p)
      83           8 :     *op_err_p = 0;
      84             : 
      85             :   do
      86             :     {
      87        2778 :       int nr = _gpgme_io_select (ctx->fdt.fds, ctx->fdt.size, 0);
      88             :       unsigned int i;
      89             : 
      90        2779 :       if (nr < 0)
      91             :         {
      92             :           /* An error occurred.  Close all fds in this context, and
      93             :              signal it.  */
      94           0 :           err = gpg_error_from_syserror ();
      95           0 :           _gpgme_cancel_with_err (ctx, err, 0);
      96             : 
      97           0 :           return err;
      98             :         }
      99             : 
     100        7297 :       for (i = 0; i < ctx->fdt.size && nr; i++)
     101             :         {
     102        4533 :           if (ctx->fdt.fds[i].fd != -1 && ctx->fdt.fds[i].signaled)
     103             :             {
     104        2978 :               gpgme_error_t op_err = 0;
     105             : 
     106        2978 :               ctx->fdt.fds[i].signaled = 0;
     107        2978 :               assert (nr);
     108        2978 :               nr--;
     109             : 
     110        2978 :               LOCK (ctx->lock);
     111        2978 :               if (ctx->canceled)
     112           0 :                 err = gpg_error (GPG_ERR_CANCELED);
     113        2978 :               UNLOCK (ctx->lock);
     114             : 
     115        2978 :               if (!err)
     116        2978 :                 err = _gpgme_run_io_cb (&ctx->fdt.fds[i], 0, &op_err);
     117        2975 :               if (err)
     118             :                 {
     119             :                   /* An error occurred.  Close all fds in this context,
     120             :                      and signal it.  */
     121          11 :                   _gpgme_cancel_with_err (ctx, err, 0);
     122             : 
     123          23 :                   return err;
     124             :                 }
     125        2964 :               else if (op_err)
     126             :                 {
     127             :                   /* An operational error occurred.  Cancel the current
     128             :                      operation but not the session, and signal it.  */
     129           1 :                   _gpgme_cancel_with_err (ctx, 0, op_err);
     130             : 
     131             :                   /* NOTE: This relies on the operational error being
     132             :                      generated after the operation really has
     133             :                      completed, for example after no further status
     134             :                      line output is generated.  Otherwise the
     135             :                      following I/O will spill over into the next
     136             :                      operation.  */
     137           1 :                   if (op_err_p)
     138           1 :                     *op_err_p = op_err;
     139           1 :                   return 0;
     140             :                 }
     141             :             }
     142             :         }
     143             : 
     144        6465 :       for (i = 0; i < ctx->fdt.size; i++)
     145        6099 :         if (ctx->fdt.fds[i].fd != -1)
     146        2398 :           break;
     147        2764 :       if (i == ctx->fdt.size)
     148             :         {
     149             :           struct gpgme_io_event_done_data data;
     150         366 :           data.err = 0;
     151         366 :           data.op_err = 0;
     152         366 :           _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_DONE, &data);
     153         366 :           hang = 0;
     154             :         }
     155        2764 :       if (cond && *cond)
     156         132 :         hang = 0;
     157             :     }
     158        2764 :   while (hang);
     159             : 
     160         401 :   return 0;
     161             : }
     162             : 
     163             : 
     164             : /* Wait until the blocking operation in context CTX has finished and
     165             :    return the error value.  This variant can not be used for
     166             :    session-based protocols.  */
     167             : gpgme_error_t
     168         177 : _gpgme_wait_one (gpgme_ctx_t ctx)
     169             : {
     170         177 :   return _gpgme_wait_on_condition (ctx, NULL, NULL);
     171             : }
     172             : 
     173             : /* Wait until the blocking operation in context CTX has finished and
     174             :    return the error value.  This is the right variant to use for
     175             :    sesion-based protocols.  */
     176             : gpgme_error_t
     177           8 : _gpgme_wait_one_ext (gpgme_ctx_t ctx, gpgme_error_t *op_err)
     178             : {
     179           8 :   return _gpgme_wait_on_condition (ctx, NULL, op_err);
     180             : }

Generated by: LCOV version 1.11