2003-01-29  Marcus Brinkmann  <marcus@g10code.de>

	* gpgme.texi (I/O Callback Interface): Document new even
	GPGME_EVENT_START.
	(Waiting For Completion): Document new possible return values.
	(I/O Callback Interface): Document return type of GpgmeIOCb.

gpgme/
2003-01-29  Marcus Brinkmann  <marcus@g10code.de>

	* context.h (gpgme_context_s): Remove member ERROR.
	* types.h (GpgmeStatusHandler): Change return type to GpgmeError.
	(GpgmeCommandHandler): Change return type to GpgmeError and add
	new argument RESULT.
	* gpgme.h (GpgmeIOCb): Change return type to GpgmeError.
	(GpgmeEventIO): New event GPGME_EVENT_START.
	(GpgmeIdleFunc): Remove type.
	(gpgme_register_idle): Remove prototype.
	* data.c: Include <assert.h>.
	(_gpgme_data_inbound_handler): Change return type to GpgmeError.
	Return any error instead ignoring it, don't close file descriptor
	on error.
	(_gpgme_data_outbound_handler): Likewise.
	* decrypt.c: Do not include <stdio.h>, <string.h> and <assert.h>.
	(_gpgme_decrypt_status_handler): Change return type to GpgmeError.
	Return error instead setting ctx->error.  Return success at end of
	function.
	(gpgme_op_decrypt): Don't work around the old kludge anymore.
	* decrypt-verify.c (decrypt_verify_status_handler): Change return
	type to GpgmeError.  Return possible errors.
	* delete.c: Do not include <stdio.h>, <string.h>, <time.h> and
	<assert.h>.
	(delete_status_handler): Change return type to GpgmeError.  Return
	error instead setting ctx->error.  Return success at end of
	function.
	* edit.c: Do not include <stdio.h> and <string.h>.
	(_gpgme_edit_status_handler): Change type to GpgmeError,
	make static and rename to ...
	(edit_status_handler): ... this.  Return error directly.
	(command_handler): Change return type to GpgmeError, add result
	argument.  Return error directly.
	* encrypt.c (status_handler_finish): Remove function.
	(_gpgme_encrypt_status_handler): Change return type to GpgmeError.
	Return error directly.
	(_gpgme_encrypt_sym_status_handler): Likewise.
	* encrypt-sign.c (encrypt_sign_status_handler): Likewise.
	* engine-gpgsm.c (close_notify_handler): Do not signal done event
	anymore.
	(status_handler): Change return type to GpgmeError.  Diddle things
	around a bit to return errors directly.
	(start): Send start event.
	* export.c: Do not include <stdio.h>, <string.h> and <assert.h>.
	(export_status_handler): Change return type to GpgmeError.  Don't
	check ctx->error.
	* genkey.c: Do not include <stdio.h> and <assert.h>.
	(genkey_status_handler): Change return type to GpgmeError.  Don't
	check ctx->error.  Return errors directly.
	* gpgme.c (_gpgme_release_result): Do not initialize ctx->error.
	(_gpgme_op_event_cb): Function removed.
	(_gpgme_op_event_cb_user): Likewise.
	* import.c: Do not include <stdio.h>, <string.h> and <assert.h>.
	(import_status_handler): Change return type to GpgmeError.  Don't
	check ctx->error.
	* keylist.c (keylist_colon_handler, keylist_status_handler, finish_key):
	Change return type to GpgmeError, return error directly.
	* Makefile (libgpgme_la_SOURCES): Add wait-global.c,
	wait-private.c and wait-user.c
	* ops.h (test_and_allocate_result): Return error instead setting
	ctx->error.
	(_gpgme_data_inbound_handler, _gpgme_data_outbound_handler,
	_gpgme_verify_status_handler, _gpgme_decrypt_status_handler,
	_gpgme_sign_status_handler, _gpgme_encrypt_staus_handler,
	_gpgme_passphrase_status_handler, _gpgme_progress_status_handler):
	Change return type to GpgmeError.
	(_gpgme_passphease_command_handler): Change return type to
	GpgmeError and add new argument RESULT.
	* op-support.c: Use new callback functions, and change private
	data to ctx everywhere.
	* passphrase.c (_gpgme_passphrase_status_handler): Change return
	type to GpgmeError, return error directly.
	(_gpgme_passphrase_command_handler): Change return type to
	GpgmeError, add result argument.  Return results accordingly.
	* progress.c (_gpgme_progress_status_handler): Change return type
	to GpgmeError, return errors directly.
	* rungpg.c (status_handler): Change return type to GpgmeError.
	Return error directly.
	(close_notify_handler): Don't send done event.
	(colon_line_handler): Change return type to GpgmeError, return
	errors directly.
	* rungpg.c (start): Send start event.
	* sign.c (_gpgme_sign_status_handler): Change return type to
	GpgmeError, return errors directly.
	* trustlist.c (trustlist_status_handler): Change return type to
	GpgmeError.  Return 0.
	(trustlist_colon_handler): Change return type GpgmeError.  Return
	errors directly.
	* verify.c (add_notation): Change return type to GpgmeError,
	return errors directly.
	(_gpgme_verify_status_handler): Likewise.
	* wait.h (struct fd_table): Remove lock member.
	(struct wait_item_s): Moved here from wait.c.
	(struct tag): New structure.
	(_gpgme_wait_event_cb): Remove prototype.
	(_gpgme_wait_private_event_cb, _gpgme_wait_global_event_cb,
	_gpgme_wait_user_add_io_cb, _gpgme_wait_user_remove_io_cb,
	_gpgme_wait_user_event_io_cb): New prototypes.
	* wait.c: Don't include <stdio.h>.
	(ftd_global, ctx_done_list, ctx_done_list_size,
	ctx_done_list_length, ctx_done_list_lock, idle_function): Remove
	global variable.
	(gpgme_register_idle, do_select, _gpgme_wait_event_cb): Remove
	function.
	(gpgme_wait): Move to file wait-global.c.
	(_gpgme_add_io_cb): Take ctx as private argument, initialize ctx
	member in wait item and tag.
	(_gpgme_remove_io_cb): Take ctx from tag.  Don't use FDT lock.
	(_gpgme_wait_one, _gpgme_wait_on_condition): Move to
	wait-private.c.
	(gpgme_fd_table_init): Don't initialize FDT->lock.
	(gpgme_fd_table_deinit): Don't destroy FDT->lock.
	(_gpgme_fd_table_put): Make static and rename to ...
	(fd_table_put): ... this function.  Don't use FDT->lock.
	(struct wait_item_s): Move to wait.h.
	* wait-global.c: New file.
	* wait-private.c: New file.
	* wait-user.c: New file.
This commit is contained in:
Marcus Brinkmann 2003-01-29 15:20:58 +00:00
parent 8a5c6d0de2
commit 2c543f6a86
36 changed files with 1306 additions and 898 deletions

27
NEWS
View File

@ -6,11 +6,38 @@ Noteworthy changes in version 0.4.1 (unreleased)
* gpgme_op_verify and gpgme_op_decrypt_verify don't return a status
summary anymore. Use gpgme_get_sig_status to retrieve the individual stati.
* GpgmeIOCb changed from a void function to a function returning a
GpgmeError value. However, it will always return 0, so you can
safely ignore the return value.
* A new I/O callback event GPGME_EVENT_START has been added. The new
requirement is that you must wait until this event until you are
allowed to call the I/O callback handlers previously registered for
this context operation. Calling I/O callback functions for this
context operation before the start event happened is unsafe because
it can lead to race conditions in a multi-threaded environment.
* The idle function feature has been removed. It was not precisely
defined in a multi-threaded environment and is obsoleted by the
user I/O callback functions. If you still need a simple way to
call something while waiting on one or multiple asynchronous
operations to complete, don't set the HANG flag in gpgme_wait (note
that this will return to your program more often than the idle
function did).
* gpgme_wait can return NULL even if hang is true, if an error
occurs. In that case *status contains the error code.
* Interface changes relative to the 0.4.0 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
GpgmeIOCb CHANGED: Return type from void to GpgmeError.
GpgmeEventIO CHANGED: New event type (all numbers changed).
gpgme_key_get_string_attr CHANGED: Don't handle GPGME_ATTR_IS_SECRET.
gpgme_op_verify CHANGED: Drop R_STAT argument.
gpgme_op_decrypt_verify CHANGED: Drop R_STAT argument.
gpgme_wait CHANGED: Can return NULL even if hang is true.
GpgmeIdleFunc REMOVED
gpgme_register_idle REMOVED
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Noteworthy changes in version 0.4.0 (2002-12-23)

View File

@ -1,3 +1,14 @@
2003-01-29 Marcus Brinkmann <marcus@g10code.de>
* gpgme.texi (I/O Callback Interface): Document new even
GPGME_EVENT_START.
(Waiting For Completion): Document new possible return values.
(I/O Callback Interface): Document return type of GpgmeIOCb.
2003-01-29 Marcus Brinkmann <marcus@g10code.de>
* gpgme.texi (Hooking Up Into Idle Time): Section removed.
2002-12-24 Marcus Brinkmann <marcus@g10code.de>
* gpgme.texi (Verify): Drop R_STAT argument in gpgme_op_verify.

View File

@ -105,7 +105,7 @@ Preparation
* Building the Source:: Compiler options to be used.
* Using Automake:: Compiler options to be used the easy way.
* Library Version Check:: Getting and verifying the library version.
* Multi Threading:: How GPGME can be used in an MT environment.
* Multi Threading:: How @acronym{GPGME} can be used in an MT environment.
Protocols and Engines
@ -191,7 +191,6 @@ Run Control
* Waiting For Completion:: Waiting until an operation is completed.
* Cancelling an Operation:: Interrupting a running operation.
* Hooking Up Into Idle Time:: Doing something when nothing has to be done.
* Using External Event Loops:: Advanced control over what happens when.
Using External Event Loops
@ -228,7 +227,7 @@ OpenPGP and the Cryptographic Message Syntax (CMS).
@node Getting Started
@section Getting Started
This library documents the @acronym{GPGME} library programming
This manual documents the @acronym{GPGME} library programming
interface. All functions and data types provided by the library are
explained.
@ -315,7 +314,7 @@ of the library are verified.
* Building the Source:: Compiler options to be used.
* Using Automake:: Compiler options to be used the easy way.
* Library Version Check:: Getting and verifying the library version.
* Multi Threading:: How GPGME can be used in an MT environment.
* Multi Threading:: How @acronym{GPGME} can be used in an MT environment.
@end menu
@ -541,12 +540,13 @@ initialize_gpgme (void)
Any @code{GpgmeData}, @code{GpgmeCtx} and @code{GpgmeRecipients}
object must only be accessed by one thread at a time. If multiple
threads want to deal with the same object, the caller has to make sure
that operations on this object are fully synchronized.
that operations on that object are fully synchronized.
@item
Only one thread at any time is allowed to call @code{gpgme_wait}. If
multiple threads call this function, the caller must make sure that
all invocations are fully synchronized.
all invocations are fully synchronized. It is safe to start
asynchronous operations while a thread is running in gpgme_wait.
@end itemize
@ -3012,7 +3012,6 @@ time.
@menu
* Waiting For Completion:: Waiting until an operation is completed.
* Cancelling an Operation:: Interrupting a running operation.
* Hooking Up Into Idle Time:: Doing something when nothing has to be done.
* Using External Event Loops:: Advanced control over what happens when.
@end menu
@ -3050,10 +3049,14 @@ and trust item list operations, do not affect @code{gpgme_wait}.
In a multi-threaded environment, only one thread should ever call
@code{gpgme_wait} at any time, irregardless if @var{ctx} is specified
or not. This means that all calls to this function should be fully
synchronized by locking primitives.
synchronized by locking primitives. It is safe to start asynchronous
operations while a thread is running in @code{gpgme_wait}.
The function returns the @var{ctx} of the context which has finished
the operation.
the operation. If @var{hang} is false, and the timeout expires,
@code{NULL} is returned and @code{*status} will be set to 0. If an
error occurs, @code{NULL} is returned and the error is returned in
@code{*status}.
@end deftypefun
@ -3073,30 +3076,6 @@ callback.
@end deftypefun
@node Hooking Up Into Idle Time
@subsection Hooking Up Into Idle Time
@cindex idle time
@cindex idle function
@deftp {Data type} {void (*GpgmeIdleFunc) (void)}
@tindex GpgmeIdleFunc
The @code{GpgmeIdleFunc} type is the type of functions usable as
an idle function that can be registered with @code{gpgme_register_idle}.
@end deftp
@deftypefun GpgmeIdleFunc gpgme_register_idle (@w{GpgmeIdleFunc @var{idle}})
The function @code{gpgme_register_idle} can be used to register
@var{idle} as the idle function.
@var{idle} will be called whenever @acronym{GPGME} thinks that it is
idle and time can better be spent elsewhere. Setting @var{idle} to
@code{NULL} disables use of the idle function (this is the default).
The function returns the old idle function, or @code{NULL} if none was
registered yet.
@end deftypefun
@node Using External Event Loops
@subsection Using External Event Loops
@cindex event loop, external
@ -3139,7 +3118,7 @@ programs.
@node I/O Callback Interface
@subsubsection I/O Callback Interface
@deftp {Data type} {void (*GpgmeIOCb) (@w{void *@var{data}}, @w{int @var{fd}})}
@deftp {Data type} {GpgmeError (*GpgmeIOCb) (@w{void *@var{data}}, @w{int @var{fd}})}
@tindex GpgmeIOCb
The @code{GpgmeIOCb} type is the type of functions which
@acronym{GPGME} wants to register as I/O callback handlers using the
@ -3149,6 +3128,9 @@ The @code{GpgmeIOCb} type is the type of functions which
callback handler is registered, and should be passed through to the
handler when it is invoked by the user because it noticed activity on
the file descriptor @var{fd}.
The callback handler always returns @code{0}, but you should consider
the return value to be reserved for later use.
@end deftp
@deftp {Data type} {GpgmeError (*GpgmeRegisterIOCb) (@w{void *@var{data}}, @w{int @var{fd}}, @w{int @var{dir}}, @w{GpgmeIOCb @var{fnc}}, @w{void *@var{fnc_data}}, @w{void **@var{tag}})}
@ -3198,6 +3180,12 @@ reported to the user by @acronym{GPGME} as a consequence of an I/O
operation. The following events are defined:
@table @code
@item GPGME_EVENT_START
The operation is fully initialized now, and you can start to run the
registered I/O callback handlers now. Note that registered I/O
callback handlers must not be run before this event is signalled.
@var{type_data} is @code{NULL} and reserved for later use.
@item GPGME_EVENT_DONE
The operation is finished, the last I/O callback for this operation
was removed. The accompanying @var{type_data} points to a

