core: Use gpgrt locking for thread safeness
[gpgme.git] / src / engine-gpgsm.c
index 3aa9f0b..a815cf0 100644 (file)
@@ -185,6 +185,8 @@ close_notify_handler (int fd, void *opaque)
 static gpgme_error_t
 default_inq_cb (engine_gpgsm_t gpgsm, const char *line)
 {
+  (void)gpgsm;
+
   if (!strncmp (line, "PINENTRY_LAUNCHED", 17) && (line[17]==' '||!line[17]))
     {
       _gpgme_allow_set_foreground_window ((pid_t)strtoul (line+17, NULL, 10));
@@ -237,7 +239,8 @@ gpgsm_release (void *engine)
 
 
 static gpgme_error_t
-gpgsm_new (void **engine, const char *file_name, const char *home_dir)
+gpgsm_new (void **engine, const char *file_name, const char *home_dir,
+           const char *version)
 {
   gpgme_error_t err = 0;
   engine_gpgsm_t gpgsm;
@@ -250,9 +253,12 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir)
 #endif
   char *dft_display = NULL;
   char dft_ttyname[64];
+  char *env_tty = NULL;
   char *dft_ttytype = NULL;
   char *optstr;
 
+  (void)version; /* Not yet used.  */
+
   gpgsm = calloc (1, sizeof *gpgsm);
   if (!gpgsm)
     return gpg_error_from_syserror ();
@@ -405,11 +411,20 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir)
        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 (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.  */
@@ -512,7 +527,7 @@ gpgsm_set_locale (void *engine, int category, const char *value)
   engine_gpgsm_t gpgsm = 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.  GPGSM needs support
@@ -560,7 +575,7 @@ gpgsm_set_locale (void *engine, int category, const char *value)
 
 
 static gpgme_error_t
-gpgsm_assuan_simple_command (engine_gpgsm_t gpgsm, char *cmd,
+gpgsm_assuan_simple_command (engine_gpgsm_t gpgsm, const char *cmd,
                             engine_status_handler_t status_fnc,
                             void *status_fnc_value)
 {
@@ -657,6 +672,9 @@ gpgsm_clear_fd (engine_gpgsm_t gpgsm, fd_type_t fd_type)
       _gpgme_io_close (gpgsm->message_cb.fd);
       break;
     }
+#else
+  (void)gpgsm;
+  (void)fd_type;
 #endif
 }
 
@@ -666,7 +684,7 @@ gpgsm_set_fd (engine_gpgsm_t gpgsm, 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;
 #if USE_DESCRIPTOR_PASSING
   int dir;
@@ -815,8 +833,13 @@ status_handler (void *opaque, int fd)
               && (line[2] == '\0' || line[2] == ' '))
        {
          if (gpgsm->status.fnc)
-           err = gpgsm->status.fnc (gpgsm->status.fnc_value,
-                                    GPGME_STATUS_EOF, "");
+            {
+              char emptystring[1] = {0};
+              err = gpgsm->status.fnc (gpgsm->status.fnc_value,
+                                       GPGME_STATUS_EOF, emptystring);
+              if (gpg_err_code (err) == GPG_ERR_FALSE)
+                err = 0; /* Drop special error code.  */
+            }
 
          if (!err && gpgsm->colon.fnc && gpgsm->colon.any)
             {
@@ -967,7 +990,11 @@ status_handler (void *opaque, int fd)
          if (r >= 0)
            {
              if (gpgsm->status.fnc)
-               err = gpgsm->status.fnc (gpgsm->status.fnc_value, r, rest);
+                {
+                  err = gpgsm->status.fnc (gpgsm->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);
@@ -1127,6 +1154,8 @@ gpgsm_delete (void *engine, gpgme_key_t key, int allow_secret)
   char *line;
   int length = 8;      /* "DELKEYS " */
 
+  (void)allow_secret;
+
   if (!fpr)
     return gpg_error (GPG_ERR_INV_VALUE);
 
@@ -1430,29 +1459,51 @@ gpgsm_export_ext (void *engine, const char *pattern[], gpgme_export_mode_t mode,
 
 
 static gpgme_error_t
-gpgsm_genkey (void *engine, gpgme_data_t help_data, int use_armor,
+gpgsm_genkey (void *engine,
+              const char *userid, const char *algo,
+              unsigned long reserved, unsigned long expires,
+              gpgme_key_t key, unsigned int flags,
+              gpgme_data_t help_data, unsigned int extraflags,
              gpgme_data_t pubkey, gpgme_data_t seckey)
 {
   engine_gpgsm_t gpgsm = engine;
   gpgme_error_t err;
 
-  if (!gpgsm || !pubkey || seckey)
+  (void)reserved;
+
+  if (!gpgsm)
     return gpg_error (GPG_ERR_INV_VALUE);
 
-  gpgsm->input_cb.data = help_data;
-  err = gpgsm_set_fd (gpgsm, INPUT_FD, map_data_enc (gpgsm->input_cb.data));
-  if (err)
-    return err;
-  gpgsm->output_cb.data = pubkey;
-  err = gpgsm_set_fd (gpgsm, OUTPUT_FD, use_armor ? "--armor"
-                     : map_data_enc (gpgsm->output_cb.data));
-  if (err)
-    return err;
-  gpgsm_clear_fd (gpgsm, MESSAGE_FD);
-  gpgsm->inline_data = NULL;
+  if (help_data)
+    {
+      if (!pubkey || seckey)
+        return gpg_error (GPG_ERR_INV_VALUE);
 
-  err = start (gpgsm, "GENKEY");
-  return err;
+      gpgsm->input_cb.data = help_data;
+      err = gpgsm_set_fd (gpgsm, INPUT_FD, map_data_enc (gpgsm->input_cb.data));
+      if (err)
+        return err;
+      gpgsm->output_cb.data = pubkey;
+      err = gpgsm_set_fd (gpgsm, OUTPUT_FD,
+                          (extraflags & GENKEY_EXTRAFLAG_ARMOR)? "--armor"
+                          : map_data_enc (gpgsm->output_cb.data));
+      if (err)
+        return err;
+      gpgsm_clear_fd (gpgsm, MESSAGE_FD);
+      gpgsm->inline_data = NULL;
+
+      err = start (gpgsm, "GENKEY");
+      return err;
+    }
+
+  (void)userid;
+  (void)algo;
+  (void)expires;
+  (void)key;
+  (void)flags;
+
+  /* The new interface has not yet been implemented,  */
+  return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
 }
 
 
@@ -1790,6 +1841,8 @@ gpgsm_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
   int i;
   gpgme_key_t key;
 
+  (void)use_textmode;
+
   if (!gpgsm)
     return gpg_error (GPG_ERR_INV_VALUE);
 
@@ -1848,11 +1901,13 @@ gpgsm_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
 
 static gpgme_error_t
 gpgsm_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_gpgsm_t gpgsm = engine;
   gpgme_error_t err;
 
+  (void)ctx;
+
   if (!gpgsm)
     return gpg_error (GPG_ERR_INV_VALUE);
 
@@ -1982,6 +2037,8 @@ gpgsm_passwd (void *engine, gpgme_key_t key, unsigned int flags)
   gpgme_error_t err;
   char *line;
 
+  (void)flags;
+
   if (!key || !key->subkeys || !key->subkeys->fpr)
     return gpg_error (GPG_ERR_INV_CERT_OBJ);
 
@@ -2035,6 +2092,8 @@ struct engine_ops _gpgme_engine_ops_gpgsm =
     gpgsm_import,
     gpgsm_keylist,
     gpgsm_keylist_ext,
+    NULL,               /* keysign */
+    NULL,               /* tofu_policy */
     gpgsm_sign,
     NULL,              /* trustlist */
     gpgsm_verify,
@@ -2042,6 +2101,7 @@ struct engine_ops _gpgme_engine_ops_gpgsm =
     NULL,               /* opassuan_transact */
     NULL,              /* conf_load */
     NULL,              /* conf_save */
+    NULL,               /* query_swdb */
     gpgsm_set_io_cbs,
     gpgsm_io_event,
     gpgsm_cancel,