Blame src/gpgme.c

Packit d7e8d0
/* gpgme.c - GnuPG Made Easy.
Packit d7e8d0
   Copyright (C) 2000 Werner Koch (dd9jn)
Packit d7e8d0
   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2012,
Packit d7e8d0
                 2014, 2015 g10 Code GmbH
Packit d7e8d0
Packit d7e8d0
   This file is part of GPGME.
Packit d7e8d0
Packit d7e8d0
   GPGME is free software; you can redistribute it and/or modify it
Packit d7e8d0
   under the terms of the GNU Lesser General Public License as
Packit d7e8d0
   published by the Free Software Foundation; either version 2.1 of
Packit d7e8d0
   the License, or (at your option) any later version.
Packit d7e8d0
Packit d7e8d0
   GPGME is distributed in the hope that it will be useful, but
Packit d7e8d0
   WITHOUT ANY WARRANTY; without even the implied warranty of
Packit d7e8d0
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit d7e8d0
   Lesser General Public License for more details.
Packit d7e8d0
Packit d7e8d0
   You should have received a copy of the GNU Lesser General Public
Packit d7e8d0
   License along with this program; if not, see <https://www.gnu.org/licenses/>.
Packit d7e8d0
 */
Packit d7e8d0
Packit d7e8d0
#if HAVE_CONFIG_H
Packit d7e8d0
#include <config.h>
Packit d7e8d0
#endif
Packit d7e8d0
#include <stdio.h>
Packit d7e8d0
#include <stdlib.h>
Packit d7e8d0
#include <string.h>
Packit d7e8d0
#include <assert.h>
Packit d7e8d0
#include <errno.h>
Packit d7e8d0
#ifdef HAVE_LOCALE_H
Packit d7e8d0
#include <locale.h>
Packit d7e8d0
#endif
Packit d7e8d0
Packit d7e8d0
#include "util.h"
Packit d7e8d0
#include "context.h"
Packit d7e8d0
#include "ops.h"
Packit d7e8d0
#include "wait.h"
Packit d7e8d0
#include "debug.h"
Packit d7e8d0
#include "priv-io.h"
Packit d7e8d0
#include "sys-util.h"
Packit d7e8d0
#include "mbox-util.h"
Packit d7e8d0
Packit d7e8d0

Packit d7e8d0
/* The default locale.  */
Packit d7e8d0
DEFINE_STATIC_LOCK (def_lc_lock);
Packit d7e8d0
static char *def_lc_ctype;
Packit d7e8d0
static char *def_lc_messages;
Packit d7e8d0
Packit d7e8d0

Packit d7e8d0
gpgme_error_t _gpgme_selftest = GPG_ERR_NOT_OPERATIONAL;
Packit d7e8d0
Packit d7e8d0
/* Protects all reference counters in result structures.  All other
Packit d7e8d0
   accesses to a result structure are read only.  */
Packit d7e8d0
DEFINE_STATIC_LOCK (result_ref_lock);
Packit d7e8d0
Packit d7e8d0

Packit d7e8d0
/* Set the global flag NAME to VALUE.  Return 0 on success.  Note that
Packit d7e8d0
   this function does not use gpgme_error and thus a non-zero return
Packit d7e8d0
   value merely means "error".  Certain flags may be set before
Packit d7e8d0
   gpgme_check_version is called.  See the manual for a description of
Packit d7e8d0
   supported flags.  The caller must assure that this function is
Packit d7e8d0
   called only by one thread at a time.  */
