2006-12-17 Marcus Brinkmann <marcus@g10code.de>
authorMarcus Brinkmann <mb@g10code.com>
Sun, 17 Dec 2006 16:40:09 +0000 (16:40 +0000)
committerMarcus Brinkmann <mb@g10code.com>
Sun, 17 Dec 2006 16:40:09 +0000 (16:40 +0000)
* engine.h (_gpgme_engine_new): Remove arguments lc_ctype and
lc_messages from prototype.
(_gpgme_engine_set_locale): New prototype.
* engine.c (_gpgme_engine_set_locale): New function.
* op-support.c (_gpgme_op_reset): Call _gpgme_engine_set_locale.
* engine-backend.h (struct engine_ops): Add new member SET_LOCALE.
Remove arguments lc_messages and lc_ctype from member NEW.
* engine-gpgsm.c (struct engine_gpgsm): New members lc_ctype_set
and lc_messages_set.
(gpgsm_new): Remove lc_messages and lc_ctype
arguments.
(gpgsm_set_locale): New function.
(_gpgme_engine_ops_gpgsm): Add gpgsm_set_locale.
* rungpg.c (struct engine_gpg): Add new members lc_messages and
lc_ctype.
(gpg_release): Release lc_messages and lc_ctype if set.
(gpg_new): Remove lc_messages and lc_ctype arguments.
(gpg_set_locale): New function.
(_gpgme_engine_ops_gpg): Add gpg_set_locale.
(add_arg): Implement in terms of:
(add_arg_ext): New function.
(start): Set lc-messages and lc-ctype arguments here.

gpgme/ChangeLog
gpgme/engine-backend.h
gpgme/engine-gpgsm.c
gpgme/engine.c
gpgme/engine.h
gpgme/op-support.c
gpgme/rungpg.c

index 9a460ea..fea3b67 100644 (file)
@@ -1,3 +1,28 @@
+2006-12-17  Marcus Brinkmann  <marcus@g10code.de>
+
+       * engine.h (_gpgme_engine_new): Remove arguments lc_ctype and
+       lc_messages from prototype.
+       (_gpgme_engine_set_locale): New prototype.
+       * engine.c (_gpgme_engine_set_locale): New function.
+       * op-support.c (_gpgme_op_reset): Call _gpgme_engine_set_locale.
+       * engine-backend.h (struct engine_ops): Add new member SET_LOCALE.
+       Remove arguments lc_messages and lc_ctype from member NEW.
+       * engine-gpgsm.c (struct engine_gpgsm): New members lc_ctype_set
+       and lc_messages_set.
+       (gpgsm_new): Remove lc_messages and lc_ctype
+       arguments.
+       (gpgsm_set_locale): New function.
+       (_gpgme_engine_ops_gpgsm): Add gpgsm_set_locale.
+       * rungpg.c (struct engine_gpg): Add new members lc_messages and
+       lc_ctype.
+       (gpg_release): Release lc_messages and lc_ctype if set.
+       (gpg_new): Remove lc_messages and lc_ctype arguments.
+       (gpg_set_locale): New function.
+       (_gpgme_engine_ops_gpg): Add gpg_set_locale.
+       (add_arg): Implement in terms of:
+       (add_arg_ext): New function.
+       (start): Set lc-messages and lc-ctype arguments here.
+
 2006-12-03  Marcus Brinkmann  <marcus@g10code.de>
 
        * engine-gpgsm.c (struct engine_gpgsm): Move members
index 27fadbc..eed8ffd 100644 (file)
@@ -45,8 +45,7 @@ struct engine_ops
   const char *(*get_req_version) (void);
 
   gpgme_error_t (*new) (void **r_engine,
-                       const char *file_name, const char *home_dir,
-                       const char *lc_ctype, const char *lc_messages);
+                       const char *file_name, const char *home_dir);
 
   /* Member functions.  */
   void (*release) (void *engine);
@@ -58,6 +57,7 @@ struct engine_ops
   gpgme_error_t (*set_colon_line_handler) (void *engine,
                                           engine_colon_line_handler_t fnc,
                                           void *fnc_value);
+  gpgme_error_t (*set_locale) (void *engine, int category, const char *value);
   gpgme_error_t (*decrypt) (void *engine, gpgme_data_t ciph,
                            gpgme_data_t plain);
   gpgme_error_t (*delete) (void *engine, gpgme_key_t key, int allow_secret);
