Exemplo n.º 1
0
/* Export the keys listed in PATTERN into KEYDATA.  */
gpgme_error_t
gpgme_op_export_ext (gpgme_ctx_t ctx, const char *pattern[],
		     gpgme_export_mode_t mode, gpgme_data_t keydata)
{
  gpgme_error_t err;

  TRACE_BEG2 (DEBUG_CTX, "gpgme_op_export_ext_start", ctx,
	      "mode=0x%x, keydata=%p", mode, keydata);

  if (_gpgme_debug_trace () && pattern)
    {
      int i = 0;

      while (pattern[i])
	{
	  TRACE_LOG2 ("pattern[%i] = %s", i, pattern[i]);
	  i++;
	}
    }

  err = export_ext_start (ctx, 1, pattern, mode, keydata);
  if (!err)
    err = _gpgme_wait_one (ctx);
  return TRACE_ERR (err);
}
Exemplo n.º 2
0
int
_gpgme_io_set_close_notify (int fd, _gpgme_close_notify_handler_t handler,
			    void *value)
{
  int i;
  TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_set_close_notify", fd,
	      "close_handler=%p/%p", handler, value);

  assert (fd != -1);

  LOCK (notify_table_lock);
  for (i=0; i < DIM (notify_table); i++)
    if (notify_table[i].inuse && notify_table[i].fd == fd)
      break;
  if (i == DIM (notify_table))
    for (i = 0; i < DIM (notify_table); i++)
      if (!notify_table[i].inuse)
	break;
  if (i == DIM (notify_table))
    {
      UNLOCK (notify_table_lock);
      errno = EINVAL;
      return TRACE_SYSRES (-1);
    }
  notify_table[i].fd = fd;
  notify_table[i].handler = handler;
  notify_table[i].value = value;
  notify_table[i].inuse = 1;
  UNLOCK (notify_table_lock);
  return TRACE_SYSRES (0);
}
Exemplo n.º 3
0
int
_gpgme_io_socket (int domain, int type, int proto)
{
  int res;
  int fd;

  TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_socket", domain,
	      "type=%i, protp=%i", type, proto);

  res = socket (domain, type, proto);
  if (res == INVALID_SOCKET)
    {
      errno = wsa2errno (WSAGetLastError ());
      return TRACE_SYSRES (-1);
    }

  fd = new_channel_from_socket (res);
  if (fd < 0)
    {
      int saved_errno = errno;
      closesocket (res);
      errno = saved_errno;
      return TRACE_SYSRES (-1);
    }

  TRACE_SUC2 ("fd=%i, socket=0x%x", fd, res);
  
  return fd;
}
Exemplo n.º 4
0
gpgme_error_t
gpgme_op_export_keys (gpgme_ctx_t ctx,
                      gpgme_key_t keys[],
                      gpgme_export_mode_t mode,
                      gpgme_data_t keydata)
{
  gpgme_error_t err;

  TRACE_BEG2 (DEBUG_CTX, "gpgme_op_export_keys", ctx,
	      "mode=0x%x, keydata=%p", mode, keydata);
  
  if (_gpgme_debug_trace () && keys)
    {
      int i = 0;

      while (keys[i])
	{
	  TRACE_LOG3 ("keys[%i] = %p (%s)", i, keys[i],
		      (keys[i]->subkeys && keys[i]->subkeys->fpr) ? 
		      keys[i]->subkeys->fpr : "invalid");
	  i++;
	}
    }

  err = export_keys_start (ctx, 1, keys, mode, keydata);
  if (!err)
    err = _gpgme_wait_one (ctx);
  return TRACE_ERR (err);
}
Exemplo n.º 5
0
gpgme_error_t
gpgme_op_trustlist_start (gpgme_ctx_t ctx, const char *pattern, int max_level)
{
  gpgme_error_t err = 0;
  void *hook;
  op_data_t opd;

  TRACE_BEG2 (DEBUG_CTX, "gpgme_op_trustlist_start", ctx,
	      "pattern=%s, max_level=%i", pattern, max_level);

  if (!pattern || !*pattern)
    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));

  err = _gpgme_op_reset (ctx, 2);
  if (err)
    return TRACE_ERR (err);

  err = _gpgme_op_data_lookup (ctx, OPDATA_TRUSTLIST, &hook,
			       sizeof (*opd), NULL);
  opd = hook;
  if (err)
    return TRACE_ERR (err);

  _gpgme_engine_set_status_handler (ctx->engine,
				    trustlist_status_handler, ctx);
  err = _gpgme_engine_set_colon_line_handler (ctx->engine,
					      trustlist_colon_handler, ctx);
  if (err)
    return TRACE_ERR (err);

  err = _gpgme_engine_op_trustlist (ctx->engine, pattern);
  return TRACE_ERR (err);
}
Exemplo n.º 6
0
gpgme_error_t
gpgme_set_protocol (gpgme_ctx_t ctx, gpgme_protocol_t protocol)
{
  TRACE_BEG2 (DEBUG_CTX, "gpgme_set_protocol", ctx, "protocol=%i (%s)",
	      protocol, gpgme_get_protocol_name (protocol)
	      ? gpgme_get_protocol_name (protocol) : "invalid");

  if (protocol != GPGME_PROTOCOL_OpenPGP
      && protocol != GPGME_PROTOCOL_CMS
      && protocol != GPGME_PROTOCOL_GPGCONF
      && protocol != GPGME_PROTOCOL_ASSUAN
      && protocol != GPGME_PROTOCOL_G13
      && protocol != GPGME_PROTOCOL_UISERVER
      && protocol != GPGME_PROTOCOL_SPAWN)
    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));

  if (!ctx)
    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));

  if (ctx->protocol != protocol)
    {
      /* Shut down the engine when switching protocols.  */
      if (ctx->engine)
	{
	  TRACE_LOG1 ("releasing ctx->engine=%p", ctx->engine);
	  _gpgme_engine_release (ctx->engine);
	  ctx->engine = NULL;
	}

      ctx->protocol = protocol;
    }
  return TRACE_ERR (0);
}
Exemplo n.º 7
0
gpgme_error_t
_gpgme_cancel_with_err (gpgme_ctx_t ctx, gpg_error_t ctx_err,
			gpg_error_t op_err)
{
  gpgme_error_t err;
  struct gpgme_io_event_done_data data;

  TRACE_BEG2 (DEBUG_CTX, "_gpgme_cancel_with_err", ctx, "ctx_err=%i, op_err=%i",
	      ctx_err, op_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);
}
Exemplo n.º 8
0
/* Set the current position from where the next read or write starts
   in the data object with the handle DH to OFFSET, relativ to
   WHENCE.  */