Packit d7e8d0
int
Packit d7e8d0
gpgme_set_global_flag (const char *name, const char *value)
Packit d7e8d0
{
Packit d7e8d0
  if (!name || !value)
Packit d7e8d0
    return -1;
Packit d7e8d0
  else if (!strcmp (name, "debug"))
Packit d7e8d0
    return _gpgme_debug_set_debug_envvar (value);
Packit d7e8d0
  else if (!strcmp (name, "disable-gpgconf"))
Packit d7e8d0
    {
Packit d7e8d0
      _gpgme_dirinfo_disable_gpgconf ();
Packit d7e8d0
      return 0;
Packit d7e8d0
    }
Packit d7e8d0
  else if (!strcmp (name, "require-gnupg"))
Packit d7e8d0
    return _gpgme_set_engine_minimal_version (value);
Packit d7e8d0
  else if (!strcmp (name, "gpgconf-name"))
Packit d7e8d0
    return _gpgme_set_default_gpgconf_name (value);
Packit d7e8d0
  else if (!strcmp (name, "gpg-name"))
Packit d7e8d0
    return _gpgme_set_default_gpg_name (value);
Packit d7e8d0
  else if (!strcmp (name, "w32-inst-dir"))
Packit d7e8d0
    return _gpgme_set_override_inst_dir (value);
Packit d7e8d0
  else
Packit d7e8d0
    return -1;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0

Packit d7e8d0
/* Create a new context as an environment for GPGME crypto
Packit d7e8d0
   operations.  */
Packit d7e8d0
gpgme_error_t
Packit d7e8d0
gpgme_new (gpgme_ctx_t *r_ctx)
Packit d7e8d0
{
Packit d7e8d0
  gpgme_error_t err;
Packit d7e8d0
  gpgme_ctx_t ctx;
Packit d7e8d0
  TRACE_BEG (DEBUG_CTX, "gpgme_new", r_ctx);
Packit d7e8d0
Packit d7e8d0
  if (_gpgme_selftest)
Packit d7e8d0
    return TRACE_ERR (_gpgme_selftest);
Packit d7e8d0
Packit d7e8d0
  if (!r_ctx)
Packit d7e8d0
    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
Packit d7e8d0
Packit d7e8d0
  ctx = calloc (1, sizeof *ctx);
Packit d7e8d0
  if (!ctx)
Packit d7e8d0
    return TRACE_ERR (gpg_error_from_syserror ());
Packit d7e8d0
Packit d7e8d0
  INIT_LOCK (ctx->lock);
Packit d7e8d0
Packit d7e8d0
  err = _gpgme_engine_info_copy (&ctx->engine_info);
Packit d7e8d0
  if (!err && !ctx->engine_info)
Packit d7e8d0
    err = gpg_error (GPG_ERR_NO_ENGINE);
Packit d7e8d0
  if (err)
Packit d7e8d0
    {
Packit d7e8d0
      free (ctx);
Packit d7e8d0
      return TRACE_ERR (err);
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
  ctx->keylist_mode = GPGME_KEYLIST_MODE_LOCAL;
Packit d7e8d0
  ctx->include_certs = GPGME_INCLUDE_CERTS_DEFAULT;
Packit d7e8d0
  ctx->protocol = GPGME_PROTOCOL_OpenPGP;
Packit d7e8d0
  ctx->sub_protocol = GPGME_PROTOCOL_DEFAULT;
Packit d7e8d0
  _gpgme_fd_table_init (&ctx->fdt);
Packit d7e8d0
Packit d7e8d0
  LOCK (def_lc_lock);
Packit d7e8d0
  if (def_lc_ctype)
Packit d7e8d0
    {
Packit d7e8d0
      ctx->lc_ctype = strdup (def_lc_ctype);
Packit d7e8d0
      if (!ctx->lc_ctype)
Packit d7e8d0
	{
Packit d7e8d0
          int saved_err = gpg_error_from_syserror ();
Packit d7e8d0
	  UNLOCK (def_lc_lock);
Packit d7e8d0
	  _gpgme_engine_info_release (ctx->engine_info);
Packit d7e8d0
	  free (ctx);
Packit d7e8d0
	  return TRACE_ERR (saved_err);
Packit d7e8d0
	}
Packit d7e8d0
    }
Packit d7e8d0
  else
Packit d7e8d0
    def_lc_ctype = NULL;
Packit d7e8d0
Packit d7e8d0
  if (def_lc_messages)
Packit d7e8d0
    {
Packit d7e8d0
      ctx->lc_messages = strdup (def_lc_messages);
Packit d7e8d0
      if (!ctx->lc_messages)
Packit d7e8d0
	{
Packit d7e8d0
          int saved_err = gpg_error_from_syserror ();
Packit d7e8d0
	  UNLOCK (def_lc_lock);
Packit d7e8d0
	  if (ctx->lc_ctype)
Packit d7e8d0
	    free (ctx->lc_ctype);
Packit d7e8d0
	  _gpgme_engine_info_release (ctx->engine_info);
Packit d7e8d0
	  free (ctx);
Packit d7e8d0
	  return TRACE_ERR (saved_err);
Packit d7e8d0
	}
Packit d7e8d0
    }
Packit d7e8d0
  else
Packit d7e8d0
    def_lc_messages = NULL;
Packit d7e8d0
  UNLOCK (def_lc_lock);
Packit d7e8d0
Packit d7e8d0
  *r_ctx = ctx;
Packit d7e8d0
Packit d7e8d0
  return TRACE_SUC1 ("ctx=%p", ctx);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
gpgme_error_t
Packit d7e8d0
_gpgme_cancel_with_err (gpgme_ctx_t ctx, gpg_error_t ctx_err,
Packit d7e8d0
			gpg_error_t op_err)
Packit d7e8d0
{
Packit d7e8d0
  gpgme_error_t err;
Packit d7e8d0
  struct gpgme_io_event_done_data data;
Packit d7e8d0
Packit d7e8d0
  TRACE_BEG2 (DEBUG_CTX, "_gpgme_cancel_with_err", ctx, "ctx_err=%i, op_err=%i",
Packit d7e8d0
	      ctx_err, op_err);
Packit d7e8d0
Packit d7e8d0
  if (ctx_err)
Packit d7e8d0
    {
Packit d7e8d0
      err = _gpgme_engine_cancel (ctx->engine);
Packit d7e8d0
      if (err)
Packit d7e8d0
	return TRACE_ERR (err);
Packit d7e8d0
    }
Packit d7e8d0
  else
Packit d7e8d0
    {
Packit d7e8d0
      err = _gpgme_engine_cancel_op (ctx->engine);
Packit d7e8d0
      if (err)
Packit d7e8d0
	return TRACE_ERR (err);
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
  data.err = ctx_err;
Packit d7e8d0
  data.op_err = op_err;
Packit d7e8d0
Packit d7e8d0
  _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_DONE, &data);
Packit d7e8d0
Packit d7e8d0
  return TRACE_ERR (0);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* Cancel a pending asynchronous operation.  */
Packit d7e8d0
gpgme_error_t
Packit d7e8d0
gpgme_cancel (gpgme_ctx_t ctx)
Packit d7e8d0
{
Packit d7e8d0
  gpg_error_t err;
Packit d7e8d0
Packit d7e8d0
  TRACE_BEG (DEBUG_CTX, "gpgme_cancel", ctx);
Packit d7e8d0
Packit d7e8d0
  if (!ctx)
Packit d7e8d0
    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
Packit d7e8d0
Packit d7e8d0
  err = _gpgme_cancel_with_err (ctx, gpg_error (GPG_ERR_CANCELED), 0);
Packit d7e8d0
Packit d7e8d0
  return TRACE_ERR (err);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* Cancel a pending operation asynchronously.  */
Packit d7e8d0
gpgme_error_t
Packit d7e8d0
gpgme_cancel_async (gpgme_ctx_t ctx)
Packit d7e8d0
{
Packit d7e8d0
  TRACE_BEG (DEBUG_CTX, "gpgme_cancel_async", ctx);
Packit d7e8d0
Packit d7e8d0
  if (!ctx)
Packit d7e8d0
    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
Packit d7e8d0
Packit d7e8d0
  LOCK (ctx->lock);
Packit d7e8d0
  ctx->canceled = 1;
Packit d7e8d0
  UNLOCK (ctx->lock);
Packit d7e8d0
Packit d7e8d0
  return TRACE_ERR (0);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* Release all resources associated with the given context.  */
Packit d7e8d0
void
Packit d7e8d0
gpgme_release (gpgme_ctx_t ctx)
Packit d7e8d0
{
Packit d7e8d0
  TRACE (DEBUG_CTX, "gpgme_release", ctx);
Packit d7e8d0
Packit d7e8d0
  if (!ctx)
Packit d7e8d0
    return;
Packit d7e8d0
Packit d7e8d0
  _gpgme_engine_release (ctx->engine);
Packit d7e8d0
  ctx->engine = NULL;
Packit d7e8d0
  _gpgme_fd_table_deinit (&ctx->fdt);
Packit d7e8d0
  _gpgme_release_result (ctx);
Packit d7e8d0
  _gpgme_signers_clear (ctx);
Packit d7e8d0
  _gpgme_sig_notation_clear (ctx);
Packit d7e8d0
  free (ctx->sender);
Packit d7e8d0
  free (ctx->signers);
Packit d7e8d0
  free (ctx->lc_ctype);
Packit d7e8d0
  free (ctx->lc_messages);
Packit d7e8d0
  free (ctx->override_session_key);
Packit d7e8d0
  _gpgme_engine_info_release (ctx->engine_info);
Packit d7e8d0
  ctx->engine_info = NULL;
Packit d7e8d0
  DESTROY_LOCK (ctx->lock);
Packit d7e8d0
  free (ctx);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
void
Packit d7e8d0
gpgme_result_ref (void *result)
Packit d7e8d0
{
Packit d7e8d0
  struct ctx_op_data *data;
Packit d7e8d0
Packit d7e8d0
  if (! result)
Packit d7e8d0
    return;
Packit d7e8d0
Packit d7e8d0
  data = (void*)((char*)result - sizeof (struct ctx_op_data));
Packit d7e8d0
Packit d7e8d0
  assert (data->magic == CTX_OP_DATA_MAGIC);
Packit d7e8d0
Packit d7e8d0
  LOCK (result_ref_lock);
Packit d7e8d0
  data->references++;
Packit d7e8d0
  UNLOCK (result_ref_lock);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
void
Packit d7e8d0
gpgme_result_unref (void *result)
Packit d7e8d0
{
Packit d7e8d0
  struct ctx_op_data *data;
Packit d7e8d0
Packit d7e8d0
  if (! result)
Packit d7e8d0
    return;
Packit d7e8d0
Packit d7e8d0
  data = (void*)((char*)result - sizeof (struct ctx_op_data));
Packit d7e8d0
Packit d7e8d0
  assert (data->magic == CTX_OP_DATA_MAGIC);
Packit d7e8d0
Packit d7e8d0
  LOCK (result_ref_lock);
Packit d7e8d0
  if (--data->references)
Packit d7e8d0
    {
Packit d7e8d0
      UNLOCK (result_ref_lock);
Packit d7e8d0
      return;
Packit d7e8d0
    }
Packit d7e8d0
  UNLOCK (result_ref_lock);
Packit d7e8d0
Packit d7e8d0
  if (data->cleanup)
Packit d7e8d0
    (*data->cleanup) (data->hook);
Packit d7e8d0
  free (data);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
void
Packit d7e8d0
_gpgme_release_result (gpgme_ctx_t ctx)
Packit d7e8d0
{
Packit d7e8d0
  struct ctx_op_data *data = ctx->op_data;
Packit d7e8d0
Packit d7e8d0
  while (data)
Packit d7e8d0
    {
Packit d7e8d0
      struct ctx_op_data *next_data = data->next;
Packit d7e8d0
      data->next = NULL;
Packit d7e8d0
      gpgme_result_unref (data->hook);
Packit d7e8d0
      data = next_data;
Packit d7e8d0
    }
Packit d7e8d0
  ctx->op_data = NULL;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
gpgme_error_t
Packit d7e8d0
gpgme_set_protocol (gpgme_ctx_t ctx, gpgme_protocol_t protocol)
Packit d7e8d0
{
Packit d7e8d0
  TRACE_BEG2 (DEBUG_CTX, "gpgme_set_protocol", ctx, "protocol=%i (%s)",
Packit d7e8d0
	      protocol, gpgme_get_protocol_name (protocol)
Packit d7e8d0
	      ? gpgme_get_protocol_name (protocol) : "invalid");
Packit d7e8d0
Packit d7e8d0
  if (protocol != GPGME_PROTOCOL_OpenPGP
Packit d7e8d0
      && protocol != GPGME_PROTOCOL_CMS
Packit d7e8d0
      && protocol != GPGME_PROTOCOL_GPGCONF
Packit d7e8d0
      && protocol != GPGME_PROTOCOL_ASSUAN
Packit d7e8d0
      && protocol != GPGME_PROTOCOL_G13
Packit d7e8d0
      && protocol != GPGME_PROTOCOL_UISERVER
Packit d7e8d0
      && protocol != GPGME_PROTOCOL_SPAWN)
Packit d7e8d0
    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
Packit d7e8d0
Packit d7e8d0
  if (!ctx)
Packit d7e8d0
    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
Packit d7e8d0
Packit d7e8d0
  if (ctx->protocol != protocol)
Packit d7e8d0
    {
Packit d7e8d0
      /* Shut down the engine when switching protocols.  */
Packit d7e8d0
      if (ctx->engine)
Packit d7e8d0
	{
Packit d7e8d0
	  TRACE_LOG1 ("releasing ctx->engine=%p", ctx->engine);
Packit d7e8d0
	  _gpgme_engine_release (ctx->engine);
Packit d7e8d0
	  ctx->engine = NULL;
Packit d7e8d0
	}
Packit d7e8d0
Packit d7e8d0
      ctx->protocol = protocol;
Packit d7e8d0
    }
Packit d7e8d0
  return TRACE_ERR (0);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
gpgme_protocol_t
Packit d7e8d0
gpgme_get_protocol (gpgme_ctx_t ctx)
Packit d7e8d0
{
Packit d7e8d0
  TRACE2 (DEBUG_CTX, "gpgme_get_protocol", ctx,
Packit d7e8d0
	  "ctx->protocol=%i (%s)", ctx->protocol,
Packit d7e8d0
	  gpgme_get_protocol_name (ctx->protocol)
Packit d7e8d0
	  ? gpgme_get_protocol_name (ctx->protocol) : "invalid");
Packit d7e8d0
Packit d7e8d0
  return ctx->protocol;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
gpgme_error_t
Packit d7e8d0
gpgme_set_sub_protocol (gpgme_ctx_t ctx, gpgme_protocol_t protocol)
Packit d7e8d0
{
Packit d7e8d0
  TRACE2 (DEBUG_CTX, "gpgme_set_sub_protocol", ctx, "protocol=%i (%s)",
Packit d7e8d0
	  protocol, gpgme_get_protocol_name (protocol)
Packit d7e8d0
	  ? gpgme_get_protocol_name (protocol) : "invalid");
Packit d7e8d0
Packit d7e8d0
  if (!ctx)
Packit d7e8d0
    return gpg_error (GPG_ERR_INV_VALUE);
Packit d7e8d0
Packit d7e8d0
  ctx->sub_protocol = protocol;
Packit d7e8d0
  return 0;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
gpgme_protocol_t
Packit d7e8d0
gpgme_get_sub_protocol (gpgme_ctx_t ctx)
Packit d7e8d0
{
Packit d7e8d0
  TRACE2 (DEBUG_CTX, "gpgme_get_sub_protocol", ctx,
Packit d7e8d0
	  "ctx->sub_protocol=%i (%s)", ctx->sub_protocol,
Packit d7e8d0
	  gpgme_get_protocol_name (ctx->sub_protocol)
Packit d7e8d0
	  ? gpgme_get_protocol_name (ctx->sub_protocol) : "invalid");
Packit d7e8d0
Packit d7e8d0
  return ctx->sub_protocol;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
const char *
Packit d7e8d0
gpgme_get_protocol_name (gpgme_protocol_t protocol)
Packit d7e8d0
{
Packit d7e8d0
  switch (protocol)
Packit d7e8d0
    {
Packit d7e8d0
    case GPGME_PROTOCOL_OpenPGP:
Packit d7e8d0
      return "OpenPGP";
Packit d7e8d0
Packit d7e8d0
    case GPGME_PROTOCOL_CMS:
Packit d7e8d0
      return "CMS";
Packit d7e8d0
Packit d7e8d0
    case GPGME_PROTOCOL_GPGCONF:
Packit d7e8d0
      return "GPGCONF";
Packit d7e8d0
Packit d7e8d0
    case GPGME_PROTOCOL_ASSUAN:
Packit d7e8d0
      return "Assuan";
Packit d7e8d0
Packit d7e8d0
    case GPGME_PROTOCOL_G13:
Packit d7e8d0
      return "G13";
Packit d7e8d0
Packit d7e8d0
    case GPGME_PROTOCOL_UISERVER:
Packit d7e8d0
      return "UIServer";
Packit d7e8d0
Packit d7e8d0
    case GPGME_PROTOCOL_SPAWN:
Packit d7e8d0
      return "Spawn";
Packit d7e8d0
Packit d7e8d0
    case GPGME_PROTOCOL_DEFAULT:
Packit d7e8d0
      return "default";
Packit d7e8d0
Packit d7e8d0
    case GPGME_PROTOCOL_UNKNOWN:
Packit d7e8d0
      return "unknown";
Packit d7e8d0
Packit d7e8d0
    default:
Packit d7e8d0
      return NULL;
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* Store the sender's address in the context.  ADDRESS is addr-spec of
Packit d7e8d0
 * mailbox but my also be a complete mailbox, in which case this
Packit d7e8d0
 * function extracts the addr-spec from it.  Returns 0 on success or
Packit d7e8d0
 * an error code if no valid addr-spec could be extracted from
Packit d7e8d0
 * ADDRESS.  */
Packit d7e8d0
gpgme_error_t
Packit d7e8d0
gpgme_set_sender (gpgme_ctx_t ctx, const char *address)
Packit d7e8d0
{
Packit d7e8d0
  char *p = NULL;
Packit d7e8d0
Packit d7e8d0
  TRACE_BEG1 (DEBUG_CTX, "gpgme_set_sender", ctx, "sender='%s'",
Packit d7e8d0
              address?address:"(null)");
Packit d7e8d0
Packit d7e8d0
  if (!ctx || (address && !(p = _gpgme_mailbox_from_userid (address))))
Packit d7e8d0
    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
Packit d7e8d0
Packit d7e8d0
  free (ctx->sender);
Packit d7e8d0
  ctx->sender = p;
Packit d7e8d0
  return TRACE_ERR (0);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* Return the sender's address (addr-spec part) from the context or
Packit d7e8d0
 * NULL if none was set.  The returned value is valid as long as the
Packit d7e8d0
 * CTX is valid and gpgme_set_sender has not been used.  */
Packit d7e8d0
const char *
Packit d7e8d0
gpgme_get_sender (gpgme_ctx_t ctx)
Packit d7e8d0
{
Packit d7e8d0
  TRACE1 (DEBUG_CTX, "gpgme_get_sender", ctx, "sender='%s'",
Packit d7e8d0
          ctx?ctx->sender:"");
Packit d7e8d0
Packit d7e8d0
  return ctx->sender;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* Enable or disable the use of an ascii armor for all output.  */
Packit d7e8d0
void
Packit d7e8d0
gpgme_set_armor (gpgme_ctx_t ctx, int use_armor)
Packit d7e8d0
{
Packit d7e8d0
  TRACE2 (DEBUG_CTX, "gpgme_set_armor", ctx, "use_armor=%i (%s)",
Packit d7e8d0
	  use_armor, use_armor ? "yes" : "no");
Packit d7e8d0
Packit d7e8d0
  if (!ctx)
Packit d7e8d0
    return;
Packit d7e8d0
Packit d7e8d0
  ctx->use_armor = !!use_armor;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* Return the state of the armor flag.  */
Packit d7e8d0
int
Packit d7e8d0
gpgme_get_armor (gpgme_ctx_t ctx)
Packit d7e8d0
{
Packit d7e8d0
  TRACE2 (DEBUG_CTX, "gpgme_get_armor", ctx, "ctx->use_armor=%i (%s)",
Packit d7e8d0
	  ctx->use_armor, ctx->use_armor ? "yes" : "no");
Packit d7e8d0
  return ctx->use_armor;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* Set the flag NAME for CTX to VALUE.  The supported flags are:
Packit d7e8d0
 *
Packit d7e8d0
 * - full-status :: With a value of "1" the status callback set by
Packit d7e8d0
 *                  gpgme_set_status_cb returns all status lines
Packit d7e8d0
 *                  except for PROGRESS lines.  With the default of
Packit d7e8d0
 *                  "0" the status callback is only called in certain
Packit d7e8d0
 *                  situations.
Packit d7e8d0
 */
Packit d7e8d0
gpgme_error_t
Packit d7e8d0
gpgme_set_ctx_flag (gpgme_ctx_t ctx, const char *name, const char *value)
Packit d7e8d0
{
Packit d7e8d0
  gpgme_error_t err = 0;
Packit d7e8d0
  int abool;
Packit d7e8d0
Packit d7e8d0
  TRACE2 (DEBUG_CTX, "gpgme_set_ctx_flag", ctx,
Packit d7e8d0
          "name='%s' value='%s'",
Packit d7e8d0
	  name? name:"(null)", value?value:"(null)");
Packit d7e8d0
Packit d7e8d0
  abool = (value && *value)? !!atoi (value) : 0;
Packit d7e8d0
Packit d7e8d0
  if (!ctx || !name || !value)
Packit d7e8d0
    err = gpg_error (GPG_ERR_INV_VALUE);
Packit d7e8d0
  else if (!strcmp (name, "redraw"))
Packit d7e8d0
    {
Packit d7e8d0
      ctx->redraw_suggested = abool;
Packit d7e8d0
    }
Packit d7e8d0
  else if (!strcmp (name, "full-status"))
Packit d7e8d0
    {
Packit d7e8d0
      ctx->full_status = abool;
Packit d7e8d0
    }
Packit d7e8d0
  else if (!strcmp (name, "raw-description"))
Packit d7e8d0
    {
Packit d7e8d0
      ctx->raw_description = abool;
Packit d7e8d0
    }
Packit d7e8d0
  else if (!strcmp (name, "export-session-key"))
Packit d7e8d0
    {
Packit d7e8d0
      ctx->export_session_keys = abool;
Packit d7e8d0
    }
Packit d7e8d0
  else if (!strcmp (name, "override-session-key"))
Packit d7e8d0
    {
Packit d7e8d0
      free (ctx->override_session_key);
Packit d7e8d0
      ctx->override_session_key = strdup (value);
Packit d7e8d0
      if (!ctx->override_session_key)
Packit d7e8d0
        err = gpg_error_from_syserror ();
Packit d7e8d0
    }
Packit d7e8d0
  else if (!strcmp (name, "auto-key-retrieve"))
Packit d7e8d0
    {
Packit d7e8d0
      ctx->auto_key_retrieve = abool;
Packit d7e8d0
    }
Packit d7e8d0
  else
Packit d7e8d0
    err = gpg_error (GPG_ERR_UNKNOWN_NAME);
Packit d7e8d0
Packit d7e8d0
  return err;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* Get the context flag named NAME.  See gpgme_set_ctx_flag for a list
Packit d7e8d0
 * of valid names.  If the NAME is unknown NULL is returned.  For a
Packit d7e8d0
 * boolean flag an empty string is returned for False and the string
Packit d7e8d0
 * "1" for True; thus either atoi or a simple string test can be
Packit d7e8d0
 * used.  */
Packit d7e8d0
const char *
Packit d7e8d0
gpgme_get_ctx_flag (gpgme_ctx_t ctx, const char *name)
Packit d7e8d0
{
Packit d7e8d0
  if (!ctx || !name)
Packit d7e8d0
    return NULL;
Packit d7e8d0
  else if (!strcmp (name, "redraw"))
Packit d7e8d0
    {
Packit d7e8d0
      return ctx->redraw_suggested? "1":"";
Packit d7e8d0
    }
Packit d7e8d0
  else if (!strcmp (name, "full-status"))
Packit d7e8d0
    {
Packit d7e8d0
      return ctx->full_status? "1":"";
Packit d7e8d0
    }
Packit d7e8d0
  else if (!strcmp (name, "raw-description"))
Packit d7e8d0
    {
Packit d7e8d0
      return ctx->raw_description? "1":"";
Packit d7e8d0
    }
Packit d7e8d0
  else if (!strcmp (name, "export-session-key"))
Packit d7e8d0
    {
Packit d7e8d0
      return ctx->export_session_keys? "1":"";
Packit d7e8d0
    }
Packit d7e8d0
  else if (!strcmp (name, "override-session-key"))
Packit d7e8d0
    {
Packit d7e8d0
      return ctx->override_session_key? ctx->override_session_key : "";
Packit d7e8d0
    }
Packit d7e8d0
  else if (!strcmp (name, "auto-key-retrieve"))
Packit d7e8d0
    {
Packit d7e8d0
      return ctx->auto_key_retrieve? "1":"";
Packit d7e8d0
    }
Packit d7e8d0
  else
Packit d7e8d0
    return NULL;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* Enable or disable the use of the special textmode.  Textmode is for
Packit d7e8d0
  example used for the RFC2015 signatures; note that the updated RFC
Packit d7e8d0
  3156 mandates that the MUA does some preparations so that textmode
Packit d7e8d0
  is not needed anymore.  */
Packit d7e8d0
void
Packit d7e8d0
gpgme_set_textmode (gpgme_ctx_t ctx, int use_textmode)
Packit d7e8d0
{
Packit d7e8d0
  TRACE2 (DEBUG_CTX, "gpgme_set_textmode", ctx, "use_textmode=%i (%s)",
Packit d7e8d0
	  use_textmode, use_textmode ? "yes" : "no");
Packit d7e8d0
Packit d7e8d0
  if (!ctx)
Packit d7e8d0
    return;
Packit d7e8d0
Packit d7e8d0
  ctx->use_textmode = !!use_textmode;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
/* Return the state of the textmode flag.  */
Packit d7e8d0
int
Packit d7e8d0
gpgme_get_textmode (gpgme_ctx_t ctx)
Packit d7e8d0
{
Packit d7e8d0
  TRACE2 (DEBUG_CTX, "gpgme_get_textmode", ctx, "ctx->use_textmode=%i (%s)",
Packit d7e8d0
	  ctx->use_textmode, ctx->use_textmode ? "yes" : "no");
Packit d7e8d0
  return ctx->use_textmode;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* Enable offline mode for this context. In offline mode dirmngr
Packit d7e8d0
  will be disabled. */
Packit d7e8d0
void
Packit d7e8d0
gpgme_set_offline (gpgme_ctx_t ctx, int offline)
Packit d7e8d0
{
Packit d7e8d0
  TRACE2 (DEBUG_CTX, "gpgme_set_offline", ctx, "offline=%i (%s)",
Packit d7e8d0
          offline, offline ? "yes" : "no");
Packit d7e8d0
Packit d7e8d0
  if (!ctx)
Packit d7e8d0
    return;
Packit d7e8d0
Packit d7e8d0
  ctx->offline = !!offline;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
/* Return the state of the offline flag.  */
Packit d7e8d0
int
Packit d7e8d0
gpgme_get_offline (gpgme_ctx_t ctx)
Packit d7e8d0
{
Packit d7e8d0
  TRACE2 (DEBUG_CTX, "gpgme_get_offline", ctx, "ctx->offline=%i (%s)",
Packit d7e8d0
          ctx->offline, ctx->offline ? "yes" : "no");
Packit d7e8d0
  return ctx->offline;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* Set the number of certifications to include in an S/MIME message.
Packit d7e8d0
   The default is GPGME_INCLUDE_CERTS_DEFAULT.  -1 means all certs,
Packit d7e8d0
   and -2 means all certs except the root cert.  */
Packit d7e8d0
void
Packit d7e8d0
gpgme_set_include_certs (gpgme_ctx_t ctx, int nr_of_certs)
Packit d7e8d0
{
Packit d7e8d0
  if (!ctx)
Packit d7e8d0
    return;
Packit d7e8d0
Packit d7e8d0
  if (nr_of_certs == GPGME_INCLUDE_CERTS_DEFAULT)
Packit d7e8d0
    ctx->include_certs = GPGME_INCLUDE_CERTS_DEFAULT;
Packit d7e8d0
  else if (nr_of_certs < -2)
Packit d7e8d0
    ctx->include_certs = -2;
Packit d7e8d0
  else
Packit d7e8d0
    ctx->include_certs = nr_of_certs;
Packit d7e8d0
Packit d7e8d0
  TRACE2 (DEBUG_CTX, "gpgme_set_include_certs", ctx, "nr_of_certs=%i%s",
Packit d7e8d0
	  nr_of_certs, nr_of_certs == ctx->include_certs ? "" : " (-2)");
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* Get the number of certifications to include in an S/MIME
Packit d7e8d0
   message.  */
Packit d7e8d0
int
Packit d7e8d0
gpgme_get_include_certs (gpgme_ctx_t ctx)
Packit d7e8d0
{
Packit d7e8d0
  TRACE1 (DEBUG_CTX, "gpgme_get_include_certs", ctx, "ctx->include_certs=%i",
Packit d7e8d0
	  ctx->include_certs);
Packit d7e8d0
  return ctx->include_certs;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* This function changes the default behaviour of the keylisting
Packit d7e8d0
   functions.  MODE is a bitwise-OR of the GPGME_KEYLIST_* flags.  The
Packit d7e8d0
   default mode is GPGME_KEYLIST_MODE_LOCAL.  */
Packit d7e8d0
gpgme_error_t
Packit d7e8d0
gpgme_set_keylist_mode (gpgme_ctx_t ctx, gpgme_keylist_mode_t mode)
Packit d7e8d0
{
Packit d7e8d0
  TRACE1 (DEBUG_CTX, "gpgme_set_keylist_mode", ctx, "keylist_mode=0x%x",
Packit d7e8d0
	  mode);
Packit d7e8d0
Packit d7e8d0
  if (!ctx)
Packit d7e8d0
    return gpg_error (GPG_ERR_INV_VALUE);
Packit d7e8d0
Packit d7e8d0
  ctx->keylist_mode = mode;
Packit d7e8d0
  return 0;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
/* This function returns the default behaviour of the keylisting
Packit d7e8d0
   functions.  */
Packit d7e8d0
gpgme_keylist_mode_t
Packit d7e8d0
gpgme_get_keylist_mode (gpgme_ctx_t ctx)
Packit d7e8d0
{
Packit d7e8d0
  TRACE1 (DEBUG_CTX, "gpgme_get_keylist_mode", ctx,
Packit d7e8d0
	  "ctx->keylist_mode=0x%x", ctx->keylist_mode);
Packit d7e8d0
  return ctx->keylist_mode;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* Set the pinentry mode for CTX to MODE. */
Packit d7e8d0
gpgme_error_t
Packit d7e8d0
gpgme_set_pinentry_mode (gpgme_ctx_t ctx, gpgme_pinentry_mode_t mode)
Packit d7e8d0
{
Packit d7e8d0
  TRACE1 (DEBUG_CTX, "gpgme_set_pinentry_mode", ctx, "pinentry_mode=%u",
Packit d7e8d0
	  (unsigned int)mode);
Packit d7e8d0
Packit d7e8d0
  if (!ctx)
Packit d7e8d0
    return gpg_error (GPG_ERR_INV_VALUE);
Packit d7e8d0
Packit d7e8d0
  switch (mode)
Packit d7e8d0
    {
Packit d7e8d0
    case GPGME_PINENTRY_MODE_DEFAULT:
Packit d7e8d0
    case GPGME_PINENTRY_MODE_ASK:
Packit d7e8d0
    case GPGME_PINENTRY_MODE_CANCEL:
Packit d7e8d0
    case GPGME_PINENTRY_MODE_ERROR:
Packit d7e8d0
    case GPGME_PINENTRY_MODE_LOOPBACK:
Packit d7e8d0
      break;
Packit d7e8d0
    default:
Packit d7e8d0
      return gpg_error (GPG_ERR_INV_VALUE);
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
  ctx->pinentry_mode = mode;
Packit d7e8d0
  return 0;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* Get the pinentry mode of CTX.  */
Packit d7e8d0
gpgme_pinentry_mode_t
Packit d7e8d0
gpgme_get_pinentry_mode (gpgme_ctx_t ctx)
Packit d7e8d0
{
Packit d7e8d0
  TRACE1 (DEBUG_CTX, "gpgme_get_pinentry_mode", ctx,
Packit d7e8d0
	  "ctx->pinentry_mode=%u", (unsigned int)ctx->pinentry_mode);
Packit d7e8d0
  return ctx->pinentry_mode;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* This function sets a callback function to be used to pass a
Packit d7e8d0
   passphrase to gpg.  */
Packit d7e8d0
void
Packit d7e8d0
gpgme_set_passphrase_cb (gpgme_ctx_t ctx, gpgme_passphrase_cb_t cb,
Packit d7e8d0
			 void *cb_value)
Packit d7e8d0
{
Packit d7e8d0
  TRACE2 (DEBUG_CTX, "gpgme_set_passphrase_cb", ctx,
Packit d7e8d0
	  "passphrase_cb=%p/%p", cb, cb_value);
Packit d7e8d0
Packit d7e8d0
  if (!ctx)
Packit d7e8d0
    return;
Packit d7e8d0
Packit d7e8d0
  ctx->passphrase_cb = cb;
Packit d7e8d0
  ctx->passphrase_cb_value = cb_value;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* This function returns the callback function to be used to pass a
Packit d7e8d0
   passphrase to the crypto engine.  */
Packit d7e8d0
void
Packit d7e8d0
gpgme_get_passphrase_cb (gpgme_ctx_t ctx, gpgme_passphrase_cb_t *r_cb,
Packit d7e8d0
			 void **r_cb_value)
Packit d7e8d0
{
Packit d7e8d0
  TRACE2 (DEBUG_CTX, "gpgme_get_passphrase_cb", ctx,
Packit d7e8d0
	  "ctx->passphrase_cb=%p/%p",
Packit d7e8d0
	  ctx->passphrase_cb, ctx->passphrase_cb_value);
Packit d7e8d0
  if (r_cb)
Packit d7e8d0
    *r_cb = ctx->passphrase_cb;
Packit d7e8d0
  if (r_cb_value)
Packit d7e8d0
    *r_cb_value = ctx->passphrase_cb_value;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* This function sets a callback function to be used as a progress
Packit d7e8d0
   indicator.  */
Packit d7e8d0
void
Packit d7e8d0
gpgme_set_progress_cb (gpgme_ctx_t ctx, gpgme_progress_cb_t cb, void *cb_value)
Packit d7e8d0
{
Packit d7e8d0
  TRACE2 (DEBUG_CTX, "gpgme_set_progress_cb", ctx, "progress_cb=%p/%p",
Packit d7e8d0
	  cb, cb_value);
Packit d7e8d0
Packit d7e8d0
  if (!ctx)
Packit d7e8d0
    return;
Packit d7e8d0
Packit d7e8d0
  ctx->progress_cb = cb;
Packit d7e8d0
  ctx->progress_cb_value = cb_value;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* This function returns the callback function to be used as a
Packit d7e8d0
   progress indicator.  */
Packit d7e8d0
void
Packit d7e8d0
gpgme_get_progress_cb (gpgme_ctx_t ctx, gpgme_progress_cb_t *r_cb,
Packit d7e8d0
		       void **r_cb_value)
Packit d7e8d0
{
Packit d7e8d0
  TRACE2 (DEBUG_CTX, "gpgme_get_progress_cb", ctx, "ctx->progress_cb=%p/%p",
Packit d7e8d0
	  ctx->progress_cb, ctx->progress_cb_value);
Packit d7e8d0
  if (r_cb)
Packit d7e8d0
    *r_cb = ctx->progress_cb;
Packit d7e8d0
  if (r_cb_value)
Packit d7e8d0
    *r_cb_value = ctx->progress_cb_value;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* This function sets a callback function to be used as a status
Packit d7e8d0
   message forwarder.  */
Packit d7e8d0
void
Packit d7e8d0
gpgme_set_status_cb (gpgme_ctx_t ctx, gpgme_status_cb_t cb, void *cb_value)
Packit d7e8d0
{
Packit d7e8d0
  TRACE2 (DEBUG_CTX, "gpgme_set_status_cb", ctx, "status_cb=%p/%p",
Packit d7e8d0
	  cb, cb_value);
Packit d7e8d0
Packit d7e8d0
  if (!ctx)
Packit d7e8d0
    return;
Packit d7e8d0
Packit d7e8d0
  ctx->status_cb = cb;
Packit d7e8d0
  ctx->status_cb_value = cb_value;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* This function returns the callback function to be used as a
Packit d7e8d0
   status message forwarder.  */
Packit d7e8d0
void
Packit d7e8d0
gpgme_get_status_cb (gpgme_ctx_t ctx, gpgme_status_cb_t *r_cb,
Packit d7e8d0
		       void **r_cb_value)
Packit d7e8d0
{
Packit d7e8d0
  TRACE2 (DEBUG_CTX, "gpgme_get_status_cb", ctx, "ctx->status_cb=%p/%p",
Packit d7e8d0
	  ctx ? ctx->status_cb : NULL, ctx ? ctx->status_cb_value : NULL);
Packit d7e8d0
Packit d7e8d0
  if (r_cb)
Packit d7e8d0
    *r_cb = NULL;
Packit d7e8d0
Packit d7e8d0
  if (r_cb_value)
Packit d7e8d0
    *r_cb_value = NULL;
Packit d7e8d0
Packit d7e8d0
  if (!ctx || !ctx->status_cb)
Packit d7e8d0
    return;
Packit d7e8d0
Packit d7e8d0
  if (r_cb)
Packit d7e8d0
    *r_cb = ctx->status_cb;
Packit d7e8d0
  if (r_cb_value)
Packit d7e8d0
    *r_cb_value = ctx->status_cb_value;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* Set the I/O callback functions for CTX to IO_CBS.  */
Packit d7e8d0
void
Packit d7e8d0
gpgme_set_io_cbs (gpgme_ctx_t ctx, gpgme_io_cbs_t io_cbs)
Packit d7e8d0
{
Packit d7e8d0
  if (!ctx)
Packit d7e8d0
    return;
Packit d7e8d0
Packit d7e8d0
  if (io_cbs)
Packit d7e8d0
    {
Packit d7e8d0
      TRACE6 (DEBUG_CTX, "gpgme_set_io_cbs", ctx,
Packit d7e8d0
	      "io_cbs=%p (add=%p/%p, remove=%p, event=%p/%p",
Packit d7e8d0
	      io_cbs, io_cbs->add, io_cbs->add_priv, io_cbs->remove,
Packit d7e8d0
	      io_cbs->event, io_cbs->event_priv);
Packit d7e8d0
      ctx->io_cbs = *io_cbs;
Packit d7e8d0
    }
Packit d7e8d0
  else
Packit d7e8d0
    {
Packit d7e8d0
      TRACE1 (DEBUG_CTX, "gpgme_set_io_cbs", ctx,
Packit d7e8d0
	      "io_cbs=%p (default)", io_cbs);
Packit d7e8d0
      ctx->io_cbs.add = NULL;
Packit d7e8d0
      ctx->io_cbs.add_priv = NULL;
Packit d7e8d0
      ctx->io_cbs.remove = NULL;
Packit d7e8d0
      ctx->io_cbs.event = NULL;
Packit d7e8d0
      ctx->io_cbs.event_priv = NULL;
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* This function provides access to the internal read function; it is
Packit d7e8d0
   normally not used.  */
Packit d7e8d0
gpgme_ssize_t
Packit d7e8d0
gpgme_io_read (int fd, void *buffer, size_t count)
Packit d7e8d0
{
Packit d7e8d0
  int ret;
Packit d7e8d0
  TRACE_BEG2 (DEBUG_GLOBAL, "gpgme_io_read", fd,
Packit d7e8d0
	      "buffer=%p, count=%u", buffer, count);
Packit d7e8d0
Packit d7e8d0
  ret = _gpgme_io_read (fd, buffer, count);
Packit d7e8d0
Packit d7e8d0
  return TRACE_SYSRES (ret);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* This function provides access to the internal write function.  It
Packit d7e8d0
   is to be used by user callbacks to return data to gpgme.  See
Packit d7e8d0
   gpgme_passphrase_cb_t and gpgme_edit_cb_t.  */
Packit d7e8d0
gpgme_ssize_t
Packit d7e8d0
gpgme_io_write (int fd, const void *buffer, size_t count)
Packit d7e8d0
{
Packit d7e8d0
  int ret;
Packit d7e8d0
  TRACE_BEG2 (DEBUG_GLOBAL, "gpgme_io_write", fd,
Packit d7e8d0
	      "buffer=%p, count=%u", buffer, count);
Packit d7e8d0
Packit d7e8d0
  ret = _gpgme_io_write (fd, buffer, count);
Packit d7e8d0
Packit d7e8d0
  return TRACE_SYSRES (ret);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
/* This function provides access to the internal write function.  It
Packit d7e8d0
   is to be used by user callbacks to return data to gpgme.  See
Packit d7e8d0
   gpgme_passphrase_cb_t and gpgme_edit_cb_t.  Note that this is a
Packit d7e8d0
   variant of gpgme_io_write which guarantees that all COUNT bytes are
Packit d7e8d0
   written or an error is return.  Returns: 0 on success or -1 on
Packit d7e8d0
   error and the sets errno. */
Packit d7e8d0
int
Packit d7e8d0
gpgme_io_writen (int fd, const void *buffer_arg, size_t count)
Packit d7e8d0
{
Packit d7e8d0
  const char *buffer = buffer_arg;
Packit d7e8d0
  int ret = 0;
Packit d7e8d0
  TRACE_BEG2 (DEBUG_GLOBAL, "gpgme_io_writen", fd,
Packit d7e8d0
	      "buffer=%p, count=%u", buffer, count);
Packit d7e8d0
  while (count)
Packit d7e8d0
    {
Packit d7e8d0
      ret = _gpgme_io_write (fd, buffer, count);
Packit d7e8d0
      if (ret < 0)
Packit d7e8d0
        break;
Packit d7e8d0
      buffer += ret;
Packit d7e8d0
      count -= ret;
Packit d7e8d0
      ret = 0;
Packit d7e8d0
    }
Packit d7e8d0
  return TRACE_SYSRES (ret);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* This function returns the callback function for I/O.  */
Packit d7e8d0
void
Packit d7e8d0
gpgme_get_io_cbs (gpgme_ctx_t ctx, gpgme_io_cbs_t io_cbs)
Packit d7e8d0
{
Packit d7e8d0
  TRACE6 (DEBUG_CTX, "gpgme_get_io_cbs", ctx,
Packit d7e8d0
	  "io_cbs=%p, ctx->io_cbs.add=%p/%p, .remove=%p, .event=%p/%p",
Packit d7e8d0
	  io_cbs, io_cbs->add, io_cbs->add_priv, io_cbs->remove,
Packit d7e8d0
	  io_cbs->event, io_cbs->event_priv);
Packit d7e8d0
Packit d7e8d0
  *io_cbs = ctx->io_cbs;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0

Packit d7e8d0
/* This function sets the locale for the context CTX, or the default
Packit d7e8d0
   locale if CTX is a null pointer.  */
Packit d7e8d0
gpgme_error_t
Packit d7e8d0
gpgme_set_locale (gpgme_ctx_t ctx, int category, const char *value)
Packit d7e8d0
{
Packit d7e8d0
  int failed = 0;
Packit d7e8d0
  char *new_lc_ctype = NULL;
Packit d7e8d0
  char *new_lc_messages = NULL;
Packit d7e8d0
Packit d7e8d0
  TRACE_BEG2 (DEBUG_CTX, "gpgme_set_locale", ctx,
Packit d7e8d0
	       "category=%i, value=%s", category, value ? value : "(null)");
Packit d7e8d0
Packit d7e8d0
#define PREPARE_ONE_LOCALE(lcat, ucat)				\
Packit d7e8d0
  if (!failed && value						\
Packit d7e8d0
      && (category == LC_ALL || category == LC_ ## ucat))	\
Packit d7e8d0
    {								\
Packit d7e8d0
      new_lc_ ## lcat = strdup (value);				\
Packit d7e8d0
      if (!new_lc_ ## lcat)					\
Packit d7e8d0
        failed = 1;						\
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
#ifdef LC_CTYPE
Packit d7e8d0
  PREPARE_ONE_LOCALE (ctype, CTYPE);
Packit d7e8d0
#endif
Packit d7e8d0
#ifdef LC_MESSAGES
Packit d7e8d0
  PREPARE_ONE_LOCALE (messages, MESSAGES);
Packit d7e8d0
#endif
Packit d7e8d0
Packit d7e8d0
  if (failed)
Packit d7e8d0
    {
Packit d7e8d0
      int saved_err = gpg_error_from_syserror ();
Packit d7e8d0
Packit d7e8d0
      if (new_lc_ctype)
Packit d7e8d0
	free (new_lc_ctype);
Packit d7e8d0
      if (new_lc_messages)
Packit d7e8d0
	free (new_lc_messages);
Packit d7e8d0
Packit d7e8d0
      return TRACE_ERR (saved_err);
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
#define SET_ONE_LOCALE(lcat, ucat)			\
Packit d7e8d0
  if (category == LC_ALL || category == LC_ ## ucat)	\
Packit d7e8d0
    {							\
Packit d7e8d0
      if (ctx)						\
Packit d7e8d0
	{						\
Packit d7e8d0
	  if (ctx->lc_ ## lcat)				\
Packit d7e8d0
	    free (ctx->lc_ ## lcat);			\
Packit d7e8d0
	  ctx->lc_ ## lcat = new_lc_ ## lcat;		\
Packit d7e8d0
	}						\
Packit d7e8d0
      else						\
Packit d7e8d0
	{						\
Packit d7e8d0
	  if (def_lc_ ## lcat)				\
Packit d7e8d0
	    free (def_lc_ ## lcat);			\
Packit d7e8d0
	  def_lc_ ## lcat = new_lc_ ## lcat;		\
Packit d7e8d0
	}						\
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
  if (!ctx)
Packit d7e8d0
    LOCK (def_lc_lock);
Packit d7e8d0
#ifdef LC_CTYPE
Packit d7e8d0
  SET_ONE_LOCALE (ctype, CTYPE);
Packit d7e8d0
#endif
Packit d7e8d0
#ifdef LC_MESSAGES
Packit d7e8d0
  SET_ONE_LOCALE (messages, MESSAGES);
Packit d7e8d0
#endif
Packit d7e8d0
  if (!ctx)
Packit d7e8d0
    UNLOCK (def_lc_lock);
Packit d7e8d0
Packit d7e8d0
  return TRACE_ERR (0);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0

Packit d7e8d0
/* Get the information about the configured engines.  A pointer to the
Packit d7e8d0
   first engine in the statically allocated linked list is returned.
Packit d7e8d0
   The returned data is valid until the next gpgme_ctx_set_engine_info.  */
Packit d7e8d0
gpgme_engine_info_t
Packit d7e8d0
gpgme_ctx_get_engine_info (gpgme_ctx_t ctx)
Packit d7e8d0
{
Packit d7e8d0
  TRACE1 (DEBUG_CTX, "gpgme_ctx_get_engine_info", ctx,
Packit d7e8d0
	  "ctx->engine_info=%p", ctx->engine_info);
Packit d7e8d0
  return ctx->engine_info;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* Set the engine info for the context CTX, protocol PROTO, to the
Packit d7e8d0
   file name FILE_NAME and the home directory HOME_DIR.  */
Packit d7e8d0
gpgme_error_t
Packit d7e8d0
gpgme_ctx_set_engine_info (gpgme_ctx_t ctx, gpgme_protocol_t proto,
Packit d7e8d0
			   const char *file_name, const char *home_dir)
Packit d7e8d0
{
Packit d7e8d0
  gpgme_error_t err;
Packit d7e8d0
  TRACE_BEG4 (DEBUG_CTX, "gpgme_ctx_set_engine_info", ctx,
Packit d7e8d0
	      "protocol=%i (%s), file_name=%s, home_dir=%s",
Packit d7e8d0
	      proto, gpgme_get_protocol_name (proto)
Packit d7e8d0
	      ? gpgme_get_protocol_name (proto) : "unknown",
Packit d7e8d0
	      file_name ? file_name : "(default)",
Packit d7e8d0
	      home_dir ? home_dir : "(default)");
Packit d7e8d0
Packit d7e8d0
  if (!ctx)
Packit d7e8d0
    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
Packit d7e8d0
Packit d7e8d0
  /* Shut down the engine when changing engine info.  */
Packit d7e8d0
  if (ctx->engine)
Packit d7e8d0
    {
Packit d7e8d0
      TRACE_LOG1 ("releasing ctx->engine=%p", ctx->engine);
Packit d7e8d0
      _gpgme_engine_release (ctx->engine);
Packit d7e8d0
      ctx->engine = NULL;
Packit d7e8d0
    }
Packit d7e8d0
  err = _gpgme_set_engine_info (ctx->engine_info, proto,
Packit d7e8d0
				file_name, home_dir);
Packit d7e8d0
  return TRACE_ERR (err);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0

Packit d7e8d0
/* Clear all notation data from the context.  */
Packit d7e8d0
void
Packit d7e8d0
_gpgme_sig_notation_clear (gpgme_ctx_t ctx)
Packit d7e8d0
{
Packit d7e8d0
  gpgme_sig_notation_t notation;
Packit d7e8d0
Packit d7e8d0
  if (!ctx)
Packit d7e8d0
    return;
Packit d7e8d0
Packit d7e8d0
  notation = ctx->sig_notations;
Packit d7e8d0
  while (notation)
Packit d7e8d0
    {
Packit d7e8d0
      gpgme_sig_notation_t next_notation = notation->next;
Packit d7e8d0
      _gpgme_sig_notation_free (notation);
Packit d7e8d0
      notation = next_notation;
Packit d7e8d0
    }
Packit d7e8d0
  ctx->sig_notations = NULL;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
void
Packit d7e8d0
gpgme_sig_notation_clear (gpgme_ctx_t ctx)
Packit d7e8d0
{
Packit d7e8d0
  TRACE (DEBUG_CTX, "gpgme_sig_notation_clear", ctx);
Packit d7e8d0
Packit d7e8d0
  if (!ctx)
Packit d7e8d0
    return;
Packit d7e8d0
Packit d7e8d0
  _gpgme_sig_notation_clear (ctx);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* Add the human-readable notation data with name NAME and value VALUE
Packit d7e8d0
   to the context CTX, using the flags FLAGS.  If NAME is NULL, then
Packit d7e8d0
   VALUE should be a policy URL.  The flag
Packit d7e8d0
   GPGME_SIG_NOTATION_HUMAN_READABLE is forced to be true for notation
Packit d7e8d0
   data, and false for policy URLs.  */
Packit d7e8d0
gpgme_error_t
Packit d7e8d0
gpgme_sig_notation_add (gpgme_ctx_t ctx, const char *name,
Packit d7e8d0
			const char *value, gpgme_sig_notation_flags_t flags)
Packit d7e8d0
{
Packit d7e8d0
  gpgme_error_t err;
Packit d7e8d0
  gpgme_sig_notation_t notation;
Packit d7e8d0
  gpgme_sig_notation_t *lastp;
Packit d7e8d0
Packit d7e8d0
  TRACE_BEG3 (DEBUG_CTX, "gpgme_sig_notation_add", ctx,
Packit d7e8d0
	      "name=%s, value=%s, flags=0x%x",
Packit d7e8d0
	      name ? name : "(null)", value ? value : "(null)",
Packit d7e8d0
	      flags);
Packit d7e8d0
Packit d7e8d0
  if (!ctx)
Packit d7e8d0
    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
Packit d7e8d0
Packit d7e8d0
  if (name)
Packit d7e8d0
    flags |= GPGME_SIG_NOTATION_HUMAN_READABLE;
Packit d7e8d0
  else
Packit d7e8d0
    flags &= ~GPGME_SIG_NOTATION_HUMAN_READABLE;
Packit d7e8d0
Packit d7e8d0
  err = _gpgme_sig_notation_create (&notation, name, name ? strlen (name) : 0,
Packit d7e8d0
				    value, value ? strlen (value) : 0, flags);
Packit d7e8d0
  if (err)
Packit d7e8d0
    return TRACE_ERR (err);
Packit d7e8d0
Packit d7e8d0
  lastp = &ctx->sig_notations;
Packit d7e8d0
  while (*lastp)
Packit d7e8d0
    lastp = &(*lastp)->next;
Packit d7e8d0
Packit d7e8d0
  *lastp = notation;
Packit d7e8d0
  return TRACE_ERR (0);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* Get the sig notations for this context.  */
Packit d7e8d0
gpgme_sig_notation_t
Packit d7e8d0
gpgme_sig_notation_get (gpgme_ctx_t ctx)
Packit d7e8d0
{
Packit d7e8d0
  if (!ctx)
Packit d7e8d0
    {
Packit d7e8d0
      TRACE (DEBUG_CTX, "gpgme_sig_notation_get", ctx);
Packit d7e8d0
      return NULL;
Packit d7e8d0
    }
Packit d7e8d0
  TRACE1 (DEBUG_CTX, "gpgme_sig_notation_get", ctx,
Packit d7e8d0
	  "ctx->sig_notations=%p", ctx->sig_notations);
Packit d7e8d0
Packit d7e8d0
  return ctx->sig_notations;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0

Packit d7e8d0
/* Return a public key algorithm string made of the algorithm and size
Packit d7e8d0
   or the curve name.  May return NULL on error.  Caller must free the
Packit d7e8d0
   result using gpgme_free.  */
Packit d7e8d0
char *
Packit d7e8d0
gpgme_pubkey_algo_string (gpgme_subkey_t subkey)
Packit d7e8d0
{
Packit d7e8d0
  const char *prefix = NULL;
Packit d7e8d0
  char *result;
Packit d7e8d0
Packit d7e8d0
  if (!subkey)
Packit d7e8d0
    {
Packit d7e8d0
      gpg_err_set_errno (EINVAL);
Packit d7e8d0
      return NULL;
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
  switch (subkey->pubkey_algo)
Packit d7e8d0
    {
Packit d7e8d0
    case GPGME_PK_RSA:
Packit d7e8d0
    case GPGME_PK_RSA_E:
Packit d7e8d0
    case GPGME_PK_RSA_S: prefix = "rsa"; break;
Packit d7e8d0
    case GPGME_PK_ELG_E: prefix = "elg"; break;
Packit d7e8d0
    case GPGME_PK_DSA:	 prefix = "dsa"; break;
Packit d7e8d0
    case GPGME_PK_ELG:   prefix = "xxx"; break;
Packit d7e8d0
    case GPGME_PK_ECC:
Packit d7e8d0
    case GPGME_PK_ECDH:
Packit d7e8d0
    case GPGME_PK_ECDSA:
Packit d7e8d0
    case GPGME_PK_EDDSA: prefix = "";    break;
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
  if (prefix && *prefix)
Packit d7e8d0
    {
Packit d7e8d0
      char buffer[40];
Packit d7e8d0
      snprintf (buffer, sizeof buffer, "%s%u", prefix, subkey->length);
Packit d7e8d0
      result = strdup (buffer);
Packit d7e8d0
    }
Packit d7e8d0
  else if (prefix && subkey->curve && *subkey->curve)
Packit d7e8d0
    result = strdup (subkey->curve);
Packit d7e8d0
  else if (prefix)
Packit d7e8d0
    result =  strdup ("E_error");
Packit d7e8d0
  else
Packit d7e8d0
    result = strdup  ("unknown");
Packit d7e8d0
Packit d7e8d0
  return result;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
const char *
Packit d7e8d0
gpgme_pubkey_algo_name (gpgme_pubkey_algo_t algo)
Packit d7e8d0
{
Packit d7e8d0
  switch (algo)
Packit d7e8d0
    {
Packit d7e8d0
    case GPGME_PK_RSA:   return "RSA";
Packit d7e8d0
    case GPGME_PK_RSA_E: return "RSA-E";
Packit d7e8d0
    case GPGME_PK_RSA_S: return "RSA-S";
Packit d7e8d0
    case GPGME_PK_ELG_E: return "ELG-E";
Packit d7e8d0
    case GPGME_PK_DSA:   return "DSA";
Packit d7e8d0
    case GPGME_PK_ECC:   return "ECC";
Packit d7e8d0
    case GPGME_PK_ELG:   return "ELG";
Packit d7e8d0
    case GPGME_PK_ECDSA: return "ECDSA";
Packit d7e8d0
    case GPGME_PK_ECDH:  return "ECDH";
Packit d7e8d0
    case GPGME_PK_EDDSA: return "EdDSA";
Packit d7e8d0
    default:             return NULL;
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
const char *
Packit d7e8d0
gpgme_hash_algo_name (gpgme_hash_algo_t algo)
Packit d7e8d0
{
Packit d7e8d0
  switch (algo)
Packit d7e8d0
    {
Packit d7e8d0
    case GPGME_MD_MD5:
Packit d7e8d0
      return "MD5";
Packit d7e8d0
Packit d7e8d0
    case GPGME_MD_SHA1:
Packit d7e8d0
      return "SHA1";
Packit d7e8d0
Packit d7e8d0
    case GPGME_MD_RMD160:
Packit d7e8d0
      return "RIPEMD160";
Packit d7e8d0
Packit d7e8d0
    case GPGME_MD_MD2:
Packit d7e8d0
      return "MD2";
Packit d7e8d0
Packit d7e8d0
    case GPGME_MD_TIGER:
Packit d7e8d0
      return "TIGER192";
Packit d7e8d0
Packit d7e8d0
    case GPGME_MD_HAVAL:
Packit d7e8d0
      return "HAVAL";
Packit d7e8d0
Packit d7e8d0
    case GPGME_MD_SHA256:
Packit d7e8d0
      return "SHA256";
Packit d7e8d0
Packit d7e8d0
    case GPGME_MD_SHA384:
Packit d7e8d0
      return "SHA384";
Packit d7e8d0
Packit d7e8d0
    case GPGME_MD_SHA512:
Packit d7e8d0
      return "SHA512";
Packit d7e8d0
Packit d7e8d0
    case GPGME_MD_SHA224:
Packit d7e8d0
      return "SHA224";
Packit d7e8d0
Packit d7e8d0
    case GPGME_MD_MD4:
Packit d7e8d0
      return "MD4";
Packit d7e8d0
Packit d7e8d0
    case GPGME_MD_CRC32:
Packit d7e8d0
      return "CRC32";
Packit d7e8d0
Packit d7e8d0
    case GPGME_MD_CRC32_RFC1510:
Packit d7e8d0
      return "CRC32RFC1510";
Packit d7e8d0
Packit d7e8d0
    case GPGME_MD_CRC24_RFC2440:
Packit d7e8d0
      return "CRC24RFC2440";
Packit d7e8d0
Packit d7e8d0
    default:
Packit d7e8d0
      return NULL;
Packit d7e8d0
    }
Packit d7e8d0
}