Add better debug printing. Use reader threads for W32
This commit is contained in:
parent
f2be414251
commit
e318473836
10
TODO
Normal file
10
TODO
Normal file
@ -0,0 +1,10 @@
|
||||
* Implement posix-sema.c
|
||||
|
||||
* Add gpgme_mime_xxx to make handling of MIME/PGP easier
|
||||
|
||||
* Allow to use GTK's main loop instead of the select stuff in
|
||||
wait.c
|
||||
|
||||
* Remove all that funny exit code handling - we donn't need it.
|
||||
|
||||
|
@ -62,7 +62,7 @@ if test "$1" = "--build-w32"; then
|
||||
|
||||
./configure --host=${host} --target=${target} ${disable_foo_tests} \
|
||||
--bindir=${crossbindir} --libdir=${crosslibdir} \
|
||||
--includedir=${crossincdir} $*
|
||||
--includedir=${crossincdir} --enable-maintainer-mode $*
|
||||
exit $?
|
||||
fi
|
||||
|
||||
|
@ -1,3 +1,18 @@
|
||||
2001-01-30 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* w32-io.c: Does now use reader threads, so that we can use
|
||||
WaitForMultipleObjects.
|
||||
* sema.h, posix-sema.c, w32-sema.c: Support for Critcial sections.
|
||||
Does currently only work for W32.
|
||||
|
||||
* debug.c, util.h : New. Changed all fprintfs to use this new
|
||||
set of debugging functions.
|
||||
|
||||
2001-01-23 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* data.c (_gpgme_data_release_and_return_string): Fixed string
|
||||
termination.
|
||||
|
||||
2001-01-22 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* delete.c: New.
|
||||
|
@ -13,7 +13,7 @@ libgpgme_la_LDFLAGS = -version-info \
|
||||
libgpgme_la_INCLUDES = -I$(top_srcdir)/lib
|
||||
|
||||
libgpgme_la_SOURCES = \
|
||||
gpgme.h types.h util.h util.c \
|
||||
gpgme.h types.h util.h util.c debug.c \
|
||||
context.h ops.h \
|
||||
data.c recipient.c signers.c \
|
||||
wait.c wait.h \
|
||||
@ -29,6 +29,7 @@ libgpgme_la_SOURCES = \
|
||||
genkey.c \
|
||||
delete.c \
|
||||
rungpg.c rungpg.h status-table.h \
|
||||
sema.h posix-sema.c w32-sema.c \
|
||||
syshdr.h io.h posix-io.c w32-io.c \
|
||||
gpgme.c version.c errors.c
|
||||
|
||||
|
11
gpgme/data.c
11
gpgme/data.c
@ -311,7 +311,7 @@ _gpgme_data_release_and_return_string ( GpgmeData dh )
|
||||
char *val = NULL;
|
||||
|
||||
if (dh) {
|
||||
if ( _gpgme_data_append ( dh, "", 0 ) ) /* append EOS */
|
||||
if ( _gpgme_data_append ( dh, "", 1 ) ) /* append EOS */
|
||||
xfree (dh->private_buffer );
|
||||
else {
|
||||
val = dh->private_buffer;
|
||||
@ -331,10 +331,11 @@ _gpgme_data_release_and_return_string ( GpgmeData dh )
|
||||
* @dh: the data object
|
||||
* @r_len: returns the length of the memory
|
||||
*
|
||||
* Release the data object @dh and return its content and the length of
|
||||
* that content. The caller has to free this data. @dh maybe NULL in
|
||||
* which case NULL is returned. I there is not enough memory for allocating
|
||||
* the return value, NULL is returned and the object is released.
|
||||
* Release the data object @dh and return its content and the length
|
||||
* of that content. The caller has to free this data. @dh maybe NULL
|
||||
* in which case NULL is returned. If there is not enough memory for
|
||||
* allocating the return value, NULL is returned and the object is
|
||||
* released.
|
||||
*
|
||||
* Return value: a pointer to an allocated buffer of length @r_len.
|
||||
**/
|
||||
|
156
gpgme/debug.c
Normal file
156
gpgme/debug.c
Normal file
@ -0,0 +1,156 @@
|
||||
/* debug.c
|
||||
* Copyright (C) 2001 Werner Koch (dd9jn)
|
||||
*
|
||||
* This file is part of GPGME.
|
||||
*
|
||||
* GPGME is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GPGME is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "sema.h"
|
||||
|
||||
DEFINE_STATIC_LOCK (debug_lock);
|
||||
|
||||
struct debug_control_s {
|
||||
FILE *fp;
|
||||
char fname[100];
|
||||
};
|
||||
|
||||
static int debug_level = 0;
|
||||
|
||||
static void
|
||||
debug_init (void)
|
||||
{
|
||||
static volatile int initialized = 0;
|
||||
|
||||
if (initialized)
|
||||
return;
|
||||
LOCK (debug_lock);
|
||||
if (!initialized) {
|
||||
const char *e = getenv ("GPGME_DEBUG");
|
||||
|
||||
debug_level = e? atoi (e): 0;
|
||||
initialized = 1;
|
||||
if (debug_level > 0)
|
||||
fprintf (stderr,"gpgme_debug: level=%d\n", debug_level);
|
||||
}
|
||||
UNLOCK (debug_lock);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_gpgme_debug (int level, const char *format, ...)
|
||||
{
|
||||
va_list arg_ptr ;
|
||||
|
||||
debug_init ();
|
||||
if ( debug_level < level )
|
||||
return;
|
||||
|
||||
va_start ( arg_ptr, format ) ;
|
||||
LOCK (debug_lock);
|
||||
vfprintf (stderr, format, arg_ptr) ;
|
||||
va_end ( arg_ptr ) ;
|
||||
if( format && *format && format[strlen(format)-1] != '\n' )
|
||||
putc ('\n', stderr);
|
||||
UNLOCK (debug_lock);
|
||||
fflush (stderr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
_gpgme_debug_begin ( void **helper, int level, const char *text)
|
||||
{
|
||||
struct debug_control_s *ctl;
|
||||
|
||||
debug_init ();
|
||||
|
||||
*helper = NULL;
|
||||
if ( debug_level < level )
|
||||
return;
|
||||
ctl = xtrycalloc (1, sizeof *ctl );
|
||||
if (!ctl) {
|
||||
_gpgme_debug (255, __FILE__ ":" STR2(__LINE__)": out of core");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Oh what a pitty sthat we don't have a asprintf or snprintf under
|
||||
* Windoze. We definitely should write our own clib for W32! */
|
||||
sprintf ( ctl->fname, "/tmp/gpgme_debug.%d.%p", getpid (), ctl );
|
||||
ctl->fp = fopen (ctl->fname, "w+");
|
||||
if (!ctl->fp) {
|
||||
_gpgme_debug (255,__FILE__ ":" STR2(__LINE__)": failed to create `%s'",
|
||||
ctl->fname );
|
||||
xfree (ctl);
|
||||
return;
|
||||
}
|
||||
*helper = ctl;
|
||||
_gpgme_debug_add (helper, "%s", text );
|
||||
}
|
||||
|
||||
int
|
||||
_gpgme_debug_enabled (void **helper)
|
||||
{
|
||||
return helper && *helper;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_gpgme_debug_add (void **helper, const char *format, ...)
|
||||
{
|
||||
struct debug_control_s *ctl = *helper;
|
||||
va_list arg_ptr ;
|
||||
|
||||
if ( !*helper )
|
||||
return;
|
||||
|
||||
va_start ( arg_ptr, format ) ;
|
||||
vfprintf (ctl->fp, format, arg_ptr) ;
|
||||
va_end ( arg_ptr ) ;
|
||||
}
|
||||
|
||||
void
|
||||
_gpgme_debug_end (void **helper, const char *text)
|
||||
{
|
||||
struct debug_control_s *ctl = *helper;
|
||||
int c, last_c=EOF;
|
||||
|
||||
if ( !*helper )
|
||||
return;
|
||||
|
||||
_gpgme_debug_add (helper, "%s", text );
|
||||
rewind (ctl->fp);
|
||||
LOCK (debug_lock);
|
||||
while ( (c=getc (ctl->fp)) != EOF ) {
|
||||
putc (c, stderr);
|
||||
last_c = c;
|
||||
}
|
||||
if (last_c != '\n')
|
||||
putc ('\n', stderr);
|
||||
UNLOCK (debug_lock);
|
||||
|
||||
remove (ctl->fname);
|
||||
xfree (ctl);
|
||||
*helper = NULL;
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ decrypt_status_handler ( GpgmeCtx ctx, GpgStatusCode code, char *args )
|
||||
break;
|
||||
|
||||
case STATUS_MISSING_PASSPHRASE:
|
||||
fprintf (stderr, "Missing passphrase - stop\n");;
|
||||
DEBUG0 ("missing passphrase - stop\n");;
|
||||
ctx->result.decrypt->no_passphrase = 1;
|
||||
break;
|
||||
|
||||
@ -174,7 +174,7 @@ command_handler ( void *opaque, GpgStatusCode code, const char *key )
|
||||
buf, &c->result.decrypt->last_pw_handle );
|
||||
xfree (buf);
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -31,8 +31,7 @@
|
||||
static void
|
||||
encrypt_status_handler ( GpgmeCtx ctx, GpgStatusCode code, char *args )
|
||||
{
|
||||
fprintf (stderr, "encrypt_status: code=%d args=`%s'\n",
|
||||
code, args );
|
||||
DEBUG2 ("encrypt_status: code=%d args=`%s'\n", code, args );
|
||||
|
||||
}
|
||||
|
||||
|
@ -31,8 +31,7 @@
|
||||
static void
|
||||
export_status_handler ( GpgmeCtx ctx, GpgStatusCode code, char *args )
|
||||
{
|
||||
fprintf (stderr, "export_status: code=%d args=`%s'\n",
|
||||
code, args );
|
||||
DEBUG2 ("export_status: code=%d args=`%s'\n", code, args );
|
||||
/* FIXME: Need to do more */
|
||||
}
|
||||
|
||||
|
@ -59,8 +59,7 @@ genkey_status_handler ( GpgmeCtx ctx, GpgStatusCode code, char *args )
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf (stderr, "genkey_status: code=%d args=`%s'\n",
|
||||
code, args );
|
||||
DEBUG2 ("genkey_status: code=%d args=`%s'\n", code, args );
|
||||
/* FIXME: Need to do more */
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,6 @@ gpgme_new (GpgmeCtx *r_ctx)
|
||||
if (!c)
|
||||
return mk_error (Out_Of_Core);
|
||||
c->verbosity = 1;
|
||||
c->use_armor = 1; /* fixme: reset this to 0 */
|
||||
*r_ctx = c;
|
||||
|
||||
return 0;
|
||||
|
@ -22,7 +22,7 @@
|
||||
#define GPGME_H
|
||||
|
||||
#ifdef _MSC_VER
|
||||
typedef long off_t
|
||||
typedef long off_t;
|
||||
#else
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
@ -126,7 +126,8 @@ typedef enum {
|
||||
GPGME_ATTR_COMMENT = 11,
|
||||
GPGME_ATTR_VALIDITY= 12,
|
||||
GPGME_ATTR_LEVEL = 13,
|
||||
GPGME_ATTR_TYPE = 14
|
||||
GPGME_ATTR_TYPE = 14,
|
||||
GPGME_ATTR_IS_SECRET= 15
|
||||
} GpgmeAttr;
|
||||
|
||||
typedef enum {
|
||||
|
@ -31,8 +31,7 @@
|
||||
static void
|
||||
import_status_handler ( GpgmeCtx ctx, GpgStatusCode code, char *args )
|
||||
{
|
||||
fprintf (stderr, "import_status: code=%d args=`%s'\n",
|
||||
code, args );
|
||||
DEBUG2 ("import_status: code=%d args=`%s'\n", code, args );
|
||||
/* FIXME: We have to check here whether the import actually worked
|
||||
* and maybe it is a good idea to save some statistics and provide
|
||||
* a progress callback */
|
||||
|
46
gpgme/key.c
46
gpgme/key.c
@ -48,8 +48,8 @@ pkalgo_to_string ( int algo )
|
||||
|
||||
|
||||
|
||||
GpgmeError
|
||||
_gpgme_key_new( GpgmeKey *r_key )
|
||||
static GpgmeError
|
||||
key_new ( GpgmeKey *r_key, int secret )
|
||||
{
|
||||
GpgmeKey key;
|
||||
|
||||
@ -59,9 +59,23 @@ _gpgme_key_new( GpgmeKey *r_key )
|
||||
return mk_error (Out_Of_Core);
|
||||
key->ref_count = 1;
|
||||
*r_key = key;
|
||||
if (secret)
|
||||
key->secret = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
GpgmeError
|
||||
_gpgme_key_new ( GpgmeKey *r_key )
|
||||
{
|
||||
return key_new ( r_key, 0 );
|
||||
}
|
||||
|
||||
GpgmeError
|
||||
_gpgme_key_new_secret ( GpgmeKey *r_key )
|
||||
{
|
||||
return key_new ( r_key, 1 );
|
||||
}
|
||||
|
||||
void
|
||||
gpgme_key_ref ( GpgmeKey key )
|
||||
{
|
||||
@ -70,8 +84,8 @@ gpgme_key_ref ( GpgmeKey key )
|
||||
}
|
||||
|
||||
|
||||
struct subkey_s *
|
||||
_gpgme_key_add_subkey (GpgmeKey key)
|
||||
static struct subkey_s *
|
||||
add_subkey (GpgmeKey key, int secret)
|
||||
{
|
||||
struct subkey_s *k, *kk;
|
||||
|
||||
@ -86,9 +100,22 @@ _gpgme_key_add_subkey (GpgmeKey key)
|
||||
kk = kk->next;
|
||||
kk->next = k;
|
||||
}
|
||||
if (secret)
|
||||
k->secret = 1;
|
||||
return k;
|
||||
}
|
||||
|
||||
struct subkey_s *
|
||||
_gpgme_key_add_subkey (GpgmeKey key)
|
||||
{
|
||||
return add_subkey (key, 0);
|
||||
}
|
||||
|
||||
struct subkey_s *
|
||||
_gpgme_key_add_secret_subkey (GpgmeKey key)
|
||||
{
|
||||
return add_subkey (key, 1);
|
||||
}
|
||||
|
||||
void
|
||||
gpgme_key_release ( GpgmeKey key )
|
||||
@ -350,6 +377,8 @@ gpgme_key_get_as_xml ( GpgmeKey key )
|
||||
|
||||
_gpgme_data_append_string ( d, "<GnupgKeyblock>\n"
|
||||
" <mainkey>\n" );
|
||||
if ( key->secret )
|
||||
_gpgme_data_append_string ( d, " <secret/>\n");
|
||||
add_tag_and_string (d, "keyid", key->keys.keyid );
|
||||
if (key->keys.fingerprint)
|
||||
add_tag_and_string (d, "fpr", key->keys.fingerprint );
|
||||
@ -374,6 +403,8 @@ gpgme_key_get_as_xml ( GpgmeKey key )
|
||||
|
||||
for (k=key->keys.next; k; k = k->next ) {
|
||||
_gpgme_data_append_string (d, " <subkey>\n");
|
||||
if ( k->secret )
|
||||
_gpgme_data_append_string ( d, " <secret/>\n");
|
||||
add_tag_and_string (d, "keyid", k->keyid );
|
||||
if (k->fingerprint)
|
||||
add_tag_and_string (d, "fpr", k->fingerprint );
|
||||
@ -456,6 +487,10 @@ gpgme_key_get_string_attr ( GpgmeKey key, GpgmeAttr what,
|
||||
case GPGME_ATTR_LEVEL: /* not used here */
|
||||
case GPGME_ATTR_TYPE:
|
||||
break;
|
||||
case GPGME_ATTR_IS_SECRET:
|
||||
if (key->secret)
|
||||
val = "1";
|
||||
break;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
@ -491,6 +526,9 @@ gpgme_key_get_ulong_attr ( GpgmeKey key, GpgmeAttr what,
|
||||
if (u)
|
||||
val = u->validity;
|
||||
break;
|
||||
case GPGME_ATTR_IS_SECRET:
|
||||
val = !!key->secret;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
struct subkey_s {
|
||||
struct subkey_s *next;
|
||||
unsigned int secret:1;
|
||||
struct {
|
||||
unsigned int revoked:1 ;
|
||||
unsigned int expired:1 ;
|
||||
@ -46,11 +47,13 @@ struct gpgme_key_s {
|
||||
unsigned int disabled:1 ;
|
||||
} gloflags;
|
||||
unsigned int ref_count;
|
||||
unsigned int secret:1;
|
||||
struct subkey_s keys;
|
||||
struct user_id_s *uids;
|
||||
};
|
||||
|
||||
struct subkey_s *_gpgme_key_add_subkey (GpgmeKey key);
|
||||
struct subkey_s *_gpgme_key_add_secret_subkey (GpgmeKey key);
|
||||
GpgmeError _gpgme_key_append_name ( GpgmeKey key, const char *s );
|
||||
|
||||
|
||||
|
@ -49,7 +49,6 @@ keylist_status_handler ( GpgmeCtx ctx, GpgStatusCode code, char *args )
|
||||
|
||||
default:
|
||||
/* ignore all other codes */
|
||||
fprintf (stderr, "keylist_status: code=%d not handled\n", code );
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -153,7 +152,7 @@ keylist_colon_handler ( GpgmeCtx ctx, char *line )
|
||||
rectype = RT_UID;
|
||||
key = ctx->tmp_key;
|
||||
}
|
||||
else if ( !strcmp ( p, "sub" ) && key ) {
|
||||
else if ( !strcmp (p, "sub") && key ) {
|
||||
/* start a new subkey */
|
||||
rectype = RT_SUB;
|
||||
if ( !(sk = _gpgme_key_add_subkey (key)) ) {
|
||||
@ -161,10 +160,18 @@ keylist_colon_handler ( GpgmeCtx ctx, char *line )
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if ( !strcmp ( p, "pub" ) ) {
|
||||
else if ( !strcmp (p, "ssb") && key ) {
|
||||
/* start a new secret subkey */
|
||||
rectype = RT_SSB;
|
||||
if ( !(sk = _gpgme_key_add_secret_subkey (key)) ) {
|
||||
ctx->out_of_core=1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if ( !strcmp (p, "pub") ) {
|
||||
/* start a new keyblock */
|
||||
if ( _gpgme_key_new ( &key ) ) {
|
||||
ctx->out_of_core=1; /* the only kind of error we can get */
|
||||
ctx->out_of_core=1; /* the only kind of error we can get*/
|
||||
return;
|
||||
}
|
||||
rectype = RT_PUB;
|
||||
@ -173,17 +180,25 @@ keylist_colon_handler ( GpgmeCtx ctx, char *line )
|
||||
assert ( !ctx->tmp_key );
|
||||
ctx->tmp_key = key;
|
||||
}
|
||||
else if ( !strcmp (p, "sec") ) {
|
||||
/* start a new keyblock */
|
||||
if ( _gpgme_key_new_secret ( &key ) ) {
|
||||
ctx->out_of_core=1; /*the only kind of error we can get*/
|
||||
return;
|
||||
}
|
||||
rectype = RT_SEC;
|
||||
if ( ctx->tmp_key )
|
||||
finish_key ( ctx );
|
||||
assert ( !ctx->tmp_key );
|
||||
ctx->tmp_key = key;
|
||||
}
|
||||
else if ( !strcmp ( p, "fpr" ) && key )
|
||||
rectype = RT_FPR;
|
||||
else if ( !strcmp ( p, "ssb" ) )
|
||||
rectype = RT_SSB;
|
||||
else if ( !strcmp ( p, "sec" ) )
|
||||
rectype = RT_SEC;
|
||||
else
|
||||
rectype = RT_NONE;
|
||||
|
||||
}
|
||||
else if ( rectype == RT_PUB ) {
|
||||
else if ( rectype == RT_PUB || rectype == RT_SEC ) {
|
||||
switch (field) {
|
||||
case 2: /* trust info */
|
||||
trust_info = p; /*save for later */
|
||||
@ -226,7 +241,7 @@ keylist_colon_handler ( GpgmeCtx ctx, char *line )
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ( rectype == RT_SUB && sk ) {
|
||||
else if ( (rectype == RT_SUB || rectype== RT_SSB) && sk ) {
|
||||
switch (field) {
|
||||
case 2: /* trust info */
|
||||
set_subkey_trust_info ( sk, p);
|
||||
@ -344,6 +359,7 @@ gpgme_op_keylist_start ( GpgmeCtx c, const char *pattern, int secret_only )
|
||||
_gpgme_release_result (c);
|
||||
c->out_of_core = 0;
|
||||
|
||||
#warning This context still keeps a gpg Zombie in some cases.
|
||||
if ( c->gpg ) {
|
||||
_gpgme_gpg_release ( c->gpg );
|
||||
c->gpg = NULL;
|
||||
|
@ -61,7 +61,8 @@ GpgmeError _gpgme_data_unread (GpgmeData dh,
|
||||
|
||||
|
||||
/*-- key.c --*/
|
||||
GpgmeError _gpgme_key_new( GpgmeKey *r_key );
|
||||
GpgmeError _gpgme_key_new ( GpgmeKey *r_key );
|
||||
GpgmeError _gpgme_key_new_secret ( GpgmeKey *r_key );
|
||||
|
||||
|
||||
/*-- verify.c --*/
|
||||
|
@ -33,17 +33,9 @@
|
||||
#include <fcntl.h>
|
||||
#include "syshdr.h"
|
||||
|
||||
#include "util.h"
|
||||
#include "io.h"
|
||||
|
||||
#define DEBUG_SELECT_ENABLED 0
|
||||
|
||||
#if DEBUG_SELECT_ENABLED
|
||||
# define DEBUG_SELECT(a) fprintf a
|
||||
#else
|
||||
# define DEBUG_SELECT(a) do { } while(0)
|
||||
#endif
|
||||
|
||||
|
||||
int
|
||||
_gpgme_io_read ( int fd, void *buffer, size_t count )
|
||||
{
|
||||
@ -137,8 +129,7 @@ _gpgme_io_spawn ( const char *path, char **argv,
|
||||
if (fd_child_list[i].dup_to != -1 ) {
|
||||
if ( dup2 (fd_child_list[i].fd,
|
||||
fd_child_list[i].dup_to ) == -1 ) {
|
||||
fprintf (stderr, "dup2 failed in child: %s\n",
|
||||
strerror (errno));
|
||||
DEBUG1 ("dup2 failed in child: %s\n", strerror (errno));
|
||||
_exit (8);
|
||||
}
|
||||
if ( fd_child_list[i].dup_to == 0 )
|
||||
@ -152,26 +143,21 @@ _gpgme_io_spawn ( const char *path, char **argv,
|
||||
if( !duped_stdin || !duped_stderr ) {
|
||||
int fd = open ( "/dev/null", O_RDWR );
|
||||
if ( fd == -1 ) {
|
||||
fprintf (stderr,"can't open `/dev/null': %s\n",
|
||||
strerror (errno) );
|
||||
DEBUG1 ("can't open `/dev/null': %s\n", strerror (errno) );
|
||||
_exit (8);
|
||||
}
|
||||
/* Make sure that the process has a connected stdin */
|
||||
if ( !duped_stdin ) {
|
||||
if ( dup2 ( fd, 0 ) == -1 ) {
|
||||
fprintf (stderr,"dup2(/dev/null, 0) failed: %s\n",
|
||||
DEBUG1("dup2(/dev/null, 0) failed: %s\n",
|
||||
strerror (errno) );
|
||||
_exit (8);
|
||||
}
|
||||
}
|
||||
/* We normally don't want all the normal output */
|
||||
if ( !duped_stderr ) {
|
||||
if (!getenv ("GPGME_DEBUG") ) {
|
||||
if ( dup2 ( fd, 2 ) == -1 ) {
|
||||
fprintf (stderr,"dup2(dev/null, 2) failed: %s\n",
|
||||
strerror (errno) );
|
||||
_exit (8);
|
||||
}
|
||||
if ( dup2 ( fd, 2 ) == -1 ) {
|
||||
DEBUG1 ("dup2(dev/null, 2) failed: %s\n", strerror (errno));
|
||||
_exit (8);
|
||||
}
|
||||
}
|
||||
close (fd);
|
||||
@ -180,7 +166,7 @@ _gpgme_io_spawn ( const char *path, char **argv,
|
||||
execv ( path, argv );
|
||||
/* Hmm: in that case we could write a special status code to the
|
||||
* status-pipe */
|
||||
fprintf (stderr,"exec of `%s' failed\n", path );
|
||||
DEBUG1 ("exec of `%s' failed\n", path );
|
||||
_exit (8);
|
||||
} /* end child */
|
||||
|
||||
@ -230,12 +216,13 @@ _gpgme_io_select ( struct io_select_fd_s *fds, size_t nfds )
|
||||
static fd_set writefds;
|
||||
int any, i, max_fd, n, count;
|
||||
struct timeval timeout = { 0, 50 }; /* Use a 50ms timeout */
|
||||
void *dbg_help;
|
||||
|
||||
FD_ZERO ( &readfds );
|
||||
FD_ZERO ( &writefds );
|
||||
max_fd = 0;
|
||||
|
||||
DEBUG_SELECT ((stderr, "gpgme:select on [ "));
|
||||
DEBUG_BEGIN (dbg_help, "gpgme:select on [ ");
|
||||
any = 0;
|
||||
for ( i=0; i < nfds; i++ ) {
|
||||
if ( fds[i].fd == -1 )
|
||||
@ -245,7 +232,7 @@ _gpgme_io_select ( struct io_select_fd_s *fds, size_t nfds )
|
||||
FD_SET ( fds[i].fd, &readfds );
|
||||
if ( fds[i].fd > max_fd )
|
||||
max_fd = fds[i].fd;
|
||||
DEBUG_SELECT ((stderr, "r%d ", fds[i].fd ));
|
||||
DEBUG_ADD1 (dbg_help, "r%d ", fds[i].fd );
|
||||
any = 1;
|
||||
}
|
||||
else if ( fds[i].for_write ) {
|
||||
@ -253,12 +240,12 @@ _gpgme_io_select ( struct io_select_fd_s *fds, size_t nfds )
|
||||
FD_SET ( fds[i].fd, &writefds );
|
||||
if ( fds[i].fd > max_fd )
|
||||
max_fd = fds[i].fd;
|
||||
DEBUG_SELECT ((stderr, "w%d ", fds[i].fd ));
|
||||
DEBUG_ADD1 (dbg_help, "w%d ", fds[i].fd );
|
||||
any = 1;
|
||||
}
|
||||
fds[i].signaled = 0;
|
||||
}
|
||||
DEBUG_SELECT ((stderr, "]\n" ));
|
||||
DEBUG_END (dbg_help, "]" );
|
||||
if ( !any )
|
||||
return 0;
|
||||
|
||||
@ -266,20 +253,20 @@ _gpgme_io_select ( struct io_select_fd_s *fds, size_t nfds )
|
||||
count = select ( max_fd+1, &readfds, &writefds, NULL, &timeout );
|
||||
} while ( count < 0 && errno == EINTR);
|
||||
if ( count < 0 ) {
|
||||
fprintf (stderr, "_gpgme_io_select failed: %s\n", strerror (errno) );
|
||||
DEBUG1 ("_gpgme_io_select failed: %s\n", strerror (errno) );
|
||||
return -1; /* error */
|
||||
}
|
||||
|
||||
#if DEBUG_SELECT_ENABLED
|
||||
fprintf (stderr, "gpgme:select OK [ " );
|
||||
for (i=0; i <= max_fd; i++ ) {
|
||||
if (FD_ISSET (i, &readfds) )
|
||||
fprintf (stderr, "r%d ", i );
|
||||
if (FD_ISSET (i, &writefds) )
|
||||
fprintf (stderr, "w%d ", i );
|
||||
DEBUG_BEGIN (dbg_help, "select OK [ " );
|
||||
if (DEBUG_ENABLED(dbg_help)) {
|
||||
for (i=0; i <= max_fd; i++ ) {
|
||||
if (FD_ISSET (i, &readfds) )
|
||||
DEBUG_ADD1 (dbg_help, "r%d ", i );
|
||||
if (FD_ISSET (i, &writefds) )
|
||||
DEBUG_ADD1 (dbg_help, "w%d ", i );
|
||||
}
|
||||
DEBUG_END (dbg_help, "]" );
|
||||
}
|
||||
fprintf (stderr, "]\n" );
|
||||
#endif
|
||||
|
||||
/* n is used to optimize it a little bit */
|
||||
for ( n=count, i=0; i < nfds && n ; i++ ) {
|
||||
|
70
gpgme/posix-sema.c
Normal file
70
gpgme/posix-sema.c
Normal file
@ -0,0 +1,70 @@
|
||||
/* posix-sema.c
|
||||
* Copyright (C) 2001 Werner Koch (dd9jn)
|
||||
*
|
||||
* This file is part of GPGME.
|
||||
*
|
||||
* GPGME is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GPGME is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <config.h>
|
||||
#ifndef HAVE_DOSISH_SYSTEM
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include "syshdr.h"
|
||||
|
||||
#include "util.h"
|
||||
#include "sema.h"
|
||||
|
||||
|
||||
|
||||
void
|
||||
_gpgme_sema_subsystem_init ()
|
||||
{
|
||||
#warning Posix semaphore support has not yet been implemented
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_gpgme_sema_cs_enter ( struct critsect_s *s )
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
_gpgme_sema_cs_leave (struct critsect_s *s)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
_gpgme_sema_cs_destroy ( struct critsect_s *s )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /*!HAVE_DOSISH_SYSTEM*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -789,7 +789,7 @@ gpg_inbound_handler ( void *opaque, int pid, int fd )
|
||||
|
||||
nread = _gpgme_io_read (fd, buf, 200 );
|
||||
if ( nread < 0 ) {
|
||||
fprintf (stderr, "read_mem_data: read failed on fd %d (n=%d): %s\n",
|
||||
DEBUG3 ("read_mem_data: read failed on fd %d (n=%d): %s",
|
||||
fd, nread, strerror (errno) );
|
||||
return 1;
|
||||
}
|
||||
@ -802,7 +802,7 @@ gpg_inbound_handler ( void *opaque, int pid, int fd )
|
||||
|
||||
err = _gpgme_data_append ( dh, buf, nread );
|
||||
if ( err ) {
|
||||
fprintf (stderr, "_gpgme_append_data failed: %s\n",
|
||||
DEBUG1 ("_gpgme_append_data failed: %s\n",
|
||||
gpgme_strerror(err));
|
||||
/* Fixme: we should close the pipe or read it to /dev/null in
|
||||
* this case. Returnin EOF is not sufficient */
|
||||
@ -836,8 +836,8 @@ write_mem_data ( GpgmeData dh, int fd )
|
||||
if (nwritten == -1 && errno == EAGAIN )
|
||||
return 0;
|
||||
if ( nwritten < 1 ) {
|
||||
fprintf (stderr, "write_mem_data(%d): write failed (n=%d): %s\n",
|
||||
fd, nwritten, strerror (errno) );
|
||||
DEBUG3 ("write_mem_data(%d): write failed (n=%d): %s",
|
||||
fd, nwritten, strerror (errno) );
|
||||
_gpgme_io_close (fd);
|
||||
return 1;
|
||||
}
|
||||
@ -863,8 +863,8 @@ write_cb_data ( GpgmeData dh, int fd )
|
||||
if (nwritten == -1 && errno == EAGAIN )
|
||||
return 0;
|
||||
if ( nwritten < 1 ) {
|
||||
fprintf (stderr, "write_cb_data(%d): write failed (n=%d): %s\n",
|
||||
fd, nwritten, strerror (errno) );
|
||||
DEBUG3 ("write_cb_data(%d): write failed (n=%d): %s",
|
||||
fd, nwritten, strerror (errno) );
|
||||
_gpgme_io_close (fd);
|
||||
return 1;
|
||||
}
|
||||
@ -872,7 +872,7 @@ write_cb_data ( GpgmeData dh, int fd )
|
||||
if ( nwritten < nbytes ) {
|
||||
/* ugly, ugly: It does currently only for for MEM type data */
|
||||
if ( _gpgme_data_unread (dh, buffer + nwritten, nbytes - nwritten ) )
|
||||
fprintf (stderr, "wite_cb_data: unread of %d bytes failed\n",
|
||||
DEBUG1 ("wite_cb_data: unread of %d bytes failed\n",
|
||||
nbytes - nwritten );
|
||||
_gpgme_io_close (fd);
|
||||
return 1;
|
||||
@ -915,7 +915,7 @@ gpg_status_handler ( void *opaque, int pid, int fd )
|
||||
assert ( fd == gpg->status.fd[0] );
|
||||
rc = read_status ( gpg );
|
||||
if ( rc ) {
|
||||
fprintf (stderr, "gpg_handler: read_status problem %d\n - stop", rc);
|
||||
DEBUG1 ("gpg_handler: read_status problem %d\n - stop", rc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1006,10 +1006,9 @@ read_status ( GpgObject gpg )
|
||||
return mk_error (Out_Of_Core);
|
||||
/* this should be the last thing we have received
|
||||
* and the next thing will be that the command
|
||||
* handler does it action */
|
||||
* handler does its action */
|
||||
if ( nread > 1 )
|
||||
fprintf (stderr, "** ERROR, unxpected data in"
|
||||
" read_status\n" );
|
||||
DEBUG0 ("ERROR, unexpected data in read_status");
|
||||
_gpgme_thaw_fd (gpg->cmd.fd);
|
||||
}
|
||||
else if ( gpg->status.fnc ) {
|
||||
@ -1061,7 +1060,7 @@ gpg_colon_line_handler ( void *opaque, int pid, int fd )
|
||||
assert ( fd == gpg->colon.fd[0] );
|
||||
rc = read_colon_line ( gpg );
|
||||
if ( rc ) {
|
||||
fprintf (stderr, "gpg_colon_line_handler: "
|
||||
DEBUG1 ("gpg_colon_line_handler: "
|
||||
"read problem %d\n - stop", rc);
|
||||
return 1;
|
||||
}
|
||||
@ -1191,7 +1190,7 @@ pipemode_cb ( void *opaque, char *buffer, size_t length, size_t *nread )
|
||||
*nread = 2;
|
||||
}
|
||||
else if (err) {
|
||||
fprintf (stderr, "** pipemode_cb: copy sig failed: %s\n",
|
||||
DEBUG1 ("pipemode_cb: copy sig failed: %s\n",
|
||||
gpgme_strerror (err) );
|
||||
return -1;
|
||||
}
|
||||
@ -1205,7 +1204,7 @@ pipemode_cb ( void *opaque, char *buffer, size_t length, size_t *nread )
|
||||
*nread = 4;
|
||||
}
|
||||
else if (err) {
|
||||
fprintf (stderr, "** pipemode_cb: copy data failed: %s\n",
|
||||
DEBUG1 ("pipemode_cb: copy data failed: %s\n",
|
||||
gpgme_strerror (err) );
|
||||
return -1;
|
||||
}
|
||||
@ -1230,32 +1229,32 @@ command_cb ( void *opaque, char *buffer, size_t length, size_t *nread )
|
||||
const char *value;
|
||||
int value_len;
|
||||
|
||||
fprintf (stderr, "** command_cb: enter\n");
|
||||
DEBUG0 ("command_cb: enter\n");
|
||||
assert (gpg->cmd.used);
|
||||
if ( !buffer || !length || !nread )
|
||||
return 0; /* those values are reserved for extensions */
|
||||
*nread =0;
|
||||
if ( !gpg->cmd.code ) {
|
||||
fprintf (stderr, "** command_cb: no code\n");
|
||||
DEBUG0 ("command_cb: no code\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( !gpg->cmd.fnc ) {
|
||||
fprintf (stderr, "** command_cb: no user cb\n");
|
||||
DEBUG0 ("command_cb: no user cb\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
value = gpg->cmd.fnc ( gpg->cmd.fnc_value,
|
||||
gpg->cmd.code, gpg->cmd.keyword );
|
||||
if ( !value ) {
|
||||
fprintf (stderr, "** command_cb: no data from user cb\n");
|
||||
DEBUG0 ("command_cb: no data from user cb\n");
|
||||
gpg->cmd.fnc ( gpg->cmd.fnc_value, 0, value);
|
||||
return -1;
|
||||
}
|
||||
|
||||
value_len = strlen (value);
|
||||
if ( value_len+1 > length ) {
|
||||
fprintf (stderr, "** command_cb: too much data from user cb\n");
|
||||
DEBUG0 ("command_cb: too much data from user cb\n");
|
||||
gpg->cmd.fnc ( gpg->cmd.fnc_value, 0, value);
|
||||
return -1;
|
||||
}
|
||||
@ -1265,8 +1264,6 @@ command_cb ( void *opaque, char *buffer, size_t length, size_t *nread )
|
||||
buffer[value_len++] = '\n';
|
||||
*nread = value_len;
|
||||
|
||||
fprintf (stderr, "** command_cb: leave (wrote `%.*s')\n",
|
||||
(int)*nread-1, buffer);
|
||||
gpg->cmd.fnc ( gpg->cmd.fnc_value, 0, value);
|
||||
gpg->cmd.code = 0;
|
||||
/* and sleep again until read_status will wake us up again */
|
||||
|
62
gpgme/sema.h
Normal file
62
gpgme/sema.h
Normal file
@ -0,0 +1,62 @@
|
||||
/* sema.h - definitions for semaphores
|
||||
* Copyright (C) 2001 Werner Koch (dd9jn)
|
||||
*
|
||||
* This file is part of GPGME.
|
||||
*
|
||||
* GPGME is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GPGME is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#ifndef SEMA_H
|
||||
#define SEMA_H
|
||||
|
||||
struct critsect_s {
|
||||
const char *name;
|
||||
void *private;
|
||||
};
|
||||
|
||||
#define DEFINE_GLOBAL_LOCK(name) \
|
||||
struct critsect_s name = { #name, NULL }
|
||||
#define DEFINE_STATIC_LOCK(name) \
|
||||
static struct critsect_s name = { #name, NULL }
|
||||
|
||||
#define DECLARE_LOCK(name) struct critsect_s name
|
||||
#define INIT_LOCK(a) do { \
|
||||
(a).name = #a; \
|
||||
(a).private = NULL; \
|
||||
} while (0)
|
||||
#define DESTROY_LOCK(name) _gpgme_sema_cs_destroy (&(name))
|
||||
|
||||
|
||||
#define LOCK(name) do { \
|
||||
_gpgme_sema_cs_enter ( &(name) );\
|
||||
} while (0)
|
||||
|
||||
#define UNLOCK(name) do { \
|
||||
_gpgme_sema_cs_leave ( &(name) );\
|
||||
} while (0)
|
||||
|
||||
|
||||
void _gpgme_sema_subsystem_init (void);
|
||||
void _gpgme_sema_cs_enter ( struct critsect_s *s );
|
||||
void _gpgme_sema_cs_leave ( struct critsect_s *s );
|
||||
void _gpgme_sema_cs_destroy ( struct critsect_s *s );
|
||||
|
||||
|
||||
#endif /* SEMA_H */
|
||||
|
||||
|
||||
|
||||
|
||||
|
63
gpgme/sign.c
63
gpgme/sign.c
@ -33,12 +33,17 @@ struct sign_result_s {
|
||||
int no_passphrase;
|
||||
int okay;
|
||||
void *last_pw_handle;
|
||||
char *userid_hint;
|
||||
char *passphrase_info;
|
||||
int bad_passphrase;
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
_gpgme_release_sign_result ( SignResult res )
|
||||
{
|
||||
xfree (res->userid_hint);
|
||||
xfree (res->passphrase_info);
|
||||
xfree (res);
|
||||
}
|
||||
|
||||
@ -64,23 +69,41 @@ sign_status_handler ( GpgmeCtx ctx, GpgStatusCode code, char *args )
|
||||
case STATUS_EOF:
|
||||
break;
|
||||
|
||||
case STATUS_USERID_HINT:
|
||||
xfree (ctx->result.sign->userid_hint);
|
||||
if (!(ctx->result.sign->userid_hint = xtrystrdup (args)) )
|
||||
ctx->out_of_core = 1;
|
||||
break;
|
||||
|
||||
case STATUS_BAD_PASSPHRASE:
|
||||
ctx->result.sign->bad_passphrase++;
|
||||
break;
|
||||
|
||||
case STATUS_GOOD_PASSPHRASE:
|
||||
ctx->result.sign->bad_passphrase = 0;
|
||||
break;
|
||||
|
||||
case STATUS_NEED_PASSPHRASE:
|
||||
case STATUS_NEED_PASSPHRASE_SYM:
|
||||
fprintf (stderr, "Ooops: Need a passphrase - use the agent\n");
|
||||
xfree (ctx->result.sign->passphrase_info);
|
||||
if (!(ctx->result.sign->passphrase_info = xtrystrdup (args)) )
|
||||
ctx->out_of_core = 1;
|
||||
break;
|
||||
|
||||
case STATUS_MISSING_PASSPHRASE:
|
||||
fprintf (stderr, "Missing passphrase - stop\n");;
|
||||
DEBUG0 ("missing passphrase - stop\n");
|
||||
ctx->result.sign->no_passphrase = 1;
|
||||
break;
|
||||
|
||||
case STATUS_SIG_CREATED:
|
||||
/* fixme: we have no error return for multible signatures */
|
||||
case STATUS_SIG_CREATED:
|
||||
/* fixme: we have no error return for multiple signatures */
|
||||
ctx->result.sign->okay =1;
|
||||
/* parse the line and save the information
|
||||
* <type> <pubkey algo> <hash algo> <class> <timestamp> <key fpr>
|
||||
*/
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf (stderr, "sign_status: code=%d not handled\n", code );
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -115,10 +138,32 @@ command_handler ( void *opaque, GpgStatusCode code, const char *key )
|
||||
return NULL;
|
||||
|
||||
if ( code == STATUS_GET_HIDDEN && !strcmp (key, "passphrase.enter") ) {
|
||||
return c->passphrase_cb (c->passphrase_cb_value,
|
||||
"Please enter your Friedrich Willem!",
|
||||
&c->result.sign->last_pw_handle );
|
||||
}
|
||||
const char *userid_hint = c->result.sign->userid_hint;
|
||||
const char *passphrase_info = c->result.sign->passphrase_info;
|
||||
int bad_passphrase = c->result.sign->bad_passphrase;
|
||||
char *buf;
|
||||
const char *s;
|
||||
|
||||
c->result.sign->bad_passphrase = 0;
|
||||
if (!userid_hint)
|
||||
userid_hint = "[User ID hint missing]";
|
||||
if (!passphrase_info)
|
||||
passphrase_info = "[passphrase info missing]";
|
||||
buf = xtrymalloc ( 20 + strlen (userid_hint)
|
||||
+ strlen (passphrase_info) + 3);
|
||||
if (!buf) {
|
||||
c->out_of_core = 1;
|
||||
return NULL;
|
||||
}
|
||||
sprintf (buf, "%s\n%s\n%s",
|
||||
bad_passphrase? "TRY_AGAIN":"ENTER",
|
||||
userid_hint, passphrase_info );
|
||||
|
||||
s = c->passphrase_cb (c->passphrase_cb_value,
|
||||
buf, &c->result.sign->last_pw_handle );
|
||||
xfree (buf);
|
||||
return s;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ gpgme_signers_enum (const GpgmeCtx c, int seq )
|
||||
int i;
|
||||
|
||||
return_null_if_fail (c);
|
||||
return_null_if_fail (seq<0);
|
||||
return_null_if_fail (seq>=0);
|
||||
|
||||
if (!c->signers)
|
||||
c->signers_size = 0;
|
||||
|
51
gpgme/util.h
51
gpgme/util.h
@ -40,6 +40,57 @@ void _gpgme_free ( void *a );
|
||||
|
||||
#define DIM(v) (sizeof(v)/sizeof((v)[0]))
|
||||
#define DIMof(type,member) DIM(((type *)0)->member)
|
||||
#ifndef STR
|
||||
#define STR(v) #v
|
||||
#endif
|
||||
#define STR2(v) STR(v)
|
||||
|
||||
|
||||
void _gpgme_debug (int level, const char *format, ...);
|
||||
void _gpgme_debug_begin ( void **helper, int level, const char *text);
|
||||
int _gpgme_debug_enabled ( void **helper );
|
||||
void _gpgme_debug_add (void **helper, const char *format, ...);
|
||||
void _gpgme_debug_end (void **helper, const char *text);
|
||||
|
||||
#define DEBUG0(x) _gpgme_debug (1, __FILE__ ":" \
|
||||
STR2 (__LINE__) ": " x )
|
||||
#define DEBUG1(x,a) _gpgme_debug (1, __FILE__ ":" \
|
||||
STR2 (__LINE__)": " x, (a) )
|
||||
#define DEBUG2(x,a,b) _gpgme_debug (1, __FILE__ ":" \
|
||||
STR2 (__LINE__) ": " x, (a), (b) )
|
||||
#define DEBUG3(x,a,b,c) _gpgme_debug (1, __FILE__ ":" \
|
||||
STR2 (__LINE__) ": " x, (a), (b), (c) )
|
||||
#define DEBUG4(x,a,b,c,d) _gpgme_debug (1, __FILE__ ":" \
|
||||
STR2 (__LINE__) ": " x, (a), (b), (c), (d) )
|
||||
#define DEBUG5(x,a,b,c,d,e) _gpgme_debug (1, __FILE__ ":" \
|
||||
STR2 (__LINE__) ": " x, (a), (b), (c), (d), (e) )
|
||||
#define DEBUG6(x,a,b,c,d,e,f) _gpgme_debug (1, __FILE__ ":" \
|
||||
STR2 (__LINE__) ": " x, (a), (b), (c), (d), (e), (f) )
|
||||
#define DEBUG7(x,a,b,c,d,e,f,g) _gpgme_debug (1, __FILE__ ":" \
|
||||
STR2 (__LINE__) ": " x, (a), (b), (c), (d), (e), (f), (g) )
|
||||
#define DEBUG8(x,a,b,c,d,e,f,g,h) _gpgme_debug (1, __FILE__ ":" \
|
||||
STR2 (__LINE__) ": " x, (a), (b), (c), (d), (e), (f), (g), (h) )
|
||||
#define DEBUG9(x,a,b,c,d,e,f,g,h,i) _gpgme_debug (1, __FILE__ ":" \
|
||||
STR2 (__LINE__) ": " x, (a), (b), (c), (d), (e), (f), (g), (h), (i) )
|
||||
#define DEBUG10(x,a,b,c,d,e,f,g,h,i,j) _gpgme_debug (1, __FILE__ ":" \
|
||||
STR2 (__LINE__) ": " x, (a), (b), (c), (d), (e), (f), (g), (h), (i), (j) )
|
||||
|
||||
#define DEBUG_BEGIN(y,x) _gpgme_debug_begin (&(y), 1, __FILE__ ":" \
|
||||
STR2 (__LINE__) ": " x )
|
||||
#define DEBUG_ENABLED(y) _gpgme_debug_enabled(&(y))
|
||||
#define DEBUG_ADD0(y,x) _gpgme_debug_add (&(y), (x), \
|
||||
)
|
||||
#define DEBUG_ADD1(y,x,a) _gpgme_debug_add (&(y), (x), \
|
||||
(a) )
|
||||
#define DEBUG_ADD2(y,x,a,b) _gpgme_debug_add (&(y), (x), \
|
||||
(a), (b) )
|
||||
#define DEBUG_ADD3(y,x,a,b,c) _gpgme_debug_add (&(y), (x), \
|
||||
(a), (b), (c) )
|
||||
#define DEBUG_ADD4(y,x,a,b,c,d) _gpgme_debug_add (&(y), (x), \
|
||||
(a), (b), (c), (d) )
|
||||
#define DEBUG_ADD5(y,x,a,b,c,d,e) _gpgme_debug_add (&(y), (x), \
|
||||
(a), (b), (c), (d), (e) )
|
||||
#define DEBUG_END(y,x) _gpgme_debug_end (&(y), (x) )
|
||||
|
||||
|
||||
|
||||
|
@ -129,7 +129,6 @@ verify_status_handler ( GpgmeCtx ctx, GpgStatusCode code, char *args )
|
||||
|
||||
default:
|
||||
/* ignore all other codes */
|
||||
fprintf (stderr, "verify_status: code=%d not handled\n", code );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "gpgme.h"
|
||||
#include "context.h"
|
||||
#include "rungpg.h"
|
||||
#include "sema.h"
|
||||
#include "util.h"
|
||||
|
||||
|
||||
@ -36,6 +37,18 @@ static char *tmp_engine_version;
|
||||
static const char *get_engine_info (void);
|
||||
|
||||
|
||||
static void
|
||||
do_subsystem_inits (void)
|
||||
{
|
||||
static int done = 0;
|
||||
|
||||
if (done)
|
||||
return;
|
||||
_gpgme_sema_subsystem_init ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const char*
|
||||
parse_version_number ( const char *s, int *number )
|
||||
{
|
||||
@ -108,13 +121,17 @@ compare_versions ( const char *my_version, const char *req_version )
|
||||
* Check that the the version of the library is at minimum the requested one
|
||||
* and return the version string; return NULL if the condition is not
|
||||
* met. If a NULL is passed to this function, no check is done and
|
||||
* the version string is simply returned.
|
||||
* the version string is simply returned. It is a pretty good idea to
|
||||
* run this function as soon as poossible, becuase it also intializes
|
||||
* some subsystems. In a multithreaded environment if should be called
|
||||
* before the first thread is created.
|
||||
*
|
||||
* Return value: The version string or NULL
|
||||
**/
|
||||
const char *
|
||||
gpgme_check_version ( const char *req_version )
|
||||
{
|
||||
do_subsystem_inits ();
|
||||
return compare_versions ( VERSION, req_version );
|
||||
}
|
||||
|
||||
@ -134,6 +151,7 @@ gpgme_check_version ( const char *req_version )
|
||||
const char *
|
||||
gpgme_get_engine_info ()
|
||||
{
|
||||
do_subsystem_inits ();
|
||||
return get_engine_info ();
|
||||
}
|
||||
|
||||
|
448
gpgme/w32-io.c
448
gpgme/w32-io.c
@ -34,17 +34,9 @@
|
||||
#include "syshdr.h"
|
||||
|
||||
#include "util.h"
|
||||
#include "sema.h"
|
||||
#include "io.h"
|
||||
|
||||
#define DEBUG_SELECT_ENABLED 1
|
||||
|
||||
#if DEBUG_SELECT_ENABLED
|
||||
# define DEBUG_SELECT(a) fprintf a
|
||||
#else
|
||||
# define DEBUG_SELECT(a) do { } while(0)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* We assume that a HANDLE can be represented by an int which should be true
|
||||
@ -58,19 +50,232 @@
|
||||
#define pid_to_handle(a) ((HANDLE)(a))
|
||||
#define handle_to_pid(a) ((int)(a))
|
||||
|
||||
#define READBUF_SIZE 4096
|
||||
|
||||
struct reader_context_s {
|
||||
HANDLE file_hd;
|
||||
HANDLE thread_hd;
|
||||
DECLARE_LOCK (mutex);
|
||||
|
||||
int eof;
|
||||
int error;
|
||||
int error_code;
|
||||
|
||||
HANDLE have_data_ev; /* manually reset */
|
||||
int have_data_flag; /* FIXME: is there another way to check whether
|
||||
it has been signaled? */
|
||||
HANDLE have_space_ev; /* auto reset */
|
||||
size_t readpos, writepos;
|
||||
char buffer[READBUF_SIZE];
|
||||
};
|
||||
|
||||
|
||||
#define MAX_READERS 20
|
||||
static struct {
|
||||
volatile int used;
|
||||
int fd;
|
||||
struct reader_context_s *context;
|
||||
} reader_table[MAX_READERS];
|
||||
static int reader_table_size= MAX_READERS;
|
||||
DEFINE_STATIC_LOCK (reader_table_lock);
|
||||
|
||||
static HANDLE
|
||||
set_synchronize (HANDLE h)
|
||||
{
|
||||
HANDLE tmp;
|
||||
|
||||
/* For NT we have to set the sync flag. It seems that the only
|
||||
* way to do it is by duplicating the handle. Tsss.. */
|
||||
if (!DuplicateHandle( GetCurrentProcess(), h,
|
||||
GetCurrentProcess(), &tmp,
|
||||
SYNCHRONIZE, FALSE, 0 ) ) {
|
||||
DEBUG1 ("** Set SYNCRONIZE failed: ec=%d\n", (int)GetLastError());
|
||||
}
|
||||
else {
|
||||
CloseHandle (h);
|
||||
h = tmp;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static DWORD CALLBACK
|
||||
reader (void *arg)
|
||||
{
|
||||
struct reader_context_s *c = arg;
|
||||
int nbytes;
|
||||
DWORD nread;
|
||||
|
||||
DEBUG2 ("reader thread %p for file %p started", c->thread_hd, c->file_hd );
|
||||
for (;;) {
|
||||
LOCK (c->mutex);
|
||||
/* leave a one byte gap so that we can see wheter it is empty or full*/
|
||||
if ((c->writepos + 1) % READBUF_SIZE == c->readpos) {
|
||||
/* wait for space */
|
||||
ResetEvent (c->have_space_ev);
|
||||
UNLOCK (c->mutex);
|
||||
DEBUG1 ("reader thread %p: waiting for space ...", c->thread_hd );
|
||||
WaitForSingleObject (c->have_space_ev, INFINITE);
|
||||
DEBUG1 ("reader thread %p: got space", c->thread_hd );
|
||||
LOCK (c->mutex);
|
||||
}
|
||||
nbytes = (c->readpos + READBUF_SIZE - c->writepos-1) % READBUF_SIZE;
|
||||
if ( nbytes > READBUF_SIZE - c->writepos )
|
||||
nbytes = READBUF_SIZE - c->writepos;
|
||||
UNLOCK (c->mutex);
|
||||
|
||||
DEBUG2 ("reader thread %p: reading %d bytes", c->thread_hd, nbytes );
|
||||
if ( !ReadFile ( c->file_hd,
|
||||
c->buffer+c->writepos, nbytes, &nread, NULL) ) {
|
||||
c->error = 1;
|
||||
c->error_code = (int)GetLastError ();
|
||||
DEBUG2 ("reader thread %p: read error: ec=%d",
|
||||
c->thread_hd, c->error_code );
|
||||
break;
|
||||
}
|
||||
if ( !nread ) {
|
||||
c->eof = 1;
|
||||
DEBUG1 ("reader thread %p: got eof", c->thread_hd );
|
||||
break;
|
||||
}
|
||||
DEBUG2 ("reader thread %p: got %d bytes", c->thread_hd, (int)nread );
|
||||
|
||||
LOCK (c->mutex);
|
||||
c->writepos = (c->writepos + nread) % READBUF_SIZE;
|
||||
c->have_data_flag = 1;
|
||||
SetEvent (c->have_data_ev);
|
||||
UNLOCK (c->mutex);
|
||||
}
|
||||
DEBUG1 ("reader thread %p ended", c->thread_hd );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct reader_context_s *
|
||||
create_reader (HANDLE fd)
|
||||
{
|
||||
struct reader_context_s *c;
|
||||
SECURITY_ATTRIBUTES sec_attr;
|
||||
DWORD tid;
|
||||
|
||||
DEBUG1 ("creating new read thread for file handle %p", fd );
|
||||
memset (&sec_attr, 0, sizeof sec_attr );
|
||||
sec_attr.nLength = sizeof sec_attr;
|
||||
sec_attr.bInheritHandle = FALSE;
|
||||
|
||||
c = xtrycalloc (1, sizeof *c );
|
||||
if (!c)
|
||||
return NULL;
|
||||
|
||||
c->file_hd = fd;
|
||||
c->have_data_ev = CreateEvent (&sec_attr, TRUE, FALSE, NULL);
|
||||
c->have_space_ev = CreateEvent (&sec_attr, FALSE, TRUE, NULL);
|
||||
if (!c->have_data_ev || !c->have_space_ev) {
|
||||
DEBUG1 ("** CreateEvent failed: ec=%d\n", (int)GetLastError ());
|
||||
if (c->have_data_ev)
|
||||
CloseHandle (c->have_data_ev);
|
||||
if (c->have_space_ev)
|
||||
CloseHandle (c->have_space_ev);
|
||||
xfree (c);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
c->have_data_ev = set_synchronize (c->have_data_ev);
|
||||
INIT_LOCK (c->mutex);
|
||||
|
||||
c->thread_hd = CreateThread (&sec_attr, 0, reader, c, 0, &tid );
|
||||
if (!c->thread_hd) {
|
||||
DEBUG1 ("** failed to create reader thread: ec=%d\n",
|
||||
(int)GetLastError ());
|
||||
DESTROY_LOCK (c->mutex);
|
||||
if (c->have_data_ev)
|
||||
CloseHandle (c->have_data_ev);
|
||||
if (c->have_space_ev)
|
||||
CloseHandle (c->have_space_ev);
|
||||
xfree (c);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Find a reader context or create a new one
|
||||
* Note that the reader context will last until a io_close.
|
||||
*/
|
||||
static struct reader_context_s *
|
||||
find_reader (int fd, int start_it)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i < reader_table_size ; i++ ) {
|
||||
if ( reader_table[i].used && reader_table[i].fd == fd )
|
||||
return reader_table[i].context;
|
||||
}
|
||||
if (!start_it)
|
||||
return NULL;
|
||||
|
||||
LOCK (reader_table_lock);
|
||||
for (i=0; i < reader_table_size; i++ ) {
|
||||
if (!reader_table[i].used) {
|
||||
reader_table[i].fd = fd;
|
||||
reader_table[i].context = create_reader (fd_to_handle (fd));
|
||||
reader_table[i].used = 1;
|
||||
UNLOCK (reader_table_lock);
|
||||
return reader_table[i].context;
|
||||
}
|
||||
}
|
||||
UNLOCK (reader_table_lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
_gpgme_io_read ( int fd, void *buffer, size_t count )
|
||||
{
|
||||
int nread = 0;
|
||||
HANDLE h = fd_to_handle (fd);
|
||||
int nread;
|
||||
struct reader_context_s *c = find_reader (fd,1);
|
||||
|
||||
DEBUG_SELECT ((stderr,"** fd %d: about to read %d bytes\n", fd, (int)count ));
|
||||
if ( !ReadFile ( h, buffer, count, &nread, NULL) ) {
|
||||
fprintf (stderr, "** ReadFile failed: ec=%d\n", (int)GetLastError ());
|
||||
DEBUG2 ("fd %d: about to read %d bytes\n", fd, (int)count );
|
||||
if ( !c ) {
|
||||
DEBUG0 ( "no reader thread\n");
|
||||
return -1;
|
||||
}
|
||||
DEBUG_SELECT ((stderr,"** fd %d: got %d bytes\n", fd, nread ));
|
||||
|
||||
LOCK (c->mutex);
|
||||
if (c->readpos == c->writepos) { /* no data avail */
|
||||
UNLOCK (c->mutex);
|
||||
DEBUG2 ("fd %d: waiting for data from thread %p", fd, c->thread_hd);
|
||||
WaitForSingleObject (c->have_data_ev, INFINITE);
|
||||
DEBUG2 ("fd %d: data from thread %p available", fd, c->thread_hd);
|
||||
LOCK (c->mutex);
|
||||
if (c->readpos == c->writepos && !c->eof && !c->error) {
|
||||
UNLOCK (c->mutex);
|
||||
if (c->eof)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
nread = c->readpos < c->writepos? c->writepos - c->readpos
|
||||
: READBUF_SIZE - c->readpos;
|
||||
if (nread > count)
|
||||
nread = count;
|
||||
memcpy (buffer, c->buffer+c->readpos, nread);
|
||||
c->readpos = (c->readpos + nread) % READBUF_SIZE;
|
||||
if (c->readpos == c->writepos) {
|
||||
c->have_data_flag = 0;
|
||||
ResetEvent (c->have_data_ev);
|
||||
}
|
||||
if (nread)
|
||||
SetEvent (c->have_space_ev);
|
||||
UNLOCK (c->mutex);
|
||||
|
||||
DEBUG2 ("fd %d: got %d bytes\n", fd, nread );
|
||||
|
||||
return nread;
|
||||
}
|
||||
@ -79,17 +284,18 @@ _gpgme_io_read ( int fd, void *buffer, size_t count )
|
||||
int
|
||||
_gpgme_io_write ( int fd, const void *buffer, size_t count )
|
||||
{
|
||||
int nwritten;
|
||||
DWORD nwritten;
|
||||
HANDLE h = fd_to_handle (fd);
|
||||
|
||||
DEBUG_SELECT ((stderr,"** fd %d: about to write %d bytes\n", fd, (int)count ));
|
||||
DEBUG2 ("fd %d: about to write %d bytes\n", fd, (int)count );
|
||||
if ( !WriteFile ( h, buffer, count, &nwritten, NULL) ) {
|
||||
fprintf (stderr, "** WriteFile failed: ec=%d\n", (int)GetLastError ());
|
||||
DEBUG1 ("WriteFile failed: ec=%d\n", (int)GetLastError ());
|
||||
return -1;
|
||||
}
|
||||
DEBUG_SELECT ((stderr,"** fd %d: wrote %d bytes\n", fd, nwritten ));
|
||||
DEBUG2 ("fd %d: wrote %d bytes\n",
|
||||
fd, (int)nwritten );
|
||||
|
||||
return nwritten;
|
||||
return (int)nwritten;
|
||||
}
|
||||
|
||||
int
|
||||
@ -110,8 +316,7 @@ _gpgme_io_pipe ( int filedes[2], int inherit_idx )
|
||||
if (!DuplicateHandle( GetCurrentProcess(), r,
|
||||
GetCurrentProcess(), &h, 0,
|
||||
TRUE, DUPLICATE_SAME_ACCESS ) ) {
|
||||
fprintf (stderr, "** DuplicateHandle failed: ec=%d\n",
|
||||
(int)GetLastError());
|
||||
DEBUG1 ("DuplicateHandle failed: ec=%d\n", (int)GetLastError());
|
||||
CloseHandle (r);
|
||||
CloseHandle (w);
|
||||
return -1;
|
||||
@ -124,8 +329,7 @@ _gpgme_io_pipe ( int filedes[2], int inherit_idx )
|
||||
if (!DuplicateHandle( GetCurrentProcess(), w,
|
||||
GetCurrentProcess(), &h, 0,
|
||||
TRUE, DUPLICATE_SAME_ACCESS ) ) {
|
||||
fprintf (stderr, "** DuplicateHandle failed: ec=%d\n",
|
||||
(int)GetLastError());
|
||||
DEBUG1 ("DuplicateHandle failed: ec=%d\n", (int)GetLastError());
|
||||
CloseHandle (r);
|
||||
CloseHandle (w);
|
||||
return -1;
|
||||
@ -136,8 +340,8 @@ _gpgme_io_pipe ( int filedes[2], int inherit_idx )
|
||||
|
||||
filedes[0] = handle_to_fd (r);
|
||||
filedes[1] = handle_to_fd (w);
|
||||
DEBUG_SELECT ((stderr,"** create pipe %p %p %d %d inherit=%d\n", r, w,
|
||||
filedes[0], filedes[1], inherit_idx ));
|
||||
DEBUG5 ("CreatePipe %p %p %d %d inherit=%d\n", r, w,
|
||||
filedes[0], filedes[1], inherit_idx );
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -147,9 +351,11 @@ _gpgme_io_close ( int fd )
|
||||
if ( fd == -1 )
|
||||
return -1;
|
||||
|
||||
DEBUG_SELECT ((stderr,"** closing handle for fd %d\n", fd));
|
||||
DEBUG1 ("** closing handle for fd %d\n", fd);
|
||||
/* fixme: destroy thread */
|
||||
|
||||
if ( !CloseHandle (fd_to_handle (fd)) ) {
|
||||
fprintf (stderr, "** CloseHandle for fd %d failed: ec=%d\n",
|
||||
DEBUG2 ("CloseHandle for fd %d failed: ec=%d\n",
|
||||
fd, (int)GetLastError ());
|
||||
return -1;
|
||||
}
|
||||
@ -230,16 +436,16 @@ _gpgme_io_spawn ( const char *path, char **argv,
|
||||
for (i=0; fd_child_list[i].fd != -1; i++ ) {
|
||||
if (fd_child_list[i].dup_to == 0 ) {
|
||||
si.hStdInput = fd_to_handle (fd_child_list[i].fd);
|
||||
DEBUG_SELECT ((stderr,"** using %d for stdin\n", fd_child_list[i].fd ));
|
||||
DEBUG1 ("using %d for stdin", fd_child_list[i].fd );
|
||||
duped_stdin=1;
|
||||
}
|
||||
else if (fd_child_list[i].dup_to == 1 ) {
|
||||
si.hStdOutput = fd_to_handle (fd_child_list[i].fd);
|
||||
DEBUG_SELECT ((stderr,"** using %d for stdout\n", fd_child_list[i].fd ));
|
||||
DEBUG1 ("using %d for stdout", fd_child_list[i].fd );
|
||||
}
|
||||
else if (fd_child_list[i].dup_to == 2 ) {
|
||||
si.hStdError = fd_to_handle (fd_child_list[i].fd);
|
||||
DEBUG_SELECT ((stderr,"** using %d for stderr\n", fd_child_list[i].fd ));
|
||||
DEBUG1 ("using %d for stderr", fd_child_list[i].fd );
|
||||
duped_stderr = 1;
|
||||
}
|
||||
}
|
||||
@ -250,7 +456,7 @@ _gpgme_io_spawn ( const char *path, char **argv,
|
||||
memset (&sa, 0, sizeof sa );
|
||||
sa.nLength = sizeof sa;
|
||||
sa.bInheritHandle = TRUE;
|
||||
hnul = CreateFile ( "/dev/nul",
|
||||
hnul = CreateFile ( "nul",
|
||||
GENERIC_READ|GENERIC_WRITE,
|
||||
FILE_SHARE_READ|FILE_SHARE_WRITE,
|
||||
&sa,
|
||||
@ -258,27 +464,23 @@ _gpgme_io_spawn ( const char *path, char **argv,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL );
|
||||
if ( hnul == INVALID_HANDLE_VALUE ) {
|
||||
fprintf (stderr,"can't open `/dev/nul': ec=%d\n",
|
||||
(int)GetLastError () );
|
||||
DEBUG1 ("can't open `nul': ec=%d\n", (int)GetLastError ());
|
||||
xfree (arg_string);
|
||||
return -1;
|
||||
}
|
||||
/* Make sure that the process has a connected stdin */
|
||||
if ( !duped_stdin ) {
|
||||
si.hStdInput = hnul;
|
||||
DEBUG_SELECT ((stderr,"** using %d for stdin\n", (int)hnul ));
|
||||
DEBUG1 ("using %d for dummy stdin", (int)hnul );
|
||||
}
|
||||
/* We normally don't want all the normal output */
|
||||
if ( !duped_stderr ) {
|
||||
if (!debug_me) {
|
||||
si.hStdError = hnul;
|
||||
DEBUG_SELECT ((stderr,"** using %d for stderr\n", (int)hnul ));
|
||||
}
|
||||
si.hStdError = hnul;
|
||||
DEBUG1 ("using %d for dummy stderr", (int)hnul );
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_SELECT ((stderr,"** CreateProcess ...\n"));
|
||||
DEBUG_SELECT ((stderr,"** args=`%s'\n", arg_string));
|
||||
DEBUG1 ("CreateProcess, args=`%s'", arg_string);
|
||||
cr_flags |= CREATE_SUSPENDED;
|
||||
if ( !CreateProcessA (GPG_PATH,
|
||||
arg_string,
|
||||
@ -291,8 +493,7 @@ _gpgme_io_spawn ( const char *path, char **argv,
|
||||
&si, /* startup information */
|
||||
&pi /* returns process information */
|
||||
) ) {
|
||||
fprintf (stderr, "** CreateProcess failed: ec=%d\n",
|
||||
(int) GetLastError ());
|
||||
DEBUG1 ("CreateProcess failed: ec=%d\n", (int) GetLastError ());
|
||||
xfree (arg_string);
|
||||
return -1;
|
||||
}
|
||||
@ -300,31 +501,28 @@ _gpgme_io_spawn ( const char *path, char **argv,
|
||||
/* close the /dev/nul handle if used */
|
||||
if (hnul != INVALID_HANDLE_VALUE ) {
|
||||
if ( !CloseHandle ( hnul ) )
|
||||
fprintf (stderr, "** CloseHandle(hnul) failed: ec=%d\n",
|
||||
(int)GetLastError());
|
||||
DEBUG1 ("CloseHandle(hnul) failed: ec=%d\n", (int)GetLastError());
|
||||
}
|
||||
|
||||
/* Close the other ends of the pipes */
|
||||
for (i=0; fd_parent_list[i].fd != -1; i++ ) {
|
||||
DEBUG_SELECT ((stderr,"** Closing fd %d\n", fd_parent_list[i].fd ));
|
||||
DEBUG1 ("Closing fd %d\n", fd_parent_list[i].fd );
|
||||
if ( !CloseHandle ( fd_to_handle (fd_parent_list[i].fd) ) )
|
||||
fprintf (stderr, "** CloseHandle failed: ec=%d\n",
|
||||
(int)GetLastError());
|
||||
DEBUG1 ("CloseHandle failed: ec=%d", (int)GetLastError());
|
||||
}
|
||||
|
||||
DEBUG_SELECT ((stderr,"** CreateProcess ready\n"
|
||||
"** hProcess=%p hThread=%p\n"
|
||||
"** dwProcessID=%d dwThreadId=%d\n",
|
||||
pi.hProcess, pi.hThread,
|
||||
(int) pi.dwProcessId, (int) pi.dwThreadId));
|
||||
DEBUG4 ("CreateProcess ready\n"
|
||||
"- hProcess=%p hThread=%p\n"
|
||||
"- dwProcessID=%d dwThreadId=%d\n",
|
||||
pi.hProcess, pi.hThread,
|
||||
(int) pi.dwProcessId, (int) pi.dwThreadId);
|
||||
|
||||
if ( ResumeThread ( pi.hThread ) < 0 ) {
|
||||
fprintf (stderr, "** ResumeThread failed: ec=%d\n",
|
||||
(int)GetLastError ());
|
||||
DEBUG1 ("ResumeThread failed: ec=%d\n", (int)GetLastError ());
|
||||
}
|
||||
|
||||
if ( !CloseHandle (pi.hThread) ) {
|
||||
fprintf (stderr, "** CloseHandle of thread failed: ec=%d\n",
|
||||
DEBUG1 ("CloseHandle of thread failed: ec=%d\n",
|
||||
(int)GetLastError ());
|
||||
}
|
||||
|
||||
@ -345,30 +543,29 @@ _gpgme_io_waitpid ( int pid, int hang, int *r_status, int *r_signal )
|
||||
code = WaitForSingleObject ( proc, hang? INFINITE : 0 );
|
||||
switch (code) {
|
||||
case WAIT_FAILED:
|
||||
fprintf (stderr, "** WFSO pid=%d failed: %d\n",
|
||||
(int)pid, (int)GetLastError () );
|
||||
DEBUG2 ("WFSO pid=%d failed: %d\n", (int)pid, (int)GetLastError () );
|
||||
break;
|
||||
|
||||
case WAIT_OBJECT_0:
|
||||
if (!GetExitCodeProcess (proc, &exc)) {
|
||||
fprintf (stderr, "** GECP pid=%d failed: ec=%d\n",
|
||||
(int)pid, (int)GetLastError () );
|
||||
DEBUG2 ("** GECP pid=%d failed: ec=%d\n",
|
||||
(int)pid, (int)GetLastError () );
|
||||
*r_status = 4;
|
||||
}
|
||||
else {
|
||||
DEBUG_SELECT ((stderr,"** GECP pid=%d exit code=%d\n",
|
||||
(int)pid, exc));
|
||||
DEBUG2 ("GECP pid=%d exit code=%d\n", (int)pid, exc);
|
||||
*r_status = exc;
|
||||
}
|
||||
ret = 1;
|
||||
break;
|
||||
|
||||
case WAIT_TIMEOUT:
|
||||
DEBUG_SELECT ((stderr,"** WFSO pid=%d timed out\n", (int)pid));
|
||||
if (hang)
|
||||
DEBUG1 ("WFSO pid=%d timed out\n", (int)pid);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf (stderr, "** WFSO pid=%d returned %d\n", (int)pid, code );
|
||||
DEBUG2 ("WFSO pid=%d returned %d\n", (int)pid, code );
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
@ -384,40 +581,50 @@ _gpgme_io_waitpid ( int pid, int hang, int *r_status, int *r_signal )
|
||||
int
|
||||
_gpgme_io_select ( struct io_select_fd_s *fds, size_t nfds )
|
||||
{
|
||||
#if 0 /* We can't use WFMO becaus a pipe handle is not a suitable object */
|
||||
#if 1
|
||||
HANDLE waitbuf[MAXIMUM_WAIT_OBJECTS];
|
||||
int code, nwait;
|
||||
int i, any, any_write;
|
||||
int count;
|
||||
void *dbg_help;
|
||||
|
||||
restart:
|
||||
DEBUG_SELECT ((stderr, "gpgme:select on [ "));
|
||||
DEBUG_BEGIN (dbg_help, "select on [ ");
|
||||
any = any_write = 0;
|
||||
nwait = 0;
|
||||
for ( i=0; i < nfds; i++ ) {
|
||||
if ( fds[i].fd == -1 )
|
||||
continue;
|
||||
if ( fds[i].for_read || fds[i].for_write ) {
|
||||
if ( fds[i].for_read ) {
|
||||
if ( nwait >= DIM (waitbuf) ) {
|
||||
DEBUG_SELECT ((stderr,stderr, "oops ]\n" ));
|
||||
fprintf (stderr, "** Too many objects for WFMO!\n" );
|
||||
DEBUG_END (dbg_help, "oops ]");
|
||||
DEBUG0 ("Too many objects for WFMO!" );
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
if ( fds[i].for_read )
|
||||
waitbuf[nwait++] = fd_to_handle (fds[i].fd);
|
||||
DEBUG_SELECT ((stderr, "%c%d ",
|
||||
fds[i].for_read? 'r':'w',fds[i].fd ));
|
||||
if ( fds[i].for_read ) {
|
||||
struct reader_context_s *c = find_reader (fds[i].fd,1);
|
||||
|
||||
if (!c) {
|
||||
DEBUG1 ("no reader thread for fd %d", fds[i].fd);
|
||||
}
|
||||
else {
|
||||
waitbuf[nwait++] = c->have_data_ev;
|
||||
}
|
||||
}
|
||||
DEBUG_ADD2 (dbg_help, "%c%d ",
|
||||
fds[i].for_read? 'r':'w',fds[i].fd );
|
||||
any = 1;
|
||||
}
|
||||
}
|
||||
fds[i].signaled = 0;
|
||||
}
|
||||
DEBUG_SELECT ((stderr, "]\n" ));
|
||||
DEBUG_END (dbg_help, "]");
|
||||
if (!any)
|
||||
return 0;
|
||||
|
||||
count = 0;
|
||||
/* no way to see whether a handle is ready for writing, signal all */
|
||||
for ( i=0; i < nfds; i++ ) {
|
||||
if ( fds[i].fd == -1 )
|
||||
continue;
|
||||
@ -428,64 +635,7 @@ _gpgme_io_select ( struct io_select_fd_s *fds, size_t nfds )
|
||||
}
|
||||
}
|
||||
code = WaitForMultipleObjects ( nwait, waitbuf, 0, any_write? 0:1000);
|
||||
if (code == WAIT_FAILED ) {
|
||||
int le = (int)GetLastError ();
|
||||
if ( le == ERROR_INVALID_HANDLE || le == ERROR_INVALID_EVENT_COUNT ) {
|
||||
any = 0;
|
||||
for ( i=0; i < nfds; i++ ) {
|
||||
if ( fds[i].fd == -1 )
|
||||
continue;
|
||||
if ( fds[i].for_read /*|| fds[i].for_write*/ ) {
|
||||
int navail;
|
||||
if (PeekNamedPipe (fd_to_handle (fds[i].fd),
|
||||
NULL, 0, NULL,
|
||||
&navail, NULL) && navail ) {
|
||||
fds[i].signaled = 1;
|
||||
any = 1;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (any)
|
||||
return count;
|
||||
/* find that handle and remove it from the list*/
|
||||
for (i=0; i < nwait; i++ ) {
|
||||
code = WaitForSingleObject ( waitbuf[i], NULL );
|
||||
if (!code) {
|
||||
int k, j = handle_to_fd (waitbuf[i]);
|
||||
|
||||
fprintf (stderr, "** handle meanwhile signaled %d\n", j);
|
||||
for (k=0 ; k < nfds; k++ ) {
|
||||
if ( fds[k].fd == j ) {
|
||||
fds[k].signaled = 1;
|
||||
count++;
|
||||
return count;
|
||||
}
|
||||
}
|
||||
fprintf (stderr, "** oops, or not???\n");
|
||||
}
|
||||
if ( GetLastError () == ERROR_INVALID_HANDLE) {
|
||||
int k, j = handle_to_fd (waitbuf[i]);
|
||||
|
||||
fprintf (stderr, "** WFMO invalid handle %d removed\n", j);
|
||||
for (k=0 ; k < nfds; i++ ) {
|
||||
if ( fds[k].fd == j ) {
|
||||
fds[k].for_read = fds[k].for_write = 0;
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
fprintf (stderr, "** oops, or not???\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fprintf (stderr, "** WFMO failed: %d\n", le );
|
||||
count = -1;
|
||||
}
|
||||
else if ( code == WAIT_TIMEOUT ) {
|
||||
fprintf (stderr, "** WFMO timed out\n" );
|
||||
}
|
||||
else if ( code >= WAIT_OBJECT_0 && code < WAIT_OBJECT_0 + nwait ) {
|
||||
if ( code >= WAIT_OBJECT_0 && code < WAIT_OBJECT_0 + nwait ) {
|
||||
/* This WFMO is a really silly function: It does return either
|
||||
* the index of the signaled object or if 2 objects have been
|
||||
* signalled at the same time, the index of the object with the
|
||||
@ -503,13 +653,32 @@ _gpgme_io_select ( struct io_select_fd_s *fds, size_t nfds )
|
||||
}
|
||||
}
|
||||
if (!any) {
|
||||
fprintf (stderr,
|
||||
"** Oops: No signaled objects found after WFMO\n");
|
||||
DEBUG0 ("Oops: No signaled objects found after WFMO");
|
||||
count = -1;
|
||||
}
|
||||
}
|
||||
else if ( code == WAIT_TIMEOUT ) {
|
||||
DEBUG0 ("WFMO timed out\n" );
|
||||
}
|
||||
else if (code == WAIT_FAILED ) {
|
||||
int le = (int)GetLastError ();
|
||||
if ( le == ERROR_INVALID_HANDLE ) {
|
||||
int k, j = handle_to_fd (waitbuf[i]);
|
||||
|
||||
DEBUG1 ("WFMO invalid handle %d removed\n", j);
|
||||
for (k=0 ; k < nfds; i++ ) {
|
||||
if ( fds[k].fd == j ) {
|
||||
fds[k].for_read = fds[k].for_write = 0;
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
DEBUG0 (" oops, or not???\n");
|
||||
}
|
||||
DEBUG1 ("WFMO failed: %d\n", le );
|
||||
count = -1;
|
||||
}
|
||||
else {
|
||||
fprintf (stderr, "** WFMO returned %d\n", code );
|
||||
DEBUG1 ("WFMO returned %d\n", code );
|
||||
count = -1;
|
||||
}
|
||||
|
||||
@ -552,15 +721,14 @@ _gpgme_io_select ( struct io_select_fd_s *fds, size_t nfds )
|
||||
continue;
|
||||
if ( fds[i].for_read ) {
|
||||
int navail;
|
||||
|
||||
|
||||
if ( !PeekNamedPipe (fd_to_handle (fds[i].fd),
|
||||
NULL, 0, NULL, &navail, NULL) ) {
|
||||
fprintf (stderr, "** select: PeekFile failed: ec=%d\n",
|
||||
(int)GetLastError ());
|
||||
DEBUG1 ("select: PeekFile failed: ec=%d\n",
|
||||
(int)GetLastError ());
|
||||
}
|
||||
else if ( navail ) {
|
||||
/*fprintf (stderr, "** fd %d has %d bytes to read\n",
|
||||
fds[i].fd, navail );*/
|
||||
DEBUG2 ("fd %d has %d bytes to read\n", fds[i].fd, navail );
|
||||
fds[i].signaled = 1;
|
||||
count++;
|
||||
}
|
||||
|
123
gpgme/w32-sema.c
Normal file
123
gpgme/w32-sema.c
Normal file
@ -0,0 +1,123 @@
|
||||
/* w32-sema.c
|
||||
* Copyright (C) 2001 Werner Koch (dd9jn)
|
||||
*
|
||||
* This file is part of GPGME.
|
||||
*
|
||||
* GPGME is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GPGME is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <config.h>
|
||||
#ifdef HAVE_DOSISH_SYSTEM
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <windows.h>
|
||||
#include "syshdr.h"
|
||||
|
||||
#include "util.h"
|
||||
#include "sema.h"
|
||||
|
||||
static void
|
||||
sema_fatal (const char *text)
|
||||
{
|
||||
fprintf (stderr, "sema.c: %s\n", text);
|
||||
abort ();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
critsect_init (struct critsect_s *s)
|
||||
{
|
||||
CRITICAL_SECTION *mp;
|
||||
static CRITICAL_SECTION init_lock;
|
||||
static int initialized;
|
||||
|
||||
if (!initialized) {
|
||||
/* the very first time we call this function, we assume that only
|
||||
* one thread is running, so that we can bootstrap the semaphore code
|
||||
*/
|
||||
InitializeCriticalSection (&init_lock);
|
||||
initialized = 1;
|
||||
}
|
||||
if (!s)
|
||||
return; /* we just want to initialize ourself */
|
||||
|
||||
/* first test whether it is really not initialized */
|
||||
EnterCriticalSection (&init_lock);
|
||||
if ( s->private ) {
|
||||
LeaveCriticalSection (&init_lock);
|
||||
return;
|
||||
}
|
||||
/* now init it */
|
||||
mp = xtrymalloc ( sizeof *mp );
|
||||
if (!mp) {
|
||||
LeaveCriticalSection (&init_lock);
|
||||
sema_fatal ("out of core while creating critical section lock");
|
||||
}
|
||||
InitializeCriticalSection (mp);
|
||||
s->private = mp;
|
||||
LeaveCriticalSection (&init_lock);
|
||||
}
|
||||
|
||||
void
|
||||
_gpgme_sema_subsystem_init ()
|
||||
{
|
||||
/* fixme: we should check that there is only one thread running */
|
||||
critsect_init (NULL);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_gpgme_sema_cs_enter ( struct critsect_s *s )
|
||||
{
|
||||
if (!s->private)
|
||||
critsect_init (s);
|
||||
EnterCriticalSection ( (CRITICAL_SECTION*)s->private );
|
||||
}
|
||||
|
||||
void
|
||||
_gpgme_sema_cs_leave (struct critsect_s *s)
|
||||
{
|
||||
if (!s->private)
|
||||
critsect_init (s);
|
||||
LeaveCriticalSection ( (CRITICAL_SECTION*)s->private );
|
||||
}
|
||||
|
||||
void
|
||||
_gpgme_sema_cs_destroy ( struct critsect_s *s )
|
||||
{
|
||||
if (s && s->private) {
|
||||
DeleteCriticalSection ((CRITICAL_SECTION*)s->private);
|
||||
xfree (s->private);
|
||||
s->private = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /*HAVE_DOSISH_SYSTEM*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -68,6 +68,7 @@ doit ( GpgmeCtx ctx, const char *pattern )
|
||||
s = gpgme_key_get_string_attr (key, GPGME_ATTR_COMMENT, NULL, i );
|
||||
printf ("<!-- comment.%d=%s -->\n", i, s );
|
||||
}
|
||||
|
||||
printf ("<!-- End key object (%p) -->\n", key );
|
||||
gpgme_key_release (key);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user