index 73e6ef8..766323a 100644 (file)
@@ -62,6 +62,9 @@ struct engine_gpgsm
 {
   assuan_context_t assuan_ctx;
 
+  int lc_ctype_set;
+  int lc_messages_set;
+
   iocb_data_t status_cb;
 
   /* Input, output etc are from the servers perspective.  */
@@ -317,8 +320,7 @@ gpgsm_release (void *engine)
 
 
 static gpgme_error_t
-gpgsm_new (void **engine, const char *file_name, const char *home_dir,
-          const char *lc_ctype, const char *lc_messages)
+gpgsm_new (void **engine, const char *file_name, const char *home_dir)
 {
   gpgme_error_t err = 0;
   engine_gpgsm_t gpgsm;
@@ -516,38 +518,6 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir,
        }
     }
 
-  if (lc_ctype)
-    {
-      if (asprintf (&optstr, "OPTION lc-ctype=%s", lc_ctype) < 0)
-       err = gpg_error_from_errno (errno);
-      else
-       {
-         err = assuan_transact (gpgsm->assuan_ctx, optstr, NULL, NULL,
-                                NULL, NULL, NULL, NULL);
-         free (optstr);
-         if (err)
-           err = map_assuan_error (err);
-       }
-    }
-  if (err)
-    goto leave;
-  
-  if (lc_messages)
-    {
-      if (asprintf (&optstr, "OPTION lc-messages=%s", lc_messages) < 0)
-       err = gpg_error_from_errno (errno);
-      else
-       {
-         err = assuan_transact (gpgsm->assuan_ctx, optstr, NULL, NULL,
-                                NULL, NULL, NULL, NULL);
-         free (optstr);
-         if (err)
-           err = map_assuan_error (err);
-       }
-    }
-  if (err)
-    goto leave;
-
   if (!err
       && (_gpgme_io_set_close_notify (gpgsm->status_cb.fd,
                                      close_notify_handler, gpgsm)))
@@ -591,6 +561,50 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir,
 }
 
 
+static gpgme_error_t
+gpgsm_set_locale (void *engine, int category, const char *value)
+{
+  engine_gpgsm_t gpgsm = engine;
+  gpgme_error_t err;
+  char *optstr;
+  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
+     for this.  */
+  if (category == LC_CTYPE)
+    {
+      catstr = "lc-ctype";
+      if (!value && gpgsm->lc_ctype_set)
+       return gpg_error (GPG_ERR_INV_VALUE);
+      if (value)
+       gpgsm->lc_ctype_set = 1;
+    }
+  else if (category == LC_MESSAGES)
+    {
+      catstr = "lc-messages";
+      if (!value && gpgsm->lc_messages_set)
+       return gpg_error (GPG_ERR_INV_VALUE);
+      if (value)
+       gpgsm->lc_messages_set = 1;
+    }
+  else
+    return gpg_error (GPG_ERR_INV_VALUE);
+
+  if (asprintf (&optstr, "OPTION %s=%s", catstr, value) < 0)
+    err = gpg_error_from_errno (errno);
+  else
+    {
+      err = assuan_transact (gpgsm->assuan_ctx, optstr, NULL, NULL,
+                            NULL, NULL, NULL, NULL);
+      free (optstr);
+      if (err)
+       err = map_assuan_error (err);
+    }
+  return err;
+}
+
+
 /* Forward declaration.  */
 static gpgme_status_code_t parse_status (const char *name);
 
@@ -1693,6 +1707,7 @@ struct engine_ops _gpgme_engine_ops_gpgsm =
     gpgsm_set_status_handler,
     NULL,              /* set_command_handler */
     gpgsm_set_colon_line_handler,
+    gpgsm_set_locale,
     gpgsm_decrypt,
     gpgsm_delete,
     NULL,              /* edit */