gpgme_off_t
gpgme_data_seek (gpgme_data_t dh, gpgme_off_t offset, int whence)
{
  TRACE_BEG2 (DEBUG_DATA, "gpgme_data_seek", dh,
	      "offset=%lli, whence=%i", offset, whence);

  if (!dh)
    {
      gpg_err_set_errno (EINVAL);
      return TRACE_SYSRES (-1);
    }
  if (!dh->cbs->seek)
    {
      gpg_err_set_errno (ENOSYS);
      return TRACE_SYSRES (-1);
    }

  /* For relative movement, we must take into account the actual
     position of the read counter.  */
  if (whence == SEEK_CUR)
    offset -= dh->pending_len;

  offset = (*dh->cbs->seek) (dh, offset, whence);
  if (offset >= 0)
    dh->pending_len = 0;

  return TRACE_SYSRES (offset);
}
Exemplo n.º 9
0
/* Add KEY to list of signers in CTX.  */
gpgme_error_t
gpgme_signers_add (gpgme_ctx_t ctx, const gpgme_key_t key)
{
  TRACE_BEG2 (DEBUG_CTX, "gpgme_signers_add", ctx,
	      "key=%p (%s)", key, (key->subkeys && key->subkeys->fpr) ?
	      key->subkeys->fpr : "invalid");

  if (!ctx || !key)
    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));

  if (ctx->signers_len == ctx->signers_size)
    {
      gpgme_key_t *newarr;
      int n = ctx->signers_size + 5;
      int j;

      newarr = realloc (ctx->signers, n * sizeof (*newarr));
      if (!newarr)
	return TRACE_ERR (gpg_error_from_errno (errno));
      for (j = ctx->signers_size; j < n; j++)
	newarr[j] = NULL;
      ctx->signers = newarr;
      ctx->signers_size = n;
    }

  gpgme_key_ref (key);
  ctx->signers[ctx->signers_len++] = key;
  return TRACE_SUC ();
}
Exemplo n.º 10
0
gpgme_error_t
gpgme_op_decrypt_start (gpgme_ctx_t ctx, gpgme_data_t cipher,
			gpgme_data_t plain)
{
  gpgme_error_t err;

  TRACE_BEG2 (DEBUG_CTX, "gpgme_op_decrypt_start", ctx,
	      "cipher=%p, plain=%p", cipher, plain);
  err = decrypt_start (ctx, 0, cipher, plain);
  return TRACE_ERR (err);
}
Exemplo n.º 11
0
/* This function provides access to the internal write function.  It
   is to be used by user callbacks to return data to gpgme.  See
   gpgme_passphrase_cb_t and gpgme_edit_cb_t.  */
