Add public function gpgme_set_pinentry_mode.
authorWerner Koch <wk@gnupg.org>
Thu, 7 Feb 2013 19:59:16 +0000 (20:59 +0100)
committerWerner Koch <wk@gnupg.org>
Thu, 7 Feb 2013 19:59:16 +0000 (20:59 +0100)
* src/gpgme.c (gpgme_set_pinentry_mode): New.
* src/gpgme.h.in (gpgme_pinentry_t): New.
(gpgme_set_pinentry_mode): New.
* src/context.h (struct gpgme_context): Add field pinentry_mode.
* src/engine-backend.h (struct engine_ops): Add field
set_pinentry_mode.
* src/engine-gpg.c (struct engine_gpg): Add field pinentry_mode.
(build_argv): Implement pinentry_mode.
(gpg_set_pinentry_mode): New.
(_gpgme_engine_ops_gpg): Register gpg_set_pinentry_mode.

--

Note that this new fucntion may only be used with gpg 2.1.

14 files changed:
NEWS
src/context.h
src/engine-assuan.c
src/engine-backend.h
src/engine-g13.c
src/engine-gpg.c
src/engine-gpgconf.c
src/engine-gpgsm.c
src/engine-uiserver.c
src/engine.c
src/engine.h
src/gpgme.c
src/gpgme.h.in
src/op-support.c

diff --git a/NEWS b/NEWS
index b4b3086..7499b14 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -3,7 +3,15 @@ Noteworthy changes in version 1.3.3 (unreleased)
 
  * Interface changes relative to the 1.3.1 release:
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ gpgme_io_writen                NEW.
  gpgme_set_global_flag          NEW.
+ gpgme_set_pinentry_mode        NEW.
+ gpgme_pinentry_mode_t          NEW.
+ GPGME_PINENTRY_MODE_DEFAULT    NEW.
+ GPGME_PINENTRY_MODE_ASK        NEW.
+ GPGME_PINENTRY_MODE_CANCEL     NEW.
+ GPGME_PINENTRY_MODE_ERROR      NEW.
+ GPGME_PINENTRY_MODE_LOOPBACK   NEW.
 
 
 Noteworthy changes in version 1.3.2 (2012-05-02)
index d984324..e921436 100644 (file)
@@ -101,6 +101,9 @@ struct gpgme_context
   /* Flags for keylist mode.  */
   gpgme_keylist_mode_t keylist_mode;
 
+  /* The current pinnetry mode.  */
+  gpgme_pinentry_mode_t pinentry_mode;
+
   /* Number of certs to be included.  */
   unsigned int include_certs;
 
index a3c9e92..5ef3047 100644 (file)
@@ -781,5 +781,7 @@ struct engine_ops _gpgme_engine_ops_assuan =
     llass_set_io_cbs,
     llass_io_event,
     llass_cancel,
-    llass_cancel_op
+    llass_cancel_op,
+    NULL,               /* passwd */
+    NULL                /* set_pinentry_mode */
   };
index 1adac92..a4c0eb2 100644 (file)
@@ -121,6 +121,9 @@ struct engine_ops
 
   /* Change the passphrase for KEY. */
   gpgme_error_t (*passwd) (void *engine, gpgme_key_t key, unsigned int flags);
+
+  /* Set the pinentry mode.  */
+  gpgme_error_t (*set_pinentry_mode) (void *engine, gpgme_pinentry_mode_t mode);
 };
 
 
index 9231a9a..de0aac8 100644 (file)
@@ -798,4 +798,6 @@ struct engine_ops _gpgme_engine_ops_g13 =
     g13_io_event,
     g13_cancel,
     g13_cancel_op,
+    NULL,               /* passwd */
+    NULL                /* set_pinentry_mode */
   };
index 825a450..3f02503 100644 (file)
@@ -134,6 +134,7 @@ struct engine_gpg
   } cmd;
 
   struct gpgme_io_cbs io_cbs;
+  gpgme_pinentry_mode_t pinentry_mode;
 };
 
 typedef struct engine_gpg *engine_gpg_t;
@@ -769,6 +770,8 @@ build_argv (engine_gpg_t gpg)
     argc++;
   if (use_agent)
     argc++;
+  if (gpg->pinentry_mode)
+    argc++;
   if (!gpg->cmd.used)
     argc++;    /* --batch */
   argc += 1;   /* --no-sk-comment */