index a7ca624..dd89c2d 100644 (file)
@@ -389,8 +389,7 @@ gpgme_set_engine_info (gpgme_protocol_t proto,
 
 \f
 gpgme_error_t
-_gpgme_engine_new (gpgme_engine_info_t info, engine_t *r_engine,
-                  const char *lc_ctype, const char *lc_messages)
+_gpgme_engine_new (gpgme_engine_info_t info, engine_t *r_engine)
 {
   engine_t engine;
 
@@ -404,9 +403,9 @@ _gpgme_engine_new (gpgme_engine_info_t info, engine_t *r_engine,
   engine->ops = engine_ops[info->protocol];
   if (engine->ops->new)
     {
-      gpgme_error_t err = (*engine->ops->new) (&engine->engine,
-                                              info->file_name, info->home_dir,
-                                              lc_ctype, lc_messages);
+      gpgme_error_t err;
+      err = (*engine->ops->new) (&engine->engine,
+                                info->file_name, info->home_dir);
       if (err)
        {
          free (engine);
@@ -477,6 +476,19 @@ _gpgme_engine_set_colon_line_handler (engine_t engine,
 }
 
 gpgme_error_t
+_gpgme_engine_set_locale (engine_t engine, int category,
+                         const char *value)
+{
+  if (!engine)
+    return gpg_error (GPG_ERR_INV_VALUE);
+
+  if (!engine->ops->set_locale)
+    return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+  return (*engine->ops->set_locale) (engine->engine, category, value);
+}
+
+gpgme_error_t
 _gpgme_engine_op_decrypt (engine_t engine, gpgme_data_t ciph,
                          gpgme_data_t plain)
 {
index be9c9b7..893e591 100644 (file)
@@ -51,9 +51,11 @@ gpgme_error_t _gpgme_set_engine_info (gpgme_engine_info_t info,
 
 
 gpgme_error_t _gpgme_engine_new (gpgme_engine_info_t info,
-                                engine_t *r_engine,
-                                const char *lc_ctype,
-                                const char *lc_messages);
+                                engine_t *r_engine);
+
+gpgme_error_t _gpgme_engine_set_locale (engine_t engine, int category,
+                                       const char *value);
+
 void _gpgme_engine_release (engine_t engine);
 void _gpgme_engine_set_status_handler (engine_t engine,
                                       engine_status_handler_t fnc,
index 68ff77d..8a42851 100644 (file)
@@ -24,6 +24,7 @@
 #include <stdlib.h>
 #include <errno.h>
 #include <string.h>
+#include <locale.h>
 
 #include "gpgme.h"
 #include "context.h"
@@ -86,11 +87,21 @@ _gpgme_op_reset (gpgme_ctx_t ctx, int type)
     }
 
   /* Create an engine object.  */
-  err = _gpgme_engine_new (info, &ctx->engine,
-                          ctx->lc_ctype, ctx->lc_messages);
+  err = _gpgme_engine_new (info, &ctx->engine);
   if (err)
     return err;
 
+  err = _gpgme_engine_set_locale (ctx->engine, LC_CTYPE, ctx->lc_ctype);
+  if (!err)
+    err = _gpgme_engine_set_locale (ctx->engine,
+                                   LC_MESSAGES, ctx->lc_messages);
+  if (err)
+    {
+      _gpgme_engine_release (ctx->engine);
+      ctx->engine = NULL;
+      return err;
+    }
+
   if (type == 1 || (type == 2 && !ctx->io_cbs.add))
     {
       /* Use private event loop.  */
index 3907c3f..f3326b3 100644 (file)
@@ -28,6 +28,7 @@
 #include <assert.h>
 #include <errno.h>
 #include <unistd.h>
+#include <locale.h>
 
 #include "gpgme.h"
 #include "util.h"
@@ -72,6 +73,9 @@ struct engine_gpg
 {
   char *file_name;
 
+  char *lc_messages;
+  char *lc_ctype;
+
   struct arg_and_data_s *arglist;
   struct arg_and_data_s **argtail;
 
@@ -181,8 +185,10 @@ close_notify_handler (int fd, void *opaque)
     }
 }
 
+/* If FRONT is true, push at the front of the list.  Use this for
+   options added late in the process.  */
 static gpgme_error_t
-add_arg (engine_gpg_t gpg, const char *arg)
+add_arg_ext (engine_gpg_t gpg, const char *arg, int front)
 {
   struct arg_and_data_s *a;
 
@@ -192,16 +198,38 @@ add_arg (engine_gpg_t gpg, const char *arg)
   a = malloc (sizeof *a + strlen (arg));
   if (!a)
     return gpg_error_from_errno (errno);
-  a->next = NULL;
+
   a->data = NULL;
   a->dup_to = -1;
   strcpy (a->arg, arg);
-  *gpg->argtail = a;
-  gpg->argtail = &a->next;
+  if (front)
+    {
+      a->next = gpg->arglist;
+      if (!gpg->arglist)
+       {
+         /* If this is the first argument, we need to update the tail
+            pointer.  */
+         gpg->argtail = &a->next;
+       }
+      gpg->arglist = a;
+    }
+  else
+    {
+      a->next = NULL;
+      *gpg->argtail = a;
+      gpg->argtail = &a->next;
+    }
+
   return 0;
 }
 
 static gpgme_error_t
+add_arg (engine_gpg_t gpg, const char *arg)
+{
+  return add_arg_ext (gpg, arg, 0);
+}
+
+static gpgme_error_t
 add_data (engine_gpg_t gpg, gpgme_data_t data, int dup_to, int inbound)
 {
   struct arg_and_data_s *a;
@@ -317,6 +345,11 @@ gpg_release (void *engine)
   if (gpg->file_name)
     free (gpg->file_name);
 
+  if (gpg->lc_messages)
+    free (gpg->lc_messages);
+  if (gpg->lc_ctype)
+    free (gpg->lc_ctype);
+
   while (gpg->arglist)
     {
       struct arg_and_data_s *next = gpg->arglist->next;
@@ -340,8 +373,7 @@ gpg_release (void *engine)
 
 
 static gpgme_error_t
-gpg_new (void **engine, const char *file_name, const char *home_dir,
-        const char *lc_ctype, const char *lc_messages)
+gpg_new (void **engine, const char *file_name, const char *home_dir)
 {
   engine_gpg_t gpg;
   gpgme_error_t rc = 0;
@@ -468,24 +500,6 @@ gpg_new (void **engine, const char *file_name, const char *home_dir,
        goto leave;
     }
 
-  if (lc_ctype)
-    {
-      rc = add_arg (gpg, "--lc-ctype");
-      if (!rc)
-       rc = add_arg (gpg, lc_ctype);
-      if (rc)
-       goto leave;
-    }
-
-  if (lc_messages)
-    {
-      rc = add_arg (gpg, "--lc-messages");
-      if (!rc)
-       rc = add_arg (gpg, lc_messages);
-      if (rc)
-       goto leave;
-    }
-
  leave:
   if (rc)
     gpg_release (gpg);
@@ -495,6 +509,40 @@ gpg_new (void **engine, const char *file_name, const char *home_dir,
 }
 
 
+static gpgme_error_t
+gpg_set_locale (void *engine, int category, const char *value)
+{
+  engine_gpg_t gpg = engine;
+
+  if (category == LC_CTYPE)
+    {
+      if (gpg->lc_ctype)
+       free (gpg->lc_ctype);
+      if (value)
+       {
+         gpg->lc_ctype = strdup (value);
+         if (!gpg->lc_ctype)
+           return gpg_error_from_syserror ();
+       }
+    }
+  else if (category == LC_MESSAGES)
+    {
+      if (gpg->lc_messages)
+       free (gpg->lc_messages);
+      if (value)
+       {
+         gpg->lc_messages = strdup (value);
+         if (!gpg->lc_messages)
+           return gpg_error_from_syserror ();
+       }
+    }
+  else
+    return gpg_error (GPG_ERR_INV_VALUE);
+
+  return 0;
+}
+
+
 /* Note, that the status_handler is allowed to modifiy the args
    value.  */
 static void
@@ -1163,6 +1211,24 @@ start (engine_gpg_t gpg)
   if (!gpg->file_name && !_gpgme_get_gpg_path ())
     return gpg_error (GPG_ERR_INV_ENGINE);
 
+  if (gpg->lc_ctype)
+    {
+      rc = add_arg_ext (gpg, gpg->lc_ctype, 1);
+      if (!rc)
+       rc = add_arg_ext (gpg, "--lc-ctype", 1);
+      if (rc)
+       return rc;
+    }
+
+  if (gpg->lc_messages)
+    {
+      rc = add_arg_ext (gpg, gpg->lc_messages, 1);
+      if (!rc)
+       rc = add_arg_ext (gpg, "--lc-messages", 1);
+      if (rc)
+       return rc;
+    }
+
   rc = build_argv (gpg);
   if (rc)
     return rc;
@@ -2015,6 +2081,7 @@ struct engine_ops _gpgme_engine_ops_gpg =
     gpg_set_status_handler,
     gpg_set_command_handler,
     gpg_set_colon_line_handler,
+    gpg_set_locale,
     gpg_decrypt,
     gpg_delete,
     gpg_edit,