api: Add new function gpgme_set_ctx_flag.
authorWerner Koch <wk@gnupg.org>
Thu, 19 May 2016 15:01:07 +0000 (17:01 +0200)
committerWerner Koch <wk@gnupg.org>
Thu, 19 May 2016 15:04:54 +0000 (17:04 +0200)
* src/gpgme.h.in (gpgme_set_ctx_flag): New prototype.
* src/gpgme.c (gpgme_set_ctx_flag): New.
* src/gpgme.def, src/libgpgme.vers: Add new function.
* src/context.h (struct gpgme_context): Add FULL_STATUS.
* src/decrypt.c (_gpgme_decrypt_status_handler): Do not call the
  status callback if FULL_STATUS is set.
* src/genkey.c (genkey_status_handler): Ditto.
* src/passphrase.c (_gpgme_passphrase_status_handler): Ditto.
* src/sign.c (_gpgme_sign_status_handler): Ditto.

* src/engine-backend.h (struct engine_ops): Add SET_STATUS_CB and add
adjust all definitions of that variable.
* src/engine.c (_gpgme_engine_set_status_cb): New.
* src/op-support.c (_gpgme_op_reset): Call this function.

* src/engine-gpg.c (struct engine_gpg): Add fields MON_CB and
MON_CB_VALUE.
(gpg_set_status_cb): New.
(_gpgme_engine_ops_gpg): Register that function.
(read_status): Call the monitor callback.

* src/engine-gpgsm.c (struct engine_gpgsm): Add fields MON_CB and
MON_CB_VALUE.
(_gpgme_engine_ops_gpgsm): Register that function.
(gpgsm_assuan_simple_command): Change first arg to be an engine
context and adjust call callers.  Call the monitor callback.

* src/engine-uiserver.c (struct engine_uiserver): Add fields MON_CB
and MON_CB_VALUE.
(_gpgme_engine_ops_uiserver): Register that function.
(uiserver_assuan_simple_command): Change first arg to be an engine
context and adjust call callers.  Call the monitor callback.

* tests/run-verify.c (status_cb): New.
(print_result): Print algo names.
(main): Add option --status.
--

This new feature is mainly intended for bug tracking.  Having access
to the raw status lines might also be useful for applications, though.

Signed-off-by: Werner Koch <wk@gnupg.org>
23 files changed:
NEWS
doc/gpgme.texi
src/context.h
src/decrypt.c
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-spawn.c
src/engine-uiserver.c
src/engine.c
src/engine.h
src/genkey.c
src/gpgme.c
src/gpgme.def
src/gpgme.h.in
src/libgpgme.vers
src/op-support.c
src/passphrase.c
src/sign.c
tests/run-verify.c

diff --git a/NEWS b/NEWS
index cfff559..119866e 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,7 @@ Noteworthy changes in version 1.7.0 (unreleased) [C25/A14/R_]
  * Interface changes relative to the 1.6.0 release:
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  gpgme_pubkey_algo_string       NEW.
+ gpgme_set_ctx_flag             NEW.
  GPGME_PK_EDDSA                 NEW.
 
 
index db94617..4d7a874 100644 (file)
@@ -2736,6 +2736,27 @@ or @var{ctx} is not a valid pointer, @code{NULL} is returned in both
 variables.
 @end deftypefun
 
+@deftypefun {gpgme_error_t} gpgme_set_ctx_flag  @
+            (@w{gpgme_ctx_t @var{ctx}}, @
+            @w{const char *@var{name}}, @
+            @w{const char *@var{value}})
+
+Some minor properties of the context can be controlled with flags set
+by this function.  The properties are identified by the following
+values for @var{name}:
+
+@table @code
+@item "full-status"
+Using a @var{value} of "1" the status callback set by
+gpgme_set_status_cb returns all status lines with the exception of
+PROGRESS lines.  With the default of "0" the status callback is only
+called in certain situations.
+
+@end table
+
+This function returns @code{0} on success.
+@end deftypefun
+
 
 @node Locale
 @subsection Locale
index 757d9b4..078f0cb 100644 (file)
@@ -101,6 +101,10 @@ struct gpgme_context
   /* True if offline mode should be used.  */
   unsigned int offline : 1;
 
+  /* True if a status callback shall be called for nearly all status
+   * lines.  */
+  unsigned int full_status : 1;
+
   /* Flags for keylist mode.  */
   gpgme_keylist_mode_t keylist_mode;
 
