#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@
# 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)
int verbosity; /* level of verbosity to use */
int use_armor;
int use_textmode;
+
+ /* GpgmePassphraseCb passphrase_cb;*/
+ /* void * passphrase_cb_value;*/
ResultType result_type;
union {
char *
-gpgme_op_get_notation ( GpgmeCtx c )
+gpgme_get_notation ( GpgmeCtx c )
{
if ( !c->notation )
return NULL;
void
-gpgme_op_set_armor ( GpgmeCtx c, int yes )
+gpgme_set_armor ( GpgmeCtx c, int yes )
{
if ( !c )
return; /* oops */
}
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
* 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"
GPGME_SIG_STAT_ERROR = 5
} GpgmeSigStat;
+/*typedef GpgmeData (*GpgmePassphraseCb)( void *opaque, const char *desc );*/
/* Context management */
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 */
}
+
+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 )
{
char **argv;
int need_special = 0;
int use_agent = !!getenv ("GPG_AGENT_INFO");
-
if ( gpg->argv ) {
free_argv ( gpg->argv );
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?
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;
#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
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 ) {
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 ();
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 )
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);
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);
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");
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);