diff --git a/NEWS b/NEWS index 53753286..27bcb132 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,10 @@ current setting, a fucntion gpgme_get_keylist_mode was added to retrieve the current mode. + * gpgme_wait accepts a new argument STATUS to return the error status + of the operation on the context. Its definition is closer to + waitpid() now than before. + * The LENGTH argument to gpgme_data_new_from_filepart changed its type from off_t to the unsigned size_t. @@ -27,6 +31,7 @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gpgme_data_new_from_filepart CHANGED: Type of LENGTH is size_t. GpgmePassphraseCb CHANGED: Type of R_HD is void **. +gpgme_wait CHANGED: New argument STATUS. gpgme_set_keylist_mode CHANGED: Type of return value is GpgmeError. The function has a new meaning! gpgme_get_keylist_mode NEW diff --git a/TODO b/TODO index 7eb7de96..ac886cf6 100644 --- a/TODO +++ b/TODO @@ -1,11 +1,6 @@ Hey Emacs, this is -*- outline -*- mode! * ABI's to break: -** The resulting error of an operation can not be retrieved - seperately; the op_foobar operations can't be implemented by the - user, they are not merely convenience, but necessity, while the - op_foobar_start functions for these are unusable (or render the - context unusable, your choice). ** string representation of non-secret keys and ATTR_IS_SECRET is NULL, which can not be differentiated from the case that it is not representable. diff --git a/doc/ChangeLog b/doc/ChangeLog index ce4bf44c..5b617efa 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,8 @@ +2002-02-06 Marcus Brinkmann + + * gpgme.texi (Waiting For Completion): Adjust doc to changes in + the code. + 2002-02-06 Marcus Brinkmann * gpgme.texi (Key Listing Mode): Update documentation. diff --git a/doc/gpgme.texi b/doc/gpgme.texi index e2f68ef8..2b4cf5a0 100644 --- a/doc/gpgme.texi +++ b/doc/gpgme.texi @@ -1337,7 +1337,7 @@ This is the type of a trust item. @item GPGME_ATTR_IS_SECRET This specifies if the key is a secret key. It is representable as a string or a number. If the key is a secret key, the representation is -``1'' or @code{1}, otherwise it is NULL or @code{0}. +``1'' or @code{1}, otherwise it is @code{NULL} or @code{0}. @item GPGME_ATTR_KEY_REVOKED This specifies if a sub key is revoked. It is representable as a @@ -2233,7 +2233,7 @@ later point. @cindex cryptographic operation, wait for @cindex wait for completion -@deftypefun GpgmeCtx gpgme_wait (@w{GpgmeCtx @var{ctx}}, @w{int @var{hang}}) +@deftypefun GpgmeCtx gpgme_wait (@w{GpgmeCtx @var{ctx}}, @w{GpgmeError *@var{status}}, @w{int @var{hang}}) The function @code{gpgme_wait} does continue the pending operation within the context @var{ctx}. In particular, it ensures the data exchange between @acronym{GPGME} and the crypto backend and watches @@ -2243,7 +2243,14 @@ If @var{hang} is true, the function does not return until the operation is completed or cancelled. Otherwise the function will not block for a long time. -The function returns @var{ctx}. +The error status of the finished operation is returned in +@var{status}. + +The @var{ctx} argument can be @code{NULL}. In that case, +@code{gpgme_wait} waits for any context to complete its operation. + +The function returns the @var{ctx} of the context which has finished +the operation. @end deftypefun diff --git a/gpgme/ChangeLog b/gpgme/ChangeLog index 05cae535..8d0a863f 100644 --- a/gpgme/ChangeLog +++ b/gpgme/ChangeLog @@ -1,3 +1,21 @@ +2002-02-06 Marcus Brinkmann + + * wait.c (gpgme_wait): Add new argument STATUS, in which the + status of the returned context is returned. + (_gpgme_wait_on_condition): Rework the function a bit, to make it + aware of cancelled processes, and to allow to use gpgme_wait with + CTX being NULL (as documented in the source). + (struct proc_s): New member REPORTED. + * gpgme.h: Fix prototype. + * verify.c (gpgme_op_verify): Fix use of gpgme_wait. + * sign.c (gpgme_op_sign): + * import.c (gpgme_op_import): + * genkey.c (gpgme_op_genkey): + * export.c (gpgme_op_export): + * encrypt.c (gpgme_op_encrypt): + * delete.c (gpgme_op_delete): + * decrypt-verify.c (gpgme_op_decrypt_verify): + 2002-02-06 Marcus Brinkmann * gpgme.c (gpgme_set_keylist_mode): Possibly return an error diff --git a/gpgme/decrypt-verify.c b/gpgme/decrypt-verify.c index bfdc011d..940b53cd 100644 --- a/gpgme/decrypt-verify.c +++ b/gpgme/decrypt-verify.c @@ -72,8 +72,7 @@ gpgme_op_decrypt_verify (GpgmeCtx ctx, err = gpgme_op_decrypt_verify_start (ctx, in, out); if (!err) { - gpgme_wait (ctx, 1); - err = ctx->error; + gpgme_wait (ctx, &err, 1); if (!err) *r_stat = _gpgme_intersect_stati (ctx->result.verify); } diff --git a/gpgme/decrypt.c b/gpgme/decrypt.c index ff834b52..8374c0fe 100644 --- a/gpgme/decrypt.c +++ b/gpgme/decrypt.c @@ -160,9 +160,6 @@ gpgme_op_decrypt (GpgmeCtx ctx, GpgmeData in, GpgmeData out) { GpgmeError err = gpgme_op_decrypt_start (ctx, in, out); if (!err) - { - gpgme_wait (ctx, 1); - err = ctx->error; - } + gpgme_wait (ctx, &err, 1); return err; } diff --git a/gpgme/delete.c b/gpgme/delete.c index 51168779..9b2735a4 100644 --- a/gpgme/delete.c +++ b/gpgme/delete.c @@ -152,9 +152,6 @@ gpgme_op_delete (GpgmeCtx ctx, const GpgmeKey key, int allow_secret) { GpgmeError err = gpgme_op_delete_start (ctx, key, allow_secret); if (!err) - { - gpgme_wait (ctx, 1); - err = ctx->error; - } + gpgme_wait (ctx, &err, 1); return err; } diff --git a/gpgme/encrypt.c b/gpgme/encrypt.c index 37c50964..1984db3b 100644 --- a/gpgme/encrypt.c +++ b/gpgme/encrypt.c @@ -212,7 +212,7 @@ gpgme_op_encrypt (GpgmeCtx ctx, GpgmeRecipients recp, int err = gpgme_op_encrypt_start (ctx, recp, plain, cipher); if (!err) { - gpgme_wait (ctx, 1); + gpgme_wait (ctx, &err, 1); /* Old gpg versions don't return status info for invalid recipients, so we simply check whether we got any output at all, and if not we assume that we don't have valid diff --git a/gpgme/export.c b/gpgme/export.c index da86967f..bbee68d8 100644 --- a/gpgme/export.c +++ b/gpgme/export.c @@ -102,9 +102,6 @@ gpgme_op_export (GpgmeCtx ctx, GpgmeRecipients recipients, GpgmeData keydata) { GpgmeError err = gpgme_op_export_start (ctx, recipients, keydata); if (!err) - { - gpgme_wait (ctx, 1); - err = ctx->error; - } + gpgme_wait (ctx, &err, 1); return err; } diff --git a/gpgme/genkey.c b/gpgme/genkey.c index 94d0e37d..2537c8ce 100644 --- a/gpgme/genkey.c +++ b/gpgme/genkey.c @@ -224,9 +224,6 @@ gpgme_op_genkey (GpgmeCtx ctx, const char *parms, { GpgmeError err = gpgme_op_genkey_start (ctx, parms, pubkey, seckey); if (!err) - { - gpgme_wait (ctx, 1); - err = ctx->error; - } + gpgme_wait (ctx, &err, 1); return err; } diff --git a/gpgme/gpgme.h b/gpgme/gpgme.h index 60dd975a..a16d03e8 100644 --- a/gpgme/gpgme.h +++ b/gpgme/gpgme.h @@ -275,7 +275,7 @@ void gpgme_cancel (GpgmeCtx ctx); /* Process the pending operation and, if HANG is non-zero, wait for the pending operation to finish. */ -GpgmeCtx gpgme_wait (GpgmeCtx ctx, int hang); +GpgmeCtx gpgme_wait (GpgmeCtx ctx, GpgmeError *status, int hang); /* Functions to handle recipients. */ diff --git a/gpgme/import.c b/gpgme/import.c index 63e4d6d6..6d070510 100644 --- a/gpgme/import.c +++ b/gpgme/import.c @@ -218,9 +218,6 @@ gpgme_op_import (GpgmeCtx ctx, GpgmeData keydata) { GpgmeError err = gpgme_op_import_start (ctx, keydata); if (!err) - { - gpgme_wait (ctx, 1); - err = ctx->error; - } + gpgme_wait (ctx, &err, 1); return err; } diff --git a/gpgme/sign.c b/gpgme/sign.c index 0c2514c8..3d4896f0 100644 --- a/gpgme/sign.c +++ b/gpgme/sign.c @@ -255,9 +255,6 @@ gpgme_op_sign (GpgmeCtx ctx, GpgmeData in, GpgmeData out, GpgmeSigMode mode) { GpgmeError err = gpgme_op_sign_start (ctx, in, out, mode); if (!err) - { - gpgme_wait (ctx, 1); - err = ctx->error; - } + gpgme_wait (ctx, &err, 1); return err; } diff --git a/gpgme/verify.c b/gpgme/verify.c index bd66dd5e..2cc88936 100644 --- a/gpgme/verify.c +++ b/gpgme/verify.c @@ -353,8 +353,7 @@ gpgme_op_verify (GpgmeCtx ctx, GpgmeData sig, GpgmeData text, err = gpgme_op_verify_start (ctx, sig, text); if (!err) { - gpgme_wait (ctx, 1); - err = ctx->error; + gpgme_wait (ctx, &err, 1); if (!err) *r_stat = _gpgme_intersect_stati (ctx->result.verify); } diff --git a/gpgme/wait.c b/gpgme/wait.c index 639f2070..83b8908d 100644 --- a/gpgme/wait.c +++ b/gpgme/wait.c @@ -49,12 +49,17 @@ DEFINE_STATIC_LOCK (fd_table_lock); static GpgmeIdleFunc idle_function; -struct proc_s { - struct proc_s *next; - int pid; - GpgmeCtx ctx; - struct wait_item_s *handler_list; - int done; +struct proc_s +{ + struct proc_s *next; + int pid; + GpgmeCtx ctx; + struct wait_item_s *handler_list; + /* Non-zero if the process has been completed. */ + int done; + /* Non-zero if the status for this process has been returned + already. */ + int reported; }; struct wait_item_s { @@ -154,9 +159,12 @@ _gpgme_remove_proc_from_wait_queue (int pid) * and no (or the given) request has finished. **/ GpgmeCtx -gpgme_wait (GpgmeCtx ctx, int hang) +gpgme_wait (GpgmeCtx ctx, GpgmeError *status, int hang) { - return _gpgme_wait_on_condition (ctx, hang, NULL); + GpgmeCtx retctx = _gpgme_wait_on_condition (ctx, hang, NULL); + if (status) + *status = retctx->error; + return retctx; } GpgmeCtx @@ -177,15 +185,29 @@ _gpgme_wait_on_condition (GpgmeCtx ctx, int hang, volatile int *cond) LOCK (proc_queue_lock); for (proc = proc_queue; proc; proc = proc->next) { + /* A process is done if it has completed voluntarily, or + if the context it lived in was canceled. */ if (!proc->done && !count_running_fds (proc)) set_process_done (proc); - if (ctx && proc->done && proc->ctx == ctx) + else if (!proc->done && proc->ctx->cancel) { + set_process_done (proc); + proc->ctx->cancel = 0; + proc->ctx->error = mk_error (Canceled); + } + /* A process that is done is eligible for election if it + is in the requested context or if it was not yet + reported. */ + if (proc->done && (proc->ctx == ctx || (!ctx && !proc->reported))) + { + if (!ctx) + ctx = proc->ctx; hang = 0; ctx->pending = 0; + proc->reported = 1; } - if (!proc->done) - any = 1; + if (!proc->done) + any = 1; } UNLOCK (proc_queue_lock); if (!any) @@ -196,12 +218,13 @@ _gpgme_wait_on_condition (GpgmeCtx ctx, int hang, volatile int *cond) if (hang) run_idle (); } - while (hang && !ctx->cancel); - if (ctx->cancel) + while (hang && (!ctx || !ctx->cancel)); + if (ctx && ctx->cancel) { + /* FIXME: Paranoia? */ ctx->cancel = 0; - ctx->error = mk_error (Canceled); ctx->pending = 0; + ctx->error = mk_error (Canceled); } return ctx; }