gpgme_ssize_t
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 TRACE_SYSRES (ret);
}
Exemplo n.º 12
0
static ssize_t
old_user_read (gpgme_data_t dh, void *buffer, size_t size)
{
  gpgme_error_t err;
  size_t amt;
  TRACE_BEG2 (DEBUG_DATA, "gpgme:old_user_read", dh,
	      "buffer=%p, size=%u", buffer, size);

  err = (*dh->data.old_user.cb) (dh->data.old_user.handle,
				 buffer, size, &amt);
  if (err)
    return TRACE_SYSRES (gpgme_error_to_errno (err));
  return TRACE_SYSRES (amt);
}
Exemplo n.º 13
0
int
_gpgme_io_read (int fd, void *buffer, size_t count)
{
  int saved_errno = 0;
  gsize nread;
  GIOChannel *chan;
  GIOStatus status;
  TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_read", fd,
	      "buffer=%p, count=%u", buffer, count);

  chan = find_channel (fd);
  if (!chan)
    {
      TRACE_LOG ("no channel registered");
      errno = EINVAL;
      return TRACE_SYSRES (-1);
    }
  TRACE_LOG1 ("channel %p", chan);

  {
    GError *err = NULL;
    status = g_io_channel_read_chars (chan, (gchar *) buffer,
				      count, &nread, &err);
    if (err)
      {
	TRACE_LOG2 ("status %i, err %s", status, err->message);
	g_error_free (err);
      }
  }

  if (status == G_IO_STATUS_EOF)
    nread = 0;
  else if (status == G_IO_STATUS_AGAIN)
    {
      nread = -1;
      saved_errno = EAGAIN;
    }
  else if (status != G_IO_STATUS_NORMAL)
    {
      TRACE_LOG1 ("status %d", status);
      nread = -1;
      saved_errno = EIO;
    }
  
  if (nread != 0 && nread != -1)
    TRACE_LOGBUF (buffer, nread);

  errno = saved_errno;
  return TRACE_SYSRES (nread);
}
Exemplo n.º 14
0
/* Decrypt ciphertext CIPHER within CTX and store the resulting
   plaintext in PLAIN.  */
gpgme_error_t
gpgme_op_decrypt (gpgme_ctx_t ctx, gpgme_data_t cipher, gpgme_data_t plain)
{
  gpgme_error_t err;

  TRACE_BEG2 (DEBUG_CTX, "gpgme_op_decrypt", ctx,
	      "cipher=%p, plain=%p", cipher, plain);

  if (!ctx)
    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));

  err = decrypt_start (ctx, 1, cipher, plain);
  if (!err)
    err = _gpgme_wait_one (ctx);
  return TRACE_ERR (err);
}
Exemplo n.º 15
0
Arquivo: spawn.c Projeto: gpg/gpgme
/* Run the command FILE with the arguments in ARGV.  Connect stdin to
   DATAIN, stdout to DATAOUT, and STDERR to DATAERR.  If one the data
   streams is NULL, connect to /dev/null instead.  */
