[git] GPGME - branch, master, updated. gpgme-1.3.2-29-g02a2cf0

by Werner Koch cvs at cvs.gnupg.org
Thu Feb 7 21:14:52 CET 2013


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GnuPG Made Easy".

The branch, master has been updated
       via  02a2cf0ccb4d01700adf6d18316d7705d519a048 (commit)
       via  61a0d92b679f248505f1bf16386bc41a5bf2ba1d (commit)
       via  29eced50687dd8a39dafe704102ae09ea8e8533a (commit)
      from  51fd6d8292cb41d743407e6ac9d86a5ab8e68d8c (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 02a2cf0ccb4d01700adf6d18316d7705d519a048
Author: Werner Koch <wk at gnupg.org>
Date:   Thu Feb 7 21:03:02 2013 +0100

    gpgme_tool: Support GPG's new pinentry-mode.
    
    * src/gpgme-tool.c (log_error): Do not always print the error source.
    (gt_set_pinentry_mode): New.
    (server_passphrase_cb): New.
    (cmd_pinentry_mode): New.
    (register_commands): Add cmd_pinentry_mode.
    (options): Add option --gpg-binary.
    (struct args): Add field gpg-binary.
    (parse_options, main): Implement that option.

diff --git a/src/gpgme-tool.c b/src/gpgme-tool.c
index eca1906..978c387 100644
--- a/src/gpgme-tool.c
+++ b/src/gpgme-tool.c
@@ -1,5 +1,5 @@
 /* gpgme-tool.c - Assuan server exposing GnuPG Made Easy operations.
-   Copyright (C) 2009, 2010, 2012 g10 Code GmbH
+   Copyright (C) 2009, 2010, 2012, 2013 g10 Code GmbH
    Copyright (C) 2001, 2003, 2009, 2011 Free Software Foundation, Inc.
 
    This file is part of GPGME.
@@ -645,8 +645,11 @@ log_error (int status, gpg_error_t errnum, const char *fmt, ...)
   vfprintf (log_stream, fmt, ap);
   va_end (ap);
   if (errnum)
-    fprintf (log_stream, ": %s <%s>", gpg_strerror (errnum),
-	     gpg_strsource (errnum));
+    {
+      fprintf (log_stream, ": %s", gpg_strerror (errnum));
+      if (gpg_err_source (errnum) != GPG_ERR_SOURCE_GPGME)
+        fprintf (log_stream, " <%s>", gpg_strsource (errnum));
+    }
   fprintf (log_stream, "\n");
   if (status)
     exit (status);
@@ -1466,6 +1469,10 @@ typedef struct gpgme_tool *gpgme_tool_t;
 /* Forward declaration.  */
 void gt_write_status (gpgme_tool_t gt,
                       status_t status, ...) GT_GCC_A_SENTINEL(0);
+static gpg_error_t
+server_passphrase_cb (void *opaque, const char *uid_hint, const char *info,
+                      int was_bad, int fd);
+
 
 void
 _gt_progress_cb (void *opaque, const char *what,
@@ -1495,9 +1502,10 @@ _gt_gpgme_new (gpgme_tool_t gt, gpgme_ctx_t *ctx)
 void
 gt_init (gpgme_tool_t gt)
 {
-  memset (gt, '\0', sizeof (*gt));
   gpg_error_t err;
 
+  memset (gt, '\0', sizeof (*gt));
+
   err = _gt_gpgme_new (gt, &gt->ctx);
   if (err)
     log_error (1, err, "can't create gpgme context");
@@ -1777,6 +1785,19 @@ gt_get_sub_protocol (gpgme_tool_t gt)
 
 
 gpg_error_t
+gt_set_pinentry_mode (gpgme_tool_t gt, gpgme_pinentry_mode_t mode, void *opaque)
+{
+  gpg_error_t err;
+
+  gpgme_set_passphrase_cb (gt->ctx, NULL, NULL);
+  err = gpgme_set_pinentry_mode (gt->ctx, mode);
+  if (!err && mode == GPGME_PINENTRY_MODE_LOOPBACK)
+    gpgme_set_passphrase_cb (gt->ctx, server_passphrase_cb, opaque);
+  return err;
+}
+
+
+gpg_error_t
 gt_set_armor (gpgme_tool_t gt, int armor)
 {
   gpgme_set_armor (gt->ctx, armor);
@@ -2151,6 +2172,41 @@ server_write_data (void *hook, const void *buf, size_t len)
 }
 
 
+static gpg_error_t
+server_passphrase_cb (void *opaque, const char *uid_hint, const char *info,
+                      int was_bad, int fd)
+{
+  struct server *server = opaque;
+  gpg_error_t err;
+  unsigned char *buf = NULL;
+  size_t buflen = 0;
+
+  if (server && server->assuan_ctx)
+    {
+      if (uid_hint)
+        assuan_write_status (server->assuan_ctx, "USERID_HINT", uid_hint);
+      if (info)
+        assuan_write_status (server->assuan_ctx, "NEED_PASSPHRASE", info);
+
+      err = assuan_inquire (server->assuan_ctx, "PASSPHRASE",
+                            &buf, &buflen, 100);
+    }
+  else
+    err = gpg_error (GPG_ERR_NO_PASSPHRASE);
+
+  if (!err)
+    {
+      /* We take care to always send a LF.  */
+      if (gpgme_io_writen (fd, buf, buflen))
+        err = gpg_error_from_syserror ();
+      else if (!memchr (buf, '\n', buflen) && gpgme_io_writen (fd, "\n", 1))
+        err = gpg_error_from_syserror ();
+    }
+  free (buf);
+  return err;
+}
+
+
 /* Wrapper around assuan_command_parse_fd to also handle a
    "file=FILENAME" argument.  On success either a filename is returned
    at FILENAME or a file descriptor at RFD; the other one is set to
@@ -2367,6 +2423,39 @@ cmd_sub_protocol (assuan_context_t ctx, char *line)
 }
 
 
+static const char hlp_pinentry_mode[] =
+  "PINENTRY_MODE <name>\n"
+  "\n"
+  "Set the pinentry mode to NAME.   Allowedvalues for NAME are:\n"
+  "  default  - reset to the default of the engine,\n"
+  "  ask      - force the use of the pinentry,\n"
+  "  cancel   - emulate use of pinentry's cancel button,\n"
+  "  error    - return a pinentry error,\n"
+  "  loopback - redirect pinentry queries to the caller.\n"
+  "Note that only recent versions of GPG support changing the pinentry mode.";
+static gpg_error_t
+cmd_pinentry_mode (assuan_context_t ctx, char *line)
+{
+  struct server *server = assuan_get_pointer (ctx);
+  gpgme_pinentry_mode_t mode;
+
+  if (!line || !*line || !strcmp (line, "default"))
+    mode = GPGME_PINENTRY_MODE_DEFAULT;
+  else if (!strcmp (line, "ask"))
+    mode = GPGME_PINENTRY_MODE_ASK;
+  else if (!strcmp (line, "cancel"))
+    mode = GPGME_PINENTRY_MODE_CANCEL;
+  else if (!strcmp (line, "error"))
+    mode = GPGME_PINENTRY_MODE_ERROR;
+  else if (!strcmp (line, "loopback"))
+    mode = GPGME_PINENTRY_MODE_LOOPBACK;
+  else
+    return gpg_error (GPG_ERR_INV_VALUE);
+
+  return gt_set_pinentry_mode (server->gt, mode, server);
+}
+
+
 static const char hlp_armor[] =
   "ARMOR [true|false]\n"
   "\n"
@@ -3354,6 +3443,7 @@ register_commands (assuan_context_t ctx)
     { "ENGINE", cmd_engine, hlp_engine },
     { "PROTOCOL", cmd_protocol, hlp_protocol },
     { "SUB_PROTOCOL", cmd_sub_protocol, hlp_sub_protocol },
+    { "PINENTRY_MODE", cmd_pinentry_mode, hlp_pinentry_mode },
     { "ARMOR", cmd_armor, hlp_armor },
     { "TEXTMODE", cmd_textmode, hlp_textmode },
     { "INCLUDE_CERTS", cmd_include_certs, hlp_include_certs },
@@ -3410,7 +3500,6 @@ register_commands (assuan_context_t ctx)
 }
 
 
-/* TODO: password callback can do INQUIRE.  */
 void
 gpgme_server (gpgme_tool_t gt)
 {
@@ -3495,6 +3584,7 @@ static char args_doc[] = "COMMAND [OPTIONS...]";
 
 static struct argp_option options[] = {
   { "server", 's', 0, 0, "Server mode" },
+  { "gpg-binary", 501, "FILE", 0, "Use FILE for the GPG backend" },
   { 0 }
 };
 
@@ -3504,6 +3594,7 @@ static struct argp argp = { options, parse_options, args_doc, doc };
 struct args
 {
   enum { CMD_DEFAULT, CMD_SERVER } cmd;
+  const char *gpg_binary;
 };
 
 void
@@ -3524,6 +3615,10 @@ parse_options (int key, char *arg, struct argp_state *state)
     case 's':
       args->cmd = CMD_SERVER;
       break;
+
+    case 501:
+      args->gpg_binary = arg;
+      break;
 #if 0
     case ARGP_KEY_ARG:
       if (state->arg_num >= 2)
@@ -3548,6 +3643,7 @@ main (int argc, char *argv[])
 {
   struct args args;
   struct gpgme_tool gt;
+  gpg_error_t err;
 
 #ifdef HAVE_SETLOCALE
   setlocale (LC_ALL, "");
@@ -3565,6 +3661,18 @@ main (int argc, char *argv[])
   argp_parse (&argp, argc, argv, 0, 0, &args);
   log_init ();
 
+  if (args.gpg_binary)
+    {
+      if (access (args.gpg_binary, X_OK))
+        err = gpg_error_from_syserror ();
+      else
+        err = gpgme_set_engine_info (GPGME_PROTOCOL_OpenPGP,
+                                     args.gpg_binary, NULL);
+      if (err)
+        log_error (1, err, "error witching OpenPGP engine to '%s'",
+                   args.gpg_binary);
+    }
+
   gt_init (&gt);
 
   switch (args.cmd)
diff --git a/src/gpgme.def b/src/gpgme.def
index 25cecb9..ccee05a 100644
--- a/src/gpgme.def
+++ b/src/gpgme.def
@@ -205,5 +205,8 @@ EXPORTS
     gpgme_set_global_flag                 @156
 
     gpgme_io_writen                       @157
+
+    gpgme_set_pinentry_mode               @158
+
 ; END
 
diff --git a/src/libgpgme.vers b/src/libgpgme.vers
index 565ec2c..c178af9 100644
--- a/src/libgpgme.vers
+++ b/src/libgpgme.vers
@@ -83,6 +83,8 @@ GPGME_1.1 {
     gpgme_set_global_flag;
 
     gpgme_io_writen;
+
+    gpgme_set_pinentry_mode;
 };
 
 

commit 61a0d92b679f248505f1bf16386bc41a5bf2ba1d
Author: Werner Koch <wk at gnupg.org>
Date:   Thu Feb 7 20:59:16 2013 +0100

    Add public function gpgme_set_pinentry_mode.
    
    * 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.

diff --git a/NEWS b/NEWS
index b4b3086..7499b14 100644
--- 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)
diff --git a/src/context.h b/src/context.h
index d984324..e921436 100644
--- a/src/context.h
+++ b/src/context.h
@@ -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;
 
diff --git a/src/engine-assuan.c b/src/engine-assuan.c
index a3c9e92..5ef3047 100644
--- a/src/engine-assuan.c
+++ b/src/engine-assuan.c
@@ -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 */
   };
diff --git a/src/engine-backend.h b/src/engine-backend.h
index 1adac92..a4c0eb2 100644
--- a/src/engine-backend.h
+++ b/src/engine-backend.h
@@ -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);
 };
 
 
diff --git a/src/engine-g13.c b/src/engine-g13.c
index 9231a9a..de0aac8 100644
--- a/src/engine-g13.c
+++ b/src/engine-g13.c
@@ -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 */
   };
