2005-09-12 Marcus Brinkmann <marcus@g10code.de>
[gpgme.git] / gpgme / engine.c
index e96af13..b331e9a 100644 (file)
@@ -1,38 +1,42 @@
 /* engine.c - GPGME engine support.
    Copyright (C) 2000 Werner Koch (dd9jn)
-   Copyright (C) 2001, 2002 g10 Code GmbH
+   Copyright (C) 2001, 2002, 2003, 2004 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 General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
+   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
-   General Public License for more details.
-   You should have received a copy of the GNU General Public License
-   along with GPGME; if not, write to the Free Software Foundation,
-   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   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
+   02111-1307, USA.  */
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 #include <stdlib.h>
 #include <string.h>
+#include <errno.h>
+#include <assert.h>
 
 #include "gpgme.h"
 #include "util.h"
 #include "sema.h"
+#include "ops.h"
 
 #include "engine.h"
 #include "engine-backend.h"
 
 
-struct engine_object_s
+struct engine
 {
   struct engine_ops *ops;
   void *engine;
@@ -50,117 +54,339 @@ static struct engine_ops *engine_ops[] =
   };
 
 
-/* Get the path of the engine for PROTOCOL.  */
-const char *
-_gpgme_engine_get_path (GpgmeProtocol proto)
+/* The engine info.  */
+static gpgme_engine_info_t engine_info;
+DEFINE_STATIC_LOCK (engine_info_lock);
+
+\f
+/* Get the file name of the engine for PROTOCOL.  */
+static char *
+engine_get_file_name (gpgme_protocol_t proto)
 {
-  if (proto > sizeof (engine_ops) / sizeof (engine_ops[0]))
+  if (proto > DIM (engine_ops))
     return NULL;
 
-  if (engine_ops[proto] && engine_ops[proto]->get_path)
-    return (*engine_ops[proto]->get_path) ();
+  if (engine_ops[proto] && engine_ops[proto]->get_file_name)
+    return (*engine_ops[proto]->get_file_name) ();
   else
     return NULL;
 }
 
 
-/* Get the version number of the engine for PROTOCOL.  */
-const char *
-_gpgme_engine_get_version (GpgmeProtocol proto)
+/* Get a malloced string containing the version number of the engine
+   for PROTOCOL.  */
+static char *
+engine_get_version (gpgme_protocol_t proto, const char *file_name)
 {
-  if (proto > sizeof (engine_ops) / sizeof (engine_ops[0]))
+  if (proto > DIM (engine_ops))
     return NULL;
 
   if (engine_ops[proto] && engine_ops[proto]->get_version)
-    return (*engine_ops[proto]->get_version) ();
+    return (*engine_ops[proto]->get_version) (file_name);
+  else
+    return NULL;
+}
+
+
+/* Get the required version number of the engine for PROTOCOL.  */
+static const char *
+engine_get_req_version (gpgme_protocol_t proto)
+{
+  if (proto > DIM (engine_ops))
+    return NULL;
+
+  if (engine_ops[proto] && engine_ops[proto]->get_req_version)
+    return (*engine_ops[proto]->get_req_version) ();
   else
     return NULL;
 }
 
 
 /* Verify the version requirement for the engine for PROTOCOL.  */
-GpgmeError
-gpgme_engine_check_version (GpgmeProtocol proto)
+gpgme_error_t
+gpgme_engine_check_version (gpgme_protocol_t proto)
 {
-  if (proto > sizeof (engine_ops) / sizeof (engine_ops[0]))
-    return mk_error (Invalid_Value);
+  int result;
+  char *engine_version = engine_get_version (proto, NULL);
 
-  if (!engine_ops[proto])
-    return mk_error (Invalid_Engine);
+  result = _gpgme_compare_versions (engine_version,
+                                   engine_get_req_version (proto));
+  if (engine_version)
+    free (engine_version);
 
-  if (engine_ops[proto]->check_version)
-    return (*engine_ops[proto]->check_version) ();
-  else
-    return 0;
+  return result ? 0 : gpg_error (GPG_ERR_INV_ENGINE);
 }
 
 
