core: Add 'is_mime' flags to the verify and decrypt results.
[gpgme.git] / src / engine-gpgconf.c
index 2ea8673..24867c7 100644 (file)
@@ -399,7 +399,7 @@ gpgconf_parse_option (gpgme_conf_opt_t opt,
                      gpgme_conf_arg_t *arg_p, char *line)
 {
   gpgme_error_t err;
-  char *mark;
+  char *mark = NULL;
 
   if (!line[0])
     return 0;
@@ -408,7 +408,8 @@ gpgconf_parse_option (gpgme_conf_opt_t opt,
     {
       gpgme_conf_arg_t arg;
 
-      mark = strchr (line, ',');
+      if (opt->type != GPGME_CONF_STRING)
+        mark = strchr (line, ',');
       if (mark)
        *mark = '\0';
 
@@ -708,10 +709,13 @@ gpgconf_write (void *engine, const char *arg1, char *arg2, gpgme_data_t conf)
 #define BUFLEN 1024
   char buf[BUFLEN];
   int buflen = 0;
-  char *argv[6];
+  char *argv[7];
   int argc = 0;
-  int rp[2];
-  struct spawn_fd_item_s cfd[] = { {-1, 0 /* STDIN_FILENO */}, {-1, -1} };
+  int rp[2] = { -1, -1 };
+  int errp[2] = { -1, -1 };
+  struct spawn_fd_item_s cfd[] = { {-1, 0 /* STDIN_FILENO */},
+                                   {-1, 2 /* STDERR_FILENO */, -1},
+                                   {-1, -1} };
   int status;
   int nwrite;
 
@@ -724,25 +728,38 @@ gpgconf_write (void *engine, const char *arg1, char *arg2, gpgme_data_t conf)
       argv[argc++] = gpgconf->home_dir;
     }
 
+  argv[argc++] = (char*)"--runtime";
   argv[argc++] = (char*)arg1;
   argv[argc++] = arg2;
   argv[argc] = NULL;
   assert (argc < DIM (argv));
 
   if (_gpgme_io_pipe (rp, 0) < 0)
-    return gpg_error_from_syserror ();
+    {
+      err = gpg_error_from_syserror ();
+      goto leave;
+    }
+
+  if (_gpgme_io_pipe (errp, 1) < 0)
+    {
+      err = gpg_error_from_syserror ();
+      goto leave;
+    }
 
   cfd[0].fd = rp[0];
+  cfd[1].fd = errp[1];
 
   status = _gpgme_io_spawn (gpgconf->file_name, argv,
                             IOSPAWN_FLAG_DETACHED, cfd, NULL, NULL, NULL);
   if (status < 0)
     {
-      _gpgme_io_close (rp[0]);
-      _gpgme_io_close (rp[1]);
-      return gpg_error_from_syserror ();
+      err = gpg_error_from_syserror ();
+      goto leave;
     }
 
+  rp[0] = -1;
+  errp[1] = -1;
+
   for (;;)
     {
       if (buflen == 0)
@@ -756,14 +773,29 @@ gpgconf_write (void *engine, const char *arg1, char *arg2, gpgme_data_t conf)
          if (buflen < 0)
            {
              err = gpg_error_from_syserror ();
-             _gpgme_io_close (rp[1]);
-             return err;
+              goto leave;
            }
          else if (buflen == 0)
            {
              /* All is written.  */
              _gpgme_io_close (rp[1]);
-             return 0;
+              rp[1] = -1;
+
+              for (;;)
+                {
+                  do
+                    {
+                      buflen = _gpgme_io_read (errp[0], buf, BUFLEN);
+                    }
+                  while (buflen < 0 && errno == EAGAIN);
+
+                  if (buflen == 0)
+                    {
+                      err = 0;
+                      goto leave;
+                    }
+                  /* XXX: Do something useful with BUF.  */
+                }
            }
        }
 
@@ -781,12 +813,24 @@ gpgconf_write (void *engine, const char *arg1, char *arg2, gpgme_data_t conf)
        }
       else if (nwrite < 0)
        {
-         _gpgme_io_close (rp[1]);
-         return gpg_error_from_syserror ();
+         err = gpg_error_from_syserror ();
+          goto leave;
        }
     }
 