View File

@ -1,5 +1,122 @@
2003-01-29 Marcus Brinkmann <marcus@g10code.de>
* context.h (gpgme_context_s): Remove member ERROR.
* types.h (GpgmeStatusHandler): Change return type to GpgmeError.
(GpgmeCommandHandler): Change return type to GpgmeError and add
new argument RESULT.
* gpgme.h (GpgmeIOCb): Change return type to GpgmeError.
(GpgmeEventIO): New event GPGME_EVENT_START.
(GpgmeIdleFunc): Remove type.
(gpgme_register_idle): Remove prototype.
* data.c: Include <assert.h>.
(_gpgme_data_inbound_handler): Change return type to GpgmeError.
Return any error instead ignoring it, don't close file descriptor
on error.
(_gpgme_data_outbound_handler): Likewise.
* decrypt.c: Do not include <stdio.h>, <string.h> and <assert.h>.
(_gpgme_decrypt_status_handler): Change return type to GpgmeError.
Return error instead setting ctx->error. Return success at end of
function.
(gpgme_op_decrypt): Don't work around the old kludge anymore.
* decrypt-verify.c (decrypt_verify_status_handler): Change return
type to GpgmeError. Return possible errors.
* delete.c: Do not include <stdio.h>, <string.h>, <time.h> and
<assert.h>.
(delete_status_handler): Change return type to GpgmeError. Return
error instead setting ctx->error. Return success at end of
function.
* edit.c: Do not include <stdio.h> and <string.h>.
(_gpgme_edit_status_handler): Change type to GpgmeError,
make static and rename to ...
(edit_status_handler): ... this. Return error directly.
(command_handler): Change return type to GpgmeError, add result
argument. Return error directly.
* encrypt.c (status_handler_finish): Remove function.
(_gpgme_encrypt_status_handler): Change return type to GpgmeError.
Return error directly.
(_gpgme_encrypt_sym_status_handler): Likewise.
* encrypt-sign.c (encrypt_sign_status_handler): Likewise.
* engine-gpgsm.c (close_notify_handler): Do not signal done event
anymore.
(status_handler): Change return type to GpgmeError. Diddle things
around a bit to return errors directly.
(start): Send start event.
* export.c: Do not include <stdio.h>, <string.h> and <assert.h>.
(export_status_handler): Change return type to GpgmeError. Don't
check ctx->error.
* genkey.c: Do not include <stdio.h> and <assert.h>.
(genkey_status_handler): Change return type to GpgmeError. Don't
check ctx->error. Return errors directly.
* gpgme.c (_gpgme_release_result): Do not initialize ctx->error.
(_gpgme_op_event_cb): Function removed.
(_gpgme_op_event_cb_user): Likewise.
* import.c: Do not include <stdio.h>, <string.h> and <assert.h>.
(import_status_handler): Change return type to GpgmeError. Don't
check ctx->error.
* keylist.c (keylist_colon_handler, keylist_status_handler, finish_key):
Change return type to GpgmeError, return error directly.
* Makefile (libgpgme_la_SOURCES): Add wait-global.c,
wait-private.c and wait-user.c
* ops.h (test_and_allocate_result): Return error instead setting
ctx->error.
(_gpgme_data_inbound_handler, _gpgme_data_outbound_handler,
_gpgme_verify_status_handler, _gpgme_decrypt_status_handler,
_gpgme_sign_status_handler, _gpgme_encrypt_staus_handler,
_gpgme_passphrase_status_handler, _gpgme_progress_status_handler):
Change return type to GpgmeError.
(_gpgme_passphease_command_handler): Change return type to
GpgmeError and add new argument RESULT.
* op-support.c: Use new callback functions, and change private
data to ctx everywhere.
* passphrase.c (_gpgme_passphrase_status_handler): Change return
type to GpgmeError, return error directly.
(_gpgme_passphrase_command_handler): Change return type to
GpgmeError, add result argument. Return results accordingly.
* progress.c (_gpgme_progress_status_handler): Change return type
to GpgmeError, return errors directly.
* rungpg.c (status_handler): Change return type to GpgmeError.
Return error directly.
(close_notify_handler): Don't send done event.
(colon_line_handler): Change return type to GpgmeError, return
errors directly.
* rungpg.c (start): Send start event.
* sign.c (_gpgme_sign_status_handler): Change return type to
GpgmeError, return errors directly.
* trustlist.c (trustlist_status_handler): Change return type to
GpgmeError. Return 0.
(trustlist_colon_handler): Change return type GpgmeError. Return
errors directly.
* verify.c (add_notation): Change return type to GpgmeError,
return errors directly.
(_gpgme_verify_status_handler): Likewise.
* wait.h (struct fd_table): Remove lock member.
(struct wait_item_s): Moved here from wait.c.
(struct tag): New structure.
(_gpgme_wait_event_cb): Remove prototype.
(_gpgme_wait_private_event_cb, _gpgme_wait_global_event_cb,
_gpgme_wait_user_add_io_cb, _gpgme_wait_user_remove_io_cb,
_gpgme_wait_user_event_io_cb): New prototypes.
* wait.c: Don't include <stdio.h>.
(ftd_global, ctx_done_list, ctx_done_list_size,
ctx_done_list_length, ctx_done_list_lock, idle_function): Remove
global variable.
(gpgme_register_idle, do_select, _gpgme_wait_event_cb): Remove
function.
(gpgme_wait): Move to file wait-global.c.
(_gpgme_add_io_cb): Take ctx as private argument, initialize ctx
member in wait item and tag.
(_gpgme_remove_io_cb): Take ctx from tag. Don't use FDT lock.
(_gpgme_wait_one, _gpgme_wait_on_condition): Move to
wait-private.c.
(gpgme_fd_table_init): Don't initialize FDT->lock.
(gpgme_fd_table_deinit): Don't destroy FDT->lock.
(_gpgme_fd_table_put): Make static and rename to ...
(fd_table_put): ... this function. Don't use FDT->lock.
(struct wait_item_s): Move to wait.h.
* wait-global.c: New file.
* wait-private.c: New file.
* wait-user.c: New file.
* key.c (gpgme_key_sig_get_string_attr): Use validity_to_string
instead otrust_to_string to calculate validity.

View File

@ -72,7 +72,9 @@ libgpgme_la_SOURCES = \
gpgme.h types.h util.h conversion.c context.h ops.h \
data.h data.c data-fd.c data-stream.c data-mem.c data-user.c \
data-compat.c \
recipient.c signers.c wait.c wait.h op-support.c \
recipient.c signers.c \
wait.c wait-global.c wait-private.c wait-user.c wait.h \
op-support.c \
encrypt.c encrypt-sign.c decrypt.c decrypt-verify.c verify.c \
sign.c passphrase.c progress.c \
key.h key.c keylist.c trustlist.c \

View File

@ -49,9 +49,6 @@ struct gpgme_context_s
int use_cms;
/* At some points we need to remember an error which we can't report
immediately. */
GpgmeError error;
/* Cancel operation requested. */
int cancel;
@ -105,7 +102,7 @@ struct gpgme_context_s
void *progress_cb_value;
/* A list of file descriptors in active use by the current
(synchronous) operation. */
operation. */
struct fd_table fdt;
struct GpgmeIOCbs io_cbs;

View File

@ -22,6 +22,7 @@
#endif
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
@ -158,65 +159,58 @@ gpgme_data_set_encoding (GpgmeData dh, GpgmeDataEncoding enc)
/* Functions to support the wait interface. */
void
GpgmeError
_gpgme_data_inbound_handler (void *opaque, int fd)
{
GpgmeData dh = opaque;
GpgmeError err;
GpgmeData dh = (GpgmeData) opaque;
char buffer[BUFFER_SIZE];
ssize_t buflen;
assert (dh);
buflen = read (fd, buffer, BUFFER_SIZE);
if (buflen <= 0)
if (buflen < 0)
return mk_error (File_Error);
if (buflen == 0)
{
_gpgme_io_close (fd);
return;
return 0;
}
err = _gpgme_data_append (dh, buffer, buflen);
if (err)
{
DEBUG1 ("_gpgme_data_append failed: %s\n", gpgme_strerror (err));
/* Fixme: we should close the pipe or read it to /dev/null in
* this case. Returning EOF is not sufficient */
_gpgme_io_close (fd); /* XXX ??? */
return;
}
return;
return _gpgme_data_append (dh, buffer, buflen);
}
void
GpgmeError
_gpgme_data_outbound_handler (void *opaque, int fd)
{
GpgmeData dh = opaque;
GpgmeData dh = (GpgmeData) opaque;
ssize_t nwritten;
assert (dh);
if (!dh->pending_len)
{
ssize_t amt = gpgme_data_read (dh, dh->pending, BUFFER_SIZE);
if (amt <= 0)
if (amt < 0)
return mk_error (File_Error);
if (amt == 0)
{
_gpgme_io_close (fd);
return;
return 0;
}
dh->pending_len = amt;
}
nwritten = _gpgme_io_write (fd, dh->pending, dh->pending_len);
if (nwritten == -1 && errno == EAGAIN )
return;
return 0;
if (nwritten <= 0)
{
DEBUG3 ("_gpgme_data_outbound_handler (%d): write failed (n=%d): %s",
fd, nwritten, strerror (errno));
_gpgme_io_close (fd);
return;
}
return mk_error (File_Error);
if (nwritten < dh->pending_len)
memmove (dh->pending, dh->pending + nwritten, dh->pending_len - nwritten);
dh->pending_len -= nwritten;
return;
return 0;
}

View File

@ -31,11 +31,13 @@
#include "ops.h"
static void
static GpgmeError
decrypt_verify_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
{
_gpgme_decrypt_status_handler (ctx, code, args);
_gpgme_verify_status_handler (ctx, code, args);
GpgmeError err = _gpgme_decrypt_status_handler (ctx, code, args);
if (err)
return err;
return _gpgme_verify_status_handler (ctx, code, args);
}

View File

@ -21,10 +21,7 @@
#if HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "util.h"
#include "context.h"
@ -87,24 +84,25 @@ skip_token (const char *string, size_t *next)
}
void
GpgmeError
_gpgme_decrypt_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
{
GpgmeError err;
size_t n;
_gpgme_passphrase_status_handler (ctx, code, args);
err = _gpgme_passphrase_status_handler (ctx, code, args);
if (err)
return err;
if (ctx->error)
return;
test_and_allocate_result (ctx, decrypt);
switch (code)
{
case GPGME_STATUS_EOF:
if (ctx->result.decrypt->failed)
ctx->error = mk_error (Decryption_Failed);
return mk_error (Decryption_Failed);
else if (!ctx->result.decrypt->okay)
ctx->error = mk_error (No_Data);
return mk_error (No_Data);
break;
case GPGME_STATUS_DECRYPTION_OKAY:
@ -153,11 +151,11 @@ _gpgme_decrypt_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
}
break;
default:
/* Ignore all other codes. */
break;
}
return 0;
}
@ -230,15 +228,5 @@ gpgme_op_decrypt (GpgmeCtx ctx, GpgmeData in, GpgmeData out)
_gpgme_decrypt_status_handler);
if (!err)
err = _gpgme_wait_one (ctx);
/* Work around the kludge in engine-gpgsm.c */
if (err == GPGME_Invalid_Engine && ctx->error)
{
if (ctx->result.decrypt->failed)
err = mk_error (Decryption_Failed);
else if (!ctx->result.decrypt->okay)
err = mk_error (No_Data);
}
return err;
}