-const char *
-_gpgme_engine_get_info (GpgmeProtocol proto)
+/* Release the engine info INFO.  */
+void
+_gpgme_engine_info_release (gpgme_engine_info_t info)
 {
-  static const char fmt[] = " <engine>\n"
-    "  <protocol>%s</protocol>\n"
-    "  <version>%s</version>\n"
-    "  <path>%s</path>\n"
-    " </engine>\n";
-  static const char *const strproto[3] = { "OpenPGP", "CMS", NULL };
-  static const char *engine_info[3];  /* FIXME: MAX_PROTO + 1*/
-  DEFINE_STATIC_LOCK (engine_info_lock);
+  while (info)
+    {
+      gpgme_engine_info_t next_info = info->next;
+
+      assert (info->file_name);
+      free (info->file_name);
+      if (info->home_dir)
+       free (info->home_dir);
+      if (info->version)
+       free (info->version);
+      free (info);
+      info = next_info;
+    }
+}
 
-  if (proto > 2 /* FIXME MAX_PROTO */ || !strproto[proto])
-    return NULL;
 
+/* Get the information about the configured and installed engines.  A
+   pointer to the first engine in the statically allocated linked list
+   is returned in *INFO.  If an error occurs, it is returned.  The
+   returned data is valid until the next gpgme_set_engine_info.  */
+gpgme_error_t
+gpgme_get_engine_info (gpgme_engine_info_t *info)
+{
   LOCK (engine_info_lock);
-  if (!engine_info[proto])
+  if (!engine_info)
     {
-      const char *path = _gpgme_engine_get_path (proto);
-      const char *version = _gpgme_engine_get_version (proto);
+      gpgme_engine_info_t *lastp = &engine_info;
+      gpgme_protocol_t proto_list[] = { GPGME_PROTOCOL_OpenPGP,
+                                       GPGME_PROTOCOL_CMS };
+      unsigned int proto;
 
-      if (path && version)
+      for (proto = 0; proto < DIM (proto_list); proto++)
        {
-         char *info = malloc (strlen (fmt) + strlen (strproto[proto])
-                                  + strlen (path) + strlen (version) + 1);
-         if (!info)
-           info = " <engine>\n"
-             "  <error>Out of core</error>\n"
-             " </engine>";
-         else
-           sprintf (info, fmt, strproto[proto], version, path);
-         engine_info[proto] = info;
+         char *file_name = engine_get_file_name (proto_list[proto]);
+
+         if (!file_name)
+           continue;
+
+         file_name = strdup (file_name);
+
+         *lastp = malloc (sizeof (*engine_info));
+         if (!*lastp || !file_name)
+           {
+             int saved_errno = errno;
+
+             _gpgme_engine_info_release (engine_info);
+             engine_info = NULL;
+
+             if (file_name)
+               free (file_name);
+
+             UNLOCK (engine_info_lock);
+             return gpg_error_from_errno (saved_errno);
+           }
+
+         (*lastp)->protocol = proto_list[proto];
+         (*lastp)->file_name = file_name;
+         (*lastp)->home_dir = NULL;
+         (*lastp)->version = engine_get_version (proto_list[proto], NULL);
+         (*lastp)->req_version = engine_get_req_version (proto_list[proto]);
+         (*lastp)->next = NULL;
+         lastp = &(*lastp)->next;
        }
     }
+
+  *info = engine_info;
   UNLOCK (engine_info_lock);
-  return engine_info[proto];
+  return 0;
 }
 
 