index 4db68a1..51e4292 100644 (file)
@@ -303,7 +303,7 @@ _gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code,
       break;
 
     case GPGME_STATUS_INQUIRE_MAXLEN:
-      if (ctx->status_cb)
+      if (ctx->status_cb && !ctx->full_status)
         {
           err = ctx->status_cb (ctx->status_cb_value, "INQUIRE_MAXLEN", args);
           if (err)
index 9902467..a396006 100644 (file)
@@ -752,6 +752,7 @@ struct engine_ops _gpgme_engine_ops_assuan =
     /* Member functions.  */
     llass_release,
     NULL,              /* reset */
+    NULL,               /* set_status_cb */
     NULL,               /* set_status_handler */
     NULL,              /* set_command_handler */
     NULL,               /* set_colon_line_handler */
index 4f4519c..ea7db14 100644 (file)
@@ -49,6 +49,7 @@ struct engine_ops
   /* Member functions.  */
   void (*release) (void *engine);
   gpgme_error_t (*reset) (void *engine);
+  void (*set_status_cb) (void *engine, gpgme_status_cb_t cb, void *cb_value);
   void (*set_status_handler) (void *engine, engine_status_handler_t fnc,
                              void *fnc_value);
   gpgme_error_t (*set_command_handler) (void *engine,
index 4a7b75c..8f24f4c 100644 (file)
@@ -768,6 +768,7 @@ struct engine_ops _gpgme_engine_ops_g13 =
 #else
     NULL,                      /* reset */
 #endif
+    NULL,               /* set_status_cb */
     NULL,               /* set_status_handler */
     NULL,              /* set_command_handler */
     NULL,               /* set_colon_line_handler */
index 9efced2..e507c68 100644 (file)
@@ -95,6 +95,8 @@ struct engine_gpg
     int eof;
     engine_status_handler_t fnc;
     void *fnc_value;
+    gpgme_status_cb_t mon_cb;
+    void *mon_cb_value;
     void *tag;
   } status;
 
@@ -609,6 +611,17 @@ gpg_set_locale (void *engine, int category, const char *value)
   return 0;
 }
 
+/* This sets a status callback for monitoring status lines before they
+ * are passed to a caller set handler.  */
+static void
+gpg_set_status_cb (void *engine, gpgme_status_cb_t cb, void *cb_value)
+{
+  engine_gpg_t gpg = engine;
+
+  gpg->status.mon_cb = cb;
+  gpg->status.mon_cb_value = cb_value;
+}
+
 
 /* Note, that the status_handler is allowed to modifiy the args
    value.  */
@@ -1019,6 +1032,7 @@ read_status (engine_gpg_t gpg)
   size_t bufsize = gpg->status.bufsize;
   char *buffer = gpg->status.buffer;
   size_t readpos = gpg->status.readpos;
+  gpgme_error_t err;
 
   assert (buffer);
   if (bufsize - readpos < 256)
@@ -1037,15 +1051,15 @@ read_status (engine_gpg_t gpg)
 
   if (!nread)
     {
+      err = 0;
       gpg->status.eof = 1;
+      if (gpg->status.mon_cb)
+        err = gpg->status.mon_cb (gpg->status.mon_cb_value,
+                                  GPGME_STATUS_EOF, "");
       if (gpg->status.fnc)
-       {
-         gpgme_error_t err;
-         err = gpg->status.fnc (gpg->status.fnc_value, GPGME_STATUS_EOF, "");
-         if (err)
-           return err;
-       }
-      return 0;
+        err = gpg->status.fnc (gpg->status.fnc_value, GPGME_STATUS_EOF, "");
+
+      return err;
     }
 
   while (nread > 0)
@@ -1071,6 +1085,15 @@ read_status (engine_gpg_t gpg)
                    *rest++ = 0;
 
                  r = _gpgme_parse_status (buffer + 9);