gpgme_error_t
gpgme_op_spawn_start (gpgme_ctx_t ctx, const char *file, const char *argv[],
                      gpgme_data_t datain,
                      gpgme_data_t dataout, gpgme_data_t dataerr,
                      unsigned int flags)
{
  gpgme_error_t err;

  TRACE_BEG2 (DEBUG_CTX, "gpgme_op_spawn_start", ctx, "file=(%s) flaggs=%x",
              file, flags);

  if (!ctx)
    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));

  err = spawn_start (ctx, 0, file, argv, datain, dataout, dataerr, flags);
  return err;
}
Exemplo n.º 16
0
int
_gpgme_io_connect (int fd, struct sockaddr *addr, int addrlen)
{
  int res;

  TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_connect", fd,
	      "addr=%p, addrlen=%i", addr, addrlen);

  res = connect (fd, addr, addrlen);
  if (!res)
    {
      errno = wsa2errno (WSAGetLastError ());
      return TRACE_SYSRES (-1);
    }

  return TRACE_SUC ();
}
Exemplo n.º 17
0
static gpgme_error_t
add_io_cb (engine_gpgsm_t gpgsm, iocb_data_t *iocbd, gpgme_io_cb_t handler)
{
  gpgme_error_t err;

  TRACE_BEG2 (DEBUG_ENGINE, "engine-gpgsm:add_io_cb", gpgsm,
              "fd %d, dir %d", iocbd->fd, iocbd->dir);
  err = (*gpgsm->io_cbs.add) (gpgsm->io_cbs.add_priv,
			      iocbd->fd, iocbd->dir,
			      handler, iocbd->data, &iocbd->tag);
  if (err)
    return TRACE_ERR (err);
  if (!iocbd->dir)
    /* FIXME Kludge around poll() problem.  */
    err = _gpgme_io_set_nonblocking (iocbd->fd);
  return TRACE_ERR (err);
}
Exemplo n.º 18
0
static off_t
old_user_seek (gpgme_data_t dh, off_t offset, int whence)
{
  gpgme_error_t err;
  TRACE_BEG2 (DEBUG_DATA, "gpgme:old_user_seek", dh,
	      "offset=%llu, whence=%i", offset, whence);

  if (whence != SEEK_SET || offset)
    {
      errno = EINVAL;
      return TRACE_SYSRES (-1);
    }
  err = (*dh->data.old_user.cb) (dh->data.old_user.handle, NULL, 0, NULL);
  if (err)
    return TRACE_SYSRES (gpgme_error_to_errno (err));
  return TRACE_SYSRES (0);
}
Exemplo n.º 19
0
/* This function provides access to the internal write function.  It
   is to be used by user callbacks to return data to gpgme.  See
   gpgme_passphrase_cb_t and gpgme_edit_cb_t.  Note that this is a
   variant of gpgme_io_write which guarantees that all COUNT bytes are
   written or an error is return.  Returns: 0 on success or -1 on
   error and the sets errno. */
int
gpgme_io_writen (int fd, const void *buffer_arg, size_t count)
{
  const char *buffer = buffer_arg;
  int ret = 0;
  TRACE_BEG2 (DEBUG_GLOBAL, "gpgme_io_writen", fd,
	      "buffer=%p, count=%u", buffer, count);
  while (count)
    {
      ret = _gpgme_io_write (fd, buffer, count);
      if (ret < 0)
        break;
      buffer += ret;
      count -= ret;
      ret = 0;
    }
  return TRACE_SYSRES (ret);
}
Exemplo n.º 20
0
/* Create a new data buffer which retrieves the data from the callback
   function READ_CB.  */
gpgme_error_t
gpgme_data_new_with_read_cb (gpgme_data_t *r_dh,
                             int (*read_cb) (void *, char *, size_t, size_t *),
                             void *read_cb_value)
{
  gpgme_error_t err;
  TRACE_BEG2 (DEBUG_DATA, "gpgme_data_new_with_read_cb", r_dh,
	      "read_cb=%p/%p", read_cb, read_cb_value);

  err = _gpgme_data_new (r_dh, &old_user_cbs);

  if (err)
    return TRACE_ERR (err);

  (*r_dh)->data.old_user.cb = read_cb;
  (*r_dh)->data.old_user.handle = read_cb_value;
  return TRACE_ERR (0);
}
Exemplo n.º 21
0
int
_gpgme_io_set_close_notify (int fd, _gpgme_close_notify_handler_t handler,
			    void *value)
{
  TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_set_close_notify", fd,
	      "close_handler=%p/%p", handler, value);

  assert (fd != -1);

  if (fd < 0 || fd >= (int) DIM (notify_table))
    {
      errno = EINVAL;
      return TRACE_SYSRES (-1);
    }
  notify_table[fd].handler = handler;
  notify_table[fd].value = value;
  return TRACE_SYSRES (0);
}
Exemplo n.º 22
0
int
_gpgme_io_socket (int domain, int type, int proto)
{
  int res;

  TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_socket", domain,
	      "type=%i, protp=%i", type, proto);

  res = socket (domain, type, proto);
  if (res == INVALID_SOCKET)
    {
      errno = wsa2errno (WSAGetLastError ());
      return TRACE_SYSRES (-1);
    }

  TRACE_SUC1 ("socket=0x%x", res);
  
  return res;
}
Exemplo n.º 23
0
int
_gpgme_io_write (int fd, const void *buffer, size_t count)
{
  int saved_errno = 0;
  gsize nwritten;
  GIOChannel *chan;
  GIOStatus status;
  GError *err = NULL;

  TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_write", fd,
	      "buffer=%p, count=%u", buffer, count);
  TRACE_LOGBUF (buffer, count);

  chan = find_channel (fd);
  if (!chan)
    {
      TRACE_LOG ("fd %d: no channel registered");
      errno = EINVAL;
      return -1;
    }

  status = g_io_channel_write_chars (chan, (gchar *) buffer, count,
				     &nwritten, &err);
  if (err)
    {
      TRACE_LOG1 ("write error: %s", err->message);
      g_error_free (err);
    }

  if (status == G_IO_STATUS_AGAIN)
    {
      nwritten = -1;
      saved_errno = EAGAIN;
    }
  else if (status != G_IO_STATUS_NORMAL)
    {
      nwritten = -1;
      saved_errno = EIO;
    }
  errno = saved_errno;

  return TRACE_SYSRES (nwritten);
}
Exemplo n.º 24
0
/* Read up to SIZE bytes into buffer BUFFER from the data object with
   the handle DH.  Return the number of characters read, 0 on EOF and
   -1 on error.  If an error occurs, errno is set.  */