View File

@ -1,4 +1,4 @@
/* delete.c - delete a key
/* delete.c - Delete a key.
Copyright (C) 2001, 2002 g10 Code GmbH
This file is part of GPGME.
@ -20,11 +20,7 @@
#if HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <assert.h>
#include "util.h"
#include "context.h"
@ -56,11 +52,9 @@ _gpgme_release_delete_result (DeleteResult result)
}
static void
static GpgmeError
delete_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
{
if (ctx->error)
return;
test_and_allocate_result (ctx, delete);
switch (code)
@ -71,15 +65,15 @@ delete_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
case DELETE_No_Problem:
break;
case DELETE_No_Such_Key:
ctx->error = mk_error(Invalid_Key);
return mk_error(Invalid_Key);
break;
case DELETE_Must_Delete_Secret_Key:
ctx->error = mk_error(Conflict);
return mk_error(Conflict);
break;
case DELETE_Ambiguous_Specification:
/* XXX Need better error value. Fall through. */
default:
ctx->error = mk_error(General_Error);
return mk_error(General_Error);
break;
}
break;
@ -89,9 +83,9 @@ delete_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
break;
default:
/* Ignore all other codes. */
break;
}
return 0;
}
@ -120,6 +114,7 @@ _gpgme_op_delete_start (GpgmeCtx ctx, int synchronous,
return err;
}
GpgmeError
gpgme_op_delete_start (GpgmeCtx ctx, const GpgmeKey key, int allow_secret)
{

View File

@ -1,4 +1,4 @@
/* edit.c - key edit functions
/* edit.c - Key edit functions.
Copyright (C) 2002 g10 Code GmbH
This file is part of GPGME.
@ -20,9 +20,7 @@
#if HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "util.h"
@ -44,31 +42,38 @@ _gpgme_release_edit_result (EditResult result)
free (result);
}
void
_gpgme_edit_status_handler (GpgmeCtx ctx, GpgmeStatusCode status, char *args)
static GpgmeError
edit_status_handler (GpgmeCtx ctx, GpgmeStatusCode status, char *args)
{
_gpgme_passphrase_status_handler (ctx, status, args);
GpgmeError err = _gpgme_passphrase_status_handler (ctx, status, args);
if (err)
return err;
if (ctx->error)
return;
ctx->error = (*ctx->result.edit->fnc) (ctx->result.edit->fnc_value, status, args, NULL);
return (*ctx->result.edit->fnc) (ctx->result.edit->fnc_value, status,
args, NULL);
}
static const char *
command_handler (void *opaque, GpgmeStatusCode status, const char *args)
{
GpgmeCtx ctx = opaque;
const char *result;
result = _gpgme_passphrase_command_handler (ctx, status, args);
static GpgmeError
command_handler (void *opaque, GpgmeStatusCode status, const char *args,
const char **result)
{
GpgmeError err;
GpgmeCtx ctx = opaque;
err = _gpgme_passphrase_command_handler (ctx, status, args, result);
if (err)
return err;
if (!result)
ctx->error = (*ctx->result.edit->fnc) (ctx->result.edit->fnc_value, status, args, &result);
err = (*ctx->result.edit->fnc) (ctx->result.edit->fnc_value, status,
args, result);
return result;
return err;
}
static GpgmeError
_gpgme_op_edit_start (GpgmeCtx ctx, int synchronous,
GpgmeKey key,
@ -106,8 +111,7 @@ _gpgme_op_edit_start (GpgmeCtx ctx, int synchronous,
if (err)
goto leave;
_gpgme_engine_set_status_handler (ctx->engine, _gpgme_edit_status_handler,
ctx);
_gpgme_engine_set_status_handler (ctx->engine, edit_status_handler, ctx);
_gpgme_engine_set_verbosity (ctx->engine, ctx->verbosity);

View File

@ -32,11 +32,13 @@
#include "ops.h"
static void
static GpgmeError
encrypt_sign_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
{
_gpgme_encrypt_status_handler (ctx, code, args);
_gpgme_sign_status_handler (ctx, code, args);
GpgmeError err = _gpgme_encrypt_status_handler (ctx, code, args);
if (err)
return err;
return _gpgme_sign_status_handler (ctx, code, args);
}

View File

@ -1,4 +1,4 @@
/* encrypt.c - encrypt functions
/* encrypt.c - Encrypt functions.
Copyright (C) 2000 Werner Koch (dd9jn)
Copyright (C) 2001, 2002 g10 Code GmbH
@ -54,11 +54,8 @@ _gpgme_release_encrypt_result (EncryptResult result)
free (result);
}
/*
* Parse the args and save the information
* in an XML structure.
* With args of NULL the xml structure is closed.
*/
/* Parse the args and save the information in an XML structure. With
args of NULL the xml structure is closed. */
static void
append_xml_encinfo (GpgmeData *rdh, char *args)
{
@ -100,38 +97,24 @@ append_xml_encinfo (GpgmeData *rdh, char *args)
}
static void
status_handler_finish (GpgmeCtx ctx)
GpgmeError
_gpgme_encrypt_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
{
test_and_allocate_result (ctx, encrypt);
switch (code)
{
case GPGME_STATUS_EOF:
if (ctx->result.encrypt->xmlinfo)
{
append_xml_encinfo (&ctx->result.encrypt->xmlinfo, NULL);
_gpgme_set_op_info (ctx, ctx->result.encrypt->xmlinfo);
ctx->result.encrypt->xmlinfo = NULL;
}
if (ctx->error)
; /* already set by kludge in engine-gpgsm */
else if (ctx->result.encrypt->no_valid_recipients)
ctx->error = mk_error (No_Recipients);
if (ctx->result.encrypt->no_valid_recipients)
return mk_error (No_Recipients);
else if (ctx->result.encrypt->invalid_recipients)
ctx->error = mk_error (Invalid_Recipients);
}
void
_gpgme_encrypt_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
{
if (ctx->error)
{
if (ctx->result.encrypt) /* check that we have allocated it. */
status_handler_finish (ctx);
return;
}
test_and_allocate_result (ctx, encrypt);
switch (code)
{
case GPGME_STATUS_EOF:
status_handler_finish (ctx);
return mk_error (Invalid_Recipients);
break;
case GPGME_STATUS_INV_RECP:
@ -146,13 +129,15 @@ _gpgme_encrypt_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
default:
break;
}
return 0;
}
void
_gpgme_encrypt_sym_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
GpgmeError
_gpgme_encrypt_sym_status_handler (GpgmeCtx ctx, GpgmeStatusCode code,
char *args)
{
_gpgme_passphrase_status_handler (ctx, code, args);
return _gpgme_passphrase_status_handler (ctx, code, args);
}
@ -202,7 +187,8 @@ _gpgme_op_encrypt_start (GpgmeCtx ctx, int synchronous,
goto leave;
}
err = _gpgme_engine_op_encrypt (ctx->engine, recp, plain, ciph, ctx->use_armor);
err = _gpgme_engine_op_encrypt (ctx->engine, recp, plain, ciph,
ctx->use_armor);
leave:
if (err)

View File

@ -125,49 +125,32 @@ static void
close_notify_handler (int fd, void *opaque)
{
GpgsmObject gpgsm = opaque;
int possibly_done = 0;
assert (fd != -1);
if (gpgsm->status_cb.fd == fd)
{
if (gpgsm->status_cb.tag)
{
(*gpgsm->io_cbs.remove) (gpgsm->status_cb.tag);
possibly_done = 1;
}
gpgsm->status_cb.fd = -1;
}
else if (gpgsm->input_cb.fd == fd)
{
if (gpgsm->input_cb.tag)
{
(*gpgsm->io_cbs.remove) (gpgsm->input_cb.tag);
possibly_done = 1;
}
gpgsm->input_cb.fd = -1;
}
else if (gpgsm->output_cb.fd == fd)
{
if (gpgsm->output_cb.tag)
{
(*gpgsm->io_cbs.remove) (gpgsm->output_cb.tag);
possibly_done = 1;
}
gpgsm->output_cb.fd = -1;
}
else if (gpgsm->message_cb.fd == fd)
{
if (gpgsm->message_cb.tag)
{
(*gpgsm->io_cbs.remove) (gpgsm->message_cb.tag);
possibly_done = 1;
}
gpgsm->message_cb.fd = -1;
}
if (possibly_done && gpgsm->io_cbs.event
&& gpgsm->status_cb.fd == -1 && gpgsm->input_cb.fd == -1
&& gpgsm->output_cb.fd == -1 && gpgsm->message_cb.fd == -1)
(*gpgsm->io_cbs.event) (gpgsm->io_cbs.event_priv, GPGME_EVENT_DONE, NULL);
}
@ -677,66 +660,55 @@ parse_status (const char *name)
}
static void
static GpgmeError
status_handler (void *opaque, int fd)
{
AssuanError err;
AssuanError assuan_err;
GpgmeError err = 0;
GpgsmObject gpgsm = opaque;
char *line;
size_t linelen;
do
{
err = assuan_read_line (gpgsm->assuan_ctx, &line, &linelen);
if (err
|| (linelen >= 2
&& line[0] == 'O' && line[1] == 'K'
&& (line[2] == '\0' || line[2] == ' '))
|| (linelen >= 3
assuan_err = assuan_read_line (gpgsm->assuan_ctx, &line, &linelen);
if (assuan_err)
{
/* Try our best to terminate the connection friendly. */
assuan_write_line (gpgsm->assuan_ctx, "BYE");
err = map_assuan_error (assuan_err);
}
else if (linelen >= 3
&& line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
&& (line[3] == '\0' || line[3] == ' ')))
{
/* XXX: If an error occured, find out what happened, then
save the error value before running the status handler
(so it takes precedence). */
if (!err && line[0] == 'E' && line[3] == ' ')
&& (line[3] == '\0' || line[3] == ' '))
{
if (line[3] == ' ')
err = map_assuan_error (atoi (&line[4]));
if (!err)
else
err = mk_error (General_Error);
}
if (err)
else if (linelen >= 2
&& line[0] == 'O' && line[1] == 'K'
&& (line[2] == '\0' || line[2] == ' '))
{
/* XXX Kludge ahead. We really, really, really must not
make use of status.fnc_value. */
GpgmeCtx ctx = (GpgmeCtx) gpgsm->status.fnc_value;
if (!ctx->error)
ctx->error = err;
}
if (gpgsm->status.fnc)
gpgsm->status.fnc (gpgsm->status.fnc_value, GPGME_STATUS_EOF, "");
if (gpgsm->colon.fnc && gpgsm->colon.any )
err = gpgsm->status.fnc (gpgsm->status.fnc_value,
GPGME_STATUS_EOF, "");
if (!err && gpgsm->colon.fnc && gpgsm->colon.any )
{
/* We must tell a colon fucntion about the EOF. We do
/* We must tell a colon function about the EOF. We do
this only when we have seen any data lines. Note
that this inlined use of colon data lines will
eventually be changed into using a regular data
channel. */
gpgsm->colon.any = 0;
gpgsm->colon.fnc (gpgsm->colon.fnc_value, NULL);
err = gpgsm->colon.fnc (gpgsm->colon.fnc_value, NULL);
}
/* XXX: Try our best to terminate the connection. */
if (err)
assuan_write_line (gpgsm->assuan_ctx, "BYE");
_gpgme_io_close (gpgsm->status_cb.fd);
return;
return err;
}
if (linelen > 2
else if (linelen > 2
&& line[0] == 'D' && line[1] == ' '
&& gpgsm->colon.fnc)
{
@ -758,17 +730,18 @@ status_handler (void *opaque, int fd)
unsigned char *newline = realloc (*aline,
*alinelen + linelen + 1);
if (!newline)
err = mk_error (Out_Of_Core);
else
{
_gpgme_io_close (gpgsm->status_cb.fd);
return;
}
*aline = newline;
gpgsm->colon.attic.linesize += linelen + 1;
}
}
if (!err)
{
dst = *aline + *alinelen;
while (src < end)
while (!err && src < end)
{
if (*src == '%' && src + 2 < end)
{
@ -795,14 +768,18 @@ status_handler (void *opaque, int fd)
*dst = '\0';
/* FIXME How should we handle the return code? */
gpgsm->colon.fnc (gpgsm->colon.fnc_value, *aline);
err = gpgsm->colon.fnc (gpgsm->colon.fnc_value, *aline);
if (!err)
{
dst = *aline;
*alinelen = 0;
}
}
else
dst++;
}
}
}
else if (linelen > 2
&& line[0] == 'S' && line[1] == ' ')
{
@ -820,13 +797,16 @@ status_handler (void *opaque, int fd)
if (r >= 0)
{
if (gpgsm->status.fnc)
gpgsm->status.fnc (gpgsm->status.fnc_value, r, rest);
err = gpgsm->status.fnc (gpgsm->status.fnc_value, r, rest);
}
else
fprintf (stderr, "[UNKNOWN STATUS]%s %s", line + 2, rest);
}
}
while (assuan_pending_line (gpgsm->assuan_ctx));
while (!err && assuan_pending_line (gpgsm->assuan_ctx));
_gpgme_io_close (gpgsm->status_cb.fd);
return err;
}
@ -863,6 +843,8 @@ start (GpgsmObject gpgsm, const char *command)
if (!err)
err = assuan_write_line (gpgsm->assuan_ctx, command);
(*gpgsm->io_cbs.event) (gpgsm->io_cbs.event_priv, GPGME_EVENT_START, NULL);
return err;
}

