From f0dccac380b172291e7bea8a43cb0ec44b49c3bf Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 24 Feb 2009 15:13:01 +0000 Subject: [PATCH] Chnaged the op-assuan interface. --- NEWS | 1 - assuan/ChangeLog | 5 +++++ assuan/assuan-buffer.c | 7 ++++-- src/ChangeLog | 17 ++++++++++++++ src/engine-assuan.c | 46 ++++++++++++++++++-------------------- src/gpgme.h.in | 19 +++++++++------- src/opassuan.c | 22 +++++++++--------- tests/ChangeLog | 4 ++++ tests/opassuan/t-command.c | 38 +++++++++++++++++++++++++------ 9 files changed, 106 insertions(+), 53 deletions(-) diff --git a/NEWS b/NEWS index c2b812a7..3999bbb2 100644 --- a/NEWS +++ b/NEWS @@ -5,7 +5,6 @@ Noteworthy changes in version 1.1.9 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GPGME_PROTOCOL_ASSUAN NEW. gpgme_assuan_data_cb_t NEW. - gpgme_assuan_sendfnc_ctx_t NEW. gpgme_assuan_inquire_cb_t NEW. gpgme_assuan_status_cb_t NEW. gpgme_op_assuan_transact_start NEW. diff --git a/assuan/ChangeLog b/assuan/ChangeLog index cc39213c..e620d205 100644 --- a/assuan/ChangeLog +++ b/assuan/ChangeLog @@ -1,3 +1,8 @@ +2009-02-24 Werner Koch + + * assuan-buffer.c (assuan_send_data): Add hack to optionally send + a final "CAN". + 2008-11-03 Marcus Brinkmann * Makefile.am (INCLUDES): Replace gpgme path with src. diff --git a/assuan/assuan-buffer.c b/assuan/assuan-buffer.c index 1fad0b5e..31f33945 100644 --- a/assuan/assuan-buffer.c +++ b/assuan/assuan-buffer.c @@ -491,6 +491,9 @@ _assuan_cookie_write_flush (void *cookie) * a INQUIRE response. However, when assuan_transact() is used, this * function takes care of sending END itself. * + * If BUFFER is NULL and LENGTH is 1 and we are a client, a "CAN" is + * send instead of an "END". + * * Return value: 0 on success or an error code **/ @@ -499,7 +502,7 @@ assuan_send_data (assuan_context_t ctx, const void *buffer, size_t length) { if (!ctx) return _assuan_error (ASSUAN_Invalid_Value); - if (!buffer && length) + if (!buffer && length > 1) return _assuan_error (ASSUAN_Invalid_Value); if (!buffer) @@ -508,7 +511,7 @@ assuan_send_data (assuan_context_t ctx, const void *buffer, size_t length) if (ctx->outbound.data.error) return ctx->outbound.data.error; if (!ctx->is_server) - return assuan_write_line (ctx, "END"); + return assuan_write_line (ctx, length == 1? "CAN":"END"); } else { diff --git a/src/ChangeLog b/src/ChangeLog index 1cd86436..f78cb11e 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,20 @@ +2009-02-24 Werner Koch + + * gpgme.h.in (struct _gpgme_op_assuan_result): New. + (gpgme_assuan_result_t): New. + (gpgme_op_assuan_result): Change return type. + (struct _gpgme_assuan_sendfnc_ctx) + (gpgme_assuan_sendfnc_ctx_t, gpgme_assuan_sendfnc_t):Remove. + (gpgme_assuan_inquire_cb_t): Changed. + * opassuan.c (op_data_t): Make use of a result structure. + (gpgme_op_assuan_result): Change return type. + (opassuan_start): Use result structure. + (result_cb): Ditto. + * engine-assuan.c (struct _gpgme_assuan_sendfnc_ctx): Remove. + (inquire_cb_sendfnc): Remove. + (inquire_cb): Change for new callback scheme. Not yet finished. + (llass_status_handler): Allow sending a CANCEL from the inquire CB. + 2009-02-04 Werner Koch * w32-glib-io.c (_gpgme_io_spawn): Make ARGV argument const to diff --git a/src/engine-assuan.c b/src/engine-assuan.c index fb748689..bfe7a037 100644 --- a/src/engine-assuan.c +++ b/src/engine-assuan.c @@ -94,12 +94,6 @@ struct engine_llass }; typedef struct engine_llass *engine_llass_t; -/* Helper to pass data to a callback. */ -struct _gpgme_assuan_sendfnc_ctx -{ - assuan_context_t assuan_ctx; -}; - /* Prototypes. */ @@ -212,6 +206,8 @@ llass_new (void **engine, const char *file_name, const char *home_dir) { home_dir++; /* Very simple parser only working for the one option we support. */ + /* Note that wk promised to write a regression test if this + parser will be extended. */ if (!strncmp (home_dir, "GPG_AGENT", 9) && (!home_dir[9] || home_dir[9] == ' ')) llass->opt.gpg_agent = 1; @@ -372,18 +368,6 @@ llass_set_locale (void *engine, int category, const char *value) } - -static gpgme_error_t -inquire_cb_sendfnc (gpgme_assuan_sendfnc_ctx_t ctx, - const void *data, size_t datalen) -{ - if (data && datalen) - return assuan_send_data (ctx->assuan_ctx, data, datalen); - else - return 0; /* Don't allow an inquire to send a flush. */ -} - - /* This is the inquiry callback. It handles stuff which ee need to handle here and passes everything on to the user callback. */ static gpgme_error_t @@ -398,12 +382,18 @@ inquire_cb (engine_llass_t llass, const char *keyword, const char *args) if (llass->user.inq_cb) { - struct _gpgme_assuan_sendfnc_ctx sendfnc_ctx; + gpgme_data_t data = NULL; - sendfnc_ctx.assuan_ctx = llass->assuan_ctx; err = llass->user.inq_cb (llass->user.inq_cb_value, - keyword, args, - inquire_cb_sendfnc, &sendfnc_ctx); + keyword, args, &data); + if (!err && data) + { + /* FIXME: Returning data is not yet implemented. However we + need to allow the caller to cleanup his data object. + Thus we run the callback in finish mode immediately. */ + err = llass->user.inq_cb (llass->user.inq_cb_value, + NULL, NULL, &data); + } } else err = 0; @@ -528,8 +518,16 @@ llass_status_handler (void *opaque, int fd) args++; err = inquire_cb (llass, src, args); - if (!err) /* Flush and send END. */ - err = assuan_send_data (llass->assuan_ctx, NULL, 0); + if (!err) + { + /* Flush and send END. */ + err = assuan_send_data (llass->assuan_ctx, NULL, 0); + } + else if (gpg_err_code (err) == GPG_ERR_ASS_CANCELED) + { + /* Flush and send CANcel. */ + err = assuan_send_data (llass->assuan_ctx, NULL, 1); + } } else if (linelen >= 3 && line[0] == 'E' && line[1] == 'R' && line[2] == 'R' diff --git a/src/gpgme.h.in b/src/gpgme.h.in index e83b1fb1..2538aaf9 100644 --- a/src/gpgme.h.in +++ b/src/gpgme.h.in @@ -1671,21 +1671,24 @@ gpgme_error_t gpgme_op_getauditlog (gpgme_ctx_t ctx, gpgme_data_t output, typedef gpgme_error_t (*gpgme_assuan_data_cb_t) (void *opaque, const void *data, size_t datalen); -struct _gpgme_assuan_sendfnc_ctx; -typedef struct _gpgme_assuan_sendfnc_ctx *gpgme_assuan_sendfnc_ctx_t; -typedef gpgme_error_t (*gpgme_assuan_sendfnc_t) - (gpgme_assuan_sendfnc_ctx_t ctx, const void *data, size_t datalen); - typedef gpgme_error_t (*gpgme_assuan_inquire_cb_t) (void *opaque, const char *name, const char *args, - gpgme_assuan_sendfnc_t sendfnc, - gpgme_assuan_sendfnc_ctx_t sendfnc_ctx); + gpgme_data_t *r_data); typedef gpgme_error_t (*gpgme_assuan_status_cb_t) (void *opaque, const char *status, const char *args); +struct _gpgme_op_assuan_result +{ + /* The result of the actual assuan command. An OK is indicated by a + value of 0 and an ERR by the respective error error value. */ + gpgme_error_t err; +}; +typedef struct _gpgme_op_assuan_result *gpgme_assuan_result_t; + + /* Return the result of the last Assuan command. */ -gpgme_error_t gpgme_op_assuan_result (gpgme_ctx_t ctx); +gpgme_assuan_result_t gpgme_op_assuan_result (gpgme_ctx_t ctx); /* Send the Assuan COMMAND and return results via the callbacks. Asynchronous variant. */ diff --git a/src/opassuan.c b/src/opassuan.c index f07dade6..09f69ee8 100644 --- a/src/opassuan.c +++ b/src/opassuan.c @@ -26,11 +26,11 @@ #include "ops.h" #include "util.h" + typedef struct { - /* The result of the assuan command with 0 for OK and an error value - for ERR. */ - gpgme_error_t result; + struct _gpgme_op_assuan_result result; + } *op_data_t; @@ -55,12 +55,12 @@ result_cb (void *priv, gpgme_error_t result) if (!opd) return gpg_error (GPG_ERR_INTERNAL); - opd->result = result; + opd->result.err = result; return 0; } -gpgme_error_t +gpgme_assuan_result_t gpgme_op_assuan_result (gpgme_ctx_t ctx) { gpgme_error_t err; @@ -69,12 +69,12 @@ gpgme_op_assuan_result (gpgme_ctx_t ctx) err = _gpgme_op_data_lookup (ctx, OPDATA_ASSUAN, &hook, -1, NULL); opd = hook; - if (err) - return err; - if (!opd) - return gpg_error (GPG_ERR_INTERNAL); + /* Check in case this function is used without having run a command + before. */ + if (err || !opd) + return NULL; - return opd->result; + return &opd->result; } @@ -105,7 +105,7 @@ opassuan_start (gpgme_ctx_t ctx, int synchronous, opd = hook; if (err) return err; - opd->result = gpg_error (GPG_ERR_UNFINISHED); + opd->result.err = gpg_error (GPG_ERR_UNFINISHED); return _gpgme_engine_op_assuan_transact (ctx->engine, command, result_cb, ctx, diff --git a/tests/ChangeLog b/tests/ChangeLog index efd756c4..027afccf 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,7 @@ +2009-02-24 Werner Koch + + * opassuan/t-command.c: Adjust for changed new op_assuan interface. + 2009-02-03 Werner Koch * gpg/t-keylist.c (main): Check that new fields is_cardkey and diff --git a/tests/opassuan/t-command.c b/tests/opassuan/t-command.c index b6a2d904..161b8a84 100644 --- a/tests/opassuan/t-command.c +++ b/tests/opassuan/t-command.c @@ -24,6 +24,7 @@ #include #include #include +#include #include @@ -52,10 +53,36 @@ data_cb (void *opaque, const void *data, size_t datalen) static gpg_error_t inq_cb (void *opaque, const char *name, const char *args, - gpgme_assuan_sendfnc_t sendfnc, - gpgme_assuan_sendfnc_ctx_t sendfnc_value) + gpgme_data_t *r_data) { - printf ("INQ_CB: name=`%s' args=`%s'\n", name, args); + gpgme_data_t data; + gpg_error_t err; + + if (name) + { + printf ("INQ_CB: name=`%s' args=`%s'\n", name, args); + /* There shall be no data object. */ + assert (!*r_data); + + err = gpgme_data_new (&data); + fail_if_err (err); + *r_data = data; + printf (" sending data object %p\n", data); + } + else /* Finished using the formerly returned data object. */ + { + printf ("INQ_CB: data object %p finished\n", *r_data); + /* There shall be a data object so that it can be cleaned up. */ + assert (r_data); + + gpgme_data_release (*r_data); + } + + /* Uncomment the next lines and send a "SCD LEARN" to test sending + cancel from in inquiry. */ + /* if (name && !strcmp (name, "KNOWNCARDP")) */ + /* return gpg_error (GPG_ERR_ASS_CANCELED); */ + return 0; } @@ -70,9 +97,6 @@ status_cb (void *opaque, const char *status, const char *args) - - - int main (int argc, char **argv) { @@ -106,7 +130,7 @@ main (int argc, char **argv) inq_cb, NULL, status_cb, NULL); fail_if_err (err); - err = gpgme_op_assuan_result (ctx); + err = gpgme_op_assuan_result (ctx)->err; if (err) fprintf (stderr, "assuan command `%s' failed: %s <%s> (%d)\n", command, gpg_strerror (err), gpg_strsource (err), err);