gpgme_ssize_t
gpgme_data_read (gpgme_data_t dh, void *buffer, size_t size)
{
  gpgme_ssize_t res;
  TRACE_BEG2 (DEBUG_DATA, "gpgme_data_read", dh,
	      "buffer=%p, size=%u", buffer, size);

  if (!dh)
    {
      gpg_err_set_errno (EINVAL);
      return TRACE_SYSRES (-1);
    }
  if (!dh->cbs->read)
    {
      gpg_err_set_errno (ENOSYS);
      return TRACE_SYSRES (-1);
    }
  do
    res = (*dh->cbs->read) (dh, buffer, size);
  while (res < 0 && errno == EINTR);

  return TRACE_SYSRES (res);
}
Exemplo n.º 25
0
int
_gpgme_io_read (int fd, void *buffer, size_t count)
{
  int nread;
  struct reader_context_s *ctx;
  TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_read", fd,
	      "buffer=%p, count=%u", buffer, count);
  
  ctx = find_reader (fd, 1);
  if (!ctx)
    {
      errno = EBADF;
      return TRACE_SYSRES (-1);
    }
  if (ctx->eof_shortcut)
    return TRACE_SYSRES (0);

  LOCK (ctx->mutex);
  if (ctx->readpos == ctx->writepos && !ctx->error)
    {
      /* No data available.  */
      UNLOCK (ctx->mutex);
      TRACE_LOG1 ("waiting for data from thread %p", ctx->thread_hd);
      WaitForSingleObject (ctx->have_data_ev, INFINITE);
      TRACE_LOG1 ("data from thread %p available", ctx->thread_hd);
      LOCK (ctx->mutex);
    }
  
  if (ctx->readpos == ctx->writepos || ctx->error)
    {
      UNLOCK (ctx->mutex);
      ctx->eof_shortcut = 1;
      if (ctx->eof)
	return TRACE_SYSRES (0);
      if (!ctx->error)
	{
	  TRACE_LOG ("EOF but ctx->eof flag not set");
	  return 0;
	}
      errno = ctx->error_code;
      return TRACE_SYSRES (-1);
    }
  
  nread = ctx->readpos < ctx->writepos
    ? ctx->writepos - ctx->readpos
    : READBUF_SIZE - ctx->readpos;
  if (nread > count)
    nread = count;
  memcpy (buffer, ctx->buffer + ctx->readpos, nread);
  ctx->readpos = (ctx->readpos + nread) % READBUF_SIZE;
  if (ctx->readpos == ctx->writepos && !ctx->eof)
    {
      if (!ResetEvent (ctx->have_data_ev))
	{
	  TRACE_LOG1 ("ResetEvent failed: ec=%d", (int) GetLastError ());
	  UNLOCK (ctx->mutex);
	  /* FIXME: Should translate the error code.  */
	  errno = EIO;
	  return TRACE_SYSRES (-1);
	}
    }
  if (!SetEvent (ctx->have_space_ev))
    {
      TRACE_LOG2 ("SetEvent (0x%x) failed: ec=%d",
		  ctx->have_space_ev, (int) GetLastError ());
      UNLOCK (ctx->mutex);
      /* FIXME: Should translate the error code.  */
      errno = EIO;
      return TRACE_SYSRES (-1);
    }
  UNLOCK (ctx->mutex);
  
  TRACE_LOGBUF (buffer, nread);
  return TRACE_SYSRES (nread);
}
Exemplo n.º 26
0
int
_gpgme_io_write (int fd, const void *buffer, size_t count)
{
  struct writer_context_s *ctx;
  TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_write", fd,
	      "buffer=%p, count=%u", buffer, count);
  TRACE_LOGBUF (buffer, count);

  if (count == 0)
    return TRACE_SYSRES (0);

  ctx = find_writer (fd, 0);
  if (!ctx)
    return TRACE_SYSRES (-1);

  LOCK (ctx->mutex);
  if (!ctx->error && ctx->nbytes)
    {
      /* Bytes are pending for send.  */

      /* Reset the is_empty event.  Better safe than sorry.  */
      if (!ResetEvent (ctx->is_empty))
	{
	  TRACE_LOG1 ("ResetEvent failed: ec=%d", (int) GetLastError ());
	  UNLOCK (ctx->mutex);
	  /* FIXME: Should translate the error code.  */
	  errno = EIO;
	  return TRACE_SYSRES (-1);
	}
      UNLOCK (ctx->mutex);
      TRACE_LOG1 ("waiting for empty buffer in thread %p", ctx->thread_hd);
      WaitForSingleObject (ctx->is_empty, INFINITE);
      TRACE_LOG1 ("thread %p buffer is empty", ctx->thread_hd);
      LOCK (ctx->mutex);
    }

  if (ctx->error)
    {
      UNLOCK (ctx->mutex);
      if (ctx->error_code == ERROR_NO_DATA)
        errno = EPIPE;
      else
        errno = EIO;
      return TRACE_SYSRES (-1);
    }

  /* If no error occured, the number of bytes in the buffer must be
     zero.  */
  assert (!ctx->nbytes);

  if (count > WRITEBUF_SIZE)
    count = WRITEBUF_SIZE;
  memcpy (ctx->buffer, buffer, count);
  ctx->nbytes = count;

  /* We have to reset the is_empty event early, because it is also
     used by the select() implementation to probe the channel.  */
  if (!ResetEvent (ctx->is_empty))
    {
      TRACE_LOG1 ("ResetEvent failed: ec=%d", (int) GetLastError ());
      UNLOCK (ctx->mutex);
      /* FIXME: Should translate the error code.  */
      errno = EIO;
      return TRACE_SYSRES (-1);
    }
  if (!SetEvent (ctx->have_data))
    {
      TRACE_LOG1 ("SetEvent failed: ec=%d", (int) GetLastError ());
      UNLOCK (ctx->mutex);
      /* FIXME: Should translate the error code.  */
      errno = EIO;
      return TRACE_SYSRES (-1);
    }
  UNLOCK (ctx->mutex);

  return TRACE_SYSRES ((int) count);
}
Exemplo n.º 27
0
/* Select on the list of fds.  Returns: -1 = error, 0 = timeout or
   nothing to select, > 0 = number of signaled fds.  */