-GpgmeError
-_gpgme_engine_new (GpgmeProtocol proto, EngineObject *r_engine)
+/* Get a deep copy of the engine info and return it in INFO.  */
+gpgme_error_t
+_gpgme_engine_info_copy (gpgme_engine_info_t *r_info)
 {
-  EngineObject engine;
+  gpgme_error_t err = 0;
+  gpgme_engine_info_t info;
+  gpgme_engine_info_t new_info;
+  gpgme_engine_info_t *lastp;
+
+  LOCK (engine_info_lock);
+  info = engine_info;
+  if (!info)
+    {
+      /* Make sure it is initialized.  */
+      UNLOCK (engine_info_lock);
+      err = gpgme_get_engine_info (&info);
+      if (err)
+       return err;
+
+      LOCK (engine_info_lock);
+    }
+
+  new_info = NULL;
+  lastp = &new_info;
+
+  while (info)
+    {
+      char *file_name;
+      char *home_dir;
+      char *version;
+
+      assert (info->file_name);
+      file_name = strdup (info->file_name);
+
+      if (info->home_dir)
+       {
+         home_dir = strdup (info->home_dir);
+         if (!home_dir)
+           err = gpg_error_from_errno (errno);
+       }
+      else
+       home_dir = NULL;
+
+      if (info->version)
+       {
+         version = strdup (info->version);
+         if (!version)
+           err = gpg_error_from_errno (errno);
+       }
+      else
+       version = NULL;
+
+      *lastp = malloc (sizeof (*engine_info));
+      if (!*lastp || !file_name || err)
+       {
+         int saved_errno = errno;
+
+         _gpgme_engine_info_release (new_info);
+
+         if (file_name)
+           free (file_name);
+         if (home_dir)
+           free (home_dir);
+         if (version)
+           free (version);
+
+         UNLOCK (engine_info_lock);
+         return gpg_error_from_errno (saved_errno);
+       }
 
-  const char *path;
-  const char *version;
+      (*lastp)->protocol = info->protocol;
+      (*lastp)->file_name = file_name;
+      (*lastp)->home_dir = home_dir;
+      (*lastp)->version = version;
+      (*lastp)->req_version = info->req_version;
+      (*lastp)->next = NULL;
+      lastp = &(*lastp)->next;
 
-  if (proto > sizeof (engine_ops) / sizeof (engine_ops[0]))
-    return mk_error (Invalid_Value);
+      info = info->next;
+    }
 
-  if (!engine_ops[proto])
-    return mk_error (Invalid_Engine);
+  *r_info = new_info;
+  UNLOCK (engine_info_lock);
+  return 0;
+}
+
+
+/* Set the engine info for the info list INFO, protocol PROTO, to the
+   file name FILE_NAME and the home directory HOME_DIR.  */
+gpgme_error_t
+_gpgme_set_engine_info (gpgme_engine_info_t info, gpgme_protocol_t proto,
+                       const char *file_name, const char *home_dir)
+{
+  char *new_file_name;
+  char *new_home_dir;
 
-  path = _gpgme_engine_get_path (proto);
-  version = _gpgme_engine_get_version (proto);
-  if (!path || !version)
-    return mk_error (Invalid_Engine);
+  /* FIXME: Use some PROTO_MAX definition.  */
+  if (proto > DIM (engine_ops))
+    return gpg_error (GPG_ERR_INV_VALUE);
+
+  while (info && info->protocol != proto)
+    info = info->next;
+
+  if (!info)
+    return gpg_error (GPG_ERR_INV_ENGINE);
+
+  /* Prepare new members.  */
+  if (file_name)
+    new_file_name = strdup (file_name);
+  else
+    {
+      new_file_name = engine_get_file_name (proto);
+      assert (new_file_name);
+      new_file_name = strdup (new_file_name);
+    }
+  if (!new_file_name)
+    return gpg_error_from_errno (errno);
+
+  if (home_dir)
+    {
+      new_home_dir = strdup (home_dir);
+      if (!new_home_dir)
+       {
+         free (new_file_name);
+         return gpg_error_from_errno (errno);
+       }
+    }
+  else
+    new_home_dir = NULL;
+
+  /* Remove the old members.  */
+  assert (info->file_name);
+  free (info->file_name);
+  if (info->home_dir)
+    free (info->home_dir);
+  if (info->version)
+    free (info->version);
+
+  /* Install the new members.  */
+  info->file_name = new_file_name;
+  info->home_dir = new_home_dir;
+  info->version = engine_get_version (proto, file_name);
+
+  return 0;
+}
+
+
+/* Set the default engine info for the protocol PROTO to the file name
+   FILE_NAME and the home directory HOME_DIR.  */
+gpgme_error_t
+gpgme_set_engine_info (gpgme_protocol_t proto,
+                      const char *file_name, const char *home_dir)
+{
+  gpgme_error_t err;
+  gpgme_engine_info_t info;
+
+  LOCK (engine_info_lock);
+  info = engine_info;
+  if (!info)
+    {
+      /* Make sure it is initialized.  */
+      UNLOCK (engine_info_lock);
+      err = gpgme_get_engine_info (&info);
+      if (err)
+       return err;
+
+      LOCK (engine_info_lock);
+    }
+
+  err = _gpgme_set_engine_info (info, proto, file_name, home_dir);
+  UNLOCK (engine_info_lock);
+  return err;
+}
+
+\f
+gpgme_error_t
+_gpgme_engine_new (gpgme_engine_info_t info, engine_t *r_engine,
+                  const char *lc_ctype, const char *lc_messages)
+{
+  engine_t engine;
+
+  if (!info->file_name || !info->version)
+    return gpg_error (GPG_ERR_INV_ENGINE);
 
   engine = calloc (1, sizeof *engine);
   if (!engine)
-    return mk_error (Out_Of_Core);
+    return gpg_error_from_errno (errno);
 
-  engine->ops = engine_ops[proto];
-  if (engine_ops[proto]->new)
+  engine->ops = engine_ops[info->protocol];
+  if (engine->ops->new)
     {
-      GpgmeError err = (*engine_ops[proto]->new) (&engine->engine);
+      gpgme_error_t err = (*engine->ops->new) (&engine->engine,
+                                              info->file_name, info->home_dir,
+                                              lc_ctype, lc_messages);
       if (err)
        {
          free (engine);
@@ -176,7 +402,7 @@ _gpgme_engine_new (GpgmeProtocol proto, EngineObject *r_engine)
 
 
 void
-_gpgme_engine_release (EngineObject engine)
+_gpgme_engine_release (engine_t engine)
 {
   if (!engine)
     return;
@@ -188,19 +414,8 @@ _gpgme_engine_release (EngineObject engine)
 
 
 void
-_gpgme_engine_set_verbosity (EngineObject engine, int verbosity)
-{
-  if (!engine)
-    return;
-
-  if (engine->ops->set_verbosity)
-    (*engine->ops->set_verbosity) (engine->engine, verbosity);
-}
-
-
-void
-_gpgme_engine_set_status_handler (EngineObject engine,
-                                 GpgmeStatusHandler fnc, void *fnc_value)
+_gpgme_engine_set_status_handler (engine_t engine,
+                                 engine_status_handler_t fnc, void *fnc_value)
 {
   if (!engine)
     return;
@@ -210,225 +425,248 @@ _gpgme_engine_set_status_handler (EngineObject engine,
 }
 
 
-GpgmeError
-_gpgme_engine_set_command_handler (EngineObject engine,
-                                  GpgmeCommandHandler fnc, void *fnc_value,
-                                  GpgmeData linked_data)
+gpgme_error_t
+_gpgme_engine_set_command_handler (engine_t engine,
+                                  engine_command_handler_t fnc,
+                                  void *fnc_value,
+                                  gpgme_data_t linked_data)
 {
   if (!engine)
-    return mk_error (Invalid_Value);
+    return gpg_error (GPG_ERR_INV_VALUE);
 
   if (!engine->ops->set_command_handler)
-    return mk_error (Not_Implemented);
+    return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
 
   return (*engine->ops->set_command_handler) (engine->engine,
                                              fnc, fnc_value, linked_data);
 }
 
-GpgmeError _gpgme_engine_set_colon_line_handler (EngineObject engine,
-                                                GpgmeColonLineHandler fnc,
-                                                void *fnc_value)
+gpgme_error_t
+_gpgme_engine_set_colon_line_handler (engine_t engine,
+                                     engine_colon_line_handler_t fnc,
+                                     void *fnc_value)
 {
   if (!engine)
-    return mk_error (Invalid_Value);
+    return gpg_error (GPG_ERR_INV_VALUE);
 
   if (!engine->ops->set_colon_line_handler)
-    return mk_error (Not_Implemented);
+    return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
 
   return (*engine->ops->set_colon_line_handler) (engine->engine,
                                                 fnc, fnc_value);
 }
 
-GpgmeError
-_gpgme_engine_op_decrypt (EngineObject engine, GpgmeData ciph, GpgmeData plain)
+gpgme_error_t
+_gpgme_engine_op_decrypt (engine_t engine, gpgme_data_t ciph,
+                         gpgme_data_t plain)
 {
   if (!engine)
-    return mk_error (Invalid_Value);
+    return gpg_error (GPG_ERR_INV_VALUE);
 
   if (!engine->ops->decrypt)
-    return mk_error (Not_Implemented);
+    return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
 
   return (*engine->ops->decrypt) (engine->engine, ciph, plain);
 }
 
-GpgmeError
-_gpgme_engine_op_delete (EngineObject engine, GpgmeKey key, int allow_secret)
+gpgme_error_t
+_gpgme_engine_op_delete (engine_t engine, gpgme_key_t key,
+                        int allow_secret)
 {
   if (!engine)
-    return mk_error (Invalid_Value);
+    return gpg_error (GPG_ERR_INV_VALUE);
 
   if (!engine->ops->delete)
-    return mk_error (Not_Implemented);
+    return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
 
   return (*engine->ops->delete) (engine->engine, key, allow_secret);
 }
 
 
-GpgmeError
-_gpgme_engine_op_edit (EngineObject engine, GpgmeKey key, GpgmeData out,
-                      GpgmeCtx ctx /* FIXME */)
+gpgme_error_t
+_gpgme_engine_op_edit (engine_t engine, int type, gpgme_key_t key,
+                      gpgme_data_t out, gpgme_ctx_t ctx /* FIXME */)
 {
   if (!engine)
-    return mk_error (Invalid_Value);
+    return gpg_error (GPG_ERR_INV_VALUE);
 
   if (!engine->ops->edit)
-    return mk_error (Not_Implemented);
+    return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
 
-  return (*engine->ops->edit) (engine->engine, key, out, ctx);
+  return (*engine->ops->edit) (engine->engine, type, key, out, ctx);
 }
 
 
-GpgmeError
-_gpgme_engine_op_encrypt (EngineObject engine, GpgmeRecipients recp,
-                         GpgmeData plain, GpgmeData ciph, int use_armor)
+gpgme_error_t
+_gpgme_engine_op_encrypt (engine_t engine, gpgme_key_t recp[],
+                         gpgme_encrypt_flags_t flags,
+                         gpgme_data_t plain, gpgme_data_t ciph, int use_armor)
 {
   if (!engine)
-    return mk_error (Invalid_Value);
+    return gpg_error (GPG_ERR_INV_VALUE);
 
   if (!engine->ops->encrypt)
-    return mk_error (Not_Implemented);
+    return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
 
-  return (*engine->ops->encrypt) (engine->engine, recp, plain, ciph,
+  return (*engine->ops->encrypt) (engine->engine, recp, flags, plain, ciph,
                                  use_armor);
 }
 
 
-GpgmeError
-_gpgme_engine_op_encrypt_sign (EngineObject engine, GpgmeRecipients recp,
-                              GpgmeData plain, GpgmeData ciph, int use_armor,
-                              GpgmeCtx ctx /* FIXME */)
+gpgme_error_t
+_gpgme_engine_op_encrypt_sign (engine_t engine, gpgme_key_t recp[],
+                              gpgme_encrypt_flags_t flags,
+                              gpgme_data_t plain, gpgme_data_t ciph,
+                              int use_armor, gpgme_ctx_t ctx /* FIXME */)
 {
   if (!engine)
-    return mk_error (Invalid_Value);
+    return gpg_error (GPG_ERR_INV_VALUE);
 
   if (!engine->ops->encrypt_sign)
-    return mk_error (Not_Implemented);
+    return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
 
-  return (*engine->ops->encrypt_sign) (engine->engine, recp, plain, ciph,
-                                      use_armor, ctx);
+  return (*engine->ops->encrypt_sign) (engine->engine, recp, flags,
+                                      plain, ciph, use_armor, ctx);
 }
 
 
-GpgmeError
-_gpgme_engine_op_export (EngineObject engine, GpgmeRecipients recp,
-                        GpgmeData keydata, int use_armor)
+gpgme_error_t
+_gpgme_engine_op_export (engine_t engine, const char *pattern,
+                        unsigned int reserved, gpgme_data_t keydata,
+                        int use_armor)
 {
   if (!engine)
-    return mk_error (Invalid_Value);
+    return gpg_error (GPG_ERR_INV_VALUE);
 
   if (!engine->ops->export)
-    return mk_error (Not_Implemented);
+    return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
 
-  return (*engine->ops->export) (engine->engine, recp, keydata,
-                                use_armor);
+  return (*engine->ops->export) (engine->engine, pattern, reserved,
+                                keydata, use_armor);
 }
 
 
-GpgmeError
-_gpgme_engine_op_genkey (EngineObject engine, GpgmeData help_data,
-                        int use_armor, GpgmeData pubkey, GpgmeData seckey)
+gpgme_error_t
+_gpgme_engine_op_export_ext (engine_t engine, const char *pattern[],
+                            unsigned int reserved, gpgme_data_t keydata,
+                            int use_armor)
 {
   if (!engine)
-    return mk_error (Invalid_Value);
+    return gpg_error (GPG_ERR_INV_VALUE);
+
+  if (!engine->ops->export_ext)
+    return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+  return (*engine->ops->export_ext) (engine->engine, pattern, reserved,
+                                    keydata, use_armor);
+}
+
+
+gpgme_error_t
+_gpgme_engine_op_genkey (engine_t engine, gpgme_data_t help_data,
+                        int use_armor, gpgme_data_t pubkey,
+                        gpgme_data_t seckey)
+{
+  if (!engine)
+    return gpg_error (GPG_ERR_INV_VALUE);
 
   if (!engine->ops->genkey)
-    return mk_error (Not_Implemented);
+    return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
 
   return (*engine->ops->genkey) (engine->engine, help_data, use_armor,
                                 pubkey, seckey);
 }
 
 
-GpgmeError
-_gpgme_engine_op_import (EngineObject engine, GpgmeData keydata)
+gpgme_error_t
+_gpgme_engine_op_import (engine_t engine, gpgme_data_t keydata)
 {
   if (!engine)
-    return mk_error (Invalid_Value);
+    return gpg_error (GPG_ERR_INV_VALUE);
 
   if (!engine->ops->import)
-    return mk_error (Not_Implemented);
+    return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
 
   return (*engine->ops->import) (engine->engine, keydata);
 }
 
 
-GpgmeError
-_gpgme_engine_op_keylist (EngineObject engine, const char *pattern,
-                         int secret_only, int keylist_mode)
+gpgme_error_t
+_gpgme_engine_op_keylist (engine_t engine, const char *pattern,
+                         int secret_only, gpgme_keylist_mode_t mode)
 {
   if (!engine)
-    return mk_error (Invalid_Value);
+    return gpg_error (GPG_ERR_INV_VALUE);
 
   if (!engine->ops->keylist)
-    return mk_error (Not_Implemented);
+    return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
 
-  return (*engine->ops->keylist) (engine->engine, pattern, secret_only,
-                                 keylist_mode);
+  return (*engine->ops->keylist) (engine->engine, pattern, secret_only, mode);
 }
 
 
-GpgmeError
-_gpgme_engine_op_keylist_ext (EngineObject engine, const char *pattern[],
-                             int secret_only, int reserved, int keylist_mode)
+gpgme_error_t
+_gpgme_engine_op_keylist_ext (engine_t engine, const char *pattern[],
+                             int secret_only, int reserved,
+                             gpgme_keylist_mode_t mode)
 {
   if (!engine)
-    return mk_error (Invalid_Value);
+    return gpg_error (GPG_ERR_INV_VALUE);
 
   if (!engine->ops->keylist_ext)
-    return mk_error (Not_Implemented);
+    return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
 
   return (*engine->ops->keylist_ext) (engine->engine, pattern, secret_only,
-                                     reserved, keylist_mode);
+                                     reserved, mode);
 }
 
 
-GpgmeError
-_gpgme_engine_op_sign (EngineObject engine, GpgmeData in, GpgmeData out,
-                      GpgmeSigMode mode, int use_armor,
+gpgme_error_t
+_gpgme_engine_op_sign (engine_t engine, gpgme_data_t in, gpgme_data_t out,
+                      gpgme_sig_mode_t mode, int use_armor,
                       int use_textmode, int include_certs,
-                      GpgmeCtx ctx /* FIXME */)
+                      gpgme_ctx_t ctx /* FIXME */)
 {
   if (!engine)
-    return mk_error (Invalid_Value);
+    return gpg_error (GPG_ERR_INV_VALUE);
 
   if (!engine->ops->sign)
-    return mk_error (Not_Implemented);
+    return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
 
   return (*engine->ops->sign) (engine->engine, in, out, mode, use_armor,
                               use_textmode, include_certs, ctx);
 }
 
 
-GpgmeError
-_gpgme_engine_op_trustlist (EngineObject engine, const char *pattern)
+gpgme_error_t
+_gpgme_engine_op_trustlist (engine_t engine, const char *pattern)
 {
   if (!engine)
-    return mk_error (Invalid_Value);
+    return gpg_error (GPG_ERR_INV_VALUE);
 
   if (!engine->ops->trustlist)
-    return mk_error (Not_Implemented);
+    return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
 
   return (*engine->ops->trustlist) (engine->engine, pattern);
 }
 
 
-GpgmeError
-_gpgme_engine_op_verify (EngineObject engine, GpgmeData sig,
-                        GpgmeData signed_text, GpgmeData plaintext)
+gpgme_error_t
+_gpgme_engine_op_verify (engine_t engine, gpgme_data_t sig,
+                        gpgme_data_t signed_text, gpgme_data_t plaintext)
 {
   if (!engine)
-    return mk_error (Invalid_Value);
+    return gpg_error (GPG_ERR_INV_VALUE);
 
   if (!engine->ops->verify)
-    return mk_error (Not_Implemented);
+    return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
 
   return (*engine->ops->verify) (engine->engine, sig, signed_text, plaintext);
 }
 
 
 void
-_gpgme_engine_set_io_cbs (EngineObject engine,
-                         struct GpgmeIOCbs *io_cbs)
+_gpgme_engine_set_io_cbs (engine_t engine, gpgme_io_cbs_t io_cbs)
 {
   if (!engine)
     return;
@@ -436,12 +674,26 @@ _gpgme_engine_set_io_cbs (EngineObject engine,
   (*engine->ops->set_io_cbs) (engine->engine, io_cbs);
 }
 
+
 void
-_gpgme_engine_io_event (EngineObject engine,
-                       GpgmeEventIO type, void *type_data)
+_gpgme_engine_io_event (engine_t engine,
+                       gpgme_event_io_t type, void *type_data)
 {
   if (!engine)
     return;
 
   (*engine->ops->io_event) (engine->engine, type, type_data);
 }
+
+
+gpgme_error_t
+_gpgme_engine_cancel (engine_t engine)
+{
+  if (!engine)
+    return gpg_error (GPG_ERR_INV_VALUE);
+
+  if (!engine->ops->cancel)
+    return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+  return (*engine->ops->cancel) (engine->engine);
+}