-  return 0;
+  assert (! "reached");
+
+ leave:
+  if (rp[0] != -1)
+    _gpgme_io_close (rp[0]);
+  if (rp[1] != -1)
+  _gpgme_io_close (rp[1]);
+  if (errp[0] != -1)
+    _gpgme_io_close (errp[0]);
+  if (errp[1] != -1)
+  _gpgme_io_close (errp[1]);
+
+  return err;
 }
 
 
@@ -942,6 +986,60 @@ gpgconf_conf_save (void *engine, gpgme_conf_comp_t comp)
 }
 
 
+struct gpgconf_config_dir_s
+{
+  const char *what;
+  char *result;
+};
+
+/* Called for each line in the gpgconf --list-dirs output.  Searches
+   for the desired line and returns the result, indicating success by
+   a special error value GPG_ERR_USER_1 (which terminates the
+   operation immediately).  */
+static gpgme_error_t
+gpgconf_config_dir_cb (void *hook, char *line)
+{
+  /* This is an input- and output-parameter.  */
+  struct gpgconf_config_dir_s *data = (struct gpgconf_config_dir_s *) hook;
+  int len = strlen(data->what);
+
+  if (!strncmp(line, data->what, len) && line[len] == ':')
+    {
+      char *result = strdup(&line[len + 1]);
+      if (!result)
+       return gpg_error_from_syserror ();
+      data->result = result;
+      return gpg_error(GPG_ERR_USER_1);
+    }
+  return 0;
+}
+
+
+/* Like gpgme_get_dirinfo, but uses the home directory of ENGINE and
+   does not cache the result.  */
+static gpgme_error_t
+gpgconf_conf_dir (void *engine, const char *what, char **result)
+{
+  gpgme_error_t err;
+  struct gpgconf_config_dir_s data;
+
+  data.what = what;
+  data.result = NULL;
+  err = gpgconf_read (engine, "--list-dirs", NULL,
+                     gpgconf_config_dir_cb, &data);
+  if (gpg_err_code (err) == GPG_ERR_USER_1)
+    {
+      /* This signals to us that a result was found.  */
+      *result = data.result;
+      return 0;
+    }
+
+  if (!err)
+    err = gpg_error(GPG_ERR_NOT_FOUND);
+  return 0;
+}
+
+
 /* Parse a line received from gpgconf --query-swdb.  This function may
  * modify LINE.  The result is stored at RESUL.  */
 static gpg_error_t
@@ -1189,8 +1287,8 @@ struct engine_ops _gpgme_engine_ops_gpgconf =
     NULL,              /* set_colon_line_handler */
     NULL,              /* set_locale */
     NULL,              /* set_protocol */
+    NULL,               /* set_engine_flags */
     NULL,              /* decrypt */
-    NULL,              /* decrypt_verify */
     NULL,              /* delete */
     NULL,              /* edit */
     NULL,              /* encrypt */
@@ -1201,6 +1299,7 @@ struct engine_ops _gpgme_engine_ops_gpgconf =
     NULL,              /* import */
     NULL,              /* keylist */
     NULL,              /* keylist_ext */
+    NULL,               /* keylist_data */
     NULL,               /* keysign */
     NULL,               /* tofu_policy */
     NULL,              /* sign */
@@ -1210,6 +1309,7 @@ struct engine_ops _gpgme_engine_ops_gpgconf =
     NULL,               /* opassuan_transact */
     gpgconf_conf_load,
     gpgconf_conf_save,
+    gpgconf_conf_dir,
     gpgconf_query_swdb,
     gpgconf_set_io_cbs,
     NULL,              /* io_event */