View File

@ -436,6 +436,7 @@ _gpgme_engine_set_io_cbs (EngineObject engine,
(*engine->ops->set_io_cbs) (engine->engine, io_cbs);
}
void
_gpgme_engine_io_event (EngineObject engine,
GpgmeEventIO type, void *type_data)

View File

@ -35,7 +35,8 @@ const char *_gpgme_engine_get_info (GpgmeProtocol proto);
GpgmeError _gpgme_engine_new (GpgmeProtocol proto, EngineObject *r_engine);
void _gpgme_engine_release (EngineObject engine);
void _gpgme_engine_set_status_handler (EngineObject engine,
GpgmeStatusHandler fnc, void *fnc_value);
GpgmeStatusHandler fnc,
void *fnc_value);
GpgmeError _gpgme_engine_set_command_handler (EngineObject engine,
GpgmeCommandHandler fnc,
void *fnc_value,
@ -80,7 +81,8 @@ GpgmeError _gpgme_engine_op_sign (EngineObject engine, GpgmeData in,
GpgmeError _gpgme_engine_op_trustlist (EngineObject engine,
const char *pattern);
GpgmeError _gpgme_engine_op_verify (EngineObject engine, GpgmeData sig,
GpgmeData signed_text, GpgmeData plaintext);
GpgmeData signed_text,
GpgmeData plaintext);
void _gpgme_engine_set_io_cbs (EngineObject engine,
struct GpgmeIOCbs *io_cbs);

View File

@ -1,4 +1,4 @@
/* export.c - encrypt functions
/* export.c - Encrypt functions.
Copyright (C) 2000 Werner Koch (dd9jn)
Copyright (C) 2001, 2002 g10 Code GmbH
@ -21,24 +21,19 @@
#if HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "util.h"
#include "context.h"
#include "ops.h"
static void
static GpgmeError
export_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
{
if (ctx->error)
return;
DEBUG2 ("export_status: code=%d args=`%s'\n", code, args);
/* FIXME: Need to do more */
return 0;
}

View File

@ -21,10 +21,8 @@
#if HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "util.h"
#include "context.h"
@ -50,13 +48,13 @@ _gpgme_release_genkey_result (GenKeyResult result)
}
static void
static GpgmeError
genkey_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
{
_gpgme_progress_status_handler (ctx, code, args);
GpgmeError err = _gpgme_progress_status_handler (ctx, code, args);
if (err)
return err;
if (ctx->error)
return;
test_and_allocate_result (ctx, genkey);
switch (code)
@ -74,7 +72,7 @@ genkey_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
free (ctx->result.genkey->fpr);
ctx->result.genkey->fpr = strdup (&args[2]);
if (!ctx->result.genkey->fpr)
ctx->error = mk_error (Out_Of_Core);
return mk_error (Out_Of_Core);
}
}
break;
@ -83,12 +81,13 @@ genkey_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
/* FIXME: Should return some more useful error value. */
if (!ctx->result.genkey->created_primary
&& !ctx->result.genkey->created_sub)
ctx->error = mk_error (General_Error);
return mk_error (General_Error);
break;
default:
break;
}
return 0;
}

View File

