Detect old gpg versions not featuring the --passwd command.
authorWerner Koch <wk@gnupg.org>
Fri, 12 Mar 2010 18:03:02 +0000 (18:03 +0000)
committerWerner Koch <wk@gnupg.org>
Fri, 12 Mar 2010 18:03:02 +0000 (18:03 +0000)
NEWS
src/ChangeLog
src/context.h
src/passwd.c

diff --git a/NEWS b/NEWS
index f85d50e..072ddee 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,8 @@ Noteworthy changes in version 1.3.1 (unreleased)
 
  * Under development.
 
+ * Detect GPG versions not supporting ---passwd.
+
  * Interface changes relative to the 1.3.0 release:
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  GPGME_EXPORT_MODE_MINIMAL  NEW.
index 2582893..887fbc5 100644 (file)
@@ -1,3 +1,11 @@
+2010-03-12  Werner Koch  <wk@g10code.com>
+
+       * passwd.c (op_data_t): New.
+       (passwd_start): Setup OPD.
+       (passwd_status_handler): Return GPG_ERR_NOT_SUPPORTED if needed.
+       * context.h (OPDATA_PASSWD): New.
+       * gpgme.h (GPGME_STATUS_SUCCESS): New.
+
 2010-03-09  Werner Koch  <wk@g10code.com>
 
        * engine-gpgsm.c (gpgsm_keylist): Try to start the agent.
index 19c7194..69d8d9b 100644 (file)
@@ -37,7 +37,8 @@ typedef enum
   {
     OPDATA_DECRYPT, OPDATA_SIGN, OPDATA_ENCRYPT, OPDATA_PASSPHRASE,
     OPDATA_IMPORT, OPDATA_GENKEY, OPDATA_KEYLIST, OPDATA_EDIT,
-    OPDATA_VERIFY, OPDATA_TRUSTLIST, OPDATA_ASSUAN, OPDATA_VFS_MOUNT
+    OPDATA_VERIFY, OPDATA_TRUSTLIST, OPDATA_ASSUAN, OPDATA_VFS_MOUNT,
+    OPDATA_PASSWD
   } ctx_op_data_id_t;
 
 
index 6766877..ab61b4a 100644 (file)
 #include "context.h"
 #include "ops.h"
 
+
+typedef struct
+{
+  int success_seen;
+  int error_seen;
+} *op_data_t;
+
+
 \f
 /* Parse an error status line and return the error code.  */
 static gpgme_error_t
@@ -63,16 +71,39 @@ static gpgme_error_t
 passwd_status_handler (void *priv, gpgme_status_code_t code, char *args)
 {
   gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
-  gpgme_error_t err = 0;
+  gpgme_error_t err;
+  void *hook;
+  op_data_t opd;
 
-  (void)ctx;
+  err = _gpgme_op_data_lookup (ctx, OPDATA_PASSWD, &hook, -1, NULL);
+  opd = hook;
+  if (err)
+    return err;
 
   switch (code)
     {
     case GPGME_STATUS_ERROR:
       err = parse_error (args);
+      if (err)
+        opd->error_seen = 1;
       break;
-                         
+
+    case GPGME_STATUS_SUCCESS:
+      opd->success_seen = 1;
+      break;
+      
+    case GPGME_STATUS_EOF:
+      /* In case the OpenPGP engine does not properly implement the
+         passwd command we won't get a success status back and thus we
+         conclude that this operation is not supported.  This is for
+         example the case for GnuPG < 2.0.16.  Note that this test is
+         obsolete for assuan based engines because they will properly
+         return an error for an unknown command.  */
+      if (ctx->protocol == GPGME_PROTOCOL_OpenPGP
+          && !opd->error_seen && !opd->success_seen)
+        err = gpg_error (GPG_ERR_NOT_SUPPORTED);
+      break;
+
     default:
       break;
     }
@@ -86,6 +117,8 @@ passwd_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t key,
               unsigned int flags)
 {
   gpgme_error_t err;
+  void *hook;
+  op_data_t opd;
 
   if (!key)
     return gpg_error (GPG_ERR_INV_VALUE);
@@ -96,6 +129,14 @@ passwd_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t key,
   if (err)
     return err;
 
+  err = _gpgme_op_data_lookup (ctx, OPDATA_PASSWD, &hook, sizeof (*opd), NULL);
+  opd = hook;
+  if (err)
+    return err;
+
+  opd->success_seen = 0;
+  opd->error_seen = 0;
+
   _gpgme_engine_set_status_handler (ctx->engine, passwd_status_handler, ctx);
 
   return _gpgme_engine_op_passwd (ctx->engine, key, flags);