+                  if (gpg->status.mon_cb && r != GPGME_STATUS_PROGRESS)
+                    {
+                      /* Note that we call the monitor even if we do
+                       * not know the status code (r < 0).  */
+                      err = gpg->status.mon_cb (gpg->status.mon_cb_value,
+                                                buffer + 9, rest);
+                      if (err)
+                        return err;
+                    }
                  if (r >= 0)
                    {
                      if (gpg->cmd.used
@@ -1099,7 +1122,6 @@ read_status (engine_gpg_t gpg)
                         }
                      else if (gpg->status.fnc)
                        {
-                         gpgme_error_t err;
                          err = gpg->status.fnc (gpg->status.fnc_value,
                                                 r, rest);
                          if (err)
@@ -2470,6 +2492,7 @@ struct engine_ops _gpgme_engine_ops_gpg =
     /* Member functions.  */
     gpg_release,
     NULL,                              /* reset */
+    gpg_set_status_cb,
     gpg_set_status_handler,
     gpg_set_command_handler,
     gpg_set_colon_line_handler,
index a2407ac..bcc9522 100644 (file)
@@ -934,6 +934,7 @@ struct engine_ops _gpgme_engine_ops_gpgconf =
     /* Member functions.  */
     gpgconf_release,
     NULL,              /* reset */
+    NULL,               /* set_status_cb */
     NULL,              /* set_status_handler */
     NULL,              /* set_command_handler */
     NULL,              /* set_colon_line_handler */
index 476e9ef..3aa9f0b 100644 (file)
@@ -88,6 +88,8 @@ struct engine_gpgsm
   {
     engine_status_handler_t fnc;
     void *fnc_value;
+    gpgme_status_cb_t mon_cb;
+    void *mon_cb_value;
   } status;
 
   struct
@@ -558,10 +560,11 @@ gpgsm_set_locale (void *engine, int category, const char *value)
 
 
 static gpgme_error_t
-gpgsm_assuan_simple_command (assuan_context_t ctx, char *cmd,
+gpgsm_assuan_simple_command (engine_gpgsm_t gpgsm, char *cmd,
                             engine_status_handler_t status_fnc,
                             void *status_fnc_value)
 {
+  assuan_context_t ctx = gpgsm->assuan_ctx;
   gpg_error_t err, cb_err;
   char *line;
   size_t linelen;
@@ -610,8 +613,15 @@ gpgsm_assuan_simple_command (assuan_context_t ctx, char *cmd,
                 *(rest++) = 0;
 
               r = _gpgme_parse_status (line + 2);
+              if (gpgsm->status.mon_cb && r != GPGME_STATUS_PROGRESS)
+                {
+                  /* Note that we call the monitor even if we do
+                   * not know the status code (r < 0).  */
+                  cb_err = gpgsm->status.mon_cb (gpgsm->status.mon_cb_value,
+                                                 line + 2, rest);
+                }
 
-              if (r >= 0 && status_fnc)
+              if (r >= 0 && status_fnc && !cb_err)
                 cb_err = status_fnc (status_fnc_value, r, rest);
             }
        }
@@ -726,7 +736,7 @@ gpgsm_set_fd (engine_gpgsm_t gpgsm, fd_type_t fd_type, const char *opt)
               which, iocb_data->server_fd_str);
 #endif
 
-  err = gpgsm_assuan_simple_command (gpgsm->assuan_ctx, line, NULL, NULL);
+  err = gpgsm_assuan_simple_command (gpgsm, line, NULL, NULL);
 
 #if USE_DESCRIPTOR_PASSING
  leave_set_fd:
@@ -1075,8 +1085,7 @@ gpgsm_reset (void *engine)
      need to reset the list of signers.  Note that RESET does not
      reset OPTION commands. */
   return (gpgsm->assuan_ctx
-          ? gpgsm_assuan_simple_command (gpgsm->assuan_ctx, "RESET",
-                                         NULL, NULL)
+          ? gpgsm_assuan_simple_command (gpgsm, "RESET", NULL, NULL)
           : 0);
 }
 #endif
@@ -1180,7 +1189,6 @@ static gpgme_error_t
 set_recipients (engine_gpgsm_t gpgsm, gpgme_key_t recp[])
 {
   gpgme_error_t err = 0;
-  assuan_context_t ctx = gpgsm->assuan_ctx;
   char *line;
   int linelen;
   int invalid_recipients = 0;
@@ -1218,7 +1226,7 @@ set_recipients (engine_gpgsm_t gpgsm, gpgme_key_t recp[])
        }
       strcpy (&line[10], fpr);
 
-      err = gpgsm_assuan_simple_command (ctx, line, gpgsm->status.fnc,
+      err = gpgsm_assuan_simple_command (gpgsm, line, gpgsm->status.fnc,
                                         gpgsm->status.fnc_value);
       /* FIXME: This requires more work.  */
       if (gpg_err_code (err) == GPG_ERR_NO_PUBKEY)
@@ -1249,7 +1257,7 @@ gpgsm_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,
 
   if (flags & GPGME_ENCRYPT_NO_ENCRYPT_TO)
     {
-      err = gpgsm_assuan_simple_command (gpgsm->assuan_ctx,
+      err = gpgsm_assuan_simple_command (gpgsm,
                                         "OPTION no-encrypt-to", NULL, NULL);
       if (err)
        return err;
@@ -1472,8 +1480,7 @@ gpgsm_import (void *engine, gpgme_data_t keydata, gpgme_key_t *keyarray)
       /* Fist check whether the engine already features the
          --re-import option.  */
       err = gpgsm_assuan_simple_command
-        (gpgsm->assuan_ctx,
-         "GETINFO cmd_has_option IMPORT re-import", NULL, NULL);
+        (gpgsm, "GETINFO cmd_has_option IMPORT re-import", NULL, NULL);
       if (err)
        return gpg_error (GPG_ERR_NOT_SUPPORTED);
 
@@ -1575,13 +1582,12 @@ gpgsm_keylist (void *engine, const char *pattern, int secret_only,
      available and thus there is no need for gpgsm to ask the agent
      whether a secret key exists for the public key.  */
   if (secret_only || (mode & GPGME_KEYLIST_MODE_WITH_SECRET))
-    gpgsm_assuan_simple_command (gpgsm->assuan_ctx, "GETINFO agent-check",
-                                 NULL, NULL);
+    gpgsm_assuan_simple_command (gpgsm, "GETINFO agent-check", NULL, NULL);
 
   /* Always send list-mode option because RESET does not reset it.  */
   if (asprintf (&line, "OPTION list-mode=%d", (list_mode & 3)) < 0)
     return gpg_error_from_syserror ();
-  err = gpgsm_assuan_simple_command (gpgsm->assuan_ctx, line, NULL, NULL);
+  err = gpgsm_assuan_simple_command (gpgsm, line, NULL, NULL);
   free (line);
   if (err)
     return err;
@@ -1591,24 +1597,24 @@ gpgsm_keylist (void *engine, const char *pattern, int secret_only,
 
   /* Use the validation mode if requested.  We don't check for an error
      yet because this is a pretty fresh gpgsm features. */
-  gpgsm_assuan_simple_command (gpgsm->assuan_ctx,
+  gpgsm_assuan_simple_command (gpgsm,
                                (mode & GPGME_KEYLIST_MODE_VALIDATE)?
                                "OPTION with-validation=1":
                                "OPTION with-validation=0" ,
                                NULL, NULL);
   /* Include the ephemeral keys if requested.  We don't check for an error
      yet because this is a pretty fresh gpgsm features. */
-  gpgsm_assuan_simple_command (gpgsm->assuan_ctx,
+  gpgsm_assuan_simple_command (gpgsm,
                                (mode & GPGME_KEYLIST_MODE_EPHEMERAL)?
                                "OPTION with-ephemeral-keys=1":
                                "OPTION with-ephemeral-keys=0" ,
                                NULL, NULL);
-  gpgsm_assuan_simple_command (gpgsm->assuan_ctx,
+  gpgsm_assuan_simple_command (gpgsm,
                                (mode & GPGME_KEYLIST_MODE_WITH_SECRET)?
                                "OPTION with-secret=1":
                                "OPTION with-secret=0" ,
                                NULL, NULL);
-  gpgsm_assuan_simple_command (gpgsm->assuan_ctx,
+  gpgsm_assuan_simple_command (gpgsm,
                                (engine_flags & GPGME_ENGINE_FLAG_OFFLINE)?
                                "OPTION offline=1":
                                "OPTION offline=0" ,
@@ -1665,7 +1671,7 @@ gpgsm_keylist_ext (void *engine, const char *pattern[], int secret_only,
   /* Always send list-mode option because RESET does not reset it.  */
   if (asprintf (&line, "OPTION list-mode=%d", (list_mode & 3)) < 0)
     return gpg_error_from_syserror ();
-  err = gpgsm_assuan_simple_command (gpgsm->assuan_ctx, line, NULL, NULL);
+  err = gpgsm_assuan_simple_command (gpgsm, line, NULL, NULL);
   free (line);
   if (err)
     return err;
@@ -1673,17 +1679,17 @@ gpgsm_keylist_ext (void *engine, const char *pattern[], int secret_only,
   /* Always send key validation because RESET does not reset it.  */
   /* Use the validation mode if required.  We don't check for an error
      yet because this is a pretty fresh gpgsm features. */
-  gpgsm_assuan_simple_command (gpgsm->assuan_ctx,
+  gpgsm_assuan_simple_command (gpgsm,
                                (mode & GPGME_KEYLIST_MODE_VALIDATE)?
                                "OPTION with-validation=1":
                                "OPTION with-validation=0" ,
                                NULL, NULL);
-  gpgsm_assuan_simple_command (gpgsm->assuan_ctx,
+  gpgsm_assuan_simple_command (gpgsm,
                                (mode & GPGME_KEYLIST_MODE_WITH_SECRET)?
                                "OPTION with-secret=1":
                                "OPTION with-secret=0" ,
                                NULL, NULL);
-  gpgsm_assuan_simple_command (gpgsm->assuan_ctx,
+  gpgsm_assuan_simple_command (gpgsm,
                                (engine_flags & GPGME_ENGINE_FLAG_OFFLINE)?
                                "OPTION offline=1":
                                "OPTION offline=0" ,
@@ -1797,8 +1803,7 @@ gpgsm_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
 
       if (asprintf (&assuan_cmd, "OPTION include-certs %i", include_certs) < 0)
        return gpg_error_from_syserror ();
-      err = gpgsm_assuan_simple_command (gpgsm->assuan_ctx, assuan_cmd,
-                                         NULL, NULL);
+      err = gpgsm_assuan_simple_command (gpgsm, assuan_cmd, NULL, NULL);
       free (assuan_cmd);
       if (err)
        return err;
@@ -1812,7 +1817,7 @@ gpgsm_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
           char buf[100];
 
           strcpy (stpcpy (buf, "SIGNER "), s);
-          err = gpgsm_assuan_simple_command (gpgsm->assuan_ctx, buf,
+          err = gpgsm_assuan_simple_command (gpgsm, buf,
                                              gpgsm->status.fnc,
                                              gpgsm->status.fnc_value);
        }
@@ -1913,6 +1918,17 @@ gpgsm_getauditlog (void *engine, gpgme_data_t output, unsigned int flags)
 }
 
 
+/* This sets a status callback for monitoring status lines before they
+ * are passed to a caller set handler.  */
+static void
+gpgsm_set_status_cb (void *engine, gpgme_status_cb_t cb, void *cb_value)
+{
+  engine_gpgsm_t gpgsm = engine;
+
+  gpgsm->status.mon_cb = cb;
+  gpgsm->status.mon_cb_value = cb_value;
+}
+
 
 static void
 gpgsm_set_status_handler (void *engine, engine_status_handler_t fnc,
@@ -2001,6 +2017,7 @@ struct engine_ops _gpgme_engine_ops_gpgsm =
 #else
     NULL,                      /* reset */
 #endif
+    gpgsm_set_status_cb,
     gpgsm_set_status_handler,
     NULL,              /* set_command_handler */
     gpgsm_set_colon_line_handler,
index eb4e038..3674efb 100644 (file)
@@ -440,6 +440,7 @@ struct engine_ops _gpgme_engine_ops_spawn =
     /* Member functions.  */
     engspawn_release,
     NULL,              /* reset */
+    NULL,               /* set_status_cb */
     NULL,              /* set_status_handler */
     NULL,              /* set_command_handler */
     NULL,              /* set_colon_line_handler */
index e4fd47c..d05ade6 100644 (file)
@@ -90,6 +90,8 @@ struct engine_uiserver
   {
     engine_status_handler_t fnc;
     void *fnc_value;
+    gpgme_status_cb_t mon_cb;
+    void *mon_cb_value;
   } status;
 
   struct
@@ -451,10 +453,11 @@ uiserver_set_protocol (void *engine, gpgme_protocol_t protocol)
 
 
 static gpgme_error_t
-uiserver_assuan_simple_command (assuan_context_t ctx, char *cmd,
-                            engine_status_handler_t status_fnc,
-                            void *status_fnc_value)
+uiserver_assuan_simple_command (engine_uiserver_t uiserver, char *cmd,
+                                engine_status_handler_t status_fnc,
+                                void *status_fnc_value)
 {
+  assuan_context_t ctx = uiserver->assuan_ctx;
   gpg_error_t err;
   char *line;
   size_t linelen;
@@ -493,8 +496,17 @@ uiserver_assuan_simple_command (assuan_context_t ctx, char *cmd,
            *(rest++) = 0;
 
          r = _gpgme_parse_status (line + 2);
+          if (uiserver->status.mon_cb && r != GPGME_STATUS_PROGRESS)
+            {
+              /* Note that we call the monitor even if we do
+               * not know the status code (r < 0).  */
+              err = uiserver->status.mon_cb (uiserver->status.mon_cb_value,
+                                             line + 2, rest);
+            }
 
-         if (r >= 0 && status_fnc)
+          if (err)
+            ;
+         else if (r >= 0 && status_fnc)
            err = status_fnc (status_fnc_value, r, rest);
          else
            err = gpg_error (GPG_ERR_GENERAL);
@@ -576,7 +588,7 @@ uiserver_set_fd (engine_uiserver_t uiserver, fd_type_t fd_type, const char *opt)
   else
     snprintf (line, COMMANDLINELEN, "%s FD", which);
 
-  err = uiserver_assuan_simple_command (uiserver->assuan_ctx, line, NULL, NULL);
+  err = uiserver_assuan_simple_command (uiserver, line, NULL, NULL);
 
  leave_set_fd:
   if (err)
@@ -915,7 +927,7 @@ uiserver_reset (void *engine)
 
   /* We must send a reset because we need to reset the list of
      signers.  Note that RESET does not reset OPTION commands. */
-  return uiserver_assuan_simple_command (uiserver->assuan_ctx, "RESET", NULL, NULL);
+  return uiserver_assuan_simple_command (uiserver, "RESET", NULL, NULL);
 }
 
 
@@ -984,7 +996,6 @@ static gpgme_error_t
 set_recipients (engine_uiserver_t uiserver, gpgme_key_t recp[])
 {
   gpgme_error_t err = 0;
-  assuan_context_t ctx = uiserver->assuan_ctx;
   char *line;
   int linelen;
   int invalid_recipients = 0;
@@ -1023,7 +1034,8 @@ set_recipients (engine_uiserver_t uiserver, gpgme_key_t recp[])
       /* FIXME: need to do proper escaping  */
       strcpy (&line[10], uid);
 
-      err = uiserver_assuan_simple_command (ctx, line, uiserver->status.fnc,
+      err = uiserver_assuan_simple_command (uiserver, line,
+                                            uiserver->status.fnc,
                                             uiserver->status.fnc_value);
       /* FIXME: This might requires more work.  */
       if (gpg_err_code (err) == GPG_ERR_NO_PUBKEY)
@@ -1160,7 +1172,7 @@ uiserver_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
           char buf[100];
 
           strcpy (stpcpy (buf, "SENDER --info "), s);
-          err = uiserver_assuan_simple_command (uiserver->assuan_ctx, buf,
+          err = uiserver_assuan_simple_command (uiserver, buf,
                                                 uiserver->status.fnc,
                                                 uiserver->status.fnc_value);
         }
@@ -1252,6 +1264,18 @@ uiserver_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
 }
 
 
+/* This sets a status callback for monitoring status lines before they
+ * are passed to a caller set handler.  */
+static void
+uiserver_set_status_cb (void *engine, gpgme_status_cb_t cb, void *cb_value)
+{
+  engine_uiserver_t uiserver = engine;
+
+  uiserver->status.mon_cb = cb;
+  uiserver->status.mon_cb_value = cb_value;
+}
+
+
 static void
 uiserver_set_status_handler (void *engine, engine_status_handler_t fnc,
                          void *fnc_value)
@@ -1309,6 +1333,7 @@ struct engine_ops _gpgme_engine_ops_uiserver =
     /* Member functions.  */
     uiserver_release,
     uiserver_reset,
+    uiserver_set_status_cb,
     uiserver_set_status_handler,
     NULL,              /* set_command_handler */
     uiserver_set_colon_line_handler,
index 8e84da9..c9449db 100644 (file)
@@ -503,6 +503,21 @@ _gpgme_engine_release (engine_t engine)
 }
 
 
+/* Set a status callback which is used to monitor the status values
+ * before they are passed to a handler set with
+ * _gpgme_engine_set_status_handler.  */
+void
+_gpgme_engine_set_status_cb (engine_t engine,
+                             gpgme_status_cb_t cb, void *cb_value)
+{
+  if (!engine)
+    return;
+
+  if (engine->ops->set_status_cb)
+    (*engine->ops->set_status_cb) (engine->engine, cb, cb_value);
+}
+
+
 void
 _gpgme_engine_set_status_handler (engine_t engine,
                                  engine_status_handler_t fnc, void *fnc_value)
index 56fcc42..238a21c 100644 (file)
@@ -62,6 +62,8 @@ gpgme_error_t _gpgme_engine_set_locale (engine_t engine, int category,
 gpgme_error_t _gpgme_engine_set_protocol (engine_t engine,
                                          gpgme_protocol_t protocol);
 void _gpgme_engine_release (engine_t engine);
+void _gpgme_engine_set_status_cb (engine_t engine,
+                                  gpgme_status_cb_t cb, void *cb_value);
 void _gpgme_engine_set_status_handler (engine_t engine,
                                       engine_status_handler_t fnc,
                                       void *fnc_value);
index 3afd3b4..34cc5af 100644 (file)
@@ -134,7 +134,7 @@ genkey_status_handler (void *priv, gpgme_status_code_t code, char *args)
       break;
 
     case GPGME_STATUS_INQUIRE_MAXLEN:
-      if (ctx->status_cb)
+      if (ctx->status_cb && !ctx->full_status)
         {
           err = ctx->status_cb (ctx->status_cb_value, "INQUIRE_MAXLEN", args);
           if (err)
index 0b42ea1..3289be9 100644 (file)
@@ -82,6 +82,30 @@ gpgme_set_global_flag (const char *name, const char *value)
 }
 
 
+/* Set the flag NAME for CTX to VALUE.  The supported flags are:
+ *
+ * - full-status :: With a value of "1" the status callback set by
+ *                  gpgme_set_status_cb returns all status lines
+ *                  except for PROGRESS lines.  With the default of
+ *                  "0" the status callback is only called in certain
+ *                  situations.
+ */
+gpgme_error_t
+gpgme_set_ctx_flag (gpgme_ctx_t ctx, const char *name, const char *value)
+{
+  if (!ctx || !name || !value)
+    return gpg_error (GPG_ERR_INV_VALUE);
+  else if (!strcmp (name, "full-status"))
+    {
+      ctx->full_status = *value? !!atoi (value) : 0;
+    }
+  else
+    return gpg_error (GPG_ERR_UNKNOWN_NAME);
+
+  return 0;
+}
+
+
 \f
 /* Create a new context as an environment for GPGME crypto
    operations.  */
index 3b56aaa..dfdb6c6 100644 (file)
@@ -225,5 +225,6 @@ EXPORTS
     gpgme_get_status_cb                   @168
 
     gpgme_pubkey_algo_string              @169
+    gpgme_set_ctx_flag                    @170
 ; END
 
index 7a58ded..5f7896d 100644 (file)
@@ -911,6 +911,10 @@ gpgme_error_t gpgme_new (gpgme_ctx_t *ctx);
 /* Release the context CTX.  */
 void gpgme_release (gpgme_ctx_t ctx);
 
+/* Set the flag NAME for CTX to VALUE.  */
+gpgme_error_t gpgme_set_ctx_flag (gpgme_ctx_t ctx,
+                                  const char *name, const char *value);
+
 /* Set the protocol to be used by CTX to PROTO.  */
 gpgme_error_t gpgme_set_protocol (gpgme_ctx_t ctx, gpgme_protocol_t proto);
 
@@ -993,7 +997,7 @@ void gpgme_get_progress_cb (gpgme_ctx_t ctx, gpgme_progress_cb_t *cb,
                            void **hook_value);
 
 /* Set the status callback function in CTX to CB.  HOOK_VALUE is
-   passed as first argument to thes status callback function.  */
+   passed as first argument to the status callback function.  */
 void gpgme_set_status_cb (gpgme_ctx_t c, gpgme_status_cb_t cb,
                           void *hook_value);
 
index c677190..873cb19 100644 (file)
@@ -100,6 +100,7 @@ GPGME_1.1 {
     gpgme_get_status_cb;
 
     gpgme_pubkey_algo_string;
+    gpgme_set_ctx_flag;
 };
 
 
index 4e388a4..a74405e 100644 (file)
@@ -148,6 +148,12 @@ _gpgme_op_reset (gpgme_ctx_t ctx, int type)
             err = 0;
         }
 
+      if (!err && ctx->status_cb && ctx->full_status)
+        {
+          _gpgme_engine_set_status_cb (ctx->engine,
+                                       ctx->status_cb, ctx->status_cb_value);
+        }
+
       if (err)
         {
           _gpgme_engine_release (ctx->engine);
index c88e57d..74d235c 100644 (file)
@@ -118,9 +118,8 @@ _gpgme_passphrase_status_handler (void *priv, gpgme_status_code_t code,
 
     case GPGME_STATUS_ERROR:
       /* We abuse this status handler to forward ERROR status codes to
-         the caller.  This should better be done in a generic handler,
-         but for now this is sufficient.  */
-      if (ctx->status_cb)
+         the caller.  */
+      if (ctx->status_cb && !ctx->full_status)
         {
           err = ctx->status_cb (ctx->status_cb_value, "ERROR", args);
           if (err)
@@ -130,9 +129,8 @@ _gpgme_passphrase_status_handler (void *priv, gpgme_status_code_t code,
 
     case GPGME_STATUS_FAILURE:
       /* We abuse this status handler to forward FAILURE status codes
-         to the caller.  This should better be done in a generic
-         handler, but for now this is sufficient.  */
-      if (ctx->status_cb)
+         to the caller.  */
+      if (ctx->status_cb && !ctx->full_status)
         {
           err = ctx->status_cb (ctx->status_cb_value, "FAILURE", args);
           if (err)
@@ -173,6 +171,7 @@ _gpgme_passphrase_command_handler (void *priv, gpgme_status_code_t code,
       if (processed)
        *processed = 1;
 
+      /* Fake a status line to to convey the MAXLEN info.  */
       if (ctx->status_cb && opd->maxlen)
         err = ctx->status_cb (ctx->status_cb_value, "INQUIRE_MAXLEN",
                               opd->maxlen);
index d8650a9..bfd9ad1 100644 (file)
@@ -369,7 +369,7 @@ _gpgme_sign_status_handler (void *priv, gpgme_status_code_t code, char *args)
       break;
 
     case GPGME_STATUS_INQUIRE_MAXLEN:
-      if (ctx->status_cb)
+      if (ctx->status_cb && !ctx->full_status)
         err = ctx->status_cb (ctx->status_cb_value, "INQUIRE_MAXLEN", args);
       break;
 
index b49ea2a..b7be320 100644 (file)
 
 static int verbose;
 
+static gpg_error_t
+status_cb (void *opaque, const char *keyword, const char *value)
+{
+  (void)opaque;
+  fprintf (stderr, "status_cb: %s %s\n", keyword, value);
+  return 0;
+}
+
+
 static void
 print_summary (gpgme_sigsum_t summary)
 {
@@ -102,8 +111,10 @@ print_result (gpgme_verify_result_t result)
       printf ("  validity ..: ");
       print_validity (sig->validity); putchar ('\n');
       printf ("  val.reason : %s\n", gpgme_strerror (sig->status));
-      printf ("  pubkey algo: %d\n", sig->pubkey_algo);
-      printf ("  digest algo: %d\n", sig->hash_algo);
+      printf ("  pubkey algo: %d (%s)\n", sig->pubkey_algo,
+              nonnull(gpgme_pubkey_algo_name (sig->pubkey_algo)));
+      printf ("  digest algo: %d (%s)\n", sig->hash_algo,
+              nonnull(gpgme_hash_algo_name (sig->hash_algo)));
       printf ("  pka address: %s\n", nonnull (sig->pka_address));
       printf ("  pka trust .: %s\n",
               sig->pka_trust == 0? "n/a" :
@@ -126,6 +137,7 @@ show_usage (int ex)
   fputs ("usage: " PGM " [options] [DETACHEDSIGFILE] FILE\n\n"
          "Options:\n"
          "  --verbose        run in verbose mode\n"
+         "  --status         print status lines from the backend\n"
          "  --openpgp        use the OpenPGP protocol (default)\n"
          "  --cms            use the CMS protocol\n"
          , stderr);
@@ -145,6 +157,7 @@ main (int argc, char **argv)
   FILE *fp_msg = NULL;
   gpgme_data_t msg = NULL;
   gpgme_verify_result_t result;
+  int print_status = 0;
 
   if (argc)
     { argc--; argv++; }
@@ -164,6 +177,11 @@ main (int argc, char **argv)
           verbose = 1;
           argc--; argv++;
         }
+      else if (!strcmp (*argv, "--status"))
+        {
+          print_status = 1;
+          argc--; argv++;
+        }
       else if (!strcmp (*argv, "--openpgp"))
         {
           protocol = GPGME_PROTOCOL_OpenPGP;
@@ -207,6 +225,11 @@ main (int argc, char **argv)
   err = gpgme_new (&ctx);
   fail_if_err (err);
   gpgme_set_protocol (ctx, protocol);
+  if (print_status)
+    {
+      gpgme_set_status_cb (ctx, status_cb, NULL);
+      gpgme_set_ctx_flag (ctx, "full-status", "1");
+    }
 
   err = gpgme_data_new_from_stream (&sig, fp_sig);
   if (err)
@@ -232,7 +255,7 @@ main (int argc, char **argv)
     print_result (result);
   if (err)
     {
-      fprintf (stderr, PGM ": signing failed: %s\n", gpgme_strerror (err));
+      fprintf (stderr, PGM ": verify failed: %s\n", gpgme_strerror (err));
       exit (1);
     }