@@ -818,6 +821,32 @@ build_argv (engine_gpg_t gpg)
         }
       argc++;
     }
+
+  if (gpg->pinentry_mode)
+    {
+      const char *s = NULL;
+      switch (gpg->pinentry_mode)
+        {
+        case GPGME_PINENTRY_MODE_DEFAULT: break;
+        case GPGME_PINENTRY_MODE_ASK:     s = "--pinentry-mode=ask"; break;
+        case GPGME_PINENTRY_MODE_CANCEL:  s = "--pinentry-mode=cancel"; break;
+        case GPGME_PINENTRY_MODE_ERROR:   s = "--pinentry-mode=error"; break;
+        case GPGME_PINENTRY_MODE_LOOPBACK:s = "--pinentry-mode=loopback"; break;
+        }
+      if (s)
+        {
+          argv[argc] = strdup (s);
+          if (!argv[argc])
+            {
+              int saved_err = gpg_error_from_syserror ();
+              free (fd_data_map);
+              free_argv (argv);
+              return saved_err;
+            }
+          argc++;
+        }
+    }
+
   if (!gpg->cmd.used)
     {
       argv[argc] = strdup ("--batch");
@@ -2348,6 +2377,17 @@ gpg_set_io_cbs (void *engine, gpgme_io_cbs_t io_cbs)
   gpg->io_cbs = *io_cbs;
 }
 
+
+static gpgme_error_t
+gpg_set_pinentry_mode (void *engine, gpgme_pinentry_mode_t mode)
+{
+  engine_gpg_t gpg = engine;
+
+  gpg->pinentry_mode = mode;
+  return 0;
+}
+
+
 \f
 struct engine_ops _gpgme_engine_ops_gpg =
   {
@@ -2389,5 +2429,6 @@ struct engine_ops _gpgme_engine_ops_gpg =
     gpg_io_event,
     gpg_cancel,
     NULL,              /* cancel_op */
-    gpg_passwd
+    gpg_passwd,
+    gpg_set_pinentry_mode
   };
index 96c6b3d..fec0fc3 100644 (file)
@@ -925,5 +925,8 @@ struct engine_ops _gpgme_engine_ops_gpgconf =
     gpgconf_conf_save,
     gpgconf_set_io_cbs,
     NULL,              /* io_event */
-    NULL               /* cancel */
+    NULL,              /* cancel */
+    NULL,               /* cancel_op */
+    NULL,               /* passwd */
+    NULL                /* set_pinentry_mode */
   };
index c4272a4..79adde2 100644 (file)
@@ -1986,5 +1986,6 @@ struct engine_ops _gpgme_engine_ops_gpgsm =
     gpgsm_io_event,
     gpgsm_cancel,
     NULL,              /* cancel_op */
-    gpgsm_passwd
+    gpgsm_passwd,
+    NULL                /* set_pinentry_mode */
   };
index 92aebbb..abdd79e 100644 (file)
@@ -1339,4 +1339,6 @@ struct engine_ops _gpgme_engine_ops_uiserver =
     uiserver_io_event,
     uiserver_cancel,
     NULL               /* cancel_op */
+    NULL,               /* passwd */
+    NULL                /* set_pinentry_mode */
   };
index d74f186..09f379c 100644 (file)
@@ -923,3 +923,16 @@ _gpgme_engine_op_passwd (engine_t engine, gpgme_key_t key,
   return (*engine->ops->passwd) (engine->engine, key, flags);
 }
 
+
+/* Set the pinentry mode for ENGINE to MODE.  */
+gpgme_error_t
+_gpgme_engine_set_pinentry_mode (engine_t engine, gpgme_pinentry_mode_t mode)
+{
+  if (!engine)
+    return gpg_error (GPG_ERR_INV_VALUE);
+
+  if (!engine->ops->set_pinentry_mode)
+    return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+  return (*engine->ops->set_pinentry_mode) (engine->engine, mode);
+}
index e868307..a0287ad 100644 (file)
@@ -160,5 +160,8 @@ gpgme_error_t _gpgme_engine_cancel_op (engine_t engine);
 gpgme_error_t _gpgme_engine_op_passwd (engine_t engine, gpgme_key_t key,
                                        unsigned int flags);
 
+gpgme_error_t _gpgme_engine_set_pinentry_mode (engine_t engine,
+                                               gpgme_pinentry_mode_t mode);
+
 
 #endif /* ENGINE_H */
