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.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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
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.
+2002-02-06 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.texi (Waiting For Completion): Adjust doc to changes in
+ the code.
+
2002-02-06 Marcus Brinkmann <marcus@g10code.de>
* gpgme.texi (Key Listing Mode): Update documentation.
@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
@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
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
+2002-02-06 Marcus Brinkmann <marcus@g10code.de>
+
+ * 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 <marcus@g10code.de>
* gpgme.c (gpgme_set_keylist_mode): Possibly return an error
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);
}
{
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;
}
{
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;
}
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
{
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;
}
{
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;
}
/* 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. */
{
GpgmeError err = gpgme_op_import_start (ctx, keydata);
if (!err)
- {
- gpgme_wait (ctx, 1);
- err = ctx->error;
- }
+ gpgme_wait (ctx, &err, 1);
return err;
}
{
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;
}
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);
}
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 {
* 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
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)
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;
}