From f9a167c516c8bf5f9dfc076fa51eb60dc96c86fb Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 20 Nov 2000 20:17:36 +0000 Subject: [PATCH] Does some basic tasks. --- acconfig.h | 8 ++++++-- configure.in | 4 ++-- gpgme/context.h | 3 +++ gpgme/gpgme.c | 22 +++++++++++++--------- gpgme/gpgme.h | 11 +++++++---- gpgme/rungpg.c | 38 ++++++++++++++++++++++++++++++++++++-- gpgme/wait.c | 46 ++++++++++++++++++++++++++++++++++++++++++---- tests/t-decrypt.c | 16 ++++++++++++++++ tests/t-sign.c | 4 ++-- tests/t-verify.c | 4 ++-- 10 files changed, 129 insertions(+), 27 deletions(-) diff --git a/acconfig.h b/acconfig.h index 2db9b12f..724fd6ff 100644 --- a/acconfig.h +++ b/acconfig.h @@ -21,9 +21,13 @@ #define GPGME_CONFIG_H /* need this, because some autoconf tests rely on this (e.g. stpcpy) - * and it should be used for new programs - */ + * and it should be used for new programs */ #define _GNU_SOURCE 1 +/* To allow the use of gpgme in multithreaded programs we have to use + * special features from the library. + * IMPORTANT: gpgme is not yet fully reentrant and you should use it + * only from one thread. */ +#define _REENTRANT 1 @TOP@ diff --git a/configure.in b/configure.in index f8301ca7..3e23edfd 100644 --- a/configure.in +++ b/configure.in @@ -13,10 +13,10 @@ AM_MAINTAINER_MODE # AGE, set REVISION to 0. # 3. Interfaces removed (BAD, breaks upward compatibility): Increment # CURRENT, set AGE and REVISION to 0. -AM_INIT_AUTOMAKE(gpgme,0.0.1) +AM_INIT_AUTOMAKE(gpgme,0.1.0) LIBGPGME_LT_CURRENT=0 LIBGPGME_LT_AGE=0 -LIBGPGME_LT_REVISION=0 +LIBGPGME_LT_REVISION=2 ############################################## AC_SUBST(LIBGPGME_LT_CURRENT) diff --git a/gpgme/context.h b/gpgme/context.h index 71c42395..e888aa8d 100644 --- a/gpgme/context.h +++ b/gpgme/context.h @@ -55,6 +55,9 @@ struct gpgme_context_s { int verbosity; /* level of verbosity to use */ int use_armor; int use_textmode; + + /* GpgmePassphraseCb passphrase_cb;*/ + /* void * passphrase_cb_value;*/ ResultType result_type; union { diff --git a/gpgme/gpgme.c b/gpgme/gpgme.c index 05f940f7..165f03cb 100644 --- a/gpgme/gpgme.c +++ b/gpgme/gpgme.c @@ -96,7 +96,7 @@ _gpgme_release_result ( GpgmeCtx c ) char * -gpgme_op_get_notation ( GpgmeCtx c ) +gpgme_get_notation ( GpgmeCtx c ) { if ( !c->notation ) return NULL; @@ -105,7 +105,7 @@ gpgme_op_get_notation ( GpgmeCtx c ) void -gpgme_op_set_armor ( GpgmeCtx c, int yes ) +gpgme_set_armor ( GpgmeCtx c, int yes ) { if ( !c ) return; /* oops */ @@ -113,19 +113,23 @@ gpgme_op_set_armor ( GpgmeCtx c, int yes ) } void -gpgme_op_set_textmode ( GpgmeCtx c, int yes ) +gpgme_set_textmode ( GpgmeCtx c, int yes ) { if ( !c ) return; /* oops */ c->use_textmode = yes; } - - - - - - +#if 0 +void +gpgme_set_passphrase_cb ( GpgmeCtx c, GpgmePassphraseCb fnc, void *fncval ) +{ + if ( c ) { + c->passphrase_cb = fnc; + c->passphrase_cb_value = fncval; + } +} +#endif diff --git a/gpgme/gpgme.h b/gpgme/gpgme.h index 6c9c7661..692362b1 100644 --- a/gpgme/gpgme.h +++ b/gpgme/gpgme.h @@ -34,7 +34,7 @@ extern "C" { * let autoconf (using the AM_PATH_GPGME macro) check that this * header matches the installed library. * Warning: Do not edit the next line. configure will do that for you! */ -#define GPGME_VERSION "0.0.1" +#define GPGME_VERSION "0.1.0" @@ -91,6 +91,7 @@ typedef enum { GPGME_SIG_STAT_ERROR = 5 } GpgmeSigStat; +/*typedef GpgmeData (*GpgmePassphraseCb)( void *opaque, const char *desc );*/ /* Context management */ @@ -98,9 +99,11 @@ GpgmeError gpgme_new (GpgmeCtx *r_ctx); void gpgme_release ( GpgmeCtx c ); GpgmeCtx gpgme_wait ( GpgmeCtx c, int hang ); -char *gpgme_op_get_notation ( GpgmeCtx c ); -void gpgme_op_set_armor ( GpgmeCtx c, int yes ); -void gpgme_op_set_textmode ( GpgmeCtx c, int yes ); +char *gpgme_get_notation ( GpgmeCtx c ); +void gpgme_set_armor ( GpgmeCtx c, int yes ); +void gpgme_set_textmode ( GpgmeCtx c, int yes ); +/*void gpgme_set_passphrase_cb ( GpgmeCtx c, + GpgmePassphraseCb fnc, void *fncval );*/ /* Functions to handle recipients */ diff --git a/gpgme/rungpg.c b/gpgme/rungpg.c index 991624f9..f75b8b14 100644 --- a/gpgme/rungpg.c +++ b/gpgme/rungpg.c @@ -201,6 +201,20 @@ kill_gpg ( GpgObject gpg ) } + +static int +set_nonblocking ( int fd ) +{ + int flags; + + flags = fcntl (fd, F_GETFL, 0); + if (flags == -1) + return -1; + flags |= O_NONBLOCK; + return fcntl (fd, F_SETFL, flags); +} + + GpgmeError _gpgme_gpg_add_arg ( GpgObject gpg, const char *arg ) { @@ -313,7 +327,6 @@ build_argv ( GpgObject gpg ) char **argv; int need_special = 0; int use_agent = !!getenv ("GPG_AGENT_INFO"); - if ( gpg->argv ) { free_argv ( gpg->argv ); @@ -583,6 +596,13 @@ _gpgme_gpg_spawn( GpgObject gpg, void *opaque ) for (i=0; gpg->fd_data_map[i].data; i++ ) { close (gpg->fd_data_map[i].peer_fd); gpg->fd_data_map[i].peer_fd = -1; + + /* Due to problems with select and write we set outbound pipes + * to non-blocking */ + if (!gpg->fd_data_map[i].inbound) { + set_nonblocking (gpg->fd_data_map[i].fd); + } + if ( _gpgme_register_pipe_handler ( opaque, gpg->fd_data_map[i].inbound? @@ -650,15 +670,29 @@ write_mem_data ( GpgmeData dh, int fd ) nbytes = dh->len - dh->readpos; if ( !nbytes ) { + fprintf (stderr, "write_mem_data(%d): closing\n", fd ); close (fd); return 1; } + /* FIXME: Arggg, the pipe blocks on large write request, although + * select told us that it is okay to write - need to figure out + * why this happens? Stevens says nothing about this problem (or + * is it my Linux kernel 2.4.0test1) + * To avoid that we have set the pipe to nonblocking. + */ + + do { + fprintf (stderr, "write_mem_data(%d): about to write %d bytes len=%d rpos=%d\n", + fd, (int)nbytes, (int)dh->len, dh->readpos ); nwritten = write ( fd, dh->data+dh->readpos, nbytes ); + fprintf (stderr, "write_mem_data(%d): wrote %d bytes\n", fd, nwritten ); } while ( nwritten == -1 && errno == EINTR ); + if (nwritten == -1 && errno == EAGAIN ) + return 0; if ( nwritten < 1 ) { - fprintf (stderr, "write_mem_data: write failed on fd %d (n=%d): %s\n", + fprintf (stderr, "write_mem_data(%d): write failed (n=%d): %s\n", fd, nwritten, strerror (errno) ); close (fd); return 1; diff --git a/gpgme/wait.c b/gpgme/wait.c index a3c50930..f54209d6 100644 --- a/gpgme/wait.c +++ b/gpgme/wait.c @@ -34,6 +34,14 @@ #include "ops.h" #include "wait.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 + /* Fixme: implement the following stuff to make the code MT safe. * To avoid the need to link against a specific threads lib, such * an implementation should require the caller to register a function @@ -243,23 +251,28 @@ the_big_select ( void ) FD_ZERO ( &readfds ); FD_ZERO ( &writefds ); max_fd = 0; + + + DEBUG_SELECT ((stderr, "gpgme:select on [ ")); lock_queue (); for ( q = wait_queue; q; q = q->next ) { if ( q->used && q->active ) { if (q->inbound) { assert ( !FD_ISSET ( q->fd, &readfds ) ); FD_SET ( q->fd, &readfds ); + DEBUG_SELECT ((stderr, "r%d ", q->fd )); } else { assert ( !FD_ISSET ( q->fd, &writefds ) ); FD_SET ( q->fd, &writefds ); + DEBUG_SELECT ((stderr, "w%d ", q->fd )); } if ( q->fd > max_fd ) max_fd = q->fd; } } unlock_queue (); - + DEBUG_SELECT ((stderr, "]\n" )); n = select ( max_fd+1, &readfds, &writefds, NULL, &timeout ); if ( n <= 0 ) { @@ -270,15 +283,40 @@ the_big_select ( void ) return 0; } +#if DEBUG_SELECT_ENABLED + { + int i; + + 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 ); + } + fprintf (stderr, "]\n" ); + } +#endif + /* something has to be done. Go over the queue and call * the handlers */ restart: while ( n ) { lock_queue (); for ( q = wait_queue; q; q = q->next ) { - if ( q->used && q->active - && FD_ISSET (q->fd, q->inbound? &readfds : &writefds ) ) { - FD_CLR (q->fd, q->inbound? &readfds : &writefds ); + if ( q->used && q->active && q->inbound + && FD_ISSET (q->fd, &readfds ) ) { + FD_CLR (q->fd, &readfds ); + assert (n); + n--; + unlock_queue (); + if ( q->handler (q->handler_value, q->pid, q->fd ) ) + q->active = 0; + goto restart; + } + if ( q->used && q->active && !q->inbound + && FD_ISSET (q->fd, &writefds ) ) { + FD_CLR (q->fd, &writefds ); assert (n); n--; unlock_queue (); diff --git a/tests/t-decrypt.c b/tests/t-decrypt.c index bf96112d..f98748da 100644 --- a/tests/t-decrypt.c +++ b/tests/t-decrypt.c @@ -50,6 +50,17 @@ print_data ( GpgmeData dh ) fail_if_err (err); } +#if 0 +static GpgmeData +passphrase_cb ( void *opaque, const char *description ) +{ + GpgmeData dh; + + assert (NULL); + gpgme_data_new_from_mem ( &dh, "abc", 3, 0 ); + return dh; +} +#endif static char * mk_fname ( const char *fname ) @@ -79,6 +90,11 @@ main (int argc, char **argv ) do { err = gpgme_new (&ctx); fail_if_err (err); +#if 0 + if ( !getenv("GPG_AGENT_INFO") { + gpgme_set_passphrase_cb ( ctx, passphrase_cb, NULL ); + } +#endif err = gpgme_data_new_from_file ( &in, cipher_1_asc, 1 ); fail_if_err (err); diff --git a/tests/t-sign.c b/tests/t-sign.c index 4d3ed340..c09b2c96 100644 --- a/tests/t-sign.c +++ b/tests/t-sign.c @@ -66,8 +66,8 @@ main (int argc, char **argv ) err = gpgme_data_new ( &out ); fail_if_err (err); - gpgme_op_set_textmode (ctx, 1); - gpgme_op_set_armor (ctx, 1); + gpgme_set_textmode (ctx, 1); + gpgme_set_armor (ctx, 1); err = gpgme_op_sign (ctx, in, out ); fail_if_err (err); diff --git a/tests/t-verify.c b/tests/t-verify.c index bc997236..ac9e3376 100644 --- a/tests/t-verify.c +++ b/tests/t-verify.c @@ -116,7 +116,7 @@ main (int argc, char **argv ) err = gpgme_op_verify (ctx, sig, text, &status ); print_sig_stat ( status ); fail_if_err (err); - if ( (nota=gpgme_op_get_notation (ctx)) ) + if ( (nota=gpgme_get_notation (ctx)) ) printf ("---Begin Notation---\n%s---End Notation---\n", nota ); puts ("checking a manipulated message:\n"); @@ -128,7 +128,7 @@ main (int argc, char **argv ) err = gpgme_op_verify (ctx, sig, text, &status ); print_sig_stat ( status ); fail_if_err (err); - if ( (nota=gpgme_op_get_notation (ctx)) ) + if ( (nota=gpgme_get_notation (ctx)) ) printf ("---Begin Notation---\n%s---End Notation---\n", nota ); gpgme_data_release (sig);