diff --git a/src/engine-gpg.c b/src/engine-gpg.c
index 825a450..3f02503 100644
--- a/src/engine-gpg.c
+++ b/src/engine-gpg.c
@@ -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;
+}
+
+
 
 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
   };
diff --git a/src/engine-gpgconf.c b/src/engine-gpgconf.c
index 96c6b3d..fec0fc3 100644
--- a/src/engine-gpgconf.c
+++ b/src/engine-gpgconf.c
@@ -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 */
   };
diff --git a/src/engine-gpgsm.c b/src/engine-gpgsm.c
index c4272a4..79adde2 100644
--- a/src/engine-gpgsm.c
+++ b/src/engine-gpgsm.c
@@ -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 */
   };
diff --git a/src/engine-uiserver.c b/src/engine-uiserver.c
index 92aebbb..abdd79e 100644
--- a/src/engine-uiserver.c
+++ b/src/engine-uiserver.c
@@ -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 */
   };
diff --git a/src/engine.c b/src/engine.c
index d74f186..09f379c 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -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);
+}
diff --git a/src/engine.h b/src/engine.h
index e868307..a0287ad 100644
--- a/src/engine.h
+++ b/src/engine.h
@@ -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 */
diff --git a/src/gpgme.c b/src/gpgme.c
index 79895db..76c13b1 100644
--- a/src/gpgme.c
+++ b/src/gpgme.c
@@ -53,8 +53,8 @@ DEFINE_STATIC_LOCK (result_ref_lock);
 
 
 /* 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
diff --git a/src/gpgme.h.in b/src/gpgme.h.in
index 27ef195..4ec2367 100644
--- a/src/gpgme.h.in
+++ b/src/gpgme.h.in
@@ -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;
 
 
+/* 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;
+
+
 /* 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,
diff --git a/src/op-support.c b/src/op-support.c
index 6a0817c..edd317d 100644
--- a/src/op-support.c
+++ b/src/op-support.c
@@ -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);

commit 29eced50687dd8a39dafe704102ae09ea8e8533a
Author: Werner Koch <wk at gnupg.org>
Date:   Thu Feb 7 20:51:29 2013 +0100

    Add public function gpgme_io_writen.
    
    * src/gpgme.c (gpgme_io_read): New.
    --
    
    This is a writen style variant for gpgme_io_write.  It is often easier
    to use this one in passphrase and edit callbacks.

diff --git a/doc/gpgme.texi b/doc/gpgme.texi
index d074b42..b73f425 100644
--- a/doc/gpgme.texi
+++ b/doc/gpgme.texi
@@ -2374,9 +2374,10 @@ previous attempts failed, then @var{prev_was_bad} is 1, otherwise it
 will be 0.
 
 The user must write the passphrase, followed by a newline character,
-to the file descriptor @var{fd}.  If the user returns 0 indicating
-success, the user must at least write a newline character before
-returning from the callback.
+to the file descriptor @var{fd}.  The function @code{gpgme_io_writen}
+should be used for the write operation.  Note that if the user returns
+0 to indicate success, the user must at least write a newline
+character before returning from the callback.
 
 If an error occurs, return the corresponding @code{gpgme_error_t}
 value.  You can use the error code @code{GPG_ERR_CANCELED} to abort
diff --git a/src/gpgme.c b/src/gpgme.c
index 86099d6..79895db 100644
--- a/src/gpgme.c
+++ b/src/gpgme.c
@@ -634,6 +634,30 @@ gpgme_io_write (int fd, const void *buffer, size_t count)
   return TRACE_SYSRES (ret);
 }
 
+/* This function provides access to the internal write function.  It
+   is to be used by user callbacks to return data to gpgme.  See
+   gpgme_passphrase_cb_t and gpgme_edit_cb_t.  Note that this is a
+   variant of gpgme_io_write which guarantees that all COUNT bytes are
+   written or an error is return.  Returns: 0 on success or -1 on
+   error and the sets errno. */
+int
+gpgme_io_writen (int fd, const void *buffer, size_t count)
+{
+  int ret = 0;
+  TRACE_BEG2 (DEBUG_GLOBAL, "gpgme_io_writen", fd,
+	      "buffer=%p, count=%u", buffer, count);
+  while (count)
+    {
+      ret = _gpgme_io_write (fd, buffer, count);
+      if (ret < 0)
+        break;
+      buffer += ret;
+      count -= ret;
+      ret = 0;
+    }
+  return TRACE_SYSRES (ret);
+}
+
 
 /* This function returns the callback function for I/O.  */
 void
