doc/
2002-05-09 Marcus Brinkmann <marcus@g10code.de> * gpgme.texi (Overview): Replace note about thread-safeness. (Multi Threading): New section. gpgme/ 2002-05-08 Marcus Brinkmann <marcus@g10code.de> * w32-util.c: New static variable GET_PATH_LOCK. (_gpgme_get_gpg_path): Remove superfluous NULL initializer. Take lock while determining path. (_gpgme_get_gpgsm_path): Likewise. * version.c (do_subsystem_inits): Set DONE to 1 after initialization. (gpgme_get_engine_info): New variable ENGINE_INFO_LOCK. Take lock while determining engine info. * rungpg.c (_gpgme_gpg_get_version): New variable GPG_VERSION_LOCK. Take the lock while determining the program version. * posix-io.c: Include "sema.h". (_gpgme_io_spawn): New variable FIXED_SIGNALS_LOCK. Take the lock while fixing the signals. (_gpgme_io_select): Make READFDS and WRITEFDS non-static. * key.c: Include "sema.h". New globals KEY_CACHE_LOCK and KEY_REF_LOCK. (capabilities_to_string): Make STRINGS very const. (_gpgme_key_cache_add): Lock the key cache. (_gpgme_key_cache_get): Likewise. (gpgme_key_ref, gpgme_key_release): Lock the key_ref_lock. * import.c (append_xml_impinfo): Make IMPORTED_FIELDS and IMPORT_RES_FIELDS very const. Make FIELD and FIELD_NAME a litle const. * engine.c (_gpgme_engine_get_info): New variable ENGINE_INFO_LOCK. Take lock while determining engine info. * engine-gpgsm.c: Include "sema.h". (_gpgme_gpgsm_get_version): New variable GPGSM_VERSION_LOCK. Take lock while getting program version.
This commit is contained in:
parent
d27e6506b1
commit
4e0d4d7cf3
3
TODO
3
TODO
@ -8,8 +8,6 @@ Hey Emacs, this is -*- outline -*- mode!
|
|||||||
* Allow to use GTK's main loop instead of the select stuff in
|
* Allow to use GTK's main loop instead of the select stuff in
|
||||||
wait.c
|
wait.c
|
||||||
|
|
||||||
* add locking to the key cache?
|
|
||||||
|
|
||||||
* cleanup the namespace - we use log_* assuan_* ascii_* mutex_*
|
* cleanup the namespace - we use log_* assuan_* ascii_* mutex_*
|
||||||
But those are only used internally. Some linker tricks should make
|
But those are only used internally. Some linker tricks should make
|
||||||
it possible to hide them from the user (didn't work last time, try
|
it possible to hide them from the user (didn't work last time, try
|
||||||
@ -30,6 +28,7 @@ Hey Emacs, this is -*- outline -*- mode!
|
|||||||
*** For pipemode, make sure to release the pipemode callback data object.
|
*** For pipemode, make sure to release the pipemode callback data object.
|
||||||
|
|
||||||
* Operations
|
* Operations
|
||||||
|
** gpgme_wait needs to be made thread safe!!!
|
||||||
** Export status handler need much more work.
|
** Export status handler need much more work.
|
||||||
** Import should return a useful error when one happened.
|
** Import should return a useful error when one happened.
|
||||||
** Genkey should return something more useful than General_Error.
|
** Genkey should return something more useful than General_Error.
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
2002-05-09 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
|
* gpgme.texi (Overview): Replace note about thread-safeness.
|
||||||
|
(Multi Threading): New section.
|
||||||
|
|
||||||
2002-05-03 Werner Koch <wk@gnupg.org>
|
2002-05-03 Werner Koch <wk@gnupg.org>
|
||||||
|
|
||||||
* gpgme.texi (Manipulating Data Buffers): Changed some data types
|
* gpgme.texi (Manipulating Data Buffers): Changed some data types
|
||||||
|
@ -104,6 +104,7 @@ Preparation
|
|||||||
* Header:: What header file you need to include.
|
* Header:: What header file you need to include.
|
||||||
* Building the Source:: Compiler options to be used.
|
* Building the Source:: Compiler options to be used.
|
||||||
* Library Version Check:: Getting and verifying the library version.
|
* Library Version Check:: Getting and verifying the library version.
|
||||||
|
* Multi Threading:: How GPGME can be used in an MT environment.
|
||||||
|
|
||||||
Protocols and Engines
|
Protocols and Engines
|
||||||
|
|
||||||
@ -278,11 +279,9 @@ including listing keys, querying their attributes, generating,
|
|||||||
importing, exporting and deleting keys, and acquiring information
|
importing, exporting and deleting keys, and acquiring information
|
||||||
about the trust path.
|
about the trust path.
|
||||||
|
|
||||||
@cindex thread-safeness
|
With some precautions, @acronym{GPGME} can be used in a multi-threaded
|
||||||
@cindex multi-threading
|
environment, although it is not completely thread safe and thus needs
|
||||||
@strong{Caution:} The @acronym{GPGME} library is not thread-safe. It
|
the support of the application.
|
||||||
will be to some extent in the future, but currently great care has to
|
|
||||||
be taken if @acronym{GPGME} is used in a multi-threaded environment.
|
|
||||||
|
|
||||||
|
|
||||||
@node Preparation
|
@node Preparation
|
||||||
@ -298,6 +297,7 @@ of the library are verified.
|
|||||||
* Header:: What header file you need to include.
|
* Header:: What header file you need to include.
|
||||||
* Building the Source:: Compiler options to be used.
|
* Building the Source:: Compiler options to be used.
|
||||||
* Library Version Check:: Getting and verifying the library version.
|
* Library Version Check:: Getting and verifying the library version.
|
||||||
|
* Multi Threading:: How GPGME can be used in an MT environment.
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
|
|
||||||
@ -402,6 +402,81 @@ features are provided by the installed version of the library.
|
|||||||
@end deftypefun
|
@end deftypefun
|
||||||
|
|
||||||
|
|
||||||
|
@node Multi Threading
|
||||||
|
@section Multi Threading
|
||||||
|
@cindex thread-safeness
|
||||||
|
@cindex multi-threading
|
||||||
|
|
||||||
|
The @acronym{GPGME} library is not entirely thread-safe, but it can
|
||||||
|
still be used in a multi-threaded environment if some care is taken.
|
||||||
|
If the following requirements are met, there should be no race
|
||||||
|
conditions to worry about:
|
||||||
|
|
||||||
|
@itemize @bullet
|
||||||
|
@item
|
||||||
|
The function @code{gpgme_check_version} must be called before any
|
||||||
|
other function in the library, because it initializes the locking
|
||||||
|
subsystem in @acronym{GPGME}. To achieve this in all generality, it
|
||||||
|
is necessary to synchronize the call to this function with all other
|
||||||
|
calls to functions in the library, using the synchronization
|
||||||
|
mechanisms available in your thread library. Otherwise, specific
|
||||||
|
compiler or CPU memory cache optimizations could lead to the situation
|
||||||
|
where a thread is started and uses @acronym{GPGME} before the effects
|
||||||
|
of the initialization are visible for this thread. It doesn't even
|
||||||
|
suffice to call @code{gpgme_check_version} before creating this other
|
||||||
|
thread@footnote{In SMP systems the new thread could be started on
|
||||||
|
another CPU before the effects of the initialization are seen by that
|
||||||
|
CPU's memory cache. Not doing proper synchronization here leads to
|
||||||
|
the same problems the double-checked locking idiom has. You might
|
||||||
|
find that if you don't do proper synchronization, it still works in
|
||||||
|
most configurations. Don't let this fool you. Someday it might lead
|
||||||
|
to subtle bugs when someone tries it on a DEC Alpha or an SMP
|
||||||
|
machine.}.
|
||||||
|
|
||||||
|
For example, if you are using POSIX threads, each thread that wants to
|
||||||
|
call functions in @acronym{GPGME} could call the following function
|
||||||
|
before any function in the library:
|
||||||
|
|
||||||
|
@example
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
void
|
||||||
|
initialize_gpgme (void)
|
||||||
|
{
|
||||||
|
static int gpgme_init;
|
||||||
|
static pthread_mutext_t gpgme_init_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
|
pthread_mutex_lock (&gpgme_init_lock);
|
||||||
|
if (!gpgme_init)
|
||||||
|
{
|
||||||
|
gpgme_check_version ();
|
||||||
|
gpgme_init = 1;
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock (&gpgme_init_lock);
|
||||||
|
}
|
||||||
|
@end example
|
||||||
|
|
||||||
|
@item
|
||||||
|
Any @code{GpgmeData}, @code{GpgmeCtx} and @code{GpgmeRecipients}
|
||||||
|
object must only be accessed by one thread at a time. If multiple
|
||||||
|
threads want to deal with the same object, the caller has to make sure
|
||||||
|
that operations on this object are fully synchronized.
|
||||||
|
|
||||||
|
@item
|
||||||
|
Only one thread is allowed to call @code{gpgme_wait} at a time. If
|
||||||
|
multiple threads call this function, the caller must make sure that
|
||||||
|
all invocations are fully synchronized.
|
||||||
|
|
||||||
|
@item
|
||||||
|
Unfortunately, the last rule implies that all calls to one of the
|
||||||
|
following functions have to be fully synchronized together with
|
||||||
|
@code{gpgme_wait}, as they call @code{gpgme_wait} internally: All
|
||||||
|
functions @code{gpgme_op_FOO} that have a corresponding
|
||||||
|
@code{gpgme_op_FOO_start} function, @code{gpgme_op_keylist_next},
|
||||||
|
@code{gpgme_op_trustlist_next}.
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
|
||||||
@node Protocols and Engines
|
@node Protocols and Engines
|
||||||
@chapter Protocols and Engines
|
@chapter Protocols and Engines
|
||||||
@cindex protocol
|
@cindex protocol
|
||||||
|
@ -1,3 +1,35 @@
|
|||||||
|
2002-05-08 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
|
* w32-util.c: New static variable GET_PATH_LOCK.
|
||||||
|
(_gpgme_get_gpg_path): Remove superfluous NULL initializer.
|
||||||
|
Take lock while determining path.
|
||||||
|
(_gpgme_get_gpgsm_path): Likewise.
|
||||||
|
* version.c (do_subsystem_inits): Set DONE to 1 after
|
||||||
|
initialization.
|
||||||
|
(gpgme_get_engine_info): New variable ENGINE_INFO_LOCK. Take lock
|
||||||
|
while determining engine info.
|
||||||
|
* rungpg.c (_gpgme_gpg_get_version): New variable
|
||||||
|
GPG_VERSION_LOCK. Take the lock while determining the program
|
||||||
|
version.
|
||||||
|
* posix-io.c: Include "sema.h".
|
||||||
|
(_gpgme_io_spawn): New variable FIXED_SIGNALS_LOCK. Take the lock
|
||||||
|
while fixing the signals.
|
||||||
|
(_gpgme_io_select): Make READFDS and WRITEFDS non-static.
|
||||||
|
* key.c: Include "sema.h". New globals KEY_CACHE_LOCK and
|
||||||
|
KEY_REF_LOCK.
|
||||||
|
(capabilities_to_string): Make STRINGS very const.
|
||||||
|
(_gpgme_key_cache_add): Lock the key cache.
|
||||||
|
(_gpgme_key_cache_get): Likewise.
|
||||||
|
(gpgme_key_ref, gpgme_key_release): Lock the key_ref_lock.
|
||||||
|
* import.c (append_xml_impinfo): Make IMPORTED_FIELDS and
|
||||||
|
IMPORT_RES_FIELDS very const. Make FIELD and FIELD_NAME a litle
|
||||||
|
const.
|
||||||
|
* engine.c (_gpgme_engine_get_info): New variable
|
||||||
|
ENGINE_INFO_LOCK. Take lock while determining engine info.
|
||||||
|
* engine-gpgsm.c: Include "sema.h".
|
||||||
|
(_gpgme_gpgsm_get_version): New variable GPGSM_VERSION_LOCK. Take
|
||||||
|
lock while getting program version.
|
||||||
|
|
||||||
2002-05-08 Marcus Brinkmann <marcus@g10code.de>
|
2002-05-08 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
* debug.h: New file.
|
* debug.h: New file.
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
#include "wait.h"
|
#include "wait.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
|
#include "sema.h"
|
||||||
|
|
||||||
#include "engine-gpgsm.h"
|
#include "engine-gpgsm.h"
|
||||||
|
|
||||||
@ -99,10 +100,12 @@ const char *
|
|||||||
_gpgme_gpgsm_get_version (void)
|
_gpgme_gpgsm_get_version (void)
|
||||||
{
|
{
|
||||||
static const char *gpgsm_version;
|
static const char *gpgsm_version;
|
||||||
|
DEFINE_STATIC_LOCK (gpgsm_version_lock);
|
||||||
|
|
||||||
/* FIXME: Locking. */
|
LOCK (gpgsm_version_lock);
|
||||||
if (!gpgsm_version)
|
if (!gpgsm_version)
|
||||||
gpgsm_version = _gpgme_get_program_version (_gpgme_get_gpgsm_path ());
|
gpgsm_version = _gpgme_get_program_version (_gpgme_get_gpgsm_path ());
|
||||||
|
UNLOCK (gpgsm_version_lock);
|
||||||
|
|
||||||
return gpgsm_version;
|
return gpgsm_version;
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#include "rungpg.h"
|
#include "rungpg.h"
|
||||||
#include "engine-gpgsm.h"
|
#include "engine-gpgsm.h"
|
||||||
|
|
||||||
|
|
||||||
struct engine_object_s
|
struct engine_object_s
|
||||||
{
|
{
|
||||||
GpgmeProtocol protocol;
|
GpgmeProtocol protocol;
|
||||||
@ -50,6 +51,7 @@ struct engine_object_s
|
|||||||
} engine;
|
} engine;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct reap_s
|
struct reap_s
|
||||||
{
|
{
|
||||||
struct reap_s *next;
|
struct reap_s *next;
|
||||||
@ -61,6 +63,7 @@ struct reap_s
|
|||||||
static struct reap_s *reap_list;
|
static struct reap_s *reap_list;
|
||||||
DEFINE_STATIC_LOCK (reap_list_lock);
|
DEFINE_STATIC_LOCK (reap_list_lock);
|
||||||
|
|
||||||
|
|
||||||
/* Get the path of the engine for PROTOCOL. */
|
/* Get the path of the engine for PROTOCOL. */
|
||||||
const char *
|
const char *
|
||||||
_gpgme_engine_get_path (GpgmeProtocol proto)
|
_gpgme_engine_get_path (GpgmeProtocol proto)
|
||||||
@ -76,6 +79,7 @@ _gpgme_engine_get_path (GpgmeProtocol proto)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Get the version number of the engine for PROTOCOL. */
|
/* Get the version number of the engine for PROTOCOL. */
|
||||||
const char *
|
const char *
|
||||||
_gpgme_engine_get_version (GpgmeProtocol proto)
|
_gpgme_engine_get_version (GpgmeProtocol proto)
|
||||||
@ -91,6 +95,7 @@ _gpgme_engine_get_version (GpgmeProtocol proto)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GpgmeError
|
GpgmeError
|
||||||
gpgme_engine_check_version (GpgmeProtocol proto)
|
gpgme_engine_check_version (GpgmeProtocol proto)
|
||||||
{
|
{
|
||||||
@ -105,6 +110,7 @@ gpgme_engine_check_version (GpgmeProtocol proto)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
_gpgme_engine_get_info (GpgmeProtocol proto)
|
_gpgme_engine_get_info (GpgmeProtocol proto)
|
||||||
{
|
{
|
||||||
@ -115,25 +121,21 @@ _gpgme_engine_get_info (GpgmeProtocol proto)
|
|||||||
" </engine>\n";
|
" </engine>\n";
|
||||||
static const char *const strproto[3] = { "OpenPGP", "CMS", NULL };
|
static const char *const strproto[3] = { "OpenPGP", "CMS", NULL };
|
||||||
static const char *engine_info[3]; /* FIXME: MAX_PROTO + 1*/
|
static const char *engine_info[3]; /* FIXME: MAX_PROTO + 1*/
|
||||||
const char *path;
|
DEFINE_STATIC_LOCK (engine_info_lock);
|
||||||
const char *version;
|
|
||||||
char *info;
|
|
||||||
|
|
||||||
if (proto > 2 /* FIXME MAX_PROTO */ || !strproto[proto])
|
if (proto > 2 /* FIXME MAX_PROTO */ || !strproto[proto])
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* FIXME: Make sure that only one instance does run. */
|
LOCK (engine_info_lock);
|
||||||
if (engine_info[proto])
|
if (!engine_info[proto])
|
||||||
return engine_info[proto];
|
{
|
||||||
|
const char *path = _gpgme_engine_get_path (proto);
|
||||||
|
const char *version = _gpgme_engine_get_version (proto);
|
||||||
|
|
||||||
path = _gpgme_engine_get_path (proto);
|
if (path && version)
|
||||||
version = _gpgme_engine_get_version (proto);
|
{
|
||||||
|
char *info = xtrymalloc (strlen (fmt) + strlen (strproto[proto])
|
||||||
if (!path || !version)
|
+ strlen (path) + strlen (version) + 1);
|
||||||
return NULL;
|
|
||||||
|
|
||||||
info = xtrymalloc (strlen(fmt) + strlen(strproto[proto]) + strlen(path)
|
|
||||||
+ strlen (version) + 1);
|
|
||||||
if (!info)
|
if (!info)
|
||||||
info = " <engine>\n"
|
info = " <engine>\n"
|
||||||
" <error>Out of core</error>\n"
|
" <error>Out of core</error>\n"
|
||||||
@ -141,10 +143,13 @@ _gpgme_engine_get_info (GpgmeProtocol proto)
|
|||||||
else
|
else
|
||||||
sprintf (info, fmt, strproto[proto], version, path);
|
sprintf (info, fmt, strproto[proto], version, path);
|
||||||
engine_info[proto] = info;
|
engine_info[proto] = info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UNLOCK (engine_info_lock);
|
||||||
return engine_info[proto];
|
return engine_info[proto];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GpgmeError
|
GpgmeError
|
||||||
_gpgme_engine_new (GpgmeProtocol proto, EngineObject *r_engine)
|
_gpgme_engine_new (GpgmeProtocol proto, EngineObject *r_engine)
|
||||||
{
|
{
|
||||||
@ -193,6 +198,7 @@ _gpgme_engine_new (GpgmeProtocol proto, EngineObject *r_engine)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_gpgme_engine_release (EngineObject engine)
|
_gpgme_engine_release (EngineObject engine)
|
||||||
{
|
{
|
||||||
@ -561,6 +567,7 @@ _gpgme_engine_start (EngineObject engine, void *opaque)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_gpgme_engine_add_child_to_reap_list (void *buf, int buflen, pid_t pid)
|
_gpgme_engine_add_child_to_reap_list (void *buf, int buflen, pid_t pid)
|
||||||
{
|
{
|
||||||
@ -572,10 +579,10 @@ _gpgme_engine_add_child_to_reap_list (void *buf, int buflen, pid_t pid)
|
|||||||
memset (child, 0, sizeof *child);
|
memset (child, 0, sizeof *child);
|
||||||
child->pid = pid;
|
child->pid = pid;
|
||||||
child->entered = time (NULL);
|
child->entered = time (NULL);
|
||||||
LOCK(reap_list_lock);
|
LOCK (reap_list_lock);
|
||||||
child->next = reap_list;
|
child->next = reap_list;
|
||||||
reap_list = child;
|
reap_list = child;
|
||||||
UNLOCK(reap_list_lock);
|
UNLOCK (reap_list_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -43,7 +43,7 @@ extern "C" {
|
|||||||
AM_PATH_GPGME macro) check that this header matches the installed
|
AM_PATH_GPGME macro) check that this header matches the installed
|
||||||
library. Warning: Do not edit the next line. configure will do
|
library. Warning: Do not edit the next line. configure will do
|
||||||
that for you! */
|
that for you! */
|
||||||
#define GPGME_VERSION "0.3.6"
|
#define GPGME_VERSION "0.3.7-cvs"
|
||||||
|
|
||||||
|
|
||||||
/* The opaque data types used by GPGME. */
|
/* The opaque data types used by GPGME. */
|
||||||
|
@ -53,14 +53,14 @@ static void
|
|||||||
append_xml_impinfo (GpgmeData *rdh, GpgStatusCode code, char *args)
|
append_xml_impinfo (GpgmeData *rdh, GpgStatusCode code, char *args)
|
||||||
{
|
{
|
||||||
#define MAX_IMPORTED_FIELDS 14
|
#define MAX_IMPORTED_FIELDS 14
|
||||||
static char *imported_fields[MAX_IMPORTED_FIELDS]
|
static const char *const imported_fields[MAX_IMPORTED_FIELDS]
|
||||||
= { "keyid", "username", 0 };
|
= { "keyid", "username", 0 };
|
||||||
static char *import_res_fields[MAX_IMPORTED_FIELDS]
|
static const char *const import_res_fields[MAX_IMPORTED_FIELDS]
|
||||||
= { "count", "no_user_id", "imported", "imported_rsa",
|
= { "count", "no_user_id", "imported", "imported_rsa",
|
||||||
"unchanged", "n_uids", "n_subk", "n_sigs", "s_sigsn_revoc",
|
"unchanged", "n_uids", "n_subk", "n_sigs", "s_sigsn_revoc",
|
||||||
"sec_read", "sec_imported", "sec_dups", "skipped_new", 0 };
|
"sec_read", "sec_imported", "sec_dups", "skipped_new", 0 };
|
||||||
char *field[MAX_IMPORTED_FIELDS];
|
const char *field[MAX_IMPORTED_FIELDS];
|
||||||
char **field_name = 0;
|
const char *const *field_name = 0;
|
||||||
GpgmeData dh;
|
GpgmeData dh;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
542
gpgme/key.c
542
gpgme/key.c
File diff suppressed because it is too large
Load Diff
@ -36,6 +36,7 @@
|
|||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
|
#include "sema.h"
|
||||||
|
|
||||||
static struct
|
static struct
|
||||||
{
|
{
|
||||||
@ -149,10 +150,12 @@ _gpgme_io_spawn (const char *path, char **argv,
|
|||||||
struct spawn_fd_item_s *fd_child_list,
|
struct spawn_fd_item_s *fd_child_list,
|
||||||
struct spawn_fd_item_s *fd_parent_list)
|
struct spawn_fd_item_s *fd_parent_list)
|
||||||
{
|
{
|
||||||
static volatile int fixed_signals;
|
static int fixed_signals;
|
||||||
|
DEFINE_STATIC_LOCK (fixed_signals_lock);
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
LOCK (fixed_signals_lock);
|
||||||
if (!fixed_signals)
|
if (!fixed_signals)
|
||||||
{
|
{
|
||||||
struct sigaction act;
|
struct sigaction act;
|
||||||
@ -166,8 +169,8 @@ _gpgme_io_spawn (const char *path, char **argv,
|
|||||||
sigaction (SIGPIPE, &act, NULL);
|
sigaction (SIGPIPE, &act, NULL);
|
||||||
}
|
}
|
||||||
fixed_signals = 1;
|
fixed_signals = 1;
|
||||||
/* XXX: This is not really MT safe. */
|
|
||||||
}
|
}
|
||||||
|
UNLOCK (fixed_signals_lock);
|
||||||
|
|
||||||
pid = fork ();
|
pid = fork ();
|
||||||
if (pid == -1)
|
if (pid == -1)
|
||||||
@ -285,8 +288,8 @@ _gpgme_io_kill (int pid, int hard)
|
|||||||
int
|
int
|
||||||
_gpgme_io_select (struct io_select_fd_s *fds, size_t nfds)
|
_gpgme_io_select (struct io_select_fd_s *fds, size_t nfds)
|
||||||
{
|
{
|
||||||
static fd_set readfds;
|
fd_set readfds;
|
||||||
static fd_set writefds;
|
fd_set writefds;
|
||||||
int any, i, max_fd, n, count;
|
int any, i, max_fd, n, count;
|
||||||
struct timeval timeout = { 1, 0 }; /* Use a 1s timeout. */
|
struct timeval timeout = { 1, 0 }; /* Use a 1s timeout. */
|
||||||
void *dbg_help = NULL;
|
void *dbg_help = NULL;
|
||||||
@ -314,7 +317,7 @@ _gpgme_io_select (struct io_select_fd_s *fds, size_t nfds)
|
|||||||
}
|
}
|
||||||
else if (fds[i].for_write)
|
else if (fds[i].for_write)
|
||||||
{
|
{
|
||||||
assert (!FD_ISSET ( fds[i].fd, &writefds));
|
assert (!FD_ISSET (fds[i].fd, &writefds));
|
||||||
FD_SET (fds[i].fd, &writefds);
|
FD_SET (fds[i].fd, &writefds);
|
||||||
if (fds[i].fd > max_fd)
|
if (fds[i].fd > max_fd)
|
||||||
max_fd = fds[i].fd;
|
max_fd = fds[i].fd;
|
||||||
|
@ -167,11 +167,12 @@ const char *
|
|||||||
_gpgme_gpg_get_version (void)
|
_gpgme_gpg_get_version (void)
|
||||||
{
|
{
|
||||||
static const char *gpg_version;
|
static const char *gpg_version;
|
||||||
|
DEFINE_STATIC_LOCK (gpg_version_lock);
|
||||||
|
|
||||||
/* FIXME: Locking. */
|
LOCK (gpg_version_lock);
|
||||||
if (!gpg_version)
|
if (!gpg_version)
|
||||||
gpg_version = _gpgme_get_program_version (_gpgme_get_gpg_path ());
|
gpg_version = _gpgme_get_program_version (_gpgme_get_gpg_path ());
|
||||||
|
UNLOCK (gpg_version_lock);
|
||||||
return gpg_version;
|
return gpg_version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@ do_subsystem_inits (void)
|
|||||||
return;
|
return;
|
||||||
_gpgme_sema_subsystem_init ();
|
_gpgme_sema_subsystem_init ();
|
||||||
_gpgme_key_cache_init ();
|
_gpgme_key_cache_init ();
|
||||||
|
done = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char*
|
static const char*
|
||||||
@ -148,14 +149,15 @@ const char *
|
|||||||
gpgme_get_engine_info ()
|
gpgme_get_engine_info ()
|
||||||
{
|
{
|
||||||
static const char *engine_info;
|
static const char *engine_info;
|
||||||
|
DEFINE_STATIC_LOCK (engine_info_lock);
|
||||||
|
|
||||||
|
LOCK (engine_info_lock);
|
||||||
|
if (!engine_info)
|
||||||
|
{
|
||||||
const char *openpgp_info = _gpgme_engine_get_info (GPGME_PROTOCOL_OpenPGP);
|
const char *openpgp_info = _gpgme_engine_get_info (GPGME_PROTOCOL_OpenPGP);
|
||||||
const char *cms_info = _gpgme_engine_get_info (GPGME_PROTOCOL_CMS);
|
const char *cms_info = _gpgme_engine_get_info (GPGME_PROTOCOL_CMS);
|
||||||
char *info;
|
char *info;
|
||||||
|
|
||||||
/* FIXME: Make sure that only one instance does run. */
|
|
||||||
if (engine_info)
|
|
||||||
return engine_info;
|
|
||||||
|
|
||||||
if (!openpgp_info && !cms_info)
|
if (!openpgp_info && !cms_info)
|
||||||
info = "<EngineInfo>\n</EngineInfo>\n";
|
info = "<EngineInfo>\n</EngineInfo>\n";
|
||||||
else if (!openpgp_info || !cms_info)
|
else if (!openpgp_info || !cms_info)
|
||||||
@ -164,7 +166,8 @@ gpgme_get_engine_info ()
|
|||||||
"%s"
|
"%s"
|
||||||
"</EngineInfo>\n";
|
"</EngineInfo>\n";
|
||||||
|
|
||||||
info = xtrymalloc (strlen(fmt) + strlen(openpgp_info
|
info = xtrymalloc (strlen (fmt)
|
||||||
|
+ strlen (openpgp_info
|
||||||
? openpgp_info : cms_info) + 1);
|
? openpgp_info : cms_info) + 1);
|
||||||
if (info)
|
if (info)
|
||||||
sprintf (info, fmt, openpgp_info ? openpgp_info : cms_info);
|
sprintf (info, fmt, openpgp_info ? openpgp_info : cms_info);
|
||||||
@ -174,7 +177,7 @@ gpgme_get_engine_info ()
|
|||||||
const char *fmt = "<EngineInfo>\n"
|
const char *fmt = "<EngineInfo>\n"
|
||||||
"%s%s"
|
"%s%s"
|
||||||
"</EngineInfo>\n";
|
"</EngineInfo>\n";
|
||||||
info = xtrymalloc (strlen(fmt) + strlen(openpgp_info)
|
info = xtrymalloc (strlen (fmt) + strlen (openpgp_info)
|
||||||
+ strlen (cms_info) + 1);
|
+ strlen (cms_info) + 1);
|
||||||
if (info)
|
if (info)
|
||||||
sprintf (info, fmt, openpgp_info, cms_info);
|
sprintf (info, fmt, openpgp_info, cms_info);
|
||||||
@ -184,9 +187,12 @@ gpgme_get_engine_info ()
|
|||||||
" <error>Out of core</error>\n"
|
" <error>Out of core</error>\n"
|
||||||
"</EngineInfo>\n";
|
"</EngineInfo>\n";
|
||||||
engine_info = info;
|
engine_info = info;
|
||||||
|
}
|
||||||
|
UNLOCK (engine_info_lock);
|
||||||
return engine_info;
|
return engine_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gpgme_check_engine:
|
* gpgme_check_engine:
|
||||||
*
|
*
|
||||||
|
@ -37,6 +37,8 @@
|
|||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
DEFINE_STATIC_LOCK (get_path_lock);
|
||||||
|
|
||||||
/* Return a string from the Win32 Registry or NULL in case of error.
|
/* Return a string from the Win32 Registry or NULL in case of error.
|
||||||
Caller must release the return value. A NULL for root is an alias
|
Caller must release the return value. A NULL for root is an alias
|
||||||
for HKEY_CURRENT_USER. */
|
for HKEY_CURRENT_USER. */
|
||||||
@ -112,27 +114,31 @@ find_program_in_registry (const char *name)
|
|||||||
const char *
|
const char *
|
||||||
_gpgme_get_gpg_path (void)
|
_gpgme_get_gpg_path (void)
|
||||||
{
|
{
|
||||||
static char *gpg_program = NULL;
|
static char *gpg_program;
|
||||||
|
|
||||||
|
LOCK (get_path_lock);
|
||||||
if (!gpg_program)
|
if (!gpg_program)
|
||||||
gpg_program = find_program_in_registry ("gpgProgram");
|
gpg_program = find_program_in_registry ("gpgProgram");
|
||||||
#ifdef GPG_PATH
|
#ifdef GPG_PATH
|
||||||
if (!gpg_program)
|
if (!gpg_program)
|
||||||
gpg_program = GPG_PATH;
|
gpg_program = GPG_PATH;
|
||||||
#endif
|
#endif
|
||||||
|
UNLOCK (get_path_lock);
|
||||||
return gpg_program;
|
return gpg_program;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
_gpgme_get_gpgsm_path (void)
|
_gpgme_get_gpgsm_path (void)
|
||||||
{
|
{
|
||||||
static char *gpgsm_program = NULL;
|
static char *gpgsm_program;
|
||||||
|
|
||||||
|
LOCK (get_path_lock);
|
||||||
if (!gpgsm_program)
|
if (!gpgsm_program)
|
||||||
gpgsm_program = find_program_in_registry ("gpgsmProgram");
|
gpgsm_program = find_program_in_registry ("gpgsmProgram");
|
||||||
#ifdef GPGSM_PATH
|
#ifdef GPGSM_PATH
|
||||||
if (!gpgsm_program)
|
if (!gpgsm_program)
|
||||||
gpgsm_program = GPGSM_PATH;
|
gpgsm_program = GPGSM_PATH;
|
||||||
#endif
|
#endif
|
||||||
|
UNLOCK (get_path_lock);
|
||||||
return gpgsm_program;
|
return gpgsm_program;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user