From 679d5c2b49fc26eb343de2958a0d7fe10a424fff Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann Date: Thu, 22 Nov 2001 03:08:58 +0000 Subject: [PATCH] 2001-11-22 Marcus Brinkmann * rungpg.c (gpg_inbound_handler, write_mem_data, write_cb_data, gpg_outbound_handler): Moved to ... * data.c (_gpgme_data_inbound_handler, write_mem_data, write_cb_data, _gpgme_data_outbound_handler): ... here. Make the _gpgme_* ones non-static. * data.c: Include io.h. * ops.h (_gpgme_data_inbound_handler): New prototype. (_gpgme_data_outbound_handler): Likewise. (_gpgme_gpg_spawn): Use these new functions. * engine-gpgsm.h (_gpgme_gpgsm_op_decrypt, _gpgme_gpgsm_op_delete, _gpgme_gpgsm_op_encrypt, _gpgme_gpgsm_op_export, _gpgme_gpgsm_op_genkey, _gpgme_gpgsm_op_import, _gpgme_gpgsm_op_keylist, _gpgme_gpgsm_op_sign, _gpgme_gpgsm_op_trustlist, _gpgme_gpgsm_op_verify, _gpgme_gpgsm_start, _gpgme_gpgsm_set_status_handler): New prototype. Include for status handler function. * engine-gpgsm.c (struct gpgsm_object_s): New members input_fd, input_data, output_fd, output_data, message_fd, message_data, command and status. (_gpgme_gpgsm_new): Open input, output and message pipes before connecting to the client. Close server's ends afterwards. (_gpgme_gpgsm_release): Close open file descriptors. Remove server process from wait queue. (_gpgme_gpgsm_op_verify, _gpgme_gpgsm_start, _gpgme_gpgsm_set_status_handler, gpgms_status_handler): New function. * engine.c (_gpgme_engine_start): Implement for GPGME_PROTOCOL_CMS. (_gpgme_engine_set_status_handler): Likewise. (_gpgme_engine_op_verify): Likewise. --- gpgme/ChangeLog | 35 +++++++ gpgme/data.c | 139 +++++++++++++++++++++++++- gpgme/engine-gpgsm.c | 233 +++++++++++++++++++++++++++++++++++++++++-- gpgme/engine-gpgsm.h | 23 +++++ gpgme/engine.c | 8 +- gpgme/ops.h | 3 + gpgme/rungpg.c | 134 +------------------------ 7 files changed, 427 insertions(+), 148 deletions(-) diff --git a/gpgme/ChangeLog b/gpgme/ChangeLog index 2ee8f900..d2707521 100644 --- a/gpgme/ChangeLog +++ b/gpgme/ChangeLog @@ -1,3 +1,38 @@ +2001-11-22 Marcus Brinkmann + + * rungpg.c (gpg_inbound_handler, write_mem_data, write_cb_data, + gpg_outbound_handler): Moved to ... + * data.c (_gpgme_data_inbound_handler, write_mem_data, + write_cb_data, _gpgme_data_outbound_handler): ... here. Make the + _gpgme_* ones non-static. + * data.c: Include io.h. + + * ops.h (_gpgme_data_inbound_handler): New prototype. + (_gpgme_data_outbound_handler): Likewise. + (_gpgme_gpg_spawn): Use these new functions. + + * engine-gpgsm.h (_gpgme_gpgsm_op_decrypt, _gpgme_gpgsm_op_delete, + _gpgme_gpgsm_op_encrypt, _gpgme_gpgsm_op_export, + _gpgme_gpgsm_op_genkey, _gpgme_gpgsm_op_import, + _gpgme_gpgsm_op_keylist, _gpgme_gpgsm_op_sign, + _gpgme_gpgsm_op_trustlist, _gpgme_gpgsm_op_verify, + _gpgme_gpgsm_start, _gpgme_gpgsm_set_status_handler): New prototype. + Include for status handler function. + + * engine-gpgsm.c (struct gpgsm_object_s): New members input_fd, + input_data, output_fd, output_data, message_fd, message_data, command + and status. + (_gpgme_gpgsm_new): Open input, output and message pipes before + connecting to the client. Close server's ends afterwards. + (_gpgme_gpgsm_release): Close open file descriptors. Remove + server process from wait queue. + (_gpgme_gpgsm_op_verify, _gpgme_gpgsm_start, + _gpgme_gpgsm_set_status_handler, gpgms_status_handler): New function. + + * engine.c (_gpgme_engine_start): Implement for GPGME_PROTOCOL_CMS. + (_gpgme_engine_set_status_handler): Likewise. + (_gpgme_engine_op_verify): Likewise. + 2001-11-21 Marcus Brinkmann * context.h: Do not include rungpg.h, but engine.h. diff --git a/gpgme/data.c b/gpgme/data.c index 6ba853d8..a17ea1d2 100644 --- a/gpgme/data.c +++ b/gpgme/data.c @@ -32,6 +32,7 @@ #include "util.h" #include "context.h" #include "ops.h" +#include "io.h" #define ALLOC_CHUNK 1024 #define my_isdigit(a) ( (a) >='0' && (a) <= '9' ) @@ -757,9 +758,6 @@ hextobyte( const byte *s ) return c; } - - - /* * Append a string with percent style (%XX) escape characters as XML */ @@ -785,3 +783,138 @@ _gpgme_data_append_percentstring_for_xml ( GpgmeData dh, const char *string ) xfree (buf); return err; } + +/* Functions to support the wait interface. */ + +int +_gpgme_data_inbound_handler (void *opaque, int pid, int fd) +{ + GpgmeData dh = opaque; + GpgmeError err; + int nread; + char buf[200]; + + assert (_gpgme_data_get_mode (dh) == GPGME_DATA_MODE_IN); + + nread = _gpgme_io_read (fd, buf, 200); + if (nread < 0) + { + DEBUG3 ("read_mem_data: read failed on fd %d (n=%d): %s", + fd, nread, strerror (errno) ); + return 1; + } + else if (!nread) + return 1; /* eof */ + + /* We could improve this with a GpgmeData function which takes + * the read function or provides a memory area for writing to it. + */ + + err = _gpgme_data_append (dh, buf, nread); + if (err) + { + 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 */ + return 1; + } + + return 0; +} + +static int +write_mem_data (GpgmeData dh, int fd) +{ + size_t nbytes; + int nwritten; + + nbytes = dh->len - dh->readpos; + if (!nbytes) + { + _gpgme_io_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. + */ + + nwritten = _gpgme_io_write (fd, dh->data+dh->readpos, nbytes); + if (nwritten == -1 && errno == EAGAIN) + return 0; + if (nwritten < 1) + { + DEBUG3 ("write_mem_data(%d): write failed (n=%d): %s", + fd, nwritten, strerror (errno)); + _gpgme_io_close (fd); + return 1; + } + + dh->readpos += nwritten; + return 0; +} + +static int +write_cb_data (GpgmeData dh, int fd) +{ + size_t nbytes; + int err, nwritten; + char buffer[512]; + + err = gpgme_data_read (dh, buffer, DIM(buffer), &nbytes); + if (err == GPGME_EOF) + { + _gpgme_io_close (fd); + return 1; + } + + nwritten = _gpgme_io_write (fd, buffer, nbytes); + if (nwritten == -1 && errno == EAGAIN ) + return 0; + if (nwritten < 1) + { + DEBUG3 ("write_cb_data(%d): write failed (n=%d): %s", + fd, nwritten, strerror (errno)); + _gpgme_io_close (fd); + return 1; + } + + if (nwritten < nbytes) + { + /* ugly, ugly: It does currently only for for MEM type data */ + if (_gpgme_data_unread (dh, buffer + nwritten, nbytes - nwritten)) + DEBUG1 ("wite_cb_data: unread of %d bytes failed\n", + nbytes - nwritten); + _gpgme_io_close (fd); + return 1; + } + + return 0; +} + +int +_gpgme_data_outbound_handler (void *opaque, int pid, int fd) +{ + GpgmeData dh = opaque; + + assert (_gpgme_data_get_mode (dh) == GPGME_DATA_MODE_OUT); + switch (gpgme_data_get_type (dh)) + { + case GPGME_DATA_TYPE_MEM: + if (write_mem_data (dh, fd)) + return 1; /* ready */ + break; + case GPGME_DATA_TYPE_CB: + if (write_cb_data (dh, fd)) + return 1; /* ready */ + break; + default: + assert (0); + } + + return 0; +} diff --git a/gpgme/engine-gpgsm.c b/gpgme/engine-gpgsm.c index 000ad116..87a00393 100644 --- a/gpgme/engine-gpgsm.c +++ b/gpgme/engine-gpgsm.c @@ -23,13 +23,6 @@ #include #endif -#include "gpgme.h" -#include "util.h" -#include "types.h" -#include "ops.h" - -#include "engine-gpgsm.h" - /* FIXME: Correct check? */ #ifdef GPGSM_PATH #define ENABLE_GPGSM 1 @@ -37,11 +30,50 @@ #ifdef ENABLE_GPGSM +#include +#include + +/* FIXME */ +#include "../assuan/assuan-defs.h" +#undef xtrymalloc +#undef xtrycalloc +#undef xtryrealloc +#undef xfree + +#include "gpgme.h" +#include "util.h" +#include "types.h" +#include "ops.h" +#include "wait.h" +#include "io.h" + +#include "engine-gpgsm.h" + #include "assuan.h" struct gpgsm_object_s { ASSUAN_CONTEXT assuan_ctx; + + /* Input, output etc are from the servers perspective. */ + int input_fd; + int input_fd_server; + GpgmeData input_data; + int output_fd; + int output_fd_server; + GpgmeData output_data; + int message_fd; + int message_fd_server; + GpgmeData message_data; + + char *command; + + struct + { + GpgStatusHandler fnc; + void *fnc_value; + } status; + }; const char * @@ -70,6 +102,9 @@ _gpgme_gpgsm_new (GpgsmObject *r_gpgsm) GpgmeError err = 0; GpgsmObject gpgsm; char *argv[] = { "gpgsm", "--server", NULL }; + int ip[2] = { -1, -1 }; + int op[2] = { -1, -1 }; + int mp[2] = { -1, -1 }; *r_gpgsm = NULL; gpgsm = xtrycalloc (1, sizeof *gpgsm); @@ -79,10 +114,39 @@ _gpgme_gpgsm_new (GpgsmObject *r_gpgsm) goto leave; } + if (_gpgme_io_pipe (ip, 0) < 0) + { + err = mk_error (General_Error); + goto leave; + } + gpgsm->input_fd = ip[1]; + gpgsm->input_fd_server = ip[0]; + if (_gpgme_io_pipe (op, 1) < 0) + { + err = mk_error (General_Error); + goto leave; + } + gpgsm->output_fd = op[0]; + gpgsm->output_fd_server = op[1]; + if (_gpgme_io_pipe (mp, 0) < 0) + { + err = mk_error (General_Error); + goto leave; + } + gpgsm->message_fd = mp[1]; + gpgsm->message_fd_server = mp[0]; + err = assuan_pipe_connect (&gpgsm->assuan_ctx, _gpgme_get_gpgsm_path (), argv); leave: + if (ip[0] != -1) + _gpgme_io_close (ip[0]); + if (op[1] != -1) + _gpgme_io_close (op[1]); + if (mp[0] != -1) + _gpgme_io_close (mp[0]); + if (err) _gpgme_gpgsm_release (gpgsm); else @@ -94,13 +158,156 @@ _gpgme_gpgsm_new (GpgsmObject *r_gpgsm) void _gpgme_gpgsm_release (GpgsmObject gpgsm) { + pid_t pid; + if (!gpgsm) return; + pid = assuan_get_pid (gpgsm->assuan_ctx); + if (pid != -1) + _gpgme_remove_proc_from_wait_queue (pid); + + if (gpgsm->input_fd != -1) + _gpgme_io_close (gpgsm->input_fd); + if (gpgsm->output_fd != -1) + _gpgme_io_close (gpgsm->output_fd); + if (gpgsm->message_fd != -1) + _gpgme_io_close (gpgsm->message_fd); + assuan_pipe_disconnect (gpgsm->assuan_ctx); xfree (gpgsm); } +#define COMMANDLINELEN 40 +static AssuanError +gpgsm_set_fd (ASSUAN_CONTEXT ctx, const char *which, int fd) +{ + AssuanError err; + char line[COMMANDLINELEN]; + + snprintf (line, COMMANDLINELEN, "%s FD=%i", which, fd); + err = _assuan_write_line (ctx, line); + if (err) + return err; + + do + { + err = _assuan_read_line (ctx); + if (err) + return err; + } + while (*ctx->inbound.line == '#' || !ctx->inbound.linelen); + + if (ctx->inbound.linelen >= 2 + && ctx->inbound.line[0] == 'O' && ctx->inbound.line[1] == 'K' + && (ctx->inbound.line[2] == '\0' || ctx->inbound.line[2] == ' ')) + return 0; + else + return ASSUAN_General_Error; +} + +GpgmeError +_gpgme_gpgsm_op_verify (GpgsmObject gpgsm, GpgmeData sig, GpgmeData text) +{ + AssuanError err; + + if (!gpgsm) + return mk_error (Invalid_Value); + + gpgsm->input_data = sig; + err = gpgsm_set_fd (gpgsm->assuan_ctx, "INPUT", gpgsm->input_fd_server); + if (err) + return mk_error (General_Error); /* FIXME */ + gpgsm->message_data = sig; + err = gpgsm_set_fd (gpgsm->assuan_ctx, "MESSAGE", gpgsm->message_fd_server); + if (err) + return mk_error (General_Error); /* FIXME */ + _gpgme_io_close (gpgsm->output_fd); + gpgsm->output_fd = -1; + + gpgsm->command = "VERIFY"; + return 0; +} + +static int +gpgsm_status_handler (void *opaque, int pid, int fd) +{ + int err; + GpgsmObject gpgsm = opaque; + ASSUAN_CONTEXT actx = gpgsm->assuan_ctx; + + assert (fd == gpgsm->assuan_ctx->inbound.fd); + + err = _assuan_read_line (gpgsm->assuan_ctx); + + if (actx->inbound.line[0] == '#' || !actx->inbound.linelen) + return 0; /* FIXME */ + + if (actx->inbound.linelen >= 2 + && actx->inbound.line[0] == 'O' && actx->inbound.line[1] == 'K' + && (actx->inbound.line[2] == '\0' || actx->inbound.line[2] == ' ')) + { + if (gpgsm->status.fnc) + gpgsm->status.fnc (gpgsm->status.fnc_value, STATUS_EOF, ""); + return 1; + } + /* FIXME: Parse the status and call the handler. */ + + fprintf (stderr, "[UNCAUGHT STATUS]%s", actx->inbound.line); + return 0; +} + +void +_gpgme_gpgsm_set_status_handler (GpgsmObject gpgsm, + GpgStatusHandler fnc, void *fnc_value) +{ + assert (gpgsm); + + gpgsm->status.fnc = fnc; + gpgsm->status.fnc_value = fnc_value; +} + +GpgmeError +_gpgme_gpgsm_start (GpgsmObject gpgsm, void *opaque) +{ + GpgmeError err = 0; + pid_t pid; + + if (!gpgsm) + return mk_error (Invalid_Value); + + pid = assuan_get_pid (gpgsm->assuan_ctx); + + err = _gpgme_register_pipe_handler (opaque, gpgsm_status_handler, gpgsm, pid, + gpgsm->assuan_ctx->inbound.fd, 1); + + if (gpgsm->input_fd != -1) + { + err = _gpgme_register_pipe_handler (opaque, _gpgme_data_outbound_handler, + gpgsm->input_data, pid, + gpgsm->input_fd, 0); + if (!err) /* FIXME Kludge around poll() problem. */ + err = _gpgme_io_set_nonblocking (gpgsm->input_fd); + } + if (!err && gpgsm->output_fd != -1) + err = _gpgme_register_pipe_handler (opaque, _gpgme_data_inbound_handler, + gpgsm->output_data, pid, + gpgsm->output_fd, 1); + if (!err && gpgsm->message_fd != -1) + { + err = _gpgme_register_pipe_handler (opaque, _gpgme_data_outbound_handler, + gpgsm->message_data, pid, + gpgsm->message_fd, 0); + if (!err) /* FIXME Kludge around poll() problem. */ + err = _gpgme_io_set_nonblocking (gpgsm->message_fd); + } + + if (!err) + err = _assuan_write_line (gpgsm->assuan_ctx, gpgsm->command); + + return err; +} + #else /* ENABLE_GPGSM */ const char * @@ -127,4 +334,16 @@ _gpgme_gpgsm_release (GpgsmObject gpgsm) return; } +GpgmeError + _gpgme_gpgsm_op_verify (GpgsmObject gpgsm, GpgmeData sig, GpgmeData text) +{ + return mk_error (Invalid_Engine); +} + +GpgmeError +_gpgme_gpgsm_start (GpgsmObject gpgsm, void *opaque) +{ + return mk_error (Invalid_Engine); +} + #endif /* ! ENABLE_GPGSM */ diff --git a/gpgme/engine-gpgsm.h b/gpgme/engine-gpgsm.h index 105405bd..5feada86 100644 --- a/gpgme/engine-gpgsm.h +++ b/gpgme/engine-gpgsm.h @@ -23,6 +23,7 @@ #define ENGINE_GPGSM_H #include "types.h" +#include "rungpg.h" /* FIXME statusHandler */ const char *_gpgme_gpgsm_get_version (void); GpgmeError _gpgme_gpgsm_check_version (void); @@ -30,4 +31,26 @@ GpgmeError _gpgme_gpgsm_check_version (void); GpgmeError _gpgme_gpgsm_new (GpgsmObject *r_gpg); void _gpgme_gpgsm_release (GpgsmObject gpg); +void _gpgme_gpgsm_set_status_handler (GpgsmObject gpgsm, + GpgStatusHandler fnc, void *fnc_value); +GpgmeError _gpgme_gpgsm_op_decrypt (GpgsmObject gpgsm, GpgmeData ciph, + GpgmeData plain); +GpgmeError _gpgme_gpgsm_op_delete (GpgsmObject gpgsm, GpgmeKey key, int allow_secret); +GpgmeError _gpgme_gpgsm_op_encrypt (GpgsmObject gpgsm, GpgmeRecipients recp, + GpgmeData plain, GpgmeData ciph, + int use_armor); +GpgmeError _gpgme_gpgsm_op_export (GpgsmObject gpgsm, GpgmeRecipients recp, + GpgmeData keydata, int use_armor); +GpgmeError _gpgme_gpgsm_op_genkey (GpgsmObject gpgsm, GpgmeData help_data, + int use_armor); +GpgmeError _gpgme_gpgsm_op_import (GpgsmObject gpgsm, GpgmeData keydata); +GpgmeError _gpgme_gpgsm_op_keylist (GpgsmObject gpgsm, const char *pattern, + int secret_only, int keylist_mode); +GpgmeError _gpgme_gpgsm_op_sign (GpgsmObject gpgsm, GpgmeData in, GpgmeData out, + GpgmeSigMode mode, int use_armor, + int use_textmode, GpgmeCtx ctx /* FIXME */); +GpgmeError _gpgme_gpgsm_op_trustlist (GpgsmObject gpgsm, const char *pattern); +GpgmeError _gpgme_gpgsm_op_verify (GpgsmObject gpgsm, GpgmeData sig, GpgmeData text); +GpgmeError _gpgme_gpgsm_start (GpgsmObject gpgsm, void *opaque); + #endif /* ENGINE_GPGSM_H */ diff --git a/gpgme/engine.c b/gpgme/engine.c index 29c91504..74951058 100644 --- a/gpgme/engine.c +++ b/gpgme/engine.c @@ -189,7 +189,7 @@ _gpgme_engine_set_status_handler (EngineObject engine, _gpgme_gpg_set_status_handler (engine->engine.gpg, fnc, fnc_value); break; case GPGME_PROTOCOL_CMS: - /* FIXME */ + _gpgme_gpgsm_set_status_handler (engine->engine.gpgsm, fnc, fnc_value); break; default: break; @@ -428,8 +428,7 @@ _gpgme_engine_op_verify (EngineObject engine, GpgmeData sig, GpgmeData text) case GPGME_PROTOCOL_OpenPGP: return _gpgme_gpg_op_verify (engine->engine.gpg, sig, text); case GPGME_PROTOCOL_CMS: - /* FIXME */ - break; + return _gpgme_gpgsm_op_verify (engine->engine.gpgsm, sig, text); default: break; } @@ -446,8 +445,7 @@ GpgmeError _gpgme_engine_start (EngineObject engine, void *opaque) case GPGME_PROTOCOL_OpenPGP: return _gpgme_gpg_spawn (engine->engine.gpg, opaque); case GPGME_PROTOCOL_CMS: - /* FIXME */ - break; + return _gpgme_gpgsm_start (engine->engine.gpgsm, opaque); default: break; } diff --git a/gpgme/ops.h b/gpgme/ops.h index 044bcef5..93103b57 100644 --- a/gpgme/ops.h +++ b/gpgme/ops.h @@ -59,6 +59,9 @@ GpgmeError _gpgme_data_append_percentstring_for_xml ( GpgmeData dh, GpgmeError _gpgme_data_unread (GpgmeData dh, const char *buffer, size_t length ); +int _gpgme_data_inbound_handler (void *opaque, int pid, int fd); +int _gpgme_data_outbound_handler (void *opaque, int pid, int fd); + /*-- key.c --*/ GpgmeError _gpgme_key_new ( GpgmeKey *r_key ); diff --git a/gpgme/rungpg.c b/gpgme/rungpg.c index 940f971b..d1c50cc8 100644 --- a/gpgme/rungpg.c +++ b/gpgme/rungpg.c @@ -132,9 +132,6 @@ DEFINE_STATIC_LOCK (reap_list_lock); static void free_argv ( char **argv ); static void free_fd_data_map ( struct fd_data_map_s *fd_data_map ); -static int gpg_inbound_handler ( void *opaque, int pid, int fd ); -static int gpg_outbound_handler ( void *opaque, int pid, int fd ); - static int gpg_status_handler ( void *opaque, int pid, int fd ); static GpgmeError read_status ( GpgObject gpg ); @@ -919,7 +916,7 @@ _gpgme_gpg_spawn( GpgObject gpg, void *opaque ) if ( _gpgme_register_pipe_handler ( opaque, gpg->fd_data_map[i].inbound? - gpg_inbound_handler:gpg_outbound_handler, + _gpgme_data_inbound_handler:_gpgme_data_outbound_handler, gpg->fd_data_map[i].data, pid, gpg->fd_data_map[i].fd, gpg->fd_data_map[i].inbound ) @@ -939,135 +936,6 @@ _gpgme_gpg_spawn( GpgObject gpg, void *opaque ) } -static int -gpg_inbound_handler ( void *opaque, int pid, int fd ) -{ - GpgmeData dh = opaque; - GpgmeError err; - int nread; - char buf[200]; - - assert ( _gpgme_data_get_mode (dh) == GPGME_DATA_MODE_IN ); - - nread = _gpgme_io_read (fd, buf, 200 ); - if ( nread < 0 ) { - DEBUG3 ("read_mem_data: read failed on fd %d (n=%d): %s", - fd, nread, strerror (errno) ); - return 1; - } - else if (!nread) - return 1; /* eof */ - - /* We could improve this with a GpgmeData function which takes - * the read function or provides a memory area for writing to it. - */ - - err = _gpgme_data_append ( dh, buf, nread ); - if ( err ) { - 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 */ - return 1; - } - - return 0; -} - - -static int -write_mem_data ( GpgmeData dh, int fd ) -{ - size_t nbytes; - int nwritten; - - nbytes = dh->len - dh->readpos; - if ( !nbytes ) { - _gpgme_io_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. - */ - - nwritten = _gpgme_io_write ( fd, dh->data+dh->readpos, nbytes ); - if (nwritten == -1 && errno == EAGAIN ) - return 0; - if ( nwritten < 1 ) { - DEBUG3 ("write_mem_data(%d): write failed (n=%d): %s", - fd, nwritten, strerror (errno) ); - _gpgme_io_close (fd); - return 1; - } - - dh->readpos += nwritten; - return 0; -} - -static int -write_cb_data ( GpgmeData dh, int fd ) -{ - size_t nbytes; - int err, nwritten; - char buffer[512]; - - err = gpgme_data_read ( dh, buffer, DIM(buffer), &nbytes ); - if (err == GPGME_EOF) { - _gpgme_io_close (fd); - return 1; - } - - nwritten = _gpgme_io_write ( fd, buffer, nbytes ); - if (nwritten == -1 && errno == EAGAIN ) - return 0; - if ( nwritten < 1 ) { - DEBUG3 ("write_cb_data(%d): write failed (n=%d): %s", - fd, nwritten, strerror (errno) ); - _gpgme_io_close (fd); - return 1; - } - - if ( nwritten < nbytes ) { - /* ugly, ugly: It does currently only for for MEM type data */ - if ( _gpgme_data_unread (dh, buffer + nwritten, nbytes - nwritten ) ) - DEBUG1 ("wite_cb_data: unread of %d bytes failed\n", - nbytes - nwritten ); - _gpgme_io_close (fd); - return 1; - } - - return 0; -} - - -static int -gpg_outbound_handler ( void *opaque, int pid, int fd ) -{ - GpgmeData dh = opaque; - - assert ( _gpgme_data_get_mode (dh) == GPGME_DATA_MODE_OUT ); - switch ( gpgme_data_get_type (dh) ) { - case GPGME_DATA_TYPE_MEM: - if ( write_mem_data ( dh, fd ) ) - return 1; /* ready */ - break; - case GPGME_DATA_TYPE_CB: - if (write_cb_data (dh, fd)) - return 1; /* ready */ - break; - default: - assert (0); - } - - return 0; -} - - - static int gpg_status_handler ( void *opaque, int pid, int fd ) {