diff --git a/src/gpgme.def b/src/gpgme.def
index 56a6428..25cecb9 100644
--- a/src/gpgme.def
+++ b/src/gpgme.def
@@ -20,128 +20,128 @@
 
 EXPORTS
     gpgme_check_version                   @1
-    gpgme_get_engine_info                 @2   
-    gpgme_engine_check_version            @3   
-                                                
-    gpgme_err_code_from_errno             @4   
-    gpgme_err_code_to_errno               @5   
-    gpgme_err_make_from_errno             @6   
-    gpgme_error_from_errno                @7   
-    gpgme_strerror                        @8   
-    gpgme_strerror_r                      @9   
-    gpgme_strsource                       @10  
-                                                
-    gpgme_data_get_encoding               @11  
-    gpgme_data_new                        @12  
-    gpgme_data_new_from_cbs               @13  
-    gpgme_data_new_from_fd                @14  
-    gpgme_data_new_from_file              @15  
-    gpgme_data_new_from_filepart          @16  
-    gpgme_data_new_from_mem               @17  
-    gpgme_data_new_from_stream            @18  
-    gpgme_data_read                       @19  
-    gpgme_data_release                    @20  
-    gpgme_data_release_and_get_mem        @21  
-    gpgme_data_seek                       @22  
-    gpgme_data_set_encoding               @23  
-    gpgme_data_write                      @24  
-                                                        
-    gpgme_get_protocol_name               @25  
-    gpgme_hash_algo_name                  @26  
-    gpgme_pubkey_algo_name                @27  
-                                                
-    gpgme_new                             @28  
-    gpgme_get_armor                       @29  
-    gpgme_get_include_certs               @30  
-    gpgme_get_io_cbs                      @31  
-    gpgme_get_keylist_mode                @32  
-    gpgme_get_passphrase_cb               @33  
-    gpgme_get_progress_cb                 @34  
-    gpgme_get_protocol                    @35  
-    gpgme_get_textmode                    @36  
-    gpgme_release                         @37  
-    gpgme_set_armor                       @38  
-    gpgme_set_include_certs               @39  
-    gpgme_set_io_cbs                      @40  
-    gpgme_set_keylist_mode                @41  
-    gpgme_set_locale                      @42  
-    gpgme_set_passphrase_cb               @43  
-    gpgme_set_progress_cb                 @44  
-    gpgme_set_protocol                    @45  
-    gpgme_set_textmode                    @46  
-    gpgme_signers_add                     @47  
-    gpgme_signers_clear                   @48  
-    gpgme_signers_enum                    @49  
-                                                
-    gpgme_key_ref                         @50  
-    gpgme_key_unref                       @51  
-    gpgme_key_release                     @52  
-                                                
-    gpgme_trust_item_ref                  @53  
-    gpgme_trust_item_unref                @54  
-                                                
-    gpgme_cancel                          @55  
-    gpgme_op_card_edit                    @56  
-    gpgme_op_card_edit_start              @57  
-    gpgme_op_decrypt                      @58  
-    gpgme_op_decrypt_result               @59  
-    gpgme_op_decrypt_start                @60  
-    gpgme_op_decrypt_verify               @61  
-    gpgme_op_decrypt_verify_start         @62  
-    gpgme_op_delete                       @63  
-    gpgme_op_delete_start                 @64  
-    gpgme_op_edit                         @65  
-    gpgme_op_edit_start                   @66  
-    gpgme_op_encrypt                      @67  
-    gpgme_op_encrypt_result               @68  
-    gpgme_op_encrypt_sign                 @69  
-    gpgme_op_encrypt_sign_start           @70  
-    gpgme_op_encrypt_start                @71  
-    gpgme_op_export                       @72  
-    gpgme_op_export_ext                   @73  
-    gpgme_op_export_ext_start             @74  
-    gpgme_op_export_start                 @75  
-    gpgme_op_genkey                       @76  
-    gpgme_op_genkey_result                @77  
-    gpgme_op_genkey_start                 @78  
-    gpgme_get_key                         @79  
-    gpgme_op_import                       @80  
-    gpgme_op_import_result                @81  
-    gpgme_op_import_start                 @82  
-    gpgme_op_keylist_end                  @83  
-    gpgme_op_keylist_ext_start            @84  
-    gpgme_op_keylist_next                 @85  
-    gpgme_op_keylist_result               @86  
-    gpgme_op_keylist_start                @87  
-    gpgme_op_sign                         @88  
-    gpgme_op_sign_result                  @89  
-    gpgme_op_sign_start                   @90  
-    gpgme_op_trustlist_end                @91  
-    gpgme_op_trustlist_next               @92  
-    gpgme_op_trustlist_start              @93  
-    gpgme_op_verify                       @94  
-    gpgme_op_verify_result                @95  
-    gpgme_op_verify_start                 @96  
-    gpgme_wait                            @97  
-                                                
-    gpgme_data_new_with_read_cb           @98  
-    gpgme_data_rewind                     @99  
-    gpgme_get_sig_status                  @100 
-    gpgme_get_sig_string_attr             @101 
-    gpgme_get_sig_ulong_attr              @102 
-    gpgme_get_sig_key                     @103 
-    gpgme_key_get_string_attr             @104 
-    gpgme_key_get_ulong_attr              @105 
-    gpgme_key_sig_get_string_attr         @106 
-    gpgme_key_sig_get_ulong_attr          @107 
-    gpgme_op_import_ext                   @108 
-    gpgme_trust_item_get_int_attr         @109 
-    gpgme_trust_item_get_string_attr      @110 
-    gpgme_trust_item_release              @111 
-                                                
-    gpgme_set_engine_info                 @112 
-                                                
-    gpgme_ctx_get_engine_info             @113 
+    gpgme_get_engine_info                 @2
+    gpgme_engine_check_version            @3
+
+    gpgme_err_code_from_errno             @4
+    gpgme_err_code_to_errno               @5
+    gpgme_err_make_from_errno             @6
+    gpgme_error_from_errno                @7
+    gpgme_strerror                        @8
+    gpgme_strerror_r                      @9
+    gpgme_strsource                       @10
+
+    gpgme_data_get_encoding               @11
+    gpgme_data_new                        @12
+    gpgme_data_new_from_cbs               @13
+    gpgme_data_new_from_fd                @14
+    gpgme_data_new_from_file              @15
+    gpgme_data_new_from_filepart          @16
+    gpgme_data_new_from_mem               @17
+    gpgme_data_new_from_stream            @18
+    gpgme_data_read                       @19
+    gpgme_data_release                    @20
+    gpgme_data_release_and_get_mem        @21
+    gpgme_data_seek                       @22
+    gpgme_data_set_encoding               @23
+    gpgme_data_write                      @24
+
+    gpgme_get_protocol_name               @25
+    gpgme_hash_algo_name                  @26
+    gpgme_pubkey_algo_name                @27
+
+    gpgme_new                             @28
+    gpgme_get_armor                       @29
+    gpgme_get_include_certs               @30
+    gpgme_get_io_cbs                      @31
+    gpgme_get_keylist_mode                @32
+    gpgme_get_passphrase_cb               @33
+    gpgme_get_progress_cb                 @34
+    gpgme_get_protocol                    @35
+    gpgme_get_textmode                    @36
+    gpgme_release                         @37
+    gpgme_set_armor                       @38
+    gpgme_set_include_certs               @39
+    gpgme_set_io_cbs                      @40
+    gpgme_set_keylist_mode                @41
+    gpgme_set_locale                      @42
+    gpgme_set_passphrase_cb               @43
+    gpgme_set_progress_cb                 @44
+    gpgme_set_protocol                    @45
+    gpgme_set_textmode                    @46
+    gpgme_signers_add                     @47
+    gpgme_signers_clear                   @48
+    gpgme_signers_enum                    @49
+
+    gpgme_key_ref                         @50
+    gpgme_key_unref                       @51
+    gpgme_key_release                     @52
+
+    gpgme_trust_item_ref                  @53
+    gpgme_trust_item_unref                @54
+
+    gpgme_cancel                          @55
+    gpgme_op_card_edit                    @56
+    gpgme_op_card_edit_start              @57
+    gpgme_op_decrypt                      @58
+    gpgme_op_decrypt_result               @59
+    gpgme_op_decrypt_start                @60
+    gpgme_op_decrypt_verify               @61
+    gpgme_op_decrypt_verify_start         @62
+    gpgme_op_delete                       @63
+    gpgme_op_delete_start                 @64
+    gpgme_op_edit                         @65
+    gpgme_op_edit_start                   @66
+    gpgme_op_encrypt                      @67
+    gpgme_op_encrypt_result               @68
+    gpgme_op_encrypt_sign                 @69
+    gpgme_op_encrypt_sign_start           @70
+    gpgme_op_encrypt_start                @71
+    gpgme_op_export                       @72
+    gpgme_op_export_ext                   @73
+    gpgme_op_export_ext_start             @74
+    gpgme_op_export_start                 @75
+    gpgme_op_genkey                       @76
+    gpgme_op_genkey_result                @77
+    gpgme_op_genkey_start                 @78
+    gpgme_get_key                         @79
+    gpgme_op_import                       @80
+    gpgme_op_import_result                @81
+    gpgme_op_import_start                 @82
+    gpgme_op_keylist_end                  @83
+    gpgme_op_keylist_ext_start            @84
+    gpgme_op_keylist_next                 @85
+    gpgme_op_keylist_result               @86
+    gpgme_op_keylist_start                @87
+    gpgme_op_sign                         @88
+    gpgme_op_sign_result                  @89
+    gpgme_op_sign_start                   @90
+    gpgme_op_trustlist_end                @91
+    gpgme_op_trustlist_next               @92
+    gpgme_op_trustlist_start              @93
+    gpgme_op_verify                       @94
+    gpgme_op_verify_result                @95
+    gpgme_op_verify_start                 @96
+    gpgme_wait                            @97
+
+    gpgme_data_new_with_read_cb           @98
+    gpgme_data_rewind                     @99
+    gpgme_get_sig_status                  @100
+    gpgme_get_sig_string_attr             @101
+    gpgme_get_sig_ulong_attr              @102
+    gpgme_get_sig_key                     @103
+    gpgme_key_get_string_attr             @104
+    gpgme_key_get_ulong_attr              @105
+    gpgme_key_sig_get_string_attr         @106
+    gpgme_key_sig_get_ulong_attr          @107
+    gpgme_op_import_ext                   @108
+    gpgme_trust_item_get_int_attr         @109
+    gpgme_trust_item_get_string_attr      @110
+    gpgme_trust_item_release              @111
+
+    gpgme_set_engine_info                 @112
+
+    gpgme_ctx_get_engine_info             @113
     gpgme_ctx_set_engine_info             @114
 
     gpgme_data_set_file_name		  @115