int
_gpgme_io_select (struct io_select_fd_s *fds, size_t nfds, int nonblock)
{
  int npollfds;
  GPollFD *pollfds;
  int *pollfds_map; 
  int i;
  int j;
  int any;
  int n;
  int count;
  /* Use a 1s timeout.  */
  int timeout = 1000;
  void *dbg_help = NULL;
  TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_select", fds,
	      "nfds=%u, nonblock=%u", nfds, nonblock);

  if (nonblock)
    timeout = 0;

  pollfds = calloc (nfds, sizeof *pollfds);
  if (!pollfds)
    return -1;
  pollfds_map = calloc (nfds, sizeof *pollfds_map);
  if (!pollfds_map)
    {
      free (pollfds);
      return -1;
    }
  npollfds = 0;

  TRACE_SEQ (dbg_help, "select on [ ");
  any = 0;
  for (i = 0; i < nfds; i++)
    {
      GIOChannel *chan = NULL;

      if (fds[i].fd == -1) 
	continue;

      if ((fds[i].for_read || fds[i].for_write)
          && !(chan = find_channel (fds[i].fd)))
        {
          TRACE_ADD1 (dbg_help, "[BAD0x%x ", fds[i].fd);
          TRACE_END (dbg_help, "]"); 
          assert (!"see log file");
        }
      else if (fds[i].for_read )
	{
          assert(chan);
          g_io_channel_win32_make_pollfd (chan, G_IO_IN, pollfds + npollfds);
          pollfds_map[npollfds] = i;
	  TRACE_ADD2 (dbg_help, "r0x%x<%d> ", fds[i].fd, pollfds[npollfds].fd);
          npollfds++;
	  any = 1;
        }
      else if (fds[i].for_write)
	{
          assert(chan);
          g_io_channel_win32_make_pollfd (chan, G_IO_OUT, pollfds + npollfds);
          pollfds_map[npollfds] = i;
	  TRACE_ADD2 (dbg_help, "w0x%x<%d> ", fds[i].fd, pollfds[npollfds].fd);
          npollfds++;
	  any = 1;
        }
      fds[i].signaled = 0;
    }
  TRACE_END (dbg_help, "]"); 
  if (!any)
    {
      count = 0;
      goto leave;
    }


  count = g_io_channel_win32_poll (pollfds, npollfds, timeout);
  if (count < 0)
    {
      int saved_errno = errno;
      errno = saved_errno;
      goto leave;
    }

  TRACE_SEQ (dbg_help, "select OK [ ");
  if (TRACE_ENABLED (dbg_help))
    {
      for (i = 0; i < npollfds; i++)
	{
	  if ((pollfds[i].revents & G_IO_IN))
	    TRACE_ADD1 (dbg_help, "r0x%x ", fds[pollfds_map[i]].fd);
          if ((pollfds[i].revents & G_IO_OUT))
            TRACE_ADD1 (dbg_help, "w0x%x ", fds[pollfds_map[i]].fd);
        }
      TRACE_END (dbg_help, "]");
    }
    
  /* COUNT is used to stop the lop as soon as possible.  */
  for (n = count, i = 0; i < npollfds && n; i++)
    {
      j = pollfds_map[i];
      assert (j >= 0 && j < nfds);
      if (fds[j].fd == -1)
	;
      else if (fds[j].for_read)
	{
	  if ((pollfds[i].revents & G_IO_IN))
	    {
	      fds[j].signaled = 1;
	      n--;
            }
        }
      else if (fds[j].for_write)
	{
	  if ((pollfds[i].revents & G_IO_OUT))
	    {
	      fds[j].signaled = 1;
	      n--;
            }
        }
    }

