Merge branch 'master' of ssh+git://playfair.gnupg.org/git/gpgme
[gpgme.git] / src / engine-uiserver.c
index 92f7536..fd5ac17 100644 (file)
@@ -1,19 +1,19 @@
 /* engine-uiserver.c - Uiserver engine.
    Copyright (C) 2000 Werner Koch (dd9jn)
    Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2009 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 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
    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
@@ -49,7 +49,6 @@
 #include "data.h"
 
 #include "assuan.h"
-#include "status-table.h"
 #include "debug.h"
 
 #include "engine-backend.h"
@@ -91,6 +90,8 @@ struct engine_uiserver
   {
     engine_status_handler_t fnc;
     void *fnc_value;
+    gpgme_status_cb_t mon_cb;
+    void *mon_cb_value;
   } status;
 
   struct
@@ -104,7 +105,7 @@ struct engine_uiserver
       int linelen;
     } attic;
     int any; /* any data line seen */
-  } colon; 
+  } colon;
 
   gpgme_data_t inline_data;  /* Used to collect D lines.  */
 
@@ -114,7 +115,7 @@ struct engine_uiserver
 typedef struct engine_uiserver *engine_uiserver_t;
 
 
-static void uiserver_io_event (void *engine, 
+static void uiserver_io_event (void *engine,
                             gpgme_event_io_t type, void *type_data);
 
 
@@ -122,14 +123,15 @@ static void uiserver_io_event (void *engine,
 static char *
 uiserver_get_version (const char *file_name)
 {
-  return strdup ("1.0");
+  (void)file_name;
+  return NULL;
 }
 
 
 static const char *
 uiserver_get_req_version (void)
 {
-  return "1.0";
+  return NULL;
 }
 
 \f
@@ -185,6 +187,8 @@ close_notify_handler (int fd, void *opaque)
 static gpgme_error_t
 default_inq_cb (engine_uiserver_t uiserver, const char *line)
 {
+  (void)uiserver;
+
   if (!strncmp (line, "PINENTRY_LAUNCHED", 17) && (line[17]==' '||!line[17]))
     {
       _gpgme_allow_set_foreground_window ((pid_t)strtoul (line+17, NULL, 10));
@@ -237,15 +241,20 @@ uiserver_release (void *engine)
 
 
 static gpgme_error_t
-uiserver_new (void **engine, const char *file_name, const char *home_dir)
+uiserver_new (void **engine, const char *file_name, const char *home_dir,
+              const char *version)
 {
   gpgme_error_t err = 0;
   engine_uiserver_t uiserver;
   char *dft_display = NULL;
   char dft_ttyname[64];
+  char *env_tty = NULL;
   char *dft_ttytype = NULL;
   char *optstr;
 
+  (void)home_dir;
+  (void)version; /* Not yet used.  */
+
   uiserver = calloc (1, sizeof *uiserver);
   if (!uiserver)
     return gpg_error_from_syserror ();
@@ -297,7 +306,7 @@ uiserver_new (void **engine, const char *file_name, const char *home_dir)
 
   err = assuan_socket_connect (uiserver->assuan_ctx,
                               file_name ?
-                              file_name : _gpgme_get_uiserver_socket_path (),
+                              file_name : _gpgme_get_default_uisrv_socket (),
                               0, ASSUAN_SOCKET_SERVER_FDPASSING);
   if (err)
     goto leave;
@@ -307,41 +316,48 @@ uiserver_new (void **engine, const char *file_name, const char *home_dir)
     goto leave;
   if (dft_display)
     {
-      if (asprintf (&optstr, "OPTION display=%s", dft_display) < 0)
+      if (gpgrt_asprintf (&optstr, "OPTION display=%s", dft_display) < 0)
         {
+         err = gpg_error_from_syserror ();
          free (dft_display);
-         err = gpg_error_from_errno (errno);
          goto leave;
        }
       free (dft_display);
 
       err = assuan_transact (uiserver->assuan_ctx, optstr, NULL, NULL, NULL,
                             NULL, NULL, NULL);
-      free (optstr);
+      gpgrt_free (optstr);
       if (err)
        goto leave;
     }
 
-  if (isatty (1))
+  err = _gpgme_getenv ("GPG_TTY", &env_tty);
+  if (isatty (1) || env_tty || err)
     {
-      int rc;
+      int rc = 0;
 
-      rc = ttyname_r (1, dft_ttyname, sizeof (dft_ttyname));
-      if (rc)
-       {
-         err = gpg_error_from_errno (rc);
-         goto leave;
-       }
+      if (err)
+        goto leave;
+      else if (env_tty)
+        {
+          snprintf (dft_ttyname, sizeof (dft_ttyname), "%s", env_tty);
+          free (env_tty);
+        }
       else
+        rc = ttyname_r (1, dft_ttyname, sizeof (dft_ttyname));
+
+      /* Even though isatty() returns 1, ttyname_r() may fail in many
+        ways, e.g., when /dev/pts is not accessible under chroot.  */
+      if (!rc)
        {
-         if (asprintf (&optstr, "OPTION ttyname=%s", dft_ttyname) < 0)
+         if (gpgrt_asprintf (&optstr, "OPTION ttyname=%s", dft_ttyname) < 0)
            {
-             err = gpg_error_from_errno (errno);
+             err = gpg_error_from_syserror ();
              goto leave;
            }
          err = assuan_transact (uiserver->assuan_ctx, optstr, NULL, NULL, NULL,
                                 NULL, NULL, NULL);
-         free (optstr);
+         gpgrt_free (optstr);
          if (err)
            goto leave;
 
@@ -350,17 +366,17 @@ uiserver_new (void **engine, const char *file_name, const char *home_dir)
            goto leave;
          if (dft_ttytype)
            {
-             if (asprintf (&optstr, "OPTION ttytype=%s", dft_ttytype) < 0)
+             if (gpgrt_asprintf (&optstr, "OPTION ttytype=%s", dft_ttytype)< 0)
                {
+                 err = gpg_error_from_syserror ();
                  free (dft_ttytype);
-                 err = gpg_error_from_errno (errno);
                  goto leave;
                }
              free (dft_ttytype);
 
              err = assuan_transact (uiserver->assuan_ctx, optstr, NULL, NULL,
                                     NULL, NULL, NULL, NULL);
-             free (optstr);
+             gpgrt_free (optstr);
              if (err)
                goto leave;
            }
@@ -395,7 +411,7 @@ uiserver_set_locale (void *engine, int category, const char *value)
   engine_uiserver_t uiserver = engine;
   gpgme_error_t err;
   char *optstr;
-  char *catstr;
+  const char *catstr;
 
   /* FIXME: If value is NULL, we need to reset the option to default.
      But we can't do this.  So we error out here.  UISERVER needs support
@@ -422,16 +438,16 @@ uiserver_set_locale (void *engine, int category, const char *value)
     return gpg_error (GPG_ERR_INV_VALUE);
 
   /* FIXME: Reset value to default.  */
-  if (!value) 
+  if (!value)
     return 0;
 
-  if (asprintf (&optstr, "OPTION %s=%s", catstr, value) < 0)
-    err = gpg_error_from_errno (errno);
+  if (gpgrt_asprintf (&optstr, "OPTION %s=%s", catstr, value) < 0)
+    err = gpg_error_from_syserror ();
   else
     {
       err = assuan_transact (uiserver->assuan_ctx, optstr, NULL, NULL,
                             NULL, NULL, NULL, NULL);
-      free (optstr);
+      gpgrt_free (optstr);
     }
 
   return err;
@@ -453,14 +469,12 @@ uiserver_set_protocol (void *engine, gpgme_protocol_t protocol)
 }
 
 
-/* Forward declaration.  */
-static gpgme_status_code_t parse_status (const char *name);
-
 static gpgme_error_t
-uiserver_assuan_simple_command (assuan_context_t ctx, char *cmd,
-                            engine_status_handler_t status_fnc,
-                            void *status_fnc_value)
+uiserver_assuan_simple_command (engine_uiserver_t uiserver, const char *cmd,
+                                engine_status_handler_t status_fnc,
+                                void *status_fnc_value)
 {
+  assuan_context_t ctx = uiserver->assuan_ctx;
   gpg_error_t err;
   char *line;
   size_t linelen;
@@ -498,9 +512,18 @@ uiserver_assuan_simple_command (assuan_context_t ctx, char *cmd,
          else
            *(rest++) = 0;
 
-         r = parse_status (line + 2);
+         r = _gpgme_parse_status (line + 2);
+          if (uiserver->status.mon_cb && r != GPGME_STATUS_PROGRESS)
+            {
+              /* Note that we call the monitor even if we do
+               * not know the status code (r < 0).  */
+              err = uiserver->status.mon_cb (uiserver->status.mon_cb_value,
+                                             line + 2, rest);
+            }
 
-         if (r >= 0 && status_fnc)
+          if (err)
+            ;
+         else if (r >= 0 && status_fnc)
            err = status_fnc (status_fnc_value, r, rest);
          else
            err = gpg_error (GPG_ERR_GENERAL);
@@ -522,7 +545,7 @@ uiserver_set_fd (engine_uiserver_t uiserver, fd_type_t fd_type, const char *opt)
 {
   gpg_error_t err = 0;
   char line[COMMANDLINELEN];
-  char *which;
+  const char *which;
   iocb_data_t *iocb_data;
   int dir;
 
@@ -557,7 +580,7 @@ uiserver_set_fd (engine_uiserver_t uiserver, fd_type_t fd_type, const char *opt)
       int fds[2];
 
       if (_gpgme_io_pipe (fds, 0) < 0)
-       return gpg_error_from_errno (errno);
+       return gpg_error_from_syserror ();
 
       iocb_data->fd = dir ? fds[0] : fds[1];
       iocb_data->server_fd = dir ? fds[1] : fds[0];
@@ -582,7 +605,7 @@ uiserver_set_fd (engine_uiserver_t uiserver, fd_type_t fd_type, const char *opt)
   else
     snprintf (line, COMMANDLINELEN, "%s FD", which);
 
-  err = uiserver_assuan_simple_command (uiserver->assuan_ctx, line, NULL, NULL);
+  err = uiserver_assuan_simple_command (uiserver, line, NULL, NULL);
 
  leave_set_fd:
   if (err)
@@ -620,27 +643,6 @@ map_data_enc (gpgme_data_t d)
 }
 
 
-static int
-status_cmp (const void *ap, const void *bp)
-{
-  const struct status_table_s *a = ap;
-  const struct status_table_s *b = bp;
-
-  return strcmp (a->name, b->name);
-}
-
-
-static gpgme_status_code_t
-parse_status (const char *name)
-{
-  struct status_table_s t, *r;
-  t.name = name;
-  r = bsearch (&t, status_table, DIM(status_table) - 1,
-              sizeof t, status_cmp);
-  return r ? r->code : -1;
-}
-
-
 static gpgme_error_t
 status_handler (void *opaque, int fd)
 {
@@ -680,9 +682,14 @@ status_handler (void *opaque, int fd)
               && (line[2] == '\0' || line[2] == ' '))
        {
          if (uiserver->status.fnc)
-           err = uiserver->status.fnc (uiserver->status.fnc_value,
-                                    GPGME_STATUS_EOF, "");
-         
+            {
+              char emptystring[1] = {0};
+              err = uiserver->status.fnc (uiserver->status.fnc_value,
+                                          GPGME_STATUS_EOF, emptystring);
+              if (gpg_err_code (err) == GPG_ERR_FALSE)
+                err = 0; /* Drop special error code.  */
+            }
+
          if (!err && uiserver->colon.fnc && uiserver->colon.any)
             {
               /* We must tell a colon function about the EOF. We do
@@ -719,11 +726,11 @@ status_handler (void *opaque, int fd)
            {
              char *newline = realloc (*aline, *alinelen + linelen + 1);
              if (!newline)
-               err = gpg_error_from_errno (errno);
+               err = gpg_error_from_syserror ();
              else
                {
                  *aline = newline;
-                 uiserver->colon.attic.linesize += linelen + 1;
+                 uiserver->colon.attic.linesize = *alinelen + linelen + 1;
                }
            }
          if (!err)
@@ -745,12 +752,12 @@ status_handler (void *opaque, int fd)
                      *dst = *src++;
                      (*alinelen)++;
                    }
-                 
+
                  if (*dst == '\n')
                    {
                      /* Terminate the pending line, pass it to the colon
                         handler and reset it.  */
-                     
+
                      uiserver->colon.any = 1;
                      if (*alinelen > 1 && *(dst - 1) == '\r')
                        dst--;
@@ -779,7 +786,7 @@ status_handler (void *opaque, int fd)
           char *src = line + 2;
          char *end = line + linelen;
          char *dst = src;
-          ssize_t nwritten;
+          gpgme_ssize_t nwritten;
 
           linelen = 0;
           while (src < end)
@@ -793,10 +800,10 @@ status_handler (void *opaque, int fd)
                 }
               else
                 *dst++ = *src++;
-              
+
               linelen++;
             }
-          
+
           src = line + 2;
           while (linelen > 0)
             {
@@ -804,7 +811,7 @@ status_handler (void *opaque, int fd)
               if (!nwritten || (nwritten < 0 && errno != EINTR)
                   || nwritten > linelen)
                 {
-                  err = gpg_error_from_errno (errno);
+                  err = gpg_error_from_syserror ();
                   break;
                 }
               src += nwritten;
@@ -820,19 +827,24 @@ status_handler (void *opaque, int fd)
        {
          char *rest;
          gpgme_status_code_t r;
-         
+
          rest = strchr (line + 2, ' ');
          if (!rest)
            rest = line + linelen; /* set to an empty string */
          else
            *(rest++) = 0;
 
-         r = parse_status (line + 2);
+         r = _gpgme_parse_status (line + 2);
 
          if (r >= 0)
            {
              if (uiserver->status.fnc)
-               err = uiserver->status.fnc (uiserver->status.fnc_value, r, rest);
+                {
+                  err = uiserver->status.fnc (uiserver->status.fnc_value,
+                                              r, rest);
+                  if (gpg_err_code (err) == GPG_ERR_FALSE)
+                    err = 0; /* Drop special error code.  */
+                }
            }
          else
            fprintf (stderr, "[UNKNOWN STATUS]%s %s", line + 2, rest);
@@ -843,7 +855,7 @@ status_handler (void *opaque, int fd)
       else if (linelen >= 7
                && line[0] == 'I' && line[1] == 'N' && line[2] == 'Q'
                && line[3] == 'U' && line[4] == 'I' && line[5] == 'R'
-               && line[6] == 'E' 
+               && line[6] == 'E'
                && (line[7] == '\0' || line[7] == ' '))
         {
           char *keyword = line+7;
@@ -856,7 +868,7 @@ status_handler (void *opaque, int fd)
 
     }
   while (!err && assuan_pending_line (uiserver->assuan_ctx));
-         
+
   return err;
 }
 
@@ -942,18 +954,27 @@ uiserver_reset (void *engine)
 
   /* We must send a reset because we need to reset the list of
      signers.  Note that RESET does not reset OPTION commands. */
-  return uiserver_assuan_simple_command (uiserver->assuan_ctx, "RESET", NULL, NULL);
+  return uiserver_assuan_simple_command (uiserver, "RESET", NULL, NULL);
 }
 
 
 static gpgme_error_t
-_uiserver_decrypt (void *engine, int verify,
-                  gpgme_data_t ciph, gpgme_data_t plain)
+uiserver_decrypt (void *engine,
+                  gpgme_decrypt_flags_t flags,
+                  gpgme_data_t ciph, gpgme_data_t plain,
+                  int export_session_key, const char *override_session_key,
+                  int auto_key_retrieve)
 {
   engine_uiserver_t uiserver = engine;
   gpgme_error_t err;
   const char *protocol;
   char *cmd;
+  int verify = !!(flags & GPGME_DECRYPT_VERIFY);
+
+  (void)override_session_key; /* Fixme: We need to see now to add this
+                               * to the UI server protocol  */
+  (void)auto_key_retrieve;    /* Not yet supported.  */
+
 
   if (!uiserver)
     return gpg_error (GPG_ERR_INV_VALUE);
@@ -966,52 +987,38 @@ _uiserver_decrypt (void *engine, int verify,
   else
     return gpgme_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
 
-  if (asprintf (&cmd, "DECRYPT%s%s", protocol,
-               verify ? "" : " --no-verify") < 0)
-    return gpg_error_from_errno (errno);
+  if (gpgrt_asprintf (&cmd, "DECRYPT%s%s%s", protocol,
+               verify ? "" : " --no-verify",
+                export_session_key ? " --export-session-key" : "") < 0)
+    return gpg_error_from_syserror ();
 
   uiserver->input_cb.data = ciph;
   err = uiserver_set_fd (uiserver, INPUT_FD,
                         map_data_enc (uiserver->input_cb.data));
   if (err)
     {
-      free (cmd);
+      gpgrt_free (cmd);
       return gpg_error (GPG_ERR_GENERAL);      /* FIXME */
     }
   uiserver->output_cb.data = plain;
   err = uiserver_set_fd (uiserver, OUTPUT_FD, 0);
   if (err)
     {
-      free (cmd);
+      gpgrt_free (cmd);
       return gpg_error (GPG_ERR_GENERAL);      /* FIXME */
     }
   uiserver->inline_data = NULL;
 
   err = start (engine, cmd);
-  free (cmd);
+  gpgrt_free (cmd);
   return err;
 }
 
 
 static gpgme_error_t
-uiserver_decrypt (void *engine, gpgme_data_t ciph, gpgme_data_t plain)
-{
-  return _uiserver_decrypt (engine, 0, ciph, plain);
-}
-
-
-static gpgme_error_t
-uiserver_decrypt_verify (void *engine, gpgme_data_t ciph, gpgme_data_t plain)
-{
-  return _uiserver_decrypt (engine, 1, ciph, plain);
-}
-
-
-static gpgme_error_t
 set_recipients (engine_uiserver_t uiserver, gpgme_key_t recp[])
 {
   gpgme_error_t err = 0;
-  assuan_context_t ctx = uiserver->assuan_ctx;
   char *line;
   int linelen;
   int invalid_recipients = 0;
@@ -1020,7 +1027,7 @@ set_recipients (engine_uiserver_t uiserver, gpgme_key_t recp[])
   linelen = 10 + 40 + 1;       /* "RECIPIENT " + guess + '\0'.  */
   line = malloc (10 + 40 + 1);
   if (!line)
-    return gpg_error_from_errno (errno);
+    return gpg_error_from_syserror ();
   strcpy (line, "RECIPIENT ");
   for (i=0; !err && recp[i]; i++)
     {
@@ -1040,9 +1047,9 @@ set_recipients (engine_uiserver_t uiserver, gpgme_key_t recp[])
          char *newline = realloc (line, newlen);
          if (! newline)
            {
-             int saved_errno = errno;
+             int saved_err = gpg_error_from_syserror ();
              free (line);
-             return gpg_error_from_errno (saved_errno);
+             return saved_err;
            }
          line = newline;
          linelen = newlen;
@@ -1050,7 +1057,8 @@ set_recipients (engine_uiserver_t uiserver, gpgme_key_t recp[])
       /* FIXME: need to do proper escaping  */
       strcpy (&line[10], uid);
 
-      err = uiserver_assuan_simple_command (ctx, line, uiserver->status.fnc,
+      err = uiserver_assuan_simple_command (uiserver, line,
+                                            uiserver->status.fnc,
                                             uiserver->status.fnc_value);
       /* FIXME: This might requires more work.  */
       if (gpg_err_code (err) == GPG_ERR_NO_PUBKEY)
@@ -1092,18 +1100,18 @@ uiserver_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,
       if (!recp || plain || ciph)
        return gpg_error (GPG_ERR_INV_VALUE);
 
-      if (asprintf (&cmd, "PREP_ENCRYPT%s%s", protocol,
+      if (gpgrt_asprintf (&cmd, "PREP_ENCRYPT%s%s", protocol,
                    (flags & GPGME_ENCRYPT_EXPECT_SIGN)
                    ? " --expect-sign" : "") < 0)
-       return gpg_error_from_errno (errno);
+       return gpg_error_from_syserror ();
     }
   else
     {
       if (!plain || !ciph)
        return gpg_error (GPG_ERR_INV_VALUE);
 
-      if (asprintf (&cmd, "ENCRYPT%s", protocol) < 0)
-       return gpg_error_from_errno (errno);
+      if (gpgrt_asprintf (&cmd, "ENCRYPT%s", protocol) < 0)
+       return gpg_error_from_syserror ();
     }
 
   if (plain)
@@ -1113,11 +1121,11 @@ uiserver_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,
                             map_data_enc (uiserver->input_cb.data));
       if (err)
        {
-         free (cmd);
+         gpgrt_free (cmd);
          return err;
        }
     }
-    
+
   if (ciph)
     {
       uiserver->output_cb.data = ciph;
@@ -1125,7 +1133,7 @@ uiserver_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,
                             : map_data_enc (uiserver->output_cb.data));
       if (err)
        {
-         free (cmd);
+         gpgrt_free (cmd);
          return err;
        }
     }
@@ -1137,13 +1145,13 @@ uiserver_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,
       err = set_recipients (uiserver, recp);
       if (err)
        {
-         free (cmd);
+         gpgrt_free (cmd);
          return err;
        }
     }
 
   err = start (uiserver, cmd);
-  free (cmd);
+  gpgrt_free (cmd);
   return err;
 }
 
@@ -1159,6 +1167,9 @@ uiserver_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
   char *cmd;
   gpgme_key_t key;
 
+  (void)use_textmode;
+  (void)include_certs;
+
   if (!uiserver || !in || !out)
     return gpg_error (GPG_ERR_INV_VALUE);
   if (uiserver->protocol == GPGME_PROTOCOL_DEFAULT)
@@ -1170,35 +1181,35 @@ uiserver_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
   else
     return gpgme_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
 
-  if (asprintf (&cmd, "SIGN%s%s", protocol,
+  if (gpgrt_asprintf (&cmd, "SIGN%s%s", protocol,
                (mode == GPGME_SIG_MODE_DETACH) ? " --detached" : "") < 0)
-    return gpg_error_from_errno (errno);
+    return gpg_error_from_syserror ();
 
   key = gpgme_signers_enum (ctx, 0);
   if (key)
     {
       const char *s = NULL;
-      
+
       if (key && key->uids)
         s = key->uids->email;
-      
+
       if (s && strlen (s) < 80)
         {
           char buf[100];
-          
+
           strcpy (stpcpy (buf, "SENDER --info "), s);
-          err = uiserver_assuan_simple_command (uiserver->assuan_ctx, buf,
+          err = uiserver_assuan_simple_command (uiserver, buf,
                                                 uiserver->status.fnc,
                                                 uiserver->status.fnc_value);
         }
       else
         err = gpg_error (GPG_ERR_INV_VALUE);
       gpgme_key_unref (key);
-      if (err) 
-      {
-       free (cmd);
-       return err;
-      }
+      if (err)
+        {
+          gpgrt_free (cmd);
+          return err;
+        }
   }
 
   uiserver->input_cb.data = in;
@@ -1206,7 +1217,7 @@ uiserver_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
                         map_data_enc (uiserver->input_cb.data));
   if (err)
     {
-      free (cmd);
+      gpgrt_free (cmd);
       return err;
     }
   uiserver->output_cb.data = out;
@@ -1214,13 +1225,13 @@ uiserver_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
                         : map_data_enc (uiserver->output_cb.data));
   if (err)
     {
-      free (cmd);
+      gpgrt_free (cmd);
       return err;
     }
   uiserver->inline_data = NULL;
 
   err = start (uiserver, cmd);
-  free (cmd);
+  gpgrt_free (cmd);
   return err;
 }
 
@@ -1228,13 +1239,16 @@ uiserver_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
 /* FIXME: Missing a way to specify --silent.  */
 static gpgme_error_t
 uiserver_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
-             gpgme_data_t plaintext)
+                 gpgme_data_t plaintext, gpgme_ctx_t ctx)
 {
   engine_uiserver_t uiserver = engine;
   gpgme_error_t err;
   const char *protocol;
   char *cmd;
 
+  (void)ctx; /* FIXME: We should to add a --sender option to the
+              * UISever protocol.  */
+
   if (!uiserver)
     return gpg_error (GPG_ERR_INV_VALUE);
   if (uiserver->protocol == GPGME_PROTOCOL_DEFAULT)
@@ -1246,15 +1260,15 @@ uiserver_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
   else
     return gpgme_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
 
-  if (asprintf (&cmd, "VERIFY%s", protocol) < 0)
-    return gpg_error_from_errno (errno);
+  if (gpgrt_asprintf (&cmd, "VERIFY%s", protocol) < 0)
+    return gpg_error_from_syserror ();
 
   uiserver->input_cb.data = sig;
   err = uiserver_set_fd (uiserver, INPUT_FD,
                         map_data_enc (uiserver->input_cb.data));
   if (err)
     {
-      free (cmd);
+      gpgrt_free (cmd);
       return err;
     }
   if (plaintext)
@@ -1274,14 +1288,26 @@ uiserver_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
   if (!err)
     err = start (uiserver, cmd);
 
-  free (cmd);
+  gpgrt_free (cmd);
   return err;
 }
 
 
+/* This sets a status callback for monitoring status lines before they
+ * are passed to a caller set handler.  */
+static void
+uiserver_set_status_cb (void *engine, gpgme_status_cb_t cb, void *cb_value)
+{
+  engine_uiserver_t uiserver = engine;
+
+  uiserver->status.mon_cb = cb;
+  uiserver->status.mon_cb_value = cb_value;
+}
+
+
 static void
 uiserver_set_status_handler (void *engine, engine_status_handler_t fnc,
-                         void *fnc_value) 
+                         void *fnc_value)
 {
   engine_uiserver_t uiserver = engine;
 
@@ -1292,7 +1318,7 @@ uiserver_set_status_handler (void *engine, engine_status_handler_t fnc,
 
 static gpgme_error_t
 uiserver_set_colon_line_handler (void *engine, engine_colon_line_handler_t fnc,
-                             void *fnc_value) 
+                             void *fnc_value)
 {
   engine_uiserver_t uiserver = engine;
 
@@ -1327,7 +1353,7 @@ uiserver_io_event (void *engine, gpgme_event_io_t type, void *type_data)
 struct engine_ops _gpgme_engine_ops_uiserver =
   {
     /* Static functions.  */
-    _gpgme_get_uiserver_socket_path,
+    _gpgme_get_default_uisrv_socket,
     NULL,
     uiserver_get_version,
     uiserver_get_req_version,
@@ -1336,13 +1362,14 @@ struct engine_ops _gpgme_engine_ops_uiserver =
     /* Member functions.  */
     uiserver_release,
     uiserver_reset,
+    uiserver_set_status_cb,
     uiserver_set_status_handler,
     NULL,              /* set_command_handler */
     uiserver_set_colon_line_handler,
     uiserver_set_locale,
     uiserver_set_protocol,
+    NULL,               /* set_engine_flags */
     uiserver_decrypt,
-    uiserver_decrypt_verify,
     NULL,              /* delete */
     NULL,              /* edit */
     uiserver_encrypt,
@@ -1353,6 +1380,9 @@ struct engine_ops _gpgme_engine_ops_uiserver =
     NULL,              /* import */
     NULL,              /* keylist */
     NULL,              /* keylist_ext */
+    NULL,               /* keylist_data */
+    NULL,               /* keysign */
+    NULL,               /* tofu_policy */
     uiserver_sign,
     NULL,              /* trustlist */
     uiserver_verify,
@@ -1360,8 +1390,13 @@ struct engine_ops _gpgme_engine_ops_uiserver =
     NULL,               /* opassuan_transact */
     NULL,              /* conf_load */
     NULL,              /* conf_save */
+    NULL,              /* conf_dir */
+    NULL,               /* query_swdb */
     uiserver_set_io_cbs,
     uiserver_io_event,
     uiserver_cancel,
-    NULL               /* cancel_op */
+    NULL,              /* cancel_op */
+    NULL,               /* passwd */
+    NULL,               /* set_pinentry_mode */
+    NULL                /* opspawn */
   };