@@ -173,7 +173,7 @@ EXPORTS
     gpgme_op_assuan_transact              @134
 
     gpgme_check_version_internal	  @135
-    
+
     gpgme_io_read                         @136
     gpgme_io_write                        @137
 
@@ -204,5 +204,6 @@ EXPORTS
 
     gpgme_set_global_flag                 @156
 
+    gpgme_io_writen                       @157
 ; END
 
diff --git a/src/gpgme.h.in b/src/gpgme.h.in
index ce469de..27ef195 100644
--- a/src/gpgme.h.in
+++ b/src/gpgme.h.in
@@ -1022,6 +1022,7 @@ void gpgme_get_io_cbs (gpgme_ctx_t ctx, gpgme_io_cbs_t io_cbs);
    gpgme_passphrase_cb_t and gpgme_edit_cb_t.  */
 ssize_t gpgme_io_read (int fd, void *buffer, size_t count);
 ssize_t gpgme_io_write (int fd, const void *buffer, size_t count);
+int     gpgme_io_writen (int fd, const void *buffer, size_t count);
 
 /* Process the pending operation and, if HANG is non-zero, wait for
    the pending operation to finish.  */
diff --git a/src/libgpgme.vers b/src/libgpgme.vers
index d59571e..565ec2c 100644
--- a/src/libgpgme.vers
+++ b/src/libgpgme.vers
@@ -48,9 +48,9 @@ GPGME_1.1 {
 
     gpgme_cancel_async;
 
-    gpgme_op_assuan_result;    
-    gpgme_op_assuan_transact;    
-    gpgme_op_assuan_transact_start;    
+    gpgme_op_assuan_result;
+    gpgme_op_assuan_transact;
+    gpgme_op_assuan_transact_start;
 
     gpgme_check_version_internal;
 
@@ -81,6 +81,8 @@ GPGME_1.1 {
     gpgme_op_passwd;
 
     gpgme_set_global_flag;
+
+    gpgme_io_writen;
 };
 
 

-----------------------------------------------------------------------

Summary of changes:
 NEWS                  |    8 ++
 doc/gpgme.texi        |    7 +-
 src/context.h         |    3 +
 src/engine-assuan.c   |    4 +-
 src/engine-backend.h  |    3 +
 src/engine-g13.c      |    2 +
 src/engine-gpg.c      |   43 ++++++++-
 src/engine-gpgconf.c  |    5 +-
 src/engine-gpgsm.c    |    3 +-
 src/engine-uiserver.c |    2 +
 src/engine.c          |   13 +++
 src/engine.h          |    3 +
 src/gpgme-tool.c      |  118 ++++++++++++++++++++++-
 src/gpgme.c           |   55 +++++++++++-
 src/gpgme.def         |  250 +++++++++++++++++++++++++------------------------
 src/gpgme.h.in        |   19 ++++-
 src/libgpgme.vers     |   10 ++-
 src/op-support.c      |    9 ++
 18 files changed, 416 insertions(+), 141 deletions(-)


hooks/post-receive
-- 
GnuPG Made Easy
http://git.gnupg.org




More information about the Gnupg-commits mailing list