@ -1,4 +1,4 @@
/* gpgme.c - GnuPG Made Easy
/* gpgme.c - GnuPG Made Easy.
Copyright (C) 2000 Werner Koch (dd9jn)
Copyright (C) 2001, 2002 g10 Code GmbH
@ -99,7 +99,6 @@ _gpgme_release_result (GpgmeCtx ctx)
_gpgme_release_edit_result (ctx->result.edit);
memset (&ctx->result, 0, sizeof (ctx->result));
_gpgme_set_op_info (ctx, NULL);
ctx->error = 0;
}
@ -546,43 +545,3 @@ gpgme_get_io_cbs (GpgmeCtx ctx, struct GpgmeIOCbs *io_cbs)
if (ctx && io_cbs)
*io_cbs = ctx->io_cbs;
}
void
_gpgme_op_event_cb (void *data, GpgmeEventIO type, void *type_data)
{
GpgmeCtx ctx = data;
switch (type)
{
case GPGME_EVENT_DONE:
ctx->pending = 0;
break;
case GPGME_EVENT_NEXT_KEY:
_gpgme_op_keylist_event_cb (data, type, type_data);
break;
case GPGME_EVENT_NEXT_TRUSTITEM:
_gpgme_op_trustlist_event_cb (data, type, type_data);
break;
}
}
void
_gpgme_op_event_cb_user (void *data, GpgmeEventIO type, void *type_data)
{
GpgmeCtx ctx = data;
if (type == GPGME_EVENT_DONE)
{
ctx->pending = 0;
if (ctx->io_cbs.event)
(*ctx->io_cbs.event) (ctx->io_cbs.event_priv, type, &ctx->error);
}
else
{
if (ctx->io_cbs.event)
(*ctx->io_cbs.event) (ctx->io_cbs.event_priv, type, type_data);
}
}

View File

@ -424,7 +424,7 @@ char *gpgme_get_op_info (GpgmeCtx ctx, int reserved);
/* Run control. */
/* The type of an I/O callback function. */
typedef void (*GpgmeIOCb) (void *data, int fd);
typedef GpgmeError (*GpgmeIOCb) (void *data, int fd);
/* The type of a function that can register FNC as the I/O callback
function for the file descriptor FD with direction dir (0: for writing,
@ -440,7 +440,8 @@ typedef GpgmeError (*GpgmeRegisterIOCb) (void *data, int fd, int dir,
function. */
typedef void (*GpgmeRemoveIOCb) (void *tag);
typedef enum { GPGME_EVENT_DONE,
typedef enum { GPGME_EVENT_START,
GPGME_EVENT_DONE,
GPGME_EVENT_NEXT_KEY,
GPGME_EVENT_NEXT_TRUSTITEM } GpgmeEventIO;
@ -802,10 +803,6 @@ const char *gpgme_get_engine_info (void);
/* Return a string describing ERR. */
const char *gpgme_strerror (GpgmeError err);
/* Register an idle function. */
typedef void (*GpgmeIdleFunc)(void);
GpgmeIdleFunc gpgme_register_idle (GpgmeIdleFunc idle);
/* Engine support functions. */

View File

@ -1,4 +1,4 @@
/* import.c - encrypt functions
/* import.c - Import functions.
Copyright (C) 2000 Werner Koch (dd9jn)
Copyright (C) 2001, 2002 g10 Code GmbH
@ -21,10 +21,8 @@
#if HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "util.h"
#include "context.h"
@ -142,11 +140,9 @@ append_xml_impinfo (GpgmeData *rdh, GpgmeStatusCode code, char *args)
}
static void
static GpgmeError
import_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
{
if (ctx->error)
return;
test_and_allocate_result (ctx, import);
switch (code)
@ -174,6 +170,7 @@ import_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
default:
break;
}
return 0;
}

View File

@ -83,11 +83,9 @@ append_xml_keylistinfo (GpgmeData *rdh, char *args)
}
static void
static GpgmeError
keylist_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
{
if (ctx->error)
return;
test_and_allocate_result (ctx, keylist);
switch (code)
@ -108,9 +106,9 @@ keylist_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
break;
default:
/* Ignore all other codes. */
break;
}
return 0;
}
@ -341,7 +339,7 @@ finish_key (GpgmeCtx ctx)
/* Note: We are allowed to modify LINE. */
static void
static GpgmeError
keylist_colon_handler (GpgmeCtx ctx, char *line)
{
enum
@ -360,14 +358,11 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
DEBUG3 ("keylist_colon_handler ctx = %p, key = %p, line = %s\n",
ctx, key, line ? line : "(null)");
if (ctx->error)
return;
if (!line)
{
/* End Of File. */
finish_key (ctx);
return;
return 0;
}
while (line && fields < NR_FIELDS)
@ -389,30 +384,21 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
/* Start a new subkey. */
rectype = RT_SUB;
if (!(subkey = _gpgme_key_add_subkey (key)))
{
ctx->error = mk_error (Out_Of_Core);
return;
}
return mk_error (Out_Of_Core);
}
else if (!strcmp (field[0], "ssb") && key)
{
/* Start a new secret subkey. */
rectype = RT_SSB;
if (!(subkey = _gpgme_key_add_secret_subkey (key)))
{
ctx->error = mk_error (Out_Of_Core);
return;
}
return mk_error (Out_Of_Core);
}
else if (!strcmp (field[0], "pub"))
{
/* Start a new keyblock. */
if (_gpgme_key_new (&key))
{
/* The only kind of error we can get. */
ctx->error = mk_error (Out_Of_Core);
return;
}
return mk_error (Out_Of_Core);
rectype = RT_PUB;
finish_key (ctx);
assert (!ctx->tmp_key);
@ -422,11 +408,7 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
{
/* Start a new keyblock, */
if (_gpgme_key_new_secret (&key))
{
/* The only kind of error we can get. */
ctx->error = mk_error (Out_Of_Core);
return;
}
return mk_error (Out_Of_Core);
rectype = RT_SEC;
finish_key (ctx);
assert (!ctx->tmp_key);
@ -436,11 +418,7 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
{
/* Start a new certificate. */
if (_gpgme_key_new (&key))
{
/* The only kind of error we can get. */
ctx->error = mk_error (Out_Of_Core);
return;
}
return mk_error (Out_Of_Core);
key->x509 = 1;
rectype = RT_CRT;
finish_key (ctx);
@ -451,11 +429,7 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
{
/* Start a new certificate. */
if (_gpgme_key_new_secret (&key))
{
/* The only kind of error we can get. */
ctx->error = mk_error (Out_Of_Core);
return;
}
return mk_error (Out_Of_Core);
key->x509 = 1;
rectype = RT_CRS;
finish_key (ctx);
@ -482,14 +456,14 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
{
key->issuer_serial = strdup (field[7]);
if (!key->issuer_serial)
ctx->error = mk_error (Out_Of_Core);
return mk_error (Out_Of_Core);
}
/* Field 10 is not used for gpg due to --fixed-list-mode option
but GPGSM stores the issuer name. */
if (fields >= 10 && _gpgme_decode_c_string (field[9],
&key->issuer_name, 0))
ctx->error = mk_error (Out_Of_Core);
return mk_error (Out_Of_Core);
/* Fall through! */
case RT_PUB:
@ -589,7 +563,7 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
if (fields >= 10)
{
if (_gpgme_key_append_name (key, field[9]))
ctx->error = mk_error (Out_Of_Core);
return mk_error (Out_Of_Core);
else
{
if (field[1])
@ -605,7 +579,7 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
{
key->keys.fingerprint = strdup (field[9]);
if (!key->keys.fingerprint)
ctx->error = mk_error (Out_Of_Core);
return mk_error (Out_Of_Core);
}
/* Field 13 has the gpgsm chain ID (take only the first one). */
@ -613,23 +587,20 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
{
key->chain_id = strdup (field[12]);
if (!key->chain_id)
ctx->error = mk_error (Out_Of_Core);
return mk_error (Out_Of_Core);
}
break;
case RT_SIG:
case RT_REV:
if (!ctx->tmp_uid)
return;
return 0;
/* Start a new (revoked) signature. */
assert (ctx->tmp_uid == key->last_uid);
certsig = _gpgme_key_add_certsig (key, (fields >= 10) ? field[9] : NULL);
if (!certsig)
{
ctx->error = mk_error (Out_Of_Core);
return;
}
return mk_error (Out_Of_Core);
/* Field 2 has the calculated trust ('!', '-', '?', '%'). */
if (fields >= 2)
@ -696,6 +667,7 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
/* Unknown record. */
break;
}
return 0;
}
@ -714,7 +686,7 @@ _gpgme_op_keylist_event_cb (void *data, GpgmeEventIO type, void *type_data)
if (!q)
{
gpgme_key_release (key);
ctx->error = mk_error (Out_Of_Core);
/* FIXME return mk_error (Out_Of_Core); */
return;
}
q->key = key;
@ -859,8 +831,6 @@ gpgme_op_keylist_next (GpgmeCtx ctx, GpgmeKey *r_key)
return mk_error (Invalid_Value);
if (!ctx->pending)
return mk_error (No_Request);
if (ctx->error)
return ctx->error;
if (!ctx->key_queue)
{
@ -912,8 +882,6 @@ gpgme_op_keylist_end (GpgmeCtx ctx)
return mk_error (Invalid_Value);
if (!ctx->pending)
return mk_error (No_Request);
if (ctx->error)
return ctx->error;
ctx->pending = 0;
return 0;

View File

@ -1,24 +1,25 @@
/* op-support.c
* Copyright (C) 2002 g10 Code GmbH
*
* This file is part of GPGME.
*
* GPGME is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GPGME is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
Copyright (C) 2002, 2003 g10 Code GmbH
This file is part of GPGME.
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GPGME; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#if HAVE_CONFIG_H
#include <config.h>
#endif
#include "gpgme.h"
#include "context.h"
@ -50,28 +51,27 @@ _gpgme_op_reset (GpgmeCtx ctx, int type)
{
/* Use private event loop. */
io_cbs.add = _gpgme_add_io_cb;
io_cbs.add_priv = &ctx->fdt;
io_cbs.add_priv = ctx;
io_cbs.remove = _gpgme_remove_io_cb;
io_cbs.event = _gpgme_op_event_cb;
io_cbs.event = _gpgme_wait_private_event_cb;
io_cbs.event_priv = ctx;
}
else if (! ctx->io_cbs.add)
{
/* Use global event loop. */
io_cbs.add = _gpgme_add_io_cb;
io_cbs.add_priv = NULL;
io_cbs.add_priv = ctx;
io_cbs.remove = _gpgme_remove_io_cb;
io_cbs.event = _gpgme_wait_event_cb;
io_cbs.event = _gpgme_wait_global_event_cb;
io_cbs.event_priv = ctx;
}
else
{
/* Use user event loop. */
io_cbs = ctx->io_cbs;
/* We have to make sure that we notice the termination of the
operation ourself, so we stack another event handler on top
of the user-provided one. */
io_cbs.event = _gpgme_op_event_cb_user;
io_cbs.add = _gpgme_wait_user_add_io_cb;
io_cbs.add_priv = ctx;
io_cbs.remove = _gpgme_wait_user_remove_io_cb;
io_cbs.event = _gpgme_wait_user_event_cb;
io_cbs.event_priv = ctx;
}
_gpgme_engine_set_io_cbs (ctx->engine, &io_cbs);

View File

@ -32,16 +32,13 @@
{ \
ctx->result.field = calloc (1, sizeof *ctx->result.field); \
if (!ctx->result.field) \
{ \
ctx->error = mk_error (Out_Of_Core); \
return; \
} \
return mk_error (Out_Of_Core); \
} \
} \
while (0)
/*-- gpgme.c --*/
void _gpgme_release_result ( GpgmeCtx c );
void _gpgme_release_result (GpgmeCtx ctx);
void _gpgme_set_op_info (GpgmeCtx c, GpgmeData info);
void _gpgme_op_event_cb (void *data, GpgmeEventIO type, void *type_data);
@ -72,8 +69,8 @@ GpgmeError _gpgme_data_append_percentstring_for_xml ( GpgmeData dh,
GpgmeError _gpgme_data_unread (GpgmeData dh,
const char *buffer, size_t length );
void _gpgme_data_inbound_handler (void *opaque, int fd);
void _gpgme_data_outbound_handler (void *opaque, int fd);
GpgmeError _gpgme_data_inbound_handler (void *opaque, int fd);
GpgmeError _gpgme_data_outbound_handler (void *opaque, int fd);
/*-- key.c --*/
GpgmeError _gpgme_key_new ( GpgmeKey *r_key );
@ -84,12 +81,12 @@ GpgmeError _gpgme_op_reset (GpgmeCtx ctx, int synchronous);
/*-- verify.c --*/
void _gpgme_release_verify_result (VerifyResult result);
void _gpgme_verify_status_handler (GpgmeCtx ctx, GpgmeStatusCode code,
GpgmeError _gpgme_verify_status_handler (GpgmeCtx ctx, GpgmeStatusCode code,
char *args);
/*-- decrypt.c --*/
void _gpgme_release_decrypt_result (DecryptResult result);
void _gpgme_decrypt_status_handler (GpgmeCtx ctx, GpgmeStatusCode code,
GpgmeError _gpgme_decrypt_status_handler (GpgmeCtx ctx, GpgmeStatusCode code,
char *args);
GpgmeError _gpgme_decrypt_start (GpgmeCtx ctx, int synchronous,
GpgmeData ciph, GpgmeData plain,
@ -98,25 +95,25 @@ GpgmeError _gpgme_decrypt_result (GpgmeCtx ctx);
/*-- sign.c --*/
void _gpgme_release_sign_result ( SignResult res );
void _gpgme_sign_status_handler (GpgmeCtx ctx, GpgmeStatusCode code,
GpgmeError _gpgme_sign_status_handler (GpgmeCtx ctx, GpgmeStatusCode code,
char *args);
/*-- encrypt.c --*/
void _gpgme_release_encrypt_result ( EncryptResult res );
void _gpgme_encrypt_status_handler (GpgmeCtx ctx, GpgmeStatusCode code,
GpgmeError _gpgme_encrypt_status_handler (GpgmeCtx ctx, GpgmeStatusCode code,
char *args);
/*-- passphrase.c --*/
void _gpgme_release_passphrase_result (PassphraseResult result);
void _gpgme_passphrase_status_handler (GpgmeCtx ctx, GpgmeStatusCode code,
GpgmeError _gpgme_passphrase_status_handler (GpgmeCtx ctx, GpgmeStatusCode code,
char *args);
const char * _gpgme_passphrase_command_handler (void *opaque,
GpgmeError _gpgme_passphrase_command_handler (void *opaque,
GpgmeStatusCode code,
const char *key);
const char *key, const char **result);
GpgmeError _gpgme_passphrase_start (GpgmeCtx ctx);
/*-- progress.c --*/
void _gpgme_progress_status_handler (GpgmeCtx ctx, GpgmeStatusCode code,
GpgmeError _gpgme_progress_status_handler (GpgmeCtx ctx, GpgmeStatusCode code,
char *args);
/*-- import.c --*/

View File

@ -52,11 +52,9 @@ _gpgme_release_passphrase_result (PassphraseResult result)
}
void
GpgmeError
_gpgme_passphrase_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
{
if (ctx->error)
return;
test_and_allocate_result (ctx, passphrase);
switch (code)
@ -64,7 +62,7 @@ _gpgme_passphrase_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args
case GPGME_STATUS_USERID_HINT:
free (ctx->result.passphrase->userid_hint);
if (!(ctx->result.passphrase->userid_hint = strdup (args)))
ctx->error = mk_error (Out_Of_Core);
return mk_error (Out_Of_Core);
break;
case GPGME_STATUS_BAD_PASSPHRASE:
@ -82,7 +80,7 @@ _gpgme_passphrase_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args
free (ctx->result.passphrase->passphrase_info);
ctx->result.passphrase->passphrase_info = strdup (args);
if (!ctx->result.passphrase->passphrase_info)
ctx->error = mk_error (Out_Of_Core);
return mk_error (Out_Of_Core);
break;
case GPGME_STATUS_MISSING_PASSPHRASE:
@ -93,18 +91,20 @@ _gpgme_passphrase_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args
case GPGME_STATUS_EOF:
if (ctx->result.passphrase->no_passphrase
|| ctx->result.passphrase->bad_passphrase)
ctx->error = mk_error (No_Passphrase);
return mk_error (No_Passphrase);
break;
default:
/* Ignore all other codes. */
break;
}
return 0;
}
const char *
_gpgme_passphrase_command_handler (void *opaque, GpgmeStatusCode code, const char *key)
GpgmeError
_gpgme_passphrase_command_handler (void *opaque, GpgmeStatusCode code,
const char *key, const char **result)
{
GpgmeCtx ctx = opaque;
@ -112,10 +112,7 @@ _gpgme_passphrase_command_handler (void *opaque, GpgmeStatusCode code, const cha
{
ctx->result.passphrase = calloc (1, sizeof *ctx->result.passphrase);
if (!ctx->result.passphrase)
{
ctx->error = mk_error (Out_Of_Core);
return NULL;
}
return mk_error (Out_Of_Core);
}
if (!code)
@ -127,11 +124,15 @@ _gpgme_passphrase_command_handler (void *opaque, GpgmeStatusCode code, const cha
ctx->passphrase_cb (ctx->passphrase_cb_value, NULL,
&ctx->result.passphrase->last_pw_handle);
}
return NULL;
*result = NULL;
return 0;
}
if (!key || !ctx->passphrase_cb)
return NULL;
{
*result = NULL;
return 0;
}
if (code == GPGME_STATUS_GET_HIDDEN && !strcmp (key, "passphrase.enter"))
{
@ -139,7 +140,6 @@ _gpgme_passphrase_command_handler (void *opaque, GpgmeStatusCode code, const cha
const char *passphrase_info = ctx->result.passphrase->passphrase_info;
int bad_passphrase = ctx->result.passphrase->bad_passphrase;
char *buf;
const char *s;
ctx->result.passphrase->bad_passphrase = 0;
if (!userid_hint)
@ -149,21 +149,19 @@ _gpgme_passphrase_command_handler (void *opaque, GpgmeStatusCode code, const cha
buf = malloc (20 + strlen (userid_hint)
+ strlen (passphrase_info) + 3);
if (!buf)
{
ctx->error = mk_error (Out_Of_Core);
return NULL;
}
return mk_error (Out_Of_Core);
sprintf (buf, "%s\n%s\n%s",
bad_passphrase ? "TRY_AGAIN":"ENTER",
userid_hint, passphrase_info);
s = ctx->passphrase_cb (ctx->passphrase_cb_value,
buf, &ctx->result.passphrase->last_pw_handle);
*result = ctx->passphrase_cb (ctx->passphrase_cb_value, buf,
&ctx->result.passphrase->last_pw_handle);
free (buf);
return s;
return 0;
}
return NULL;
*result = NULL;
return 0;
}

View File

@ -1,23 +1,22 @@
/* progress.c - status handler for progress status
* Copyright (C) 2000 Werner Koch (dd9jn)
* Copyright (C) 2001, 2002 g10 Code GmbH
*
* This file is part of GPGME.
*
* GPGME is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GPGME is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
Copyright (C) 2000 Werner Koch (dd9jn)
Copyright (C) 2001, 2002 g10 Code GmbH
This file is part of GPGME.
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GPGME; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifdef HAVE_CONFIG_H
#include <config.h>
@ -29,7 +28,7 @@
#include "context.h"
void
GpgmeError
_gpgme_progress_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
{
char *p;
@ -39,14 +38,11 @@ _gpgme_progress_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
int total = 0;
if (code != GPGME_STATUS_PROGRESS || !*args || !ctx->progress_cb)
return;
return 0;
args_cpy = strdup (args);
if (!args_cpy)
{
ctx->error = mk_error (Out_Of_Core);
return;
}
return mk_error (Out_Of_Core);
p = strchr (args_cpy, ' ');
if (p)
@ -77,4 +73,5 @@ _gpgme_progress_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
ctx->progress_cb (ctx->progress_cb_value, args_cpy, type, current, total);
free (args_cpy);
return 0;
}

View File

@ -138,17 +138,12 @@ static void
close_notify_handler (int fd, void *opaque)
{
GpgObject gpg = opaque;
int possibly_done = 0;
int not_done = 0;
assert (fd != -1);
if (gpg->status.fd[0] == fd)
{
if (gpg->status.tag)
{
(*gpg->io_cbs.remove) (gpg->status.tag);
possibly_done = 1;
}
gpg->status.fd[0] = -1;
}
else if (gpg->status.fd[1] == fd)
@ -156,10 +151,7 @@ close_notify_handler (int fd, void *opaque)
else if (gpg->colon.fd[0] == fd)
{
if (gpg->colon.tag)
{
(*gpg->io_cbs.remove) (gpg->colon.tag);
possibly_done = 1;
}
gpg->colon.fd[0] = -1;
}
else if (gpg->colon.fd[1] == fd)
@ -173,10 +165,7 @@ close_notify_handler (int fd, void *opaque)
if (gpg->fd_data_map[i].fd == fd)
{
if (gpg->fd_data_map[i].tag)
{
(*gpg->io_cbs.remove) (gpg->fd_data_map[i].tag);
possibly_done = 1;
}
gpg->fd_data_map[i].fd = -1;
break;
}
@ -187,25 +176,6 @@ close_notify_handler (int fd, void *opaque)
}
}
}
if (!possibly_done)
not_done = 1;
else if (gpg->status.fd[0] != -1)
not_done = 1;
else if (gpg->colon.fd[0] != -1)
not_done = 1;
else if (gpg->fd_data_map)
{
int i;
for (i = 0; gpg->fd_data_map[i].data; i++)
if (gpg->fd_data_map[i].fd != -1)
{
not_done = 1;
break;
}
}
if (!not_done)
gpg_io_event (gpg, GPGME_EVENT_DONE, NULL);
}
static GpgmeError
@ -500,12 +470,13 @@ command_cb (void *opaque, char *buffer, size_t length, size_t *nread)
return -1;
}
value = gpg->cmd.fnc (gpg->cmd.fnc_value,
gpg->cmd.code, gpg->cmd.keyword);
/* FIXME catch error */
gpg->cmd.fnc (gpg->cmd.fnc_value,
gpg->cmd.code, gpg->cmd.keyword, &value);
if (!value)
{
DEBUG0 ("command_cb: no data from user cb\n");
gpg->cmd.fnc (gpg->cmd.fnc_value, 0, value);
gpg->cmd.fnc (gpg->cmd.fnc_value, 0, value, &value);
return -1;
}
@ -513,7 +484,7 @@ command_cb (void *opaque, char *buffer, size_t length, size_t *nread)
if (value_len + 1 > length)
{
DEBUG0 ("command_cb: too much data from user cb\n");
gpg->cmd.fnc (gpg->cmd.fnc_value, 0, value);
gpg->cmd.fnc (gpg->cmd.fnc_value, 0, value, &value);
return -1;
}
@ -522,7 +493,7 @@ command_cb (void *opaque, char *buffer, size_t length, size_t *nread)
buffer[value_len++] = '\n';
*nread = value_len;
gpg->cmd.fnc (gpg->cmd.fnc_value, 0, value);
gpg->cmd.fnc (gpg->cmd.fnc_value, 0, value, &value);
gpg->cmd.code = 0;
/* And sleep again until read_status will wake us up again. */
/* XXX We must check if there are any more fds active after removing
@ -957,7 +928,7 @@ read_status (GpgObject gpg)
}
static void
static GpgmeError
status_handler (void *opaque, int fd)
{
GpgObject gpg = opaque;
@ -967,16 +938,13 @@ status_handler (void *opaque, int fd)
err = read_status (gpg);
if (err)
{
/* XXX Horrible kludge. We really must not make use of
fnc_value. */
GpgmeCtx ctx = (GpgmeCtx) gpg->status.fnc_value;
ctx->error = err;
DEBUG1 ("gpg_handler: read_status problem %d\n - stop", err);
_gpgme_io_close (fd);
return;
return err;
}
if (gpg->status.eof)
_gpgme_io_close (fd);
return 0;
}
@ -1058,7 +1026,7 @@ read_colon_line (GpgObject gpg)
might be better to enhance the GpgmeData object to act as a wrapper
for a callback. Same goes for the status thing. For now we use
this thing here because it is easier to implement. */
static void
static GpgmeError
colon_line_handler (void *opaque, int fd)
{
GpgObject gpg = opaque;
@ -1067,14 +1035,10 @@ colon_line_handler (void *opaque, int fd)
assert (fd == gpg->colon.fd[0]);
rc = read_colon_line (gpg);
if (rc)
{
DEBUG1 ("gpg_colon_line_handler: "
"read problem %d\n - stop", rc);
_gpgme_io_close (fd);
return;
}
return rc;
if (gpg->colon.eof)
_gpgme_io_close (fd);
return 0;
}
@ -1199,6 +1163,8 @@ start (GpgObject gpg)
}
}
(*gpg->io_cbs.event) (gpg->io_cbs.event_priv, GPGME_EVENT_START, NULL);
/* fixme: check what data we can release here */
return 0;
}

View File

@ -136,13 +136,13 @@ append_xml_siginfo (GpgmeData *rdh, char *args)
_gpgme_data_append_string (dh, "</fpr>\n");
}
void
GpgmeError
_gpgme_sign_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
{
_gpgme_passphrase_status_handler (ctx, code, args);
GpgmeError err = _gpgme_passphrase_status_handler (ctx, code, args);
if (err)
return err;
if (ctx->error)
return;
test_and_allocate_result (ctx, sign);
switch (code)
@ -154,8 +154,8 @@ _gpgme_sign_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
_gpgme_set_op_info (ctx, ctx->result.sign->xmlinfo);
ctx->result.sign->xmlinfo = NULL;
}
if (!ctx->error && !ctx->result.sign->okay)
ctx->error = mk_error (No_Data); /* Hmmm: choose a better error? */
if (!ctx->result.sign->okay)
return mk_error (No_Data); /* Hmmm: choose a better error? */
break;
case GPGME_STATUS_SIG_CREATED:
@ -167,6 +167,7 @@ _gpgme_sign_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
default:
break;
}
return 0;
}
static GpgmeError

View File

@ -1,4 +1,4 @@
/* trustlist.c - key listing
/* trustlist.c - Trust item listing.
Copyright (C) 2000 Werner Koch (dd9jn)
Copyright (C) 2001, 2002 g10 Code GmbH
@ -52,12 +52,9 @@ trust_item_new (void)
}
static void
static GpgmeError
trustlist_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
{
if (ctx->error)
return;
switch (code)
{
case GPGME_STATUS_EOF:
@ -66,6 +63,7 @@ trustlist_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
default:
break;
}
return 0;
}
@ -80,17 +78,15 @@ trustlist_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
counter and only available on U lines CC is the same for the
complete count NAME ist the username and only printed on U
lines. */
static void
static GpgmeError
trustlist_colon_handler (GpgmeCtx ctx, char *line)
{
char *p, *pend;
int field = 0;
GpgmeTrustItem item = NULL;
if (ctx->error)
return;
if (!line)
return; /* EOF */
return 0; /* EOF */
for (p = line; p; p = pend)
{
@ -104,10 +100,7 @@ trustlist_colon_handler (GpgmeCtx ctx, char *line)
case 1: /* level */
item = trust_item_new ();
if (!item)
{
ctx->error = mk_error (Out_Of_Core);
return;
}
return mk_error (Out_Of_Core);
item->level = atoi (p);
break;
case 2: /* long keyid */
@ -128,13 +121,14 @@ trustlist_colon_handler (GpgmeCtx ctx, char *line)
case 9: /* user ID */
item->name = strdup (p);
if (!item->name)
ctx->error = mk_error (Out_Of_Core);
return mk_error (Out_Of_Core);
break;
}
}
if (item)
_gpgme_engine_io_event (ctx->engine, GPGME_EVENT_NEXT_TRUSTITEM, item);
return 0;
}
@ -145,13 +139,14 @@ _gpgme_op_trustlist_event_cb (void *data, GpgmeEventIO type, void *type_data)
GpgmeTrustItem item = (GpgmeTrustItem) type_data;
struct trust_queue_item_s *q, *q2;
assert (type == GPGME_EVENT_NEXT_KEY);
assert (type == GPGME_EVENT_NEXT_TRUSTITEM);
q = malloc (sizeof *q);
if (!q)
{
gpgme_trust_item_release (item);
ctx->error = mk_error (Out_Of_Core);
/* FIXME */
/* ctx->error = mk_error (Out_Of_Core); */
return;
}
q->item = item;
@ -215,8 +210,6 @@ gpgme_op_trustlist_next (GpgmeCtx ctx, GpgmeTrustItem *r_item)
return mk_error (Invalid_Value);
if (!ctx->pending)
return mk_error (No_Request);
if (ctx->error)
return ctx->error;
if (!ctx->trust_queue)
{
@ -266,8 +259,6 @@ gpgme_op_trustlist_end (GpgmeCtx ctx)
return mk_error (Invalid_Value);
if (!ctx->pending)
return mk_error (No_Request);
if (ctx->error)
return ctx->error;
ctx->pending = 0;
return 0;

View File

@ -35,11 +35,11 @@ typedef unsigned long ulong;
* Declaration of internal objects
*/
typedef void (*GpgmeStatusHandler) (GpgmeCtx, GpgmeStatusCode code,
typedef GpgmeError (*GpgmeStatusHandler) (GpgmeCtx, GpgmeStatusCode code,
char *args);
typedef void (*GpgmeColonLineHandler) (GpgmeCtx, char *line);
typedef const char *(*GpgmeCommandHandler) (void*, GpgmeStatusCode code,
const char *keyword);
typedef GpgmeError (*GpgmeColonLineHandler) (GpgmeCtx, char *line);
typedef GpgmeError (*GpgmeCommandHandler) (void*, GpgmeStatusCode code,
const char *keyword, const char **result);
/*-- engine.c --*/

View File

@ -119,7 +119,7 @@ copy_token (const char *string, char *buffer, size_t length)
/* FIXME: Check that we are adding this to the correct signature. */
static void
static GpgmeError
add_notation (GpgmeCtx ctx, GpgmeStatusCode code, const char *data)
{
GpgmeData dh = ctx->result.verify->notation;
@ -127,10 +127,7 @@ add_notation (GpgmeCtx ctx, GpgmeStatusCode code, const char *data)
if (!dh)
{
if (gpgme_data_new (&dh))
{
ctx->error = mk_error (Out_Of_Core);
return;
}
return mk_error (Out_Of_Core);
ctx->result.verify->notation = dh;
_gpgme_data_append_string (dh, " <notation>\n");
}
@ -141,7 +138,7 @@ add_notation (GpgmeCtx ctx, GpgmeStatusCode code, const char *data)
_gpgme_data_append_string (dh, " <data>");
_gpgme_data_append_percentstring_for_xml (dh, data);
ctx->result.verify->notation_in_data = 1;
return;
return 0;
}
if (ctx->result.verify->notation_in_data)
@ -164,19 +161,20 @@ add_notation (GpgmeCtx ctx, GpgmeStatusCode code, const char *data)
}
else
assert (0);
return 0;
}
/* Finish a pending signature info collection and prepare for a new
signature info collection. */
static void
static GpgmeError
finish_sig (GpgmeCtx ctx, int stop)
{
if (ctx->result.verify->status == GPGME_SIG_STAT_GOOD)
ctx->result.verify->status = ctx->result.verify->expstatus;
if (stop)
return; /* nothing to do */
return 0; /* nothing to do */
if (ctx->result.verify->collecting)
{
@ -186,28 +184,25 @@ finish_sig (GpgmeCtx ctx, int stop)
/* Create a new result structure. */
res2 = calloc (1, sizeof *res2);
if (!res2)
{
ctx->error = mk_error (Out_Of_Core);
return;
}
return mk_error (Out_Of_Core);
res2->next = ctx->result.verify;
ctx->result.verify = res2;
}
ctx->result.verify->collecting = 1;
return 0;
}
void
GpgmeError
_gpgme_verify_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
{
GpgmeError err;
char *p;
size_t n;
int i;
if (ctx->error)
return;
test_and_allocate_result (ctx, verify);
if (code == GPGME_STATUS_GOODSIG
@ -216,9 +211,9 @@ _gpgme_verify_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
|| code == GPGME_STATUS_BADSIG
|| code == GPGME_STATUS_ERRSIG)
{
finish_sig (ctx,0);
if (ctx->error)
return;
err = finish_sig (ctx,0);
if (err)
return err;
}
switch (code)
@ -284,7 +279,9 @@ _gpgme_verify_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
case GPGME_STATUS_NOTATION_NAME:
case GPGME_STATUS_NOTATION_DATA:
case GPGME_STATUS_POLICY_URL:
add_notation (ctx, code, args);
err = add_notation (ctx, code, args);
if (err)
return err;
break;
case GPGME_STATUS_TRUST_UNDEFINED:
@ -333,7 +330,9 @@ _gpgme_verify_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
break;
case GPGME_STATUS_EOF:
finish_sig (ctx,1);
err = finish_sig (ctx,1);
if (err)
return err;
/* FIXME: Put all notation data into one XML fragment. */
if (ctx->result.verify->notation)
@ -355,6 +354,7 @@ _gpgme_verify_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
/* Ignore all other codes. */
break;
}
return 0;
}

356
gpgme/wait-global.c Normal file
View File

@ -0,0 +1,356 @@
/* wait-global.c
Copyright (C) 2000 Werner Koch (dd9jn)
Copyright (C) 2001, 2002, 2003 g10 Code GmbH
This file is part of GPGME.
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GPGME; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#if HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "gpgme.h"
#include "sema.h"
#include "util.h"
#include "context.h"
#include "wait.h"
#include "io.h"
/* The global event loop is used for all asynchronous operations
(except key listing) for which no user I/O callbacks are specified.
A context sets up its initial I/O callbacks and then sends the
GPGME_EVENT_START event. After that, it is added to the global
list of active contexts.
The gpgme_wait function contains a select() loop over all file
descriptors in all active contexts. If an error occurs, it closes
all fds in that context and moves the context to the global done
list. Likewise, if a context has removed all I/O callbacks, it is
moved to the global done list.
All contexts in the global done list are eligible for being
returned by gpgme_wait if requested by the caller. */
/* The ctx_list_lock protects the list of active and done contexts.
Insertion into any of these lists is only allowed when the lock is
held. This allows a muli-threaded program to loop over gpgme_wait
and in parallel start asynchronous gpgme operations.
However, the fd tables in the contexts are not protected by this
lock. They are only allowed to change either before the context is
added to the active list (ie, before the start event is signalled)
or in a callback handler. */
DEFINE_STATIC_LOCK (ctx_list_lock);
/* A ctx_list_item is an item in the global list of active or done
contexts. */
struct ctx_list_item
{
/* Every ctx_list_item is an element in a doubly linked list. The
list pointers are protected by the ctx_list_lock. */
struct ctx_list_item *next;
struct ctx_list_item *prev;
GpgmeCtx ctx;
/* The status is set when the ctx is moved to the done list. */
GpgmeError status;
};
/* The active list contains all contexts that are in the global event
loop, have active I/O callbacks, and have already seen the start
event. */
static struct ctx_list_item *ctx_active_list;
/* The done list contains all contexts that have previously been
active but now are not active any longer, either because they finished
successfully or an I/O callback returned an error. The status field
in the list item contains the error value (or 0 if successful). */
static struct ctx_list_item *ctx_done_list;
/* Enter the context CTX into the active list. */
static GpgmeError
ctx_active (GpgmeCtx ctx)
{
struct ctx_list_item *li = malloc (sizeof (struct ctx_list_item));
if (!li)
return mk_error (Out_Of_Core);
li->ctx = ctx;
LOCK (ctx_list_lock);
/* Add LI to active list. */
li->next = ctx_active_list;
li->prev = NULL;
if (ctx_active_list)
ctx_active_list->prev = li;
ctx_active_list = li;
UNLOCK (ctx_list_lock);
return 0;
}
/* Enter the context CTX into the done list with status STATUS. */
static void
ctx_done (GpgmeCtx ctx, GpgmeError status)
{
struct ctx_list_item *li;
LOCK (ctx_list_lock);
li = ctx_active_list;
while (li && li->ctx != ctx)
li = li->next;
assert (li);
/* Remove LI from active list. */
if (li->next)
li->next->prev = li->prev;
if (li->prev)
li->prev->next = li->next;
else
ctx_active_list = li->next;
li->status = status;
/* Add LI to done list. */
li->next = ctx_done_list;
li->prev = NULL;
if (ctx_done_list)
ctx_done_list->prev = li;
ctx_done_list = li;
UNLOCK (ctx_list_lock);
}
/* Find finished context CTX (or any context if CTX is NULL) and
return its status in STATUS after removing it from the done list.
If a matching context could be found, return it. Return NULL if no
context could be found. */
static GpgmeCtx
ctx_wait (GpgmeCtx ctx, GpgmeError *status)
{
struct ctx_list_item *li;
LOCK (ctx_list_lock);
li = ctx_done_list;
if (ctx)
{
/* A specific context is requested. */
while (li && li->ctx != ctx)
li = li->next;
}
if (li)
{
ctx = li->ctx;
if (status)
*status = li->status;
/* Remove LI from done list. */
if (li->next)
li->next->prev = li->prev;
if (li->prev)
li->prev->next = li->next;
else
ctx_done_list = li->next;
free (li);
}
else
ctx = NULL;
UNLOCK (ctx_list_lock);
return ctx;
}
/* Internal I/O callback functions. */
/* The add_io_cb and remove_io_cb handlers are shared with the private
event loops. */
void
_gpgme_wait_global_event_cb (void *data, GpgmeEventIO type, void *type_data)
{
GpgmeCtx ctx = (GpgmeCtx) data;
assert (ctx);
switch (type)
{
case GPGME_EVENT_START:
{
GpgmeError err = ctx_active (ctx);
if (err)
{
/* An error occured. Close all fds in this context, and
send the error in a done event. */
int idx;
for (idx = 0; idx <= ctx->fdt.size; idx++)
if (ctx->fdt.fds[idx].fd != -1)
_gpgme_io_close (ctx->fdt.fds[idx].fd);
_gpgme_engine_io_event (ctx->engine, GPGME_EVENT_DONE, &err);
}
}
break;
case GPGME_EVENT_DONE:
{
GpgmeError *errp = (GpgmeError *) type_data;
assert (errp);
ctx_done (ctx, *errp);
}
break;
case GPGME_EVENT_NEXT_KEY:
assert (!"Unexpected event GPGME_EVENT_NEXT_KEY");
break;
case GPGME_EVENT_NEXT_TRUSTITEM:
assert (!"Unexpected event GPGME_EVENT_NEXT_TRUSTITEM");
break;
default:
assert (!"Unexpected event");
break;
}
}
/* Perform asynchronous operations in the global event loop (ie, any
asynchronous operation except key listing and trustitem listing
operations). If CTX is not a null pointer, the function will
return if the asynchronous operation in the context CTX finished.
Otherwise the function will return if any asynchronous operation
finished. If HANG is zero, the function will not block for a long
time. Otherwise the function does not return until an operation
matching CTX finished.
If a matching context finished, it is returned, and *STATUS is set
to the error value of the operation in that context. Otherwise, if
the timeout expires, NULL is returned and *STATUS is 0. If an
error occurs, NULL is returned and *STATUS is set to the error
value. */
GpgmeCtx
gpgme_wait (GpgmeCtx ctx, GpgmeError *status, int hang)
{
do
{
int i = 0;
struct ctx_list_item *li;
struct fd_table fdt;
int nr;
/* Collect the active file descriptors. */
LOCK (ctx_list_lock);
for (li = ctx_active_list; li; li = li->next)
i += li->ctx->fdt.size;
fdt.fds = malloc (i * sizeof (struct io_select_fd_s));
if (!fdt.fds)
{
UNLOCK (ctx_list_lock);
if (status)
*status = mk_error (Out_Of_Core);
return NULL;
}
fdt.size = i;
i = 0;
for (li = ctx_active_list; li; li = li->next)
{
memcpy (&fdt.fds[i], li->ctx->fdt.fds,
li->ctx->fdt.size * sizeof (struct io_select_fd_s));
i += li->ctx->fdt.size;
}
UNLOCK (ctx_list_lock);
nr = _gpgme_io_select (fdt.fds, fdt.size, 0);
if (nr < 0)
{
free (fdt.fds);
if (status)
*status = mk_error (File_Error);
return NULL;
}
for (i = 0; i < fdt.size && nr; i++)
{
if (fdt.fds[i].fd != -1 && fdt.fds[i].signaled)
{
GpgmeCtx ictx;
GpgmeError err;
struct wait_item_s *item;
assert (nr);
nr--;
item = (struct wait_item_s *) fdt.fds[i].opaque;
assert (item);
ictx = item->ctx;
assert (ictx);
err = item->handler (item->handler_value, fdt.fds[i].fd);
if (!err && ictx->cancel)
err = mk_error (Canceled);
if (err)
{
/* An error occured. Close all fds in this context,
and signal it. */
int idx;
for (idx = 0; idx < ictx->fdt.size; idx++)
if (ictx->fdt.fds[idx].fd != -1)
_gpgme_io_close (ictx->fdt.fds[idx].fd);
_gpgme_engine_io_event (ictx->engine, GPGME_EVENT_DONE, &err);
}
}
}
free (fdt.fds);
/* Now some contexts might have finished successfully. */
LOCK (ctx_list_lock);
for (li = ctx_active_list; li; li = li->next)
{
for (i = 0; i < ctx->fdt.size; i++)
if (ctx->fdt.fds[i].fd != -1)
break;
if (i == ctx->fdt.size)
{
GpgmeError err = 0;
_gpgme_engine_io_event (ctx->engine, GPGME_EVENT_DONE, &err);
}
}
UNLOCK (ctx_list_lock);
{
GpgmeCtx dctx = ctx_wait (ctx, status);
if (dctx)
{
ctx = dctx;
hang = 0;
ctx->pending = 0;
}
}
}
while (hang);
return ctx;
}

153
gpgme/wait-private.c Normal file
View File

@ -0,0 +1,153 @@
/* wait-private.c
Copyright (C) 2000 Werner Koch (dd9jn)
Copyright (C) 2001, 2002, 2003 g10 Code GmbH
This file is part of GPGME.
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GPGME; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#if HAVE_CONFIG_H
#include <config.h>
#endif
#include <assert.h>
#include "gpgme.h"
#include "context.h"
#include "wait.h"
#include "ops.h"
#include "io.h"
#include "util.h"
/* The private event loops are used for all blocking operations, and
for the key and trust item listing operations. They are completely
separated from each other. */
/* Internal I/O callback functions. */
/* The add_io_cb and remove_io_cb handlers are shared with the global
event loops. */
void
_gpgme_wait_private_event_cb (void *data, GpgmeEventIO type, void *type_data)
{
GpgmeCtx ctx = data;
switch (type)
{
case GPGME_EVENT_START:
/* Nothing to do here, as the wait routine is called after the
initialization is finished. */
break;
case GPGME_EVENT_DONE:
ctx->pending = 0;
break;
case GPGME_EVENT_NEXT_KEY:
_gpgme_op_keylist_event_cb (data, type, type_data);
break;
case GPGME_EVENT_NEXT_TRUSTITEM:
_gpgme_op_trustlist_event_cb (data, type, type_data);
break;
}
}
/* If COND is a null pointer, wait until the blocking operation in CTX
finished and return its error value. Otherwise, wait until COND is
satisfied or the operation finished. */
GpgmeError
_gpgme_wait_on_condition (GpgmeCtx ctx, volatile int *cond)
{
GpgmeError err = 0;
int hang = 1;
do
{
int nr = _gpgme_io_select (ctx->fdt.fds, ctx->fdt.size, 0);
int i;
if (nr < 0)
{
/* An error occured. Close all fds in this context, and
signal it. */
int idx;
err = mk_error (File_Error);
for (idx = 0; idx < ctx->fdt.size; idx++)
if (ctx->fdt.fds[idx].fd != -1)
_gpgme_io_close (ctx->fdt.fds[idx].fd);
_gpgme_engine_io_event (ctx->engine, GPGME_EVENT_DONE, &err);
return err;
}
for (i = 0; i < ctx->fdt.size && nr; i++)
{
if (ctx->fdt.fds[i].fd != -1 && ctx->fdt.fds[i].signaled)
{
struct wait_item_s *item;
ctx->fdt.fds[i].signaled = 0;
assert (nr);
nr--;
item = (struct wait_item_s *) ctx->fdt.fds[i].opaque;
err = item->handler (item->handler_value, ctx->fdt.fds[i].fd);
if (!err && ctx->cancel)
err = mk_error (Canceled);
if (err)
{
/* An error occured. Close all fds in this context,
and signal it. */
int idx;
for (idx = 0; idx < ctx->fdt.size; idx++)
if (ctx->fdt.fds[idx].fd != -1)
_gpgme_io_close (ctx->fdt.fds[idx].fd);
_gpgme_engine_io_event (ctx->engine, GPGME_EVENT_DONE, &err);
return err;
}
}
}
for (i = 0; i < ctx->fdt.size; i++)
if (ctx->fdt.fds[i].fd != -1)
break;
if (i == ctx->fdt.size)
{
_gpgme_engine_io_event (ctx->engine, GPGME_EVENT_DONE, &err);
hang = 0;
}
if (cond && *cond)
hang = 0;
}
while (hang);
return 0;
}
/* Wait until the blocking operation in context CTX has finished and
return the error value. */
GpgmeError
_gpgme_wait_one (GpgmeCtx ctx)
{
return _gpgme_wait_on_condition (ctx, NULL);
}

127
gpgme/wait-user.c Normal file
View File

@ -0,0 +1,127 @@
/* wait.c
Copyright (C) 2000 Werner Koch (dd9jn)
Copyright (C) 2001, 2002, 2003 g10 Code GmbH
This file is part of GPGME.
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GPGME; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#if HAVE_CONFIG_H
#include <config.h>
#endif
#include <assert.h>
#include "gpgme.h"
#include "context.h"
#include "io.h"
#include "wait.h"
/* The user event loops are used for all asynchronous operations for
which a user callback is defined. */
/* Internal I/O Callbacks. */
GpgmeError
_gpgme_user_io_cb_handler (void *data, int fd)
{
GpgmeError err;
struct tag *tag = (struct tag *) data;
GpgmeCtx ctx;
struct wait_item_s *item;
assert (data);
ctx = tag->ctx;
assert (ctx);
item = (struct wait_item_s *) ctx->fdt.fds[tag->idx].opaque;
assert (item);
err = (*item->handler) (item->handler_value, fd);
if (err)
{
int idx;
for (idx = 0; idx < ctx->fdt.size; idx++)
if (ctx->fdt.fds[idx].fd != -1)
_gpgme_io_close (ctx->fdt.fds[idx].fd);
_gpgme_engine_io_event (ctx->engine, GPGME_EVENT_DONE, &err);
}
return 0;
}
/* Register the file descriptor FD with the handler FNC (which gets
FNC_DATA as its first argument) for the direction DIR. DATA should
be the context for which the fd is added. R_TAG will hold the tag
that can be used to remove the fd. */
GpgmeError
_gpgme_wait_user_add_io_cb (void *data, int fd, int dir, GpgmeIOCb fnc,
void *fnc_data, void **r_tag)
{
GpgmeCtx ctx = (GpgmeCtx) data;
struct tag *tag;
GpgmeError err;
assert (ctx);
err = _gpgme_add_io_cb (data, fd, dir, fnc, fnc_data, r_tag);
if (err)
return err;
tag = *r_tag;
assert (tag);
err = (*ctx->io_cbs.add) (ctx->io_cbs.add_priv, fd, dir,
_gpgme_user_io_cb_handler, *r_tag,
&tag->user_tag);
if (err)
_gpgme_remove_io_cb (*r_tag);
return err;
}
void
_gpgme_wait_user_remove_io_cb (void *data)
{
struct tag *tag = (struct tag *) data;
GpgmeCtx ctx;
int i;
assert (tag);
ctx = tag->ctx;
(*ctx->io_cbs.remove) (tag->user_tag);
_gpgme_remove_io_cb (data);
for (i = 0; i < ctx->fdt.size; i++)
if (ctx->fdt.fds[i].fd != -1)
break;
if (i == ctx->fdt.size)
{
GpgmeError err = 0;
_gpgme_engine_io_event (ctx->engine, GPGME_EVENT_DONE, &err);
}
}
void
_gpgme_wait_user_event_cb (void *data, GpgmeEventIO type, void *type_data)
{
GpgmeCtx ctx = data;
if (type == GPGME_EVENT_DONE)
ctx->pending = 0;
if (ctx->io_cbs.event)
(*ctx->io_cbs.event) (ctx->io_cbs.event_priv, type, type_data);
}

View File

@ -1,26 +1,26 @@
/* wait.c
* Copyright (C) 2000 Werner Koch (dd9jn)
* Copyright (C) 2001, 2002 g10 Code GmbH
*
* This file is part of GPGME.
*
* GPGME is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GPGME is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
Copyright (C) 2000 Werner Koch (dd9jn)
Copyright (C) 2001, 2002, 2003 g10 Code GmbH
This file is part of GPGME.
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GPGME; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#if HAVE_CONFIG_H
#include <config.h>
#include <stdio.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <assert.h>
@ -35,28 +35,10 @@
#include "io.h"
#include "engine.h"
static struct fd_table fdt_global;
static GpgmeCtx *ctx_done_list;
static int ctx_done_list_size;
static int ctx_done_list_length;
DEFINE_STATIC_LOCK (ctx_done_list_lock);
static GpgmeIdleFunc idle_function;
struct wait_item_s
{
struct wait_item_s *next;
GpgmeIOCb handler;
void *handler_value;
int dir;
};
void
_gpgme_fd_table_init (fd_table_t fdt)
{
INIT_LOCK (fdt->lock);
fdt->fds = NULL;
fdt->size = 0;
}
@ -64,19 +46,18 @@ _gpgme_fd_table_init (fd_table_t fdt)
void
_gpgme_fd_table_deinit (fd_table_t fdt)
{
DESTROY_LOCK (fdt->lock);
if (fdt->fds)
free (fdt->fds);
}
/* XXX We should keep a marker and roll over for speed. */
GpgmeError
_gpgme_fd_table_put (fd_table_t fdt, int fd, int dir, void *opaque, int *idx)
static GpgmeError
fd_table_put (fd_table_t fdt, int fd, int dir, void *opaque, int *idx)
{
int i, j;
struct io_select_fd_s *new_fds;
LOCK (fdt->lock);
for (i = 0; i < fdt->size; i++)
{
if (fdt->fds[i].fd == -1)
@ -88,10 +69,7 @@ _gpgme_fd_table_put (fd_table_t fdt, int fd, int dir, void *opaque, int *idx)
new_fds = realloc (fdt->fds, (fdt->size + FDT_ALLOCSIZE)
* sizeof (*new_fds));
if (!new_fds)
{
UNLOCK (fdt->lock);
return mk_error (Out_Of_Core);
}
fdt->fds = new_fds;
fdt->size += FDT_ALLOCSIZE;
@ -105,272 +83,76 @@ _gpgme_fd_table_put (fd_table_t fdt, int fd, int dir, void *opaque, int *idx)
fdt->fds[i].frozen = 0;
fdt->fds[i].signaled = 0;
fdt->fds[i].opaque = opaque;
UNLOCK (fdt->lock);
*idx = i;
return 0;
}
/**
* gpgme_register_idle:
* @fnc: Callers idle function
*
* Register a function with GPGME called by GPGME whenever it feels
* that is is idle. NULL may be used to remove this function.
*
* Return value: The idle function pointer that was passed to the
* function at the last time it was invoked, or NULL if the function
* is invoked the first time.
**/
GpgmeIdleFunc
gpgme_register_idle (GpgmeIdleFunc idle)
{
GpgmeIdleFunc old_idle = idle_function;
idle_function = idle;
return old_idle;
}
/* Wait on all file descriptors listed in FDT and process them using
the registered callbacks. Returns -1 on error (with errno set), 0
if nothing to run and 1 if it did run something. */
static int
do_select (fd_table_t fdt)
{
int i, n;
int any = 0;
LOCK (fdt->lock);
n = _gpgme_io_select (fdt->fds, fdt->size, 0);
if (n <= 0)
{
UNLOCK (fdt->lock);
return n; /* Error or timeout. */
}
for (i = 0; i < fdt->size && n; i++)
{
if (fdt->fds[i].fd != -1 && fdt->fds[i].signaled)
{
struct wait_item_s *item;
assert (n);
n--;
item = (struct wait_item_s *) fdt->fds[i].opaque;
assert (item);
any = 1;
fdt->fds[i].signaled = 0;
UNLOCK (fdt->lock);
item->handler (item->handler_value, fdt->fds[i].fd);
LOCK (fdt->lock);
}
}
UNLOCK (fdt->lock);
return any;
}
void
_gpgme_wait_event_cb (void *data, GpgmeEventIO type, void *type_data)
{
if (type != GPGME_EVENT_DONE)
return;
if (ctx_done_list_size == ctx_done_list_length)
{
#define CTX_DONE_LIST_SIZE_INITIAL 8
int new_size = ctx_done_list_size ? 2 * ctx_done_list_size
: CTX_DONE_LIST_SIZE_INITIAL;
GpgmeCtx *new_list = realloc (ctx_done_list,
new_size * sizeof (GpgmeCtx *));
assert (new_list);
#if 0
if (!new_list)
return mk_error (Out_Of_Core);
#endif
ctx_done_list = new_list;
ctx_done_list_size = new_size;
}
ctx_done_list[ctx_done_list_length++] = (GpgmeCtx) data;
}
/**
* gpgme_wait:
* @c:
* @hang:
*
* Wait for a finished request, if @c is given the function does only
* wait on a finished request for that context, otherwise it will return
* on any request. When @hang is true the function will wait, otherwise
* it will return immediately when there is no pending finished request.
*
* Return value: Context of the finished request or NULL if @hang is false
* and no (or not the given) request has finished.
**/
GpgmeCtx
gpgme_wait (GpgmeCtx ctx, GpgmeError *status, int hang)
{
DEBUG2 ("waiting... ctx=%p hang=%d", ctx, hang);
do
{
int i;
/* XXX We are ignoring all errors from select here. */
do_select (&fdt_global);
LOCK (ctx_done_list_lock);
/* A process that is done is eligible for election if it is the
requested context or if it was not yet reported. */
for (i = 0; i < ctx_done_list_length; i++)
if (!ctx || ctx == ctx_done_list[i])
break;
if (i < ctx_done_list_length)
{
if (!ctx)
ctx = ctx_done_list[i];
hang = 0;
ctx->pending = 0;
if (--ctx_done_list_length)
memcpy (&ctx_done_list[i],
&ctx_done_list[i + 1],
(ctx_done_list_length - i) * sizeof (GpgmeCtx *));
}
UNLOCK (ctx_done_list_lock);
if (hang && idle_function)
idle_function ();
}
while (hang && (!ctx || !ctx->cancel));
if (ctx && ctx->cancel)
{
/* FIXME: Paranoia? */
ctx->cancel = 0;
ctx->pending = 0;
ctx->error = mk_error (Canceled);
}
if (ctx && status)
*status = ctx->error;
return ctx;
}
/* Register the file descriptor FD with the handler FNC (which gets
FNC_DATA as its first argument) for the direction DIR. DATA should
be the context for which the fd is added. R_TAG will hold the tag
that can be used to remove the fd. */
GpgmeError
_gpgme_wait_one (GpgmeCtx ctx)
{
return _gpgme_wait_on_condition (ctx, NULL);
}
GpgmeError
_gpgme_wait_on_condition (GpgmeCtx ctx, volatile int *cond)
{
GpgmeError err = 0;
int hang = 1;
DEBUG1 ("waiting... ctx=%p", ctx);
do
{
if (do_select (&ctx->fdt) < 0)
{
err = mk_error (File_Error);
hang = 0;
}
else if (cond && *cond)
hang = 0;
else
{
int any = 0;
int i;
LOCK (ctx->fdt.lock);
for (i = 0; i < ctx->fdt.size; i++)
{
if (ctx->fdt.fds[i].fd != -1)
{
any = 1;
break;
}
}
if (!any)
hang = 0;
UNLOCK (ctx->fdt.lock);
}
}
while (hang && !ctx->cancel);
if (!err && ctx->cancel)
{
/* FIXME: Paranoia? */
ctx->cancel = 0;
ctx->pending = 0;
ctx->error = mk_error (Canceled);
}
return err ? err : ctx->error;
}
struct tag
{
fd_table_t fdt;
int idx;
};
GpgmeError
_gpgme_add_io_cb (void *data, int fd, int dir,
GpgmeIOCb fnc, void *fnc_data, void **r_tag)
_gpgme_add_io_cb (void *data, int fd, int dir, GpgmeIOCb fnc, void *fnc_data,
void **r_tag)
{
GpgmeError err;
fd_table_t fdt = (fd_table_t) (data ? data : &fdt_global);
GpgmeCtx ctx = (GpgmeCtx) data;
fd_table_t fdt;
struct wait_item_s *item;
struct tag *tag;
assert (fdt);
assert (fnc);
assert (ctx);
fdt = &ctx->fdt;
assert (fdt);
*r_tag = NULL;
tag = malloc (sizeof *tag);
if (!tag)
return mk_error (Out_Of_Core);
tag->fdt = fdt;
tag->ctx = ctx;
/* Allocate a structure to hold info about the handler. */
/* Allocate a structure to hold information about the handler. */
item = calloc (1, sizeof *item);
if (!item)
{
free (tag);
return mk_error (Out_Of_Core);
}
item->ctx = ctx;
item->dir = dir;
item->handler = fnc;
item->handler_value = fnc_data;
err = _gpgme_fd_table_put (fdt, fd, dir, item, &tag->idx);
err = fd_table_put (fdt, fd, dir, item, &tag->idx);
if (err)
{
free (tag);
free (item);
return mk_error (Out_Of_Core);
return err;
}
*r_tag = tag;
return 0;
}
void
_gpgme_remove_io_cb (void *data)
{
struct tag *tag = data;
fd_table_t fdt = tag->fdt;
int idx = tag->idx;
GpgmeCtx ctx;
fd_table_t fdt;
int idx;
assert (tag);
ctx = tag->ctx;
assert (ctx);
fdt = &ctx->fdt;
assert (fdt);
idx = tag->idx;
LOCK (fdt->lock);
DEBUG2 ("setting fd %d (item=%p) done", fdt->fds[idx].fd,
fdt->fds[idx].opaque);
free (fdt->fds[idx].opaque);
@ -381,6 +163,4 @@ _gpgme_remove_io_cb (void *data)
fdt->fds[idx].for_read = 0;
fdt->fds[idx].for_write = 0;
fdt->fds[idx].opaque = NULL;
UNLOCK (fdt->lock);
}

View File

@ -1,23 +1,22 @@
/* wait.h - Definitions for the wait queue interface.
* Copyright (C) 2000 Werner Koch (dd9jn)
* Copyright (C) 2001, 2002 g10 Code GmbH
*
* This file is part of GPGME.
*
* GPGME is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GPGME is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
Copyright (C) 2000 Werner Koch (dd9jn)
Copyright (C) 2001, 2002, 2003 g10 Code GmbH
This file is part of GPGME.
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GPGME; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef WAIT_H
#define WAIT_H
@ -27,19 +26,49 @@
struct fd_table
{
DECLARE_LOCK (lock);
struct io_select_fd_s *fds;
size_t size;
};
typedef struct fd_table *fd_table_t;
/* Wait items are hooked into the io_select_fd_s to connect an fd with
a callback handler. */
struct wait_item_s
{
GpgmeCtx ctx;
GpgmeIOCb handler;
void *handler_value;
int dir;
};
/* A registered fd handler is removed later using the tag that
identifies it. */
struct tag
{
/* The context for which the fd was registered. */
GpgmeCtx ctx;
/* The index into the fd table for this context. */
int idx;
/* This is used by the wrappers for the user event loop. */
void *user_tag;
};
void _gpgme_fd_table_init (fd_table_t fdt);
void _gpgme_fd_table_deinit (fd_table_t fdt);
GpgmeError _gpgme_add_io_cb (void *data, int fd, int dir,
GpgmeIOCb fnc, void *fnc_data, void **r_tag);
void _gpgme_remove_io_cb (void *tag);
void _gpgme_wait_event_cb (void *data, GpgmeEventIO type, void *type_data);
void _gpgme_wait_private_event_cb (void *data, GpgmeEventIO type, void *type_data);
void _gpgme_wait_global_event_cb (void *data, GpgmeEventIO type, void *type_data);
GpgmeError _gpgme_wait_user_add_io_cb (void *data, int fd, int dir,
GpgmeIOCb fnc, void *fnc_data, void **r_tag);
void _gpgme_wait_user_remove_io_cb (void *tag);
void _gpgme_wait_user_event_cb (void *data, GpgmeEventIO type, void *type_data);
GpgmeError _gpgme_wait_one (GpgmeCtx ctx);