index 79895db..76c13b1 100644 (file)
@@ -53,8 +53,8 @@ DEFINE_STATIC_LOCK (result_ref_lock);
 
 \f
 /* Set the global flag NAME to VALUE.  Return 0 on success.  Note that
-   this function does use gpgme_error and thus a non-zero return value
-   merely means "error".  Certain flags may be set before
+   this function does not use gpgme_error and thus a non-zero return
+   value merely means "error".  Certain flags may be set before
    gpgme_check_version is called.  See the manual for a description of
    supported flags.  The caller must assure that this function is
    called only by one thread at a time.  */
@@ -512,6 +512,33 @@ gpgme_get_keylist_mode (gpgme_ctx_t ctx)
 }
 
 
+/* Set the pinentry mode for CTX to MODE. */
+gpgme_error_t
+gpgme_set_pinentry_mode (gpgme_ctx_t ctx, gpgme_keylist_mode_t mode)
+{
+  TRACE1 (DEBUG_CTX, "gpgme_set_pinentry_mode", ctx, "pinentry_mode=%u",
+         (unsigned int)mode);
+
+  if (!ctx)
+    return gpg_error (GPG_ERR_INV_VALUE);
+
+  switch (mode)
+    {
+    case GPGME_PINENTRY_MODE_DEFAULT:
+    case GPGME_PINENTRY_MODE_ASK:
+    case GPGME_PINENTRY_MODE_CANCEL:
+    case GPGME_PINENTRY_MODE_ERROR:
+    case GPGME_PINENTRY_MODE_LOOPBACK:
+      break;
+    default:
+      return gpg_error (GPG_ERR_INV_VALUE);
+    }
+
+  ctx->pinentry_mode = mode;
+  return 0;
+}
+
+
 /* This function sets a callback function to be used to pass a
    passphrase to gpg.  */
 void
index 27ef195..4ec2367 100644 (file)
@@ -1,7 +1,7 @@
 /* gpgme.h - Public interface to GnuPG Made Easy.                   -*- c -*-
    Copyright (C) 2000 Werner Koch (dd9jn)
    Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2009
-                 2010, 2011, 2012 g10 Code GmbH
+                 2010, 2011, 2012, 2013 g10 Code GmbH
 
    This file is part of GPGME.
 
@@ -354,6 +354,18 @@ gpgme_protocol_t;
 typedef unsigned int gpgme_keylist_mode_t;
 
 \f
+/* The pinentry modes. */
+typedef enum
+  {
+    GPGME_PINENTRY_MODE_DEFAULT  = 0,
+    GPGME_PINENTRY_MODE_ASK      = 1,
+    GPGME_PINENTRY_MODE_CANCEL   = 2,
+    GPGME_PINENTRY_MODE_ERROR    = 3,
+    GPGME_PINENTRY_MODE_LOOPBACK = 4
+  }
+gpgme_pinentry_mode_t;
+
+\f
 /* The available export mode flags.  */
 #define GPGME_EXPORT_MODE_EXTERN                2
 #define GPGME_EXPORT_MODE_MINIMAL               4
@@ -859,6 +871,10 @@ gpgme_error_t gpgme_set_keylist_mode (gpgme_ctx_t ctx,
 /* Get keylist mode in CTX.  */
 gpgme_keylist_mode_t gpgme_get_keylist_mode (gpgme_ctx_t ctx);
 
+/* Set the pinentry mode for CTX to MODE. */
+gpgme_error_t gpgme_set_pinentry_mode (gpgme_ctx_t ctx,
+                                       gpgme_pinentry_mode_t mode);
+
 /* Set the passphrase callback function in CTX to CB.  HOOK_VALUE is
    passed as first argument to the passphrase callback function.  */
 void gpgme_set_passphrase_cb (gpgme_ctx_t ctx,
index 6a0817c..edd317d 100644 (file)
@@ -134,6 +134,15 @@ _gpgme_op_reset (gpgme_ctx_t ctx, int type)
 #endif
       if (gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED)
        err = 0;
+
+      if (!err)
+        {
+          err = _gpgme_engine_set_pinentry_mode (ctx->engine,
+                                                 ctx->pinentry_mode);
+          if (gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED)
+            err = 0;
+        }
+
       if (err)
         {
           _gpgme_engine_release (ctx->engine);