diff options
| author | Marcus Brinkmann <[email protected]> | 2003-09-14 00:02:41 +0000 | 
|---|---|---|
| committer | Marcus Brinkmann <[email protected]> | 2003-09-14 00:02:41 +0000 | 
| commit | 256ef2e87ee107705f6bb6de4a63d9dc130c507f (patch) | |
| tree | 78d4519e467dfe8f55f135dd8764c8f68b611ee1 | |
| parent | doc/ (diff) | |
| download | gpgme-256ef2e87ee107705f6bb6de4a63d9dc130c507f.tar.gz gpgme-256ef2e87ee107705f6bb6de4a63d9dc130c507f.zip | |
doc/
2003-09-14  Marcus Brinkmann  <[email protected]>
	* gpgme.texi (Locale): New section.
	(Multi Threading): Set locale in example.
gpgme/
2003-09-14  Marcus Brinkmann  <[email protected]>
	* context.h (struct gpgme_context): New members lc_ctype and
	lc_messages.
	* gpgme.c: Include <locale.h>.
	(def_lc_lock, def_lc_ctype, def_lc_messages): New static
	variables.
	(gpgme_set_locale): New function.
	* engine.c (_gpgme_engine_new): Add arguments lc_ctype and
	lc_messages.
	* engine.h (_gpgme_engine_new): Likewise.
	* engine-gpgsm.c (gpgsm_new): Likewise.
	* rungpg.c (gpg_new): Likewise.
	* engine-backend.h (struct engine_ops): Likewise to NEW.
	* op-support.c (_gpgme_op_reset): Likewise to invocation of
	_gpgme_engine_new.
