doc/
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:
parent
8a5c6d0de2
commit
2c543f6a86
27
NEWS
27
NEWS
@ -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)
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
117
gpgme/ChangeLog
117
gpgme/ChangeLog
@ -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.
|
||||
|
||||
|
@ -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 \
|
||||
|
@ -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;
|
||||
|
||||
|
48
gpgme/data.c
48
gpgme/data.c
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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:
|
||||
@ -152,12 +150,12 @@ _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;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
44
gpgme/edit.c
44
gpgme/edit.c
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
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);
|
||||
else if (ctx->result.encrypt->invalid_recipients)
|
||||
ctx->error = mk_error (Invalid_Recipients);
|
||||
}
|
||||
|
||||
void
|
||||
GpgmeError
|
||||
_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);
|
||||
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->result.encrypt->no_valid_recipients)
|
||||
return mk_error (No_Recipients);
|
||||
else if (ctx->result.encrypt->invalid_recipients)
|
||||
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)
|
||||
|
@ -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->io_cbs.remove) (gpgsm->status_cb.tag);
|
||||
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->io_cbs.remove) (gpgsm->input_cb.tag);
|
||||
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->io_cbs.remove) (gpgsm->output_cb.tag);
|
||||
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->io_cbs.remove) (gpgsm->message_cb.tag);
|
||||
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,68 +660,57 @@ 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
|
||||
&& line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
|
||||
&& (line[3] == '\0' || line[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] == ' '))
|
||||
{
|
||||
if (line[3] == ' ')
|
||||
err = map_assuan_error (atoi (&line[4]));
|
||||
else
|
||||
err = mk_error (General_Error);
|
||||
}
|
||||
else if (linelen >= 2
|
||||
&& line[0] == 'O' && line[1] == 'K'
|
||||
&& (line[2] == '\0' || line[2] == ' '))
|
||||
{
|
||||
/* 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] == ' ')
|
||||
{
|
||||
err = map_assuan_error (atoi (&line[4]));
|
||||
if (!err)
|
||||
err = mk_error (General_Error);
|
||||
}
|
||||
if (err)
|
||||
{
|
||||
/* 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
|
||||
&& line[0] == 'D' && line[1] == ' '
|
||||
&& gpgsm->colon.fnc)
|
||||
else if (linelen > 2
|
||||
&& line[0] == 'D' && line[1] == ' '
|
||||
&& gpgsm->colon.fnc)
|
||||
{
|
||||
/* We are using the colon handler even for plain inline data
|
||||
- strange name for that function but for historic reasons
|
||||
@ -756,59 +728,64 @@ status_handler (void *opaque, int fd)
|
||||
< *alinelen + linelen + 1)
|
||||
{
|
||||
unsigned char *newline = realloc (*aline,
|
||||
*alinelen + linelen + 1);
|
||||
*alinelen + linelen + 1);
|
||||
if (!newline)
|
||||
{
|
||||
_gpgme_io_close (gpgsm->status_cb.fd);
|
||||
return;
|
||||
}
|
||||
*aline = newline;
|
||||
gpgsm->colon.attic.linesize += linelen + 1;
|
||||
}
|
||||
|
||||
dst = *aline + *alinelen;
|
||||
|
||||
while (src < end)
|
||||
{
|
||||
if (*src == '%' && src + 2 < end)
|
||||
{
|
||||
/* Handle escaped characters. */
|
||||
++src;
|
||||
*dst = xtoi_2 (src);
|
||||
(*alinelen)++;
|
||||
src += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
*dst = *src++;
|
||||
(*alinelen)++;
|
||||
}
|
||||
|
||||
if (*dst == '\n')
|
||||
{
|
||||
/* Terminate the pending line, pass it to the colon
|
||||
handler and reset it. */
|
||||
|
||||
gpgsm->colon.any = 1;
|
||||
if (*alinelen > 1 && *(dst - 1) == '\r')
|
||||
dst--;
|
||||
*dst = '\0';
|
||||
|
||||
/* FIXME How should we handle the return code? */
|
||||
gpgsm->colon.fnc (gpgsm->colon.fnc_value, *aline);
|
||||
dst = *aline;
|
||||
*alinelen = 0;
|
||||
}
|
||||
err = mk_error (Out_Of_Core);
|
||||
else
|
||||
dst++;
|
||||
}
|
||||
{
|
||||
*aline = newline;
|
||||
gpgsm->colon.attic.linesize += linelen + 1;
|
||||
}
|
||||
}
|
||||
if (!err)
|
||||
{
|
||||
dst = *aline + *alinelen;
|
||||
|
||||
while (!err && src < end)
|
||||
{
|
||||
if (*src == '%' && src + 2 < end)
|
||||
{
|
||||
/* Handle escaped characters. */
|
||||
++src;
|
||||
*dst = xtoi_2 (src);
|
||||
(*alinelen)++;
|
||||
src += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
*dst = *src++;
|
||||
(*alinelen)++;
|
||||
}
|
||||
|
||||
if (*dst == '\n')
|
||||
{
|
||||
/* Terminate the pending line, pass it to the colon
|
||||
handler and reset it. */
|
||||
|
||||
gpgsm->colon.any = 1;
|
||||
if (*alinelen > 1 && *(dst - 1) == '\r')
|
||||
dst--;
|
||||
*dst = '\0';
|
||||
|
||||
/* FIXME How should we handle the return code? */
|
||||
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] == ' ')
|
||||
&& line[0] == 'S' && line[1] == ' ')
|
||||
{
|
||||
char *rest;
|
||||
GpgmeStatusCode r;
|
||||
|
||||
|
||||
rest = strchr (line + 2, ' ');
|
||||
if (!rest)
|
||||
rest = line + linelen; /* set to an empty string */
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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. */
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -83,14 +83,12 @@ 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)
|
||||
switch (code)
|
||||
{
|
||||
case GPGME_STATUS_TRUNCATED:
|
||||
ctx->result.keylist->truncated = 1;
|
||||
@ -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;
|
||||
}
|
||||
/* The only kind of error we can get. */
|
||||
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;
|
||||
|
@ -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);
|
||||
|
59
gpgme/ops.h
59
gpgme/ops.h
@ -25,23 +25,20 @@
|
||||
|
||||
/* Support macros. */
|
||||
|
||||
#define test_and_allocate_result(ctx,field) \
|
||||
do \
|
||||
{ \
|
||||
if (!ctx->result.field) \
|
||||
{ \
|
||||
ctx->result.field = calloc (1, sizeof *ctx->result.field); \
|
||||
if (!ctx->result.field) \
|
||||
{ \
|
||||
ctx->error = mk_error (Out_Of_Core); \
|
||||
return; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
#define test_and_allocate_result(ctx,field) \
|
||||
do \
|
||||
{ \
|
||||
if (!ctx->result.field) \
|
||||
{ \
|
||||
ctx->result.field = calloc (1, sizeof *ctx->result.field); \
|
||||
if (!ctx->result.field) \
|
||||
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,13 +81,13 @@ 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,
|
||||
char *args);
|
||||
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,
|
||||
char *args);
|
||||
GpgmeError _gpgme_decrypt_status_handler (GpgmeCtx ctx, GpgmeStatusCode code,
|
||||
char *args);
|
||||
GpgmeError _gpgme_decrypt_start (GpgmeCtx ctx, int synchronous,
|
||||
GpgmeData ciph, GpgmeData plain,
|
||||
void *status_handler);
|
||||
@ -98,26 +95,26 @@ GpgmeError _gpgme_decrypt_result (GpgmeCtx ctx);
|
||||
|
||||
/*-- sign.c --*/
|
||||
void _gpgme_release_sign_result ( SignResult res );
|
||||
void _gpgme_sign_status_handler (GpgmeCtx ctx, GpgmeStatusCode code,
|
||||
char *args);
|
||||
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,
|
||||
char *args);
|
||||
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,
|
||||
char *args);
|
||||
const char * _gpgme_passphrase_command_handler (void *opaque,
|
||||
GpgmeStatusCode code,
|
||||
const char *key);
|
||||
GpgmeError _gpgme_passphrase_status_handler (GpgmeCtx ctx, GpgmeStatusCode code,
|
||||
char *args);
|
||||
GpgmeError _gpgme_passphrase_command_handler (void *opaque,
|
||||
GpgmeStatusCode code,
|
||||
const char *key, const char **result);
|
||||
GpgmeError _gpgme_passphrase_start (GpgmeCtx ctx);
|
||||
|
||||
/*-- progress.c --*/
|
||||
void _gpgme_progress_status_handler (GpgmeCtx ctx, GpgmeStatusCode code,
|
||||
char *args);
|
||||
GpgmeError _gpgme_progress_status_handler (GpgmeCtx ctx, GpgmeStatusCode code,
|
||||
char *args);
|
||||
|
||||
/*-- import.c --*/
|
||||
void _gpgme_release_import_result (ImportResult res);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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->io_cbs.remove) (gpg->status.tag);
|
||||
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->io_cbs.remove) (gpg->colon.tag);
|
||||
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->io_cbs.remove) (gpg->fd_data_map[i].tag);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@ -1198,6 +1162,8 @@ start (GpgObject gpg)
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
(*gpg->io_cbs.event) (gpg->io_cbs.event_priv, GPGME_EVENT_START, NULL);
|
||||
|
||||
/* fixme: check what data we can release here */
|
||||
return 0;
|
||||
|
13
gpgme/sign.c
13
gpgme/sign.c
@ -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
|
||||
|
@ -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;
|
||||
|
@ -35,11 +35,11 @@ typedef unsigned long ulong;
|
||||
* Declaration of internal objects
|
||||
*/
|
||||
|
||||
typedef void (*GpgmeStatusHandler) (GpgmeCtx, GpgmeStatusCode code,
|
||||
char *args);
|
||||
typedef void (*GpgmeColonLineHandler) (GpgmeCtx, char *line);
|
||||
typedef const char *(*GpgmeCommandHandler) (void*, GpgmeStatusCode code,
|
||||
const char *keyword);
|
||||
typedef GpgmeError (*GpgmeStatusHandler) (GpgmeCtx, GpgmeStatusCode code,
|
||||
char *args);
|
||||
typedef GpgmeError (*GpgmeColonLineHandler) (GpgmeCtx, char *line);
|
||||
typedef GpgmeError (*GpgmeCommandHandler) (void*, GpgmeStatusCode code,
|
||||
const char *keyword, const char **result);
|
||||
|
||||
|
||||
/*-- engine.c --*/
|
||||
|
@ -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
356
gpgme/wait-global.c
Normal 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
153
gpgme/wait-private.c
Normal 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
127
gpgme/wait-user.c
Normal 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);
|
||||
}
|
324
gpgme/wait.c
324
gpgme/wait.c
@ -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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
|
71
gpgme/wait.h
71
gpgme/wait.h
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user