Add public function gpgme_set_pinentry_mode.
[gpgme.git] / src / engine-assuan.c
index 07a21fa..5ef3047 100644 (file)
 
 #include <stdlib.h>
 #include <string.h>
-#include <sys/types.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
 #include <assert.h>
-#include <unistd.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifdef HAVE_LOCALE_H
 #include <locale.h>
+#endif
 #include <errno.h>
 
 #include "gpgme.h"
@@ -70,9 +76,8 @@ struct engine_llass
 
   struct gpgme_io_cbs io_cbs;
 
-  /* Internal callbacks.  */
-  engine_assuan_result_cb_t result_cb;
-  void *result_cb_value; 
+  /* Hack for old opassuan.c interface, see there the result struct.  */
+  gpg_error_t last_op_err;
 
   /* User provided callbacks.  */
   struct {
@@ -95,6 +100,12 @@ struct engine_llass
 typedef struct engine_llass *engine_llass_t;
 
 
+gpg_error_t _gpgme_engine_assuan_last_op_err (void *engine)
+{
+  engine_llass_t llass = engine;
+  return llass->last_op_err;
+}
+
 
 /* Prototypes.  */
 static void llass_io_event (void *engine,
@@ -169,6 +180,21 @@ llass_cancel (void *engine)
 }
 
 
+static gpgme_error_t
+llass_cancel_op (void *engine)
+{
+  engine_llass_t llass = engine;
+
+  if (!llass)
+    return gpg_error (GPG_ERR_INV_VALUE);
+
+  if (llass->status_cb.fd != -1)
+    _gpgme_io_close (llass->status_cb.fd);
+
+  return 0;
+}
+
+
 static void
 llass_release (void *engine)
 {
@@ -184,7 +210,7 @@ llass_release (void *engine)
 
 
 /* Create a new instance. If HOME_DIR is NULL standard options for use
-   with gpg-agent are issued.  */  
+   with gpg-agent are issued.  */
 static gpgme_error_t
 llass_new (void **engine, const char *file_name, const char *home_dir)
 {
@@ -208,15 +234,19 @@ llass_new (void **engine, const char *file_name, const char *home_dir)
       /* Very simple parser only working for the one option we support.  */
       /* Note that wk promised to write a regression test if this
          parser will be extended.  */
-      if (!strncmp (home_dir, "GPG_AGENT", 9) 
+      if (!strncmp (home_dir, "GPG_AGENT", 9)
           && (!home_dir[9] || home_dir[9] == ' '))
         llass->opt.gpg_agent = 1;
     }
 
-  err = assuan_new (&llass->assuan_ctx);
+  err = assuan_new_ext (&llass->assuan_ctx, GPG_ERR_SOURCE_GPGME,
+                       &_gpgme_assuan_malloc_hooks, _gpgme_assuan_log_cb,
+                       NULL);
   if (err)
     goto leave;
-  err = assuan_socket_connect (llass->assuan_ctx, file_name, 0);
+  assuan_ctx_set_system_hooks (llass->assuan_ctx, &_gpgme_assuan_system_hooks);
+
+  err = assuan_socket_connect (llass->assuan_ctx, file_name, 0, 0);
   if (err)
     goto leave;
 
@@ -282,7 +312,7 @@ llass_new (void **engine, const char *file_name, const char *home_dir)
                  goto leave;
                }
              free (dft_ttytype);
-              
+
              err = assuan_transact (llass->assuan_ctx, optstr, NULL, NULL,
                                     NULL, NULL, NULL, NULL);
              free (optstr);
@@ -334,7 +364,10 @@ llass_set_locale (void *engine, int category, const char *value)
   /* FIXME: If value is NULL, we need to reset the option to default.
      But we can't do this.  So we error out here.  gpg-agent needs
      support for this.  */
-  if (category == LC_CTYPE)
+  if (0)
+    ;
+#ifdef LC_CTYPE
+  else if (category == LC_CTYPE)
     {
       catstr = "lc-ctype";
       if (!value && llass->lc_ctype_set)
@@ -342,6 +375,7 @@ llass_set_locale (void *engine, int category, const char *value)
       if (value)
        llass->lc_ctype_set = 1;
     }
+#endif
 #ifdef LC_MESSAGES
   else if (category == LC_MESSAGES)
     {
@@ -360,7 +394,7 @@ llass_set_locale (void *engine, int category, const char *value)
     return 0;
 
   if (asprintf (&optstr, "OPTION %s=%s", catstr, value) < 0)
-    err = gpg_error_from_errno (errno);
+    err = gpg_error_from_syserror ();
   else
     {
       err = assuan_transact (llass->assuan_ctx, optstr, NULL, NULL,
@@ -408,8 +442,9 @@ inquire_cb (engine_llass_t llass, const char *keyword, const char *args)
 static gpgme_error_t
 llass_status_handler (void *opaque, int fd)
 {
+  struct io_cb_data *data = (struct io_cb_data *) opaque;
+  engine_llass_t llass = (engine_llass_t) data->handler_value;
   gpgme_error_t err = 0;
-  engine_llass_t llass = opaque;
   char *line;
   size_t linelen;
 
@@ -428,7 +463,7 @@ llass_status_handler (void *opaque, int fd)
              err = 0;
              continue;
            }
-         
+
          TRACE2 (DEBUG_CTX, "gpgme:llass_status_handler", llass,
                  "fd 0x%x: error reading assuan line: %s",
                   fd, gpg_strerror (err));
@@ -459,8 +494,6 @@ llass_status_handler (void *opaque, int fd)
           if (linelen && llass->user.data_cb)
             err = llass->user.data_cb (llass->user.data_cb_value,
                                        src, linelen);
-          else
-            err = 0;
 
           TRACE2 (DEBUG_CTX, "gpgme:llass_status_handler", llass,
                  "fd 0x%x: D inlinedata; status from cb: %s",
@@ -474,8 +507,6 @@ llass_status_handler (void *opaque, int fd)
           /* END received.  Tell the data callback.  */
           if (llass->user.data_cb)
             err = llass->user.data_cb (llass->user.data_cb_value, NULL, 0);
-          else
-            err = 0;
 
           TRACE2 (DEBUG_CTX, "gpgme:llass_status_handler", llass,
                  "fd 0x%x: END line; status from cb: %s",
@@ -502,8 +533,6 @@ llass_status_handler (void *opaque, int fd)
           if (llass->user.status_cb)
             err = llass->user.status_cb (llass->user.status_cb_value,
                                          src, args);
-          else
-            err = 0;
 
           TRACE3 (DEBUG_CTX, "gpgme:llass_status_handler", llass,
                  "fd 0x%x: S line (%s) - status from cb: %s",
@@ -532,7 +561,7 @@ llass_status_handler (void *opaque, int fd)
             args++;
 
           err = inquire_cb (llass, src, args);
-          if (!err) 
+          if (!err)
             {
               /* Flush and send END.  */
               err = assuan_send_data (llass->assuan_ctx, NULL, 0);
@@ -554,17 +583,15 @@ llass_status_handler (void *opaque, int fd)
           TRACE2 (DEBUG_CTX, "gpgme:llass_status_handler", llass,
                  "fd 0x%x: ERR line: %s",
                   fd, err ? gpg_strerror (err) : "ok");
+
          /* Command execution errors are not fatal, as we use
             a session based protocol.  */
-          if (llass->result_cb)
-            err = llass->result_cb (llass->result_cb_value, err);
-          else
-            err = 0;
-          if (!err)
-            {
-              _gpgme_io_close (llass->status_cb.fd);
-              return 0;
-            }
+         data->op_err = err;
+         llass->last_op_err = err;
+
+         /* The caller will do the rest (namely, call cancel_op,
+            which closes status_fd).  */
+         return 0;
        }
       else if (linelen >= 2
               && line[0] == 'O' && line[1] == 'K'
@@ -572,15 +599,11 @@ llass_status_handler (void *opaque, int fd)
        {
           TRACE1 (DEBUG_CTX, "gpgme:llass_status_handler", llass,
                  "fd 0x%x: OK line", fd);
-          if (llass->result_cb)
-            err = llass->result_cb (llass->result_cb_value, 0);
-          else
-            err = 0;
-          if (!err)
-            {
-              _gpgme_io_close (llass->status_cb.fd);
-              return 0;
-            }
+
+         llass->last_op_err = 0;
+
+         _gpgme_io_close (llass->status_cb.fd);
+         return 0;
        }
       else
         {
@@ -617,16 +640,21 @@ static gpgme_error_t
 start (engine_llass_t llass, const char *command)
 {
   gpgme_error_t err;
+  assuan_fd_t afdlist[5];
   int fdlist[5];
   int nfds;
+  int i;
 
   /* We need to know the fd used by assuan for reads.  We do this by
      using the assumption that the first returned fd from
      assuan_get_active_fds() is always this one.  */
   nfds = assuan_get_active_fds (llass->assuan_ctx, 0 /* read fds */,
-                                fdlist, DIM (fdlist));
+                                afdlist, DIM (afdlist));
   if (nfds < 1)
     return gpg_error (GPG_ERR_GENERAL);        /* FIXME */
+  /* For now... */
+  for (i = 0; i < nfds; i++)
+    fdlist[i] = (int) afdlist[i];
 
   /* We "duplicate" the file descriptor, so we can close it here (we
      can't close fdlist[0], as that is closed by libassuan, and
@@ -667,8 +695,6 @@ start (engine_llass_t llass, const char *command)
 static gpgme_error_t
 llass_transact (void *engine,
                 const char *command,
-                engine_assuan_result_cb_t result_cb,
-                void *result_cb_value,
                 gpgme_assuan_data_cb_t data_cb,
                 void *data_cb_value,
                 gpgme_assuan_inquire_cb_t inq_cb,
@@ -682,8 +708,6 @@ llass_transact (void *engine,
   if (!llass || !command || !*command)
     return gpg_error (GPG_ERR_INV_VALUE);
 
-  llass->result_cb = result_cb;
-  llass->result_cb_value = result_cb_value;
   llass->user.data_cb = data_cb;
   llass->user.data_cb_value = data_cb_value;
   llass->user.inq_cb = inq_cb;
@@ -734,7 +758,9 @@ struct engine_ops _gpgme_engine_ops_assuan =
     NULL,              /* set_command_handler */
     NULL,               /* set_colon_line_handler */
     llass_set_locale,
+    NULL,              /* set_protocol */
     NULL,               /* decrypt */
+    NULL,               /* decrypt_verify */
     NULL,               /* delete */
     NULL,              /* edit */
     NULL,               /* encrypt */
@@ -754,5 +780,8 @@ struct engine_ops _gpgme_engine_ops_assuan =
     NULL,              /* conf_save */
     llass_set_io_cbs,
     llass_io_event,
-    llass_cancel
+    llass_cancel,
+    llass_cancel_op,
+    NULL,               /* passwd */
+    NULL                /* set_pinentry_mode */
   };