leave:
  free (pollfds);
  free (pollfds_map);
  return TRACE_SYSRES (count);
}
Exemplo n.º 28
0
int
_gpgme_io_pipe (int filedes[2], int inherit_idx)
{
  int fds[2];

  TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_pipe", filedes,
	      "inherit_idx=%i (GPGME uses it for %s)",
	      inherit_idx, inherit_idx ? "reading" : "writing");

#define PIPEBUF_SIZE  4096
  if (_pipe (fds, PIPEBUF_SIZE, O_NOINHERIT | O_BINARY) == -1)
    return TRACE_SYSRES (-1);

  /* Make one end inheritable. */
  if (inherit_idx == 0)
    {
      int new_read;

      new_read = _dup (fds[0]);
      _close (fds[0]);
      fds[0] = new_read;

      if (new_read < 0)
	{
	  _close (fds[1]);
	  return TRACE_SYSRES (-1);
	}
    }
  else if (inherit_idx == 1)
    {
      int new_write;

      new_write = _dup (fds[1]);
      _close (fds[1]);
      fds[1] = new_write;

      if (new_write < 0)
	{
	  _close (fds[0]);
	  return TRACE_SYSRES (-1);
	}
    }

  /* For _gpgme_io_close.  */
  filedes[inherit_idx] = new_dummy_channel_from_fd (fds[inherit_idx]);
  if (filedes[inherit_idx] < 0)
    {
      int saved_errno = errno;
      
      _close (fds[0]);
      _close (fds[1]);
      errno = saved_errno;
      return TRACE_SYSRES (-1);
    }

  /* Now we have a pipe with the correct end inheritable.  The other end
     should have a giochannel.  */
  filedes[1 - inherit_idx] = new_channel_from_fd (fds[1 - inherit_idx]);
  if (filedes[1 - inherit_idx] < 0)
    {
      int saved_errno = errno;
      
      _gpgme_io_close (fds[inherit_idx]);
      _close (fds[1 - inherit_idx]);
      errno = saved_errno;
      return TRACE_SYSRES (-1);
    }
  
  return TRACE_SUC5 ("read=0x%x/%p, write=0x%x/%p, channel=%p",
		     filedes[0],
		     (HANDLE) _get_osfhandle (giochannel_table[filedes[0]].fd),
		     filedes[1],
		     (HANDLE) _get_osfhandle (giochannel_table[filedes[1]].fd),
		     giochannel_table[1 - inherit_idx].chan);
}
Exemplo n.º 29
0
int
_gpgme_io_pipe (int filedes[2], int inherit_idx)
{
  HANDLE rh;
  HANDLE wh;
  SECURITY_ATTRIBUTES sec_attr;
  TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_pipe", filedes,
	      "inherit_idx=%i (GPGME uses it for %s)",
	      inherit_idx, inherit_idx ? "reading" : "writing");

  memset (&sec_attr, 0, sizeof (sec_attr));
  sec_attr.nLength = sizeof (sec_attr);
  sec_attr.bInheritHandle = FALSE;
  
  if (!CreatePipe (&rh, &wh, &sec_attr, PIPEBUF_SIZE))
    {
      TRACE_LOG1 ("CreatePipe failed: ec=%d", (int) GetLastError ());
      /* FIXME: Should translate the error code.  */
      errno = EIO;
      return TRACE_SYSRES (-1);
    }

  /* Make one end inheritable.  */
  if (inherit_idx == 0)
    {
      struct writer_context_s *ctx;
      HANDLE hd;
      if (!DuplicateHandle (GetCurrentProcess(), rh,
			    GetCurrentProcess(), &hd, 0,
			    TRUE, DUPLICATE_SAME_ACCESS))
	{
	  TRACE_LOG1 ("DuplicateHandle failed: ec=%d",
		      (int) GetLastError ());
	  CloseHandle (rh);
	  CloseHandle (wh);
	  /* FIXME: Should translate the error code.  */
	  errno = EIO;
	  return TRACE_SYSRES (-1);
        }
      CloseHandle (rh);
      rh = hd;

      ctx = find_writer (handle_to_fd (wh), 0);
      assert (ctx == NULL);
      ctx = find_writer (handle_to_fd (wh), 1);
      if (!ctx)
	{
	  CloseHandle (rh);
	  CloseHandle (wh);
	  /* FIXME: Should translate the error code.  */
	  errno = EIO;
	  return TRACE_SYSRES (-1);
	}
    }
  else if (inherit_idx == 1)
    {
      struct reader_context_s *ctx;
      HANDLE hd;
      if (!DuplicateHandle( GetCurrentProcess(), wh,
			    GetCurrentProcess(), &hd, 0,
			    TRUE, DUPLICATE_SAME_ACCESS))
	{
	  TRACE_LOG1 ("DuplicateHandle failed: ec=%d",
		      (int) GetLastError ());
	  CloseHandle (rh);
	  CloseHandle (wh);
	  /* FIXME: Should translate the error code.  */
	  errno = EIO;
	  return TRACE_SYSRES (-1);
        }
      CloseHandle (wh);
      wh = hd;

      ctx = find_reader (handle_to_fd (rh), 0);
      assert (ctx == NULL);
      ctx = find_reader (handle_to_fd (rh), 1);
      if (!ctx)
	{
	  CloseHandle (rh);
	  CloseHandle (wh);
	  /* FIXME: Should translate the error code.  */
	  errno = EIO;
	  return TRACE_SYSRES (-1);
	}
    }
  
  filedes[0] = handle_to_fd (rh);
  filedes[1] = handle_to_fd (wh);
  return TRACE_SUC2 ("read=%p, write=%p", rh, wh);
}
Exemplo n.º 30
0
int
_gpgme_io_connect (int fd, struct sockaddr *addr, int addrlen)
{
  GIOChannel *chan; 
  int sockfd;
  int res;
  GIOFlags flags;
  GIOStatus status;
  GError *err = NULL;

  TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_connect", fd,
	      "addr=%p, addrlen=%i", addr, addrlen);

  chan = find_channel (fd);
  if (! chan)
    {
      errno = EINVAL;
      return TRACE_SYSRES (-1);
    }

  flags = g_io_channel_get_flags (chan);
  if (flags & G_IO_FLAG_NONBLOCK)
    {
      status = g_io_channel_set_flags (chan, flags & ~G_IO_FLAG_NONBLOCK, &err);
      if (err)
	{
	  TRACE_LOG1 ("setting flags error: %s", err->message);
	  g_error_free (err);
	  err = NULL;
	}
      if (status != G_IO_STATUS_NORMAL)
	{
	  errno = EIO;
	  return TRACE_SYSRES (-1);
	}
    }

  sockfd = giochannel_table[fd].socket;
  if (sockfd == INVALID_SOCKET)
    {
      errno = EINVAL;
      return TRACE_SYSRES (-1);
    }

  TRACE_LOG1 ("connect sockfd=0x%x", sockfd);
  res = connect (sockfd, addr, addrlen);

  /* FIXME: Error ignored here.  */
  if (! (flags & G_IO_FLAG_NONBLOCK))
    g_io_channel_set_flags (chan, flags, NULL);

  if (res)
    {
      TRACE_LOG2 ("connect failed: %i %i", res, WSAGetLastError ());

      errno = wsa2errno (WSAGetLastError ());
      return TRACE_SYSRES (-1);
    }

  return TRACE_SUC ();
}