| -rw-r--r-- | NEWS | 19 | ||||
| -rw-r--r-- | doc/ChangeLog | 5 | ||||
| -rw-r--r-- | doc/gpgme.texi | 79 | ||||
| -rw-r--r-- | gpgme/ChangeLog | 17 | ||||
| -rw-r--r-- | gpgme/context.h | 4 | ||||
| -rw-r--r-- | gpgme/engine-backend.h | 3 | ||||
| -rw-r--r-- | gpgme/engine-gpgsm.c | 62 | ||||
| -rw-r--r-- | gpgme/engine.c | 7 | ||||
| -rw-r--r-- | gpgme/engine.h | 4 | ||||
| -rw-r--r-- | gpgme/gpgme.c | 106 | ||||
| -rw-r--r-- | gpgme/op-support.c | 3 | ||||
| -rw-r--r-- | gpgme/rungpg.c | 2 | 
12 files changed, 252 insertions, 59 deletions
| @@ -38,6 +38,24 @@ Noteworthy changes in version 0.4.3 (unreleased)     than an unsigned long (the old class field is preserved for     backwards compatibility). + * A new function gpgme_set_locale() is provided to allow configuring +   the locale for the crypto backend.  This is necessary for text +   terminals so that programs like the pinentry can be started with +   the right locale settings for the terminal the application is running +   on, in case the terminal has different settings than the system +   default (for example, if it is a remote terminal).  You are highly +   recommended to call the following functions directly after +   gpgme_check_version: + +   #include <locale.h> + +   setlocale (LC_ALL, ""); +   gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL)); +   gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL)); + +   GPGME can not do this for you, as setlocale is not thread safe, and +   there is no alternative. +   * Interface changes relative to the 0.4.2 release:  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  gpgme_strerror_t		NEW @@ -45,6 +63,7 @@ gpgme_get_key			CHANGED: Fails correctly if key ID not unique.  gpgme_key_t			EXTENDED: New field can_authenticate.  gpgme_subkey_t			EXTENDED: New field can_authenticate.  gpgme_new_signature_t		CHANGED: New type for class field. +gpgme_set_locale		NEW  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/ChangeLog b/doc/ChangeLog index dd2c2f02..11cc544b 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,8 @@ +2003-09-14  Marcus Brinkmann  <[email protected]> + +	* gpgme.texi (Locale): New section. +	(Multi Threading): Set locale in example. +  2003-09-13  Marcus Brinkmann  <[email protected]>  	* gpgme.texi (Error Strings): Add gpgme_strerror_r. diff --git a/doc/gpgme.texi b/doc/gpgme.texi index 1e00d752..eaa197c3 100644 --- a/doc/gpgme.texi +++ b/doc/gpgme.texi @@ -159,6 +159,7 @@ Context Attributes  * Key Listing Mode::              Selecting key listing mode.  * Passphrase Callback::           Getting the passphrase from the user.  * Progress Meter Callback::       Being informed about the progress. +* Locale::                        Setting the locale of a context.  Key Management @@ -492,6 +493,31 @@ features are provided by the installed version of the library.  @end deftypefun +After initializing @acronym{GPGME}, you should set the locale +information to the locale required for your output terminal (only +required if your program runs on a text terminal, rather than in the X +Window environment).  Here is an example of a complete initialization: + +@example +#include <locale.h> +#include <gpgme.h> + +void +init_program (void) +@{ +  /* Initialize the locale environment.  */ +  setlocale (LC_ALL, ""); +  gpgme_check_version (NULL); +  gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL)); +  gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL)); +@} +@end example + +Note that you are highly recommended to initialize the locale settings +like this.  @acronym{GPGME} can not do this for you because it would +not be thread safe. + +  @node Multi Threading  @section Multi Threading  @cindex thread-safeness @@ -548,7 +574,10 @@ call functions in @acronym{GPGME} could call the following function  before any function in the library:  @example +#include <stdlib.h> +#include <locale.h>  #include <pthread.h> +#include <gpgme.h>  void  initialize_gpgme (void) @@ -559,7 +588,9 @@ initialize_gpgme (void)    pthread_mutex_lock (&gpgme_init_lock);    if (!gpgme_init)      @{ -      gpgme_check_version (); +      gpgme_check_version (NULL); +      gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL)); +      gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL));        gpgme_init = 1;      @}    pthread_mutex_unlock (&gpgme_init_lock); @@ -950,21 +981,21 @@ error code part of an error value.  The error source is left  unspecified and might be anything.  @end deftp -@deftypefun {static __inline__ gpgme_err_code_t} gpgme_err_code (@w{gpgme_error_t @var{err}}) +@deftypefun {static inline gpgme_err_code_t} gpgme_err_code (@w{gpgme_error_t @var{err}})  The static inline function @code{gpgme_err_code} returns the  @code{gpgme_err_code_t} component of the error value @var{err}.  This  function must be used to extract the error code from an error value in  order to compare it with the @code{GPG_ERR_*} error code macros.  @end deftypefun -@deftypefun {static __inline__ gpgme_err_source_t} gpgme_err_source (@w{gpgme_error_t @var{err}}) +@deftypefun {static inline gpgme_err_source_t} gpgme_err_source (@w{gpgme_error_t @var{err}})  The static inline function @code{gpgme_err_source} returns the  @code{gpgme_err_source_t} component of the error value @var{err}.  This  function must be used to extract the error source from an error value in  order to compare it with the @code{GPG_ERR_SOURCE_*} error source macros.  @end deftypefun -@deftypefun {static __inline__ gpgme_error_t} gpgme_err_make (@w{gpgme_err_source_t @var{source}}, @w{gpgme_err_code_t @var{code}}) +@deftypefun {static inline gpgme_error_t} gpgme_err_make (@w{gpgme_err_source_t @var{source}}, @w{gpgme_err_code_t @var{code}})  The static inline function @code{gpgme_err_make} returns the error  value consisting of the error source @var{source} and the error code  @var{code}. @@ -973,7 +1004,7 @@ This function can be used in callback functions to construct an error  value to return it to the library.  @end deftypefun -@deftypefun {static __inline__ gpgme_error_t} gpgme_error (@w{gpgme_err_code_t @var{code}}) +@deftypefun {static inline gpgme_error_t} gpgme_error (@w{gpgme_err_code_t @var{code}})  The static inline function @code{gpgme_error} returns the error value  consisting of the default error source and the error code @var{code}. @@ -1736,6 +1767,7 @@ The function @code{gpgme_release} destroys the context with the handle  * Key Listing Mode::              Selecting key listing mode.  * Passphrase Callback::           Getting the passphrase from the user.  * Progress Meter Callback::       Being informed about the progress. +* Locale::                        Setting the locale of a context.  @end menu @@ -2013,6 +2045,43 @@ the corresponding value will not be returned.  @end deftypefun +@node Locale +@subsection Locale +@cindex locale, default +@cindex locale, of a context + +A locale setting can be associated with a context.  This locale is +passed to the crypto engine, and used for applications like the PIN +entry, which is displayed to the user when entering a passphrase is +required. + +The default locale is used to initialize the locale setting of all +contexts created afterwards. + +@deftypefun gpgme_error_t gpgme_set_locale (@w{gpgme_ctx_t @var{ctx}}, @w{int @var{category}}, @w{const char *@var{value}}) +The function @code{gpgme_set_locale} sets the locale of the context +@var{ctx}, or the default locale if @var{ctx} is a null pointer. + +The locale settings that should be changed are specified by +@var{category}.  Supported categories are @code{LC_CTYPE}, +@code{LC_MESSAGES}, and @code{LC_ALL}, which is a wildcard you can use +if you want to change all the categories at once. + +The value to be used for the locale setting is @var{value}, which will +be copied to @acronym{GPGME}'s internal data structures.  @var{value} +can be a null pointer, which disables setting the locale, and will +make PIN entry and other applications use their default setting, which +is usually not what you want. + +Note that the settings are only used if the application runs on a text +terminal, and that the settings should fit the configuration of the +output terminal.  Normally, it is sufficient to initialize the default +value at startup. + +The function returns an error if not enough memory is available. +@end deftypefun + +  @node Key Management  @section Key Management  @cindex key management diff --git a/gpgme/ChangeLog b/gpgme/ChangeLog index 0e33c914..acd4251d 100644 --- a/gpgme/ChangeLog +++ b/gpgme/ChangeLog @@ -1,3 +1,20 @@ +2003-09-14  Marcus Brinkmann  <[email protected]> + +	* context.h (struct gpgme_context): New members lc_ctype and +	lc_messages. +	* gpgme.c: Include <locale.h>. +	(def_lc_lock, def_lc_ctype, def_lc_messages): New static +	variables. +	(gpgme_set_locale): New function. +	* engine.c (_gpgme_engine_new): Add arguments lc_ctype and +	lc_messages. +	* engine.h (_gpgme_engine_new): Likewise. +	* engine-gpgsm.c (gpgsm_new): Likewise. +	* rungpg.c (gpg_new): Likewise. +	* engine-backend.h (struct engine_ops): Likewise to NEW. +	* op-support.c (_gpgme_op_reset): Likewise to invocation of +	_gpgme_engine_new. +  2003-09-13  Marcus Brinkmann  <[email protected]>  	* gpgme.h (gpgme_strerror_r): New prototype. diff --git a/gpgme/context.h b/gpgme/context.h index 4dca9ba8..64c5276c 100644 --- a/gpgme/context.h +++ b/gpgme/context.h @@ -87,6 +87,10 @@ struct gpgme_context    unsigned int signers_size;    gpgme_key_t *signers; +  /* The locale for the pinentry.  */ +  char *lc_ctype; +  char *lc_messages; +    /* The operation data hooked into the context.  */    ctx_op_data_t op_data; diff --git a/gpgme/engine-backend.h b/gpgme/engine-backend.h index e57ffc28..0a59972d 100644 --- a/gpgme/engine-backend.h +++ b/gpgme/engine-backend.h @@ -33,7 +33,8 @@ struct engine_ops    const char *(*get_file_name) (void);    const char *(*get_version) (void);    const char *(*get_req_version) (void); -  gpgme_error_t (*new) (void **r_engine); +  gpgme_error_t (*new) (void **r_engine, +			const char *lc_ctype, const char *lc_messages);    /* Member functions.  */    void (*release) (void *engine); diff --git a/gpgme/engine-gpgsm.c b/gpgme/engine-gpgsm.c index 4b925f1e..270380a5 100644 --- a/gpgme/engine-gpgsm.c +++ b/gpgme/engine-gpgsm.c @@ -294,7 +294,7 @@ gpgsm_release (void *engine)  static gpgme_error_t -gpgsm_new (void **engine) +gpgsm_new (void **engine, const char *lc_ctype, const char *lc_messages)  {    gpgme_error_t err = 0;    engine_gpgsm_t gpgsm; @@ -304,8 +304,6 @@ gpgsm_new (void **engine)    char *dft_display = NULL;    char dft_ttyname[64];    char *dft_ttytype = NULL; -  char *old_lc = NULL; -  char *dft_lc = NULL;    char *optstr;    int fdlist[5];    int nfds; @@ -470,52 +468,25 @@ gpgsm_new (void **engine)  	    }  	} -      old_lc = setlocale (LC_CTYPE, NULL); -      if (old_lc) -        { -          old_lc = strdup (old_lc); -          if (!old_lc) -            { -              err = gpg_error_from_errno (errno); -              goto leave; -            } -        } -      dft_lc = setlocale (LC_CTYPE, ""); -      if (dft_lc) +      if (lc_ctype)  	{ -	  if (asprintf (&optstr, "OPTION lc-ctype=%s", dft_lc) < 0) +	  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); +				     NULL, NULL, NULL, NULL);  	      free (optstr);  	      if (err)  		err = map_assuan_error (err);  	    }  	} -      if (old_lc) -        { -          setlocale (LC_CTYPE, old_lc); -          free (old_lc); -        }        if (err)  	goto leave; -      old_lc = setlocale (LC_MESSAGES, NULL); -      if (old_lc) -        { -          old_lc = strdup (old_lc); -          if (!old_lc) -            { -              err = gpg_error_from_errno (errno); -              goto leave; -            } -        } -      dft_lc = setlocale (LC_MESSAGES, ""); -      if (dft_lc) +      if (lc_messages)  	{ -	  if (asprintf (&optstr, "OPTION lc-messages=%s", dft_lc) < 0) +	  if (asprintf (&optstr, "OPTION lc-messages=%s", lc_messages) < 0)  	    err = gpg_error_from_errno (errno);  	  else  	    { @@ -526,24 +497,19 @@ gpgsm_new (void **engine)  		err = map_assuan_error (err);  	    }  	} -      if (old_lc) -        { -          setlocale (LC_MESSAGES, old_lc); -          free (old_lc); -        }        if (err)  	goto leave;      } -  if (!err && -      (_gpgme_io_set_close_notify (gpgsm->status_cb.fd, -				   close_notify_handler, gpgsm) -       || _gpgme_io_set_close_notify (gpgsm->input_cb.fd, -				   close_notify_handler, gpgsm) -       || _gpgme_io_set_close_notify (gpgsm->output_cb.fd, +  if (!err +      && (_gpgme_io_set_close_notify (gpgsm->status_cb.fd,  				      close_notify_handler, gpgsm) -       || _gpgme_io_set_close_notify (gpgsm->message_cb.fd, -				      close_notify_handler, gpgsm))) +	  || _gpgme_io_set_close_notify (gpgsm->input_cb.fd, +					 close_notify_handler, gpgsm) +	  || _gpgme_io_set_close_notify (gpgsm->output_cb.fd, +					 close_notify_handler, gpgsm) +	  || _gpgme_io_set_close_notify (gpgsm->message_cb.fd, +					 close_notify_handler, gpgsm)))      {        err = gpg_error (GPG_ERR_GENERAL);        goto leave; diff --git a/gpgme/engine.c b/gpgme/engine.c index d974db5a..04cefc8c 100644 --- a/gpgme/engine.c +++ b/gpgme/engine.c @@ -158,7 +158,8 @@ gpgme_get_engine_info (gpgme_engine_info_t *info)  gpgme_error_t -_gpgme_engine_new (gpgme_protocol_t proto, engine_t *r_engine) +_gpgme_engine_new (gpgme_protocol_t proto, engine_t *r_engine, +		   const char *lc_ctype, const char *lc_messages)  {    engine_t engine; @@ -183,7 +184,9 @@ _gpgme_engine_new (gpgme_protocol_t proto, engine_t *r_engine)    engine->ops = engine_ops[proto];    if (engine_ops[proto]->new)      { -      gpgme_error_t err = (*engine_ops[proto]->new) (&engine->engine); +      gpgme_error_t err = (*engine_ops[proto]->new) (&engine->engine, +						     lc_ctype, +						     lc_messages);        if (err)  	{  	  free (engine); diff --git a/gpgme/engine.h b/gpgme/engine.h index c6dc09c0..563b35b0 100644 --- a/gpgme/engine.h +++ b/gpgme/engine.h @@ -36,7 +36,9 @@ typedef gpgme_error_t (*engine_command_handler_t) (void *priv,  						   int fd);  gpgme_error_t _gpgme_engine_new (gpgme_protocol_t proto, -				 engine_t *r_engine); +				 engine_t *r_engine, +				 const char *lc_ctype, +				 const char *lc_messages);  void _gpgme_engine_release (engine_t engine);  void _gpgme_engine_set_status_handler (engine_t engine,  				       engine_status_handler_t fnc, diff --git a/gpgme/gpgme.c b/gpgme/gpgme.c index 3143d938..d4f0cf1f 100644 --- a/gpgme/gpgme.c +++ b/gpgme/gpgme.c @@ -26,12 +26,20 @@  #include <string.h>  #include <assert.h>  #include <errno.h> +#include <locale.h>  #include "util.h"  #include "context.h"  #include "ops.h"  #include "wait.h" + +/* The default locale.  */ +DEFINE_STATIC_LOCK (def_lc_lock); +static char *def_lc_ctype; +static char *def_lc_messages; + +  /* Create a new context as an environment for GPGME crypto     operations.  */  gpgme_error_t @@ -46,6 +54,37 @@ gpgme_new (gpgme_ctx_t *r_ctx)    ctx->include_certs = 1;    ctx->protocol = GPGME_PROTOCOL_OpenPGP;    _gpgme_fd_table_init (&ctx->fdt); + +  LOCK (def_lc_lock); +  if (def_lc_ctype) +    { +      ctx->lc_ctype = strdup (def_lc_ctype); +      if (!ctx->lc_ctype) +	{ +	  UNLOCK (def_lc_lock); +	  free (ctx); +	  return gpg_error_from_errno (errno); +	} +    } +  else +    def_lc_ctype = NULL; + +  if (def_lc_messages) +    { +      ctx->lc_messages = strdup (def_lc_messages); +      if (!ctx->lc_messages) +	{ +	  UNLOCK (def_lc_lock); +	  if (ctx->lc_ctype) +	    free (ctx->lc_ctype); +	  free (ctx); +	  return gpg_error_from_errno (errno); +	} +    } +  else +    def_lc_messages = NULL; +  UNLOCK (def_lc_lock); +    *r_ctx = ctx;    return 0;  } @@ -61,6 +100,10 @@ gpgme_release (gpgme_ctx_t ctx)    gpgme_signers_clear (ctx);    if (ctx->signers)      free (ctx->signers); +  if (ctx->lc_ctype) +    free (ctx->lc_ctype); +  if (ctx->lc_messages) +    free (ctx->lc_messages);    free (ctx);  } @@ -267,7 +310,70 @@ gpgme_get_io_cbs (gpgme_ctx_t ctx, gpgme_io_cbs_t io_cbs)    *io_cbs = ctx->io_cbs;  } + +/* This function sets the locale for the context CTX, or the default +   locale if CTX is a null pointer.  */ +gpgme_error_t +gpgme_set_locale (gpgme_ctx_t ctx, int category, const char *value) +{ +  int failed = 0; +  char *new_lc_ctype; +  char *new_lc_messages; + +#define PREPARE_ONE_LOCALE(lcat, ucat)				\ +  if (!failed && value						\ +      && (category == LC_ALL || category == LC_ ## ucat))	\ +    {								\ +      new_lc_ ## lcat = strdup (value);				\ +      if (!new_lc_ ## lcat)					\ +        failed = 1;						\ +    }								\ +  else								\ +    new_lc_ ## lcat = NULL; + +  PREPARE_ONE_LOCALE (ctype, CTYPE); +  PREPARE_ONE_LOCALE (messages, MESSAGES); + +  if (failed) +    { +      int saved_errno = errno; + +      if (new_lc_ctype) +	free (new_lc_ctype); +      if (new_lc_messages) +	free (new_lc_messages); + +      return gpg_error_from_errno (saved_errno); +    } + +#define SET_ONE_LOCALE(lcat, ucat)			\ +  if (category == LC_ALL || category == LC_ ## ucat)	\ +    {							\ +      if (ctx)						\ +	{						\ +	  if (ctx->lc_ ## lcat)				\ +	    free (ctx->lc_ ## lcat);			\ +	  ctx->lc_ ## lcat = new_lc_ ## lcat;		\ +	}						\ +      else						\ +	{						\ +	  if (def_lc_ ## lcat)				\ +	    free (def_lc_ ## lcat);			\ +	  def_lc_ ## lcat = new_lc_ ## lcat;		\ +	}						\ +    } + +  if (!ctx) +    LOCK (def_lc_lock); +  SET_ONE_LOCALE (ctype, CTYPE); +  SET_ONE_LOCALE (messages, MESSAGES); +  if (!ctx) +    UNLOCK (def_lc_lock); + +  return 0; +} +  const char *  gpgme_pubkey_algo_name (gpgme_pubkey_algo_t algo)  { diff --git a/gpgme/op-support.c b/gpgme/op-support.c index 68ac39c3..e406af9c 100644 --- a/gpgme/op-support.c +++ b/gpgme/op-support.c @@ -76,7 +76,8 @@ _gpgme_op_reset (gpgme_ctx_t ctx, int type)        _gpgme_engine_release (ctx->engine);        ctx->engine = NULL;      } -  err = _gpgme_engine_new (ctx->protocol, &ctx->engine); +  err = _gpgme_engine_new (ctx->protocol, &ctx->engine, +			   ctx->lc_ctype, ctx->lc_messages);    if (err)      return err; diff --git a/gpgme/rungpg.c b/gpgme/rungpg.c index 50223c19..d13a9c1c 100644 --- a/gpgme/rungpg.c +++ b/gpgme/rungpg.c @@ -325,7 +325,7 @@ gpg_release (void *engine)  static gpgme_error_t -gpg_new (void **engine) +gpg_new (void **engine, const char *lc_ctype, const char *lc_messages)  {    engine_gpg_t gpg;    gpgme_error_t rc = 0; | 
