2002-06-10 Marcus Brinkmann <marcus@g10code.de>

* engine-gpgsm.c (_gpgme_gpgsm_start): Move the code that sets the
	close notification for the status fd to ...
	(_gpgme_gpgsm_new): ... here.
	* wait.h: Include "sema.h".  Remove prototypes of
	_gpgme_remove_proc_from_wait_queue and
	_gpgme_register_pipe_handler.  Add prototypes of
	_gpgme_fd_table_init, _gpgme_fd_table_deinit, _gpgme_fd_table_put,
	_gpgme_add_io_cb, _gpgme_remove_io_cb, _gpgme_wait_event_cb and
	_gpgme_wait_one..
	* wait.c: Remove global variables PROC_QUEUE, PROC_QUEUE_LOCK,
	FD_TABLE_SIZE, FD_TABLE, FD_TABLE_LOCK.  New global variables
	FDT_GLOBAL, CTX_DONE_LIST, CTX_DONE_LIST_SIZE,
	CTX_DONE_LIST_LENGTH and CTX_DONE_LIST_LOCK.  Remove struct
	proc_s.  Replace struct wait_item_s.
	(_gpgme_fd_table_init): New function.
	(_gpgme_fd_table_deinit): Likewise.
	(_gpgme_fd_table_put): Likewise.
	(set_process_done): Remove function.
	(do_select): Take argument FDT.  Use that to decide which fds to
	select on.
	(_gpgme_remove_proc_from_wait_queue): Remove function.
	(_gpgme_wait_event_cb): New function.
	(_gpgme_wait_one): Likewise.
	(_gpgme_register_pipe_hanldler): Remove function.
	(_gpgme_add_io_cb): New function.
	(_gpgme_remove_io_cb): Likewise.
	(_gpgme_freeze_fd): Remove function.
	(_gpgme_thaw_fd): Remove function.
	* rungpg.c (struct fd_data_map_s): Add new member TAG.
	(struct gpg_object_s): Likewise for STATUS and COLON.  Add member
	IDX to CMD.  Add new member IO_CBS.
	(close_notify_handler): New variables POSSIBLY_DONE and NOT_DONE.
	For each I/O callback, check if it should be unregistered.  If all
	callbacks have been unregistered, trigger GPGME_EVENT_DONE.
	Remove member RUNNING.
	(_gpgme_gpg_new): Initialize new members.
	(_gpgme_gpg_release): Check PID not RUNNING.  Don't call
	_gpgme_remove_proc_from_wait_queue.  Close GPG->CMD.FD if set.
	(build_argv): Store away the index instead the file descriptor for
	CMD.
	(_gpgme_gpg_add_io_cb): New function.
	(_gpgme_gpg_spawn): Use _gpgme_gpg_add_io_cb to register IO
	callbacks.
	(gpg_status_handler): Change return type to void, remove PID
	argument, close filedescriptor if EOF or error occurs.
	(read_status): Use _gpgme_gpg_add_io_cb instead _gpgme_thaw_fd.
	Use IO_CBS->remove instead _gpgme_freeze_fd.
	(gpg_colon_line_handler): Change return type to void, remove PID
	argument, close filedescriptor if EOF or error occurs.
	(command_cb): Use IO_CBS->remove instead _gpgme_freeze_fd.
	(_gpgme_gpg_set_io_cbs): New function.
	* rungpg.h (_gpgme_gpg_set_io_cbs): Prototype for
	_gpgme_gpg_set_io_cbs.
	* gpgme.h (GpgmeIOCb): New type.
	(GpgmeRegisterIOCb): Likewise.
	(GpgmeRemoveIOCb): Likewise.
	(GpgmeEventIO): Likewise.
	(GpgmeEventIOCb): Likewise.
	(struct GpgmeIOCbs): New structure to hold I/O callbacks.
	(gpgme_set_op_io_cbs): New prototype.
	(gpgme_get_op_io_cbs): Likewise.
	* ops.h: New prototype for _gpgme_op_event_cb.  Remove prototypes
	for _gpgme_freeze_fd and _gpgme_thaw_fd.  Remove PID argument from
	_gpgme_data_inbound_handler and _gpgme_data_outbound_handler
	prototype.  Add prototype for _gpgme_op_reset.
	Add synchronous argument to _gpgme_decrypt_start prototype.
	* io.h: Beautification.
	* gpgme.c: Include "wait.h".
	(gpgme_new): Initialize FDT.
	(gpgme_set_io_cbs): New function.
	(gpgme_get_io_cbs): Likewise.
	(_gpgme_op_event_cb): Likewise.
	* data.c (_gpgme_data_inbound_handler): Change return type to
	void.  Drop PID argument.  Close FD on error and EOF.
	(write_mem_data): Don't close FD here ...
	(write_cb_data): ... or here ...
	(_gpgme_data_outbound_handler): ... but here.  Change return type
	to void.  Drop PID argument.
	* context.h: Include "wait.h".
	(struct gpgme_context_s): New members FDT and IO_CBS.
	* op-support.c: New file.
	* Makefile.am (libgpgme_la_SOURCES): Add op-support.c.
	* ops.h: Add prototype for _gpgme_op_reset().
	* decrypt.c (_gpgme_decrypt_start): New argument SYNCHRONOUS.  Use
	_gpgme_op_reset.
	(gpgme_op_decrypt_start): Add synchronous argument.
	(gpgme_op_decrypt): Likewise.  Use _gpgme_wait_one instead
	gpgme_wait.
	* delete.c (gpgme_op_delete_start): Rename to ...
	(_gpgme_op_delete_start): ... this.  New argument SYNCHRONOUS.
	Use _gpgme_op_reset.  Make function static.
	(gpgme_op_delete_start): Just a wrapper around
	_gpgme_op_delete_start now.
	(gpgme_op_delete): Add synchronous argument.  Use _gpgme_wait_one
	instead gpgme_wait.
	* encrypt.c: Include "wait.h".
	(ggpgme_op_encrypt_start): Rename to ...
	(_gpgme_op_encrypt_start): ... this.  New argument SYNCHRONOUS.
	Use _gpgme_op_reset.  Make function static.
	(gpgme_op_encrypt_start): Just a wrapper around
	_gpgme_op_encrypt_start now.
	(gpgme_op_encrypt): Add synchronous argument.  Use _gpgme_wait_one
	instead gpgme_wait.
	* encrypt_sign.c (gpgme_op_encrypt_sign_start): Rename to ...
	(_gpgme_op_encrypt_sign_start): ... this.  New argument
	SYNCHRONOUS.  Use _gpgme_op_reset.  Make function static.
	(gpgme_op_encrypt_sign_start): Just a wrapper around
	_gpgme_op_encrypt_sign_start now.
	(gpgme_op_encrypt_sign): Add synchronous argument.  Use
	_gpgme_wait_one instead gpgme_wait.
	* export.c (gpgme_op_export_start): Rename to ...
	(_gpgme_op_export_start): ... this.  New argument SYNCHRONOUS.
	Use _gpgme_op_reset.  Make function static.
	(gpgme_op_export_start): Just a wrapper around
	_gpgme_op_export_start now.
	(gpgme_op_export): Add synchronous argument.  Use _gpgme_wait_one
	instead gpgme_wait.
	* genkey.c (gpgme_op_genkey_start): Rename to ...
	(_gpgme_op_genkey_start): ... this.  New argument SYNCHRONOUS.
	Use _gpgme_op_reset.  Make function static.
	(gpgme_op_genkey_start): Just a wrapper around
	_gpgme_op_genkey_start now.
	(gpgme_op_genkey): Add synchronous argument.  Use _gpgme_wait_one
	instead gpgme_wait.
	* import.c (gpgme_op_import_start): Rename to ...
	(_gpgme_op_import_start): ... this.  New argument SYNCHRONOUS.
	Use _gpgme_op_reset.  Make function static.
	(gpgme_op_import_start): Just a wrapper around
	_gpgme_op_import_start now.
	(gpgme_op_import): Add synchronous argument.  Use _gpgme_wait_one
	instead gpgme_wait.
	* keylist.c (gpgme_op_keylist_start): Use _gpgme_op_reset.
	(gpgme_op_keylist_ext_start): Likewise.
	* sign.c (gpgme_op_sign_start): Rename to ...
	(_gpgme_op_sign_start): ... this.  New argument SYNCHRONOUS.  Use
	_gpgme_op_reset.  Make function static.
	(gpgme_op_sign_start): Just a wrapper around _gpgme_op_sign_start
	now.
	(gpgme_op_sign): Add synchronous argument.  Use _gpgme_wait_one
	instead gpgme_wait.
	* trustlist.c (gpgme_op_trustlist_start): Use _gpgme_op_reset.
	* verify.c (gpgme_op_verify_start): Rename to ...
	(_gpgme_op_verify_start): ... this.  New argument SYNCHRONOUS.
	Use _gpgme_op_reset.  Make function static.
	(gpgme_op_verify_start): Just a wrapper around
	_gpgme_op_verify_start now.
	(gpgme_op_verify): Add synchronous argument.  Use _gpgme_wait_one
	instead gpgme_wait.
	* engine-gpgsm.c (iocb_data_t): New type.
	(struct gpgsm_object_s): New member status_cb.  Replace input_fd
	and input_data with input_cb.  Replace output_fd and output_data
	with output_cb.  Replace message_fd and message_data with
	message_cb.  New member io_cbs.
	(_gpgme_gpgsm_new): Initialize all new members (and drop the old
	ones).
	(close_notify_handler): New variable POSSIBLY_DONE.  For each I/O
	callback, check if it should be unregistered.  If all callbacks
	have been unregistered, trigger GPGME_EVENT_DONE.
	(_gpgme_gpgsm_release): Remove variable PID.  Use new variable
	names to close the file descriptors.
	(_gpgme_gpgsm_op_decrypt): Use new variable names,
	(_gpgme_gpgsm_op_encrypt): Likewise.
	(_gpgme_gpgsm_op_genkey): Likewise.
	(_gpgme_gpgsm_op_import): Likewise.
	(_gpgme_gpgsm_op_keylist): Likewise.
	(_gpgme_gpgsm_op_keylist_ext): Likewise.
	(_gpgme_gpgsm_op_sign): Likewise.
	(_gpgme_gpgsm_op_verify): Likewise.
	(gpgsm_status_handler): Drop argument PID.  Change return type to
	void.  Close status pipe before returning because of EOF or error.
	(_gpgme_gpgsm_add_io_cb): New function.
	(_gpgme_gpgsm_start): Use _gpgme_gpgsm_add_io_cb to register
	callback function.
	(_gpgme_gpgsm_set_io_cbs): New function.
	* engine-gpgsm.h: New prototype for _gpgme_gpgsm_set_io_cbs.
	* engine.c (_gpgme_engine_set_io_cbs): New function.
	* engine.h: New prototype for _gpgme_engine_set_io_cbs.
This commit is contained in:
Marcus Brinkmann 2002-06-10 14:13:55 +00:00
parent 7b8ab474d3
commit 5b75138331
29 changed files with 1767 additions and 1299 deletions

View File

@ -1,3 +1,183 @@
2002-06-10 Marcus Brinkmann <marcus@g10code.de>
* engine-gpgsm.c (_gpgme_gpgsm_start): Move the code that sets the
close notification for the status fd to ...
(_gpgme_gpgsm_new): ... here.
* wait.h: Include "sema.h". Remove prototypes of
_gpgme_remove_proc_from_wait_queue and
_gpgme_register_pipe_handler. Add prototypes of
_gpgme_fd_table_init, _gpgme_fd_table_deinit, _gpgme_fd_table_put,
_gpgme_add_io_cb, _gpgme_remove_io_cb, _gpgme_wait_event_cb and
_gpgme_wait_one..
* wait.c: Remove global variables PROC_QUEUE, PROC_QUEUE_LOCK,
FD_TABLE_SIZE, FD_TABLE, FD_TABLE_LOCK. New global variables
FDT_GLOBAL, CTX_DONE_LIST, CTX_DONE_LIST_SIZE,
CTX_DONE_LIST_LENGTH and CTX_DONE_LIST_LOCK. Remove struct
proc_s. Replace struct wait_item_s.
(_gpgme_fd_table_init): New function.
(_gpgme_fd_table_deinit): Likewise.
(_gpgme_fd_table_put): Likewise.
(set_process_done): Remove function.
(do_select): Take argument FDT. Use that to decide which fds to
select on.
(_gpgme_remove_proc_from_wait_queue): Remove function.
(_gpgme_wait_event_cb): New function.
(_gpgme_wait_one): Likewise.
(_gpgme_register_pipe_hanldler): Remove function.
(_gpgme_add_io_cb): New function.
(_gpgme_remove_io_cb): Likewise.
(_gpgme_freeze_fd): Remove function.
(_gpgme_thaw_fd): Remove function.
* rungpg.c (struct fd_data_map_s): Add new member TAG.
(struct gpg_object_s): Likewise for STATUS and COLON. Add member
IDX to CMD. Add new member IO_CBS.
(close_notify_handler): New variables POSSIBLY_DONE and NOT_DONE.
For each I/O callback, check if it should be unregistered. If all
callbacks have been unregistered, trigger GPGME_EVENT_DONE.
Remove member RUNNING.
(_gpgme_gpg_new): Initialize new members.
(_gpgme_gpg_release): Check PID not RUNNING. Don't call
_gpgme_remove_proc_from_wait_queue. Close GPG->CMD.FD if set.
(build_argv): Store away the index instead the file descriptor for
CMD.
(_gpgme_gpg_add_io_cb): New function.
(_gpgme_gpg_spawn): Use _gpgme_gpg_add_io_cb to register IO
callbacks.
(gpg_status_handler): Change return type to void, remove PID
argument, close filedescriptor if EOF or error occurs.
(read_status): Use _gpgme_gpg_add_io_cb instead _gpgme_thaw_fd.
Use IO_CBS->remove instead _gpgme_freeze_fd.
(gpg_colon_line_handler): Change return type to void, remove PID
argument, close filedescriptor if EOF or error occurs.
(command_cb): Use IO_CBS->remove instead _gpgme_freeze_fd.
(_gpgme_gpg_set_io_cbs): New function.
* rungpg.h (_gpgme_gpg_set_io_cbs): Prototype for
_gpgme_gpg_set_io_cbs.
* gpgme.h (GpgmeIOCb): New type.
(GpgmeRegisterIOCb): Likewise.
(GpgmeRemoveIOCb): Likewise.
(GpgmeEventIO): Likewise.
(GpgmeEventIOCb): Likewise.
(struct GpgmeIOCbs): New structure to hold I/O callbacks.
(gpgme_set_op_io_cbs): New prototype.
(gpgme_get_op_io_cbs): Likewise.
* ops.h: New prototype for _gpgme_op_event_cb. Remove prototypes
for _gpgme_freeze_fd and _gpgme_thaw_fd. Remove PID argument from
_gpgme_data_inbound_handler and _gpgme_data_outbound_handler
prototype. Add prototype for _gpgme_op_reset.
Add synchronous argument to _gpgme_decrypt_start prototype.
* io.h: Beautification.
* gpgme.c: Include "wait.h".
(gpgme_new): Initialize FDT.
(gpgme_set_io_cbs): New function.
(gpgme_get_io_cbs): Likewise.
(_gpgme_op_event_cb): Likewise.
* data.c (_gpgme_data_inbound_handler): Change return type to
void. Drop PID argument. Close FD on error and EOF.
(write_mem_data): Don't close FD here ...
(write_cb_data): ... or here ...
(_gpgme_data_outbound_handler): ... but here. Change return type
to void. Drop PID argument.
* context.h: Include "wait.h".
(struct gpgme_context_s): New members FDT and IO_CBS.
* op-support.c: New file.
* Makefile.am (libgpgme_la_SOURCES): Add op-support.c.
* ops.h: Add prototype for _gpgme_op_reset().
* decrypt.c (_gpgme_decrypt_start): New argument SYNCHRONOUS. Use
_gpgme_op_reset.
(gpgme_op_decrypt_start): Add synchronous argument.
(gpgme_op_decrypt): Likewise. Use _gpgme_wait_one instead
gpgme_wait.
* delete.c (gpgme_op_delete_start): Rename to ...
(_gpgme_op_delete_start): ... this. New argument SYNCHRONOUS.
Use _gpgme_op_reset. Make function static.
(gpgme_op_delete_start): Just a wrapper around
_gpgme_op_delete_start now.
(gpgme_op_delete): Add synchronous argument. Use _gpgme_wait_one
instead gpgme_wait.
* encrypt.c: Include "wait.h".
(ggpgme_op_encrypt_start): Rename to ...
(_gpgme_op_encrypt_start): ... this. New argument SYNCHRONOUS.
Use _gpgme_op_reset. Make function static.
(gpgme_op_encrypt_start): Just a wrapper around
_gpgme_op_encrypt_start now.
(gpgme_op_encrypt): Add synchronous argument. Use _gpgme_wait_one
instead gpgme_wait.
* encrypt_sign.c (gpgme_op_encrypt_sign_start): Rename to ...
(_gpgme_op_encrypt_sign_start): ... this. New argument
SYNCHRONOUS. Use _gpgme_op_reset. Make function static.
(gpgme_op_encrypt_sign_start): Just a wrapper around
_gpgme_op_encrypt_sign_start now.
(gpgme_op_encrypt_sign): Add synchronous argument. Use
_gpgme_wait_one instead gpgme_wait.
* export.c (gpgme_op_export_start): Rename to ...
(_gpgme_op_export_start): ... this. New argument SYNCHRONOUS.
Use _gpgme_op_reset. Make function static.
(gpgme_op_export_start): Just a wrapper around
_gpgme_op_export_start now.
(gpgme_op_export): Add synchronous argument. Use _gpgme_wait_one
instead gpgme_wait.
* genkey.c (gpgme_op_genkey_start): Rename to ...
(_gpgme_op_genkey_start): ... this. New argument SYNCHRONOUS.
Use _gpgme_op_reset. Make function static.
(gpgme_op_genkey_start): Just a wrapper around
_gpgme_op_genkey_start now.
(gpgme_op_genkey): Add synchronous argument. Use _gpgme_wait_one
instead gpgme_wait.
* import.c (gpgme_op_import_start): Rename to ...
(_gpgme_op_import_start): ... this. New argument SYNCHRONOUS.
Use _gpgme_op_reset. Make function static.
(gpgme_op_import_start): Just a wrapper around
_gpgme_op_import_start now.
(gpgme_op_import): Add synchronous argument. Use _gpgme_wait_one
instead gpgme_wait.
* keylist.c (gpgme_op_keylist_start): Use _gpgme_op_reset.
(gpgme_op_keylist_ext_start): Likewise.
* sign.c (gpgme_op_sign_start): Rename to ...
(_gpgme_op_sign_start): ... this. New argument SYNCHRONOUS. Use
_gpgme_op_reset. Make function static.
(gpgme_op_sign_start): Just a wrapper around _gpgme_op_sign_start
now.
(gpgme_op_sign): Add synchronous argument. Use _gpgme_wait_one
instead gpgme_wait.
* trustlist.c (gpgme_op_trustlist_start): Use _gpgme_op_reset.
* verify.c (gpgme_op_verify_start): Rename to ...
(_gpgme_op_verify_start): ... this. New argument SYNCHRONOUS.
Use _gpgme_op_reset. Make function static.
(gpgme_op_verify_start): Just a wrapper around
_gpgme_op_verify_start now.
(gpgme_op_verify): Add synchronous argument. Use _gpgme_wait_one
instead gpgme_wait.
* engine-gpgsm.c (iocb_data_t): New type.
(struct gpgsm_object_s): New member status_cb. Replace input_fd
and input_data with input_cb. Replace output_fd and output_data
with output_cb. Replace message_fd and message_data with
message_cb. New member io_cbs.
(_gpgme_gpgsm_new): Initialize all new members (and drop the old
ones).
(close_notify_handler): New variable POSSIBLY_DONE. For each I/O
callback, check if it should be unregistered. If all callbacks
have been unregistered, trigger GPGME_EVENT_DONE.
(_gpgme_gpgsm_release): Remove variable PID. Use new variable
names to close the file descriptors.
(_gpgme_gpgsm_op_decrypt): Use new variable names,
(_gpgme_gpgsm_op_encrypt): Likewise.
(_gpgme_gpgsm_op_genkey): Likewise.
(_gpgme_gpgsm_op_import): Likewise.
(_gpgme_gpgsm_op_keylist): Likewise.
(_gpgme_gpgsm_op_keylist_ext): Likewise.
(_gpgme_gpgsm_op_sign): Likewise.
(_gpgme_gpgsm_op_verify): Likewise.
(gpgsm_status_handler): Drop argument PID. Change return type to
void. Close status pipe before returning because of EOF or error.
(_gpgme_gpgsm_add_io_cb): New function.
(_gpgme_gpgsm_start): Use _gpgme_gpgsm_add_io_cb to register
callback function.
(_gpgme_gpgsm_set_io_cbs): New function.
* engine-gpgsm.h: New prototype for _gpgme_gpgsm_set_io_cbs.
* engine.c (_gpgme_engine_set_io_cbs): New function.
* engine.h: New prototype for _gpgme_engine_set_io_cbs.
2002-06-04 Marcus Brinkmann <marcus@g10code.de>
* Makefile.am (libgpgme_la_SOURCES): Remove mutex.h.

View File

@ -58,7 +58,8 @@ libgpgme_la_SOURCES = \
util.h util.c \
context.h ops.h \
data.c recipient.c signers.c \
wait.c wait.h \
wait.c wait.h \
op-support.c \
encrypt.c \
encrypt-sign.c \
decrypt.c \

View File

@ -25,14 +25,18 @@
#include "gpgme.h"
#include "types.h"
#include "engine.h"
#include "wait.h"
struct key_queue_item_s {
struct key_queue_item_s *next;
GpgmeKey key;
struct key_queue_item_s
{
struct key_queue_item_s *next;
GpgmeKey key;
};
struct trust_queue_item_s {
struct trust_queue_item_s *next;
GpgmeTrustItem item;
struct trust_queue_item_s
{
struct trust_queue_item_s *next;
GpgmeTrustItem item;
};
@ -98,6 +102,11 @@ struct gpgme_context_s
GpgmeProgressCb progress_cb;
void *progress_cb_value;
/* A list of file descriptors in active use by the current
(synchronous) operation. */
struct fd_table fdt;
struct GpgmeIOCbs io_cbs;
GpgmeData help_data_1;
};

View File

@ -874,8 +874,8 @@ _gpgme_data_append_percentstring_for_xml (GpgmeData dh, const char *string)
/* Functions to support the wait interface. */
int
_gpgme_data_inbound_handler (void *opaque, int pid, int fd)
void
_gpgme_data_inbound_handler (void *opaque, int fd)
{
GpgmeData dh = opaque;
GpgmeError err;
@ -889,11 +889,14 @@ _gpgme_data_inbound_handler (void *opaque, int pid, int fd)
{
DEBUG3 ("read_mem_data: read failed on fd %d (n=%d): %s",
fd, nread, strerror (errno) );
return 1;
_gpgme_io_close (fd); /* XXX ??? */
return;
}
else if (!nread)
return 1; /* eof */
{
_gpgme_io_close (fd);
return; /* eof */
}
/* We could improve this with a GpgmeData function which takes
* the read function or provides a memory area for writing to it.
*/
@ -905,10 +908,11 @@ _gpgme_data_inbound_handler (void *opaque, int pid, int fd)
gpgme_strerror(err));
/* Fixme: we should close the pipe or read it to /dev/null in
* this case. Returnin EOF is not sufficient */
return 1;
_gpgme_io_close (fd); /* XXX ??? */
return;
}
return 0;
return;
}
static int
@ -920,7 +924,6 @@ write_mem_data (GpgmeData dh, int fd)
nbytes = dh->len - dh->readpos;
if (!nbytes)
{
_gpgme_io_close (fd);
return 1;
}
@ -938,7 +941,6 @@ write_mem_data (GpgmeData dh, int fd)
{
DEBUG3 ("write_mem_data(%d): write failed (n=%d): %s",
fd, nwritten, strerror (errno));
_gpgme_io_close (fd);
return 1;
}
@ -956,7 +958,6 @@ write_cb_data (GpgmeData dh, int fd)
err = gpgme_data_read (dh, buffer, DIM(buffer), &nbytes);
if (err == GPGME_EOF)
{
_gpgme_io_close (fd);
return 1;
}
@ -967,7 +968,6 @@ write_cb_data (GpgmeData dh, int fd)
{
DEBUG3 ("write_cb_data(%d): write failed (n=%d): %s",
fd, nwritten, strerror (errno));
_gpgme_io_close (fd);
return 1;
}
@ -977,15 +977,14 @@ write_cb_data (GpgmeData dh, int fd)
if (_gpgme_data_unread (dh, buffer + nwritten, nbytes - nwritten))
DEBUG1 ("wite_cb_data: unread of %d bytes failed\n",
nbytes - nwritten);
_gpgme_io_close (fd);
return 1;
}
return 0;
}
int
_gpgme_data_outbound_handler (void *opaque, int pid, int fd)
void
_gpgme_data_outbound_handler (void *opaque, int fd)
{
GpgmeData dh = opaque;
@ -994,15 +993,13 @@ _gpgme_data_outbound_handler (void *opaque, int pid, int fd)
{
case GPGME_DATA_TYPE_MEM:
if (write_mem_data (dh, fd))
return 1; /* ready */
_gpgme_io_close (fd);
break;
case GPGME_DATA_TYPE_CB:
if (write_cb_data (dh, fd))
return 1; /* ready */
_gpgme_io_close (fd);
break;
default:
assert (0);
}
return 0;
}

View File

@ -41,7 +41,7 @@ decrypt_verify_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
GpgmeError
gpgme_op_decrypt_verify_start (GpgmeCtx ctx, GpgmeData ciph, GpgmeData plain)
{
return _gpgme_decrypt_start (ctx, ciph, plain,
return _gpgme_decrypt_start (ctx, 0, ciph, plain,
decrypt_verify_status_handler);
}
@ -69,10 +69,11 @@ gpgme_op_decrypt_verify (GpgmeCtx ctx,
ctx->notation = NULL;
*r_stat = GPGME_SIG_STAT_NONE;
err = gpgme_op_decrypt_verify_start (ctx, in, out);
err = _gpgme_decrypt_start (ctx, 1, in, out,
decrypt_verify_status_handler);
if (!err)
{
gpgme_wait (ctx, &err, 1);
err = _gpgme_wait_one (ctx);
if (!err)
*r_stat = _gpgme_intersect_stati (ctx->result.verify);
}

View File

@ -80,20 +80,12 @@ _gpgme_decrypt_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
GpgmeError
_gpgme_decrypt_start (GpgmeCtx ctx, GpgmeData ciph, GpgmeData plain,
void *status_handler)
_gpgme_decrypt_start (GpgmeCtx ctx, int synchronous,
GpgmeData ciph, GpgmeData plain, void *status_handler)
{
GpgmeError err = 0;
fail_on_pending_request (ctx);
ctx->pending = 1;
_gpgme_release_result (ctx);
/* Create a process object. */
_gpgme_engine_release (ctx->engine);
err = _gpgme_engine_new (ctx->use_cms ? GPGME_PROTOCOL_CMS
: GPGME_PROTOCOL_OpenPGP, &ctx->engine);
err = _gpgme_op_reset (ctx, synchronous);
if (err)
goto leave;
@ -138,7 +130,7 @@ _gpgme_decrypt_start (GpgmeCtx ctx, GpgmeData ciph, GpgmeData plain,
GpgmeError
gpgme_op_decrypt_start (GpgmeCtx ctx, GpgmeData ciph, GpgmeData plain)
{
return _gpgme_decrypt_start (ctx, ciph, plain,
return _gpgme_decrypt_start (ctx, 0, ciph, plain,
_gpgme_decrypt_status_handler);
}
@ -158,8 +150,9 @@ gpgme_op_decrypt_start (GpgmeCtx ctx, GpgmeData ciph, GpgmeData plain)
GpgmeError
gpgme_op_decrypt (GpgmeCtx ctx, GpgmeData in, GpgmeData out)
{
GpgmeError err = gpgme_op_decrypt_start (ctx, in, out);
GpgmeError err = _gpgme_decrypt_start (ctx, 1, in, out,
_gpgme_decrypt_status_handler);
if (!err)
gpgme_wait (ctx, &err, 1);
err = _gpgme_wait_one (ctx);
return err;
}

View File

@ -91,30 +91,13 @@ delete_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
}
GpgmeError
gpgme_op_delete_start (GpgmeCtx ctx, const GpgmeKey key, int allow_secret)
static GpgmeError
_gpgme_op_delete_start (GpgmeCtx ctx, int synchronous,
const GpgmeKey key, int allow_secret)
{
GpgmeError err = 0;
fail_on_pending_request (ctx);
ctx->pending = 1;
if (!key)
{
err = mk_error (Invalid_Value);
goto leave;
}
if (ctx->engine)
{
_gpgme_engine_release (ctx->engine);
ctx->engine = NULL;
}
_gpgme_release_result (ctx);
err = _gpgme_engine_new (ctx->use_cms ? GPGME_PROTOCOL_CMS
: GPGME_PROTOCOL_OpenPGP, &ctx->engine);
err = _gpgme_op_reset (ctx, synchronous);
if (err)
goto leave;
@ -135,6 +118,12 @@ gpgme_op_delete_start (GpgmeCtx ctx, const GpgmeKey key, int allow_secret)
return err;
}
GpgmeError
gpgme_op_delete_start (GpgmeCtx ctx, const GpgmeKey key, int allow_secret)
{
return _gpgme_op_delete_start (ctx, 0, key, allow_secret);
}
/**
* gpgme_op_delete:
@ -150,8 +139,8 @@ gpgme_op_delete_start (GpgmeCtx ctx, const GpgmeKey key, int allow_secret)
GpgmeError
gpgme_op_delete (GpgmeCtx ctx, const GpgmeKey key, int allow_secret)
{
GpgmeError err = gpgme_op_delete_start (ctx, key, allow_secret);
GpgmeError err = _gpgme_op_delete_start (ctx, 1, key, allow_secret);
if (!err)
gpgme_wait (ctx, &err, 1);
err = _gpgme_wait_one (ctx);
return err;
}

View File

@ -50,30 +50,14 @@ encrypt_sign_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
}
GpgmeError
gpgme_op_encrypt_sign_start (GpgmeCtx ctx, GpgmeRecipients recp,
GpgmeData plain, GpgmeData cipher)
static GpgmeError
_gpgme_op_encrypt_sign_start (GpgmeCtx ctx, int synchronous,
GpgmeRecipients recp,
GpgmeData plain, GpgmeData cipher)
{
int err = 0;
GpgmeError err = 0;
fail_on_pending_request (ctx);
ctx->pending = 1;
_gpgme_release_result (ctx);
/* Do some checks. */
if (!gpgme_recipients_count (recp))
{
/* FIXME: In this case we should do symmetric encryption. */
err = mk_error (No_Recipients);
goto leave;
}
/* Create an engine object. */
_gpgme_engine_release (ctx->engine);
ctx->engine = NULL;
err = _gpgme_engine_new (ctx->use_cms ? GPGME_PROTOCOL_CMS
: GPGME_PROTOCOL_OpenPGP, &ctx->engine);
err = _gpgme_op_reset (ctx, synchronous);
if (err)
goto leave;
@ -115,6 +99,13 @@ gpgme_op_encrypt_sign_start (GpgmeCtx ctx, GpgmeRecipients recp,
return err;
}
GpgmeError
gpgme_op_encrypt_sign_start (GpgmeCtx ctx, GpgmeRecipients recp,
GpgmeData plain, GpgmeData cipher)
{
return _gpgme_op_encrypt_sign_start (ctx, 0, recp, plain, cipher);
}
/**
* gpgme_op_encrypt_sign:
@ -133,11 +124,11 @@ GpgmeError
gpgme_op_encrypt_sign (GpgmeCtx ctx, GpgmeRecipients recp,
GpgmeData plain, GpgmeData cipher)
{
GpgmeError err = gpgme_op_encrypt_sign_start (ctx, recp, plain, cipher);
GpgmeError err = _gpgme_op_encrypt_sign_start (ctx, 1, recp, plain, cipher);
if (!err)
{
gpgme_wait (ctx, &err, 1);
err = _gpgme_wait_one (ctx);
/* Old gpg versions don't return status info for invalid
recipients, so we simply check whether we got any output at
all, and if not we assume that we don't have valid

View File

@ -28,6 +28,7 @@
#include "util.h"
#include "context.h"
#include "ops.h"
#include "wait.h"
#define SKIP_TOKEN_OR_RETURN(a) do { \
while (*(a) && *(a) != ' ') (a)++; \
@ -142,18 +143,13 @@ _gpgme_encrypt_sym_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
}
GpgmeError
gpgme_op_encrypt_start (GpgmeCtx ctx, GpgmeRecipients recp, GpgmeData plain,
GpgmeData ciph)
static GpgmeError
_gpgme_op_encrypt_start (GpgmeCtx ctx, int synchronous,
GpgmeRecipients recp, GpgmeData plain, GpgmeData ciph)
{
int err = 0;
GpgmeError err = 0;
int symmetric = 0;
fail_on_pending_request (ctx);
ctx->pending = 1;
_gpgme_release_result (ctx);
/* Do some checks. */
if (!recp)
symmetric = 1;
@ -163,11 +159,7 @@ gpgme_op_encrypt_start (GpgmeCtx ctx, GpgmeRecipients recp, GpgmeData plain,
goto leave;
}
/* Create an engine object. */
_gpgme_engine_release (ctx->engine);
ctx->engine = NULL;
err = _gpgme_engine_new (ctx->use_cms ? GPGME_PROTOCOL_CMS
: GPGME_PROTOCOL_OpenPGP, &ctx->engine);
err = _gpgme_op_reset (ctx, synchronous);
if (err)
goto leave;
@ -216,6 +208,14 @@ gpgme_op_encrypt_start (GpgmeCtx ctx, GpgmeRecipients recp, GpgmeData plain,
}
GpgmeError
gpgme_op_encrypt_start (GpgmeCtx ctx, GpgmeRecipients recp, GpgmeData plain,
GpgmeData ciph)
{
return _gpgme_op_encrypt_start (ctx, 0, recp, plain, ciph);
}
/**
* gpgme_op_encrypt:
* @c: The context
@ -233,10 +233,10 @@ GpgmeError
gpgme_op_encrypt (GpgmeCtx ctx, GpgmeRecipients recp,
GpgmeData plain, GpgmeData cipher)
{
int err = gpgme_op_encrypt_start (ctx, recp, plain, cipher);
int err = _gpgme_op_encrypt_start (ctx, 1, recp, plain, cipher);
if (!err)
{
gpgme_wait (ctx, &err, 1);
err = _gpgme_wait_one (ctx);
/* Old gpg versions don't return status info for invalid
recipients, so we simply check whether we got any output at
all, and if not we assume that we don't have valid

View File

@ -59,20 +59,30 @@
#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
typedef struct
{
int fd; /* FD we talk about. */
int dir; /* Inbound/Outbound, maybe given implicit? */
void *data; /* Handler-specific data. */
void *tag; /* ID from the user for gpgme_remove_io_callback. */
} iocb_data_t;
struct gpgsm_object_s
{
ASSUAN_CONTEXT assuan_ctx;
iocb_data_t status_cb;
/* Input, output etc are from the servers perspective. */
int input_fd;
iocb_data_t input_cb;
int input_fd_server;
GpgmeData input_data;
int output_fd;
iocb_data_t output_cb;
int output_fd_server;
GpgmeData output_data;
int message_fd;
iocb_data_t message_cb;
int message_fd_server;
GpgmeData message_data;
char *command;
@ -93,6 +103,8 @@ struct gpgsm_object_s
int linelen;
} attic;
} colon;
struct GpgmeIOCbs io_cbs;
};
@ -124,14 +136,49 @@ static void
close_notify_handler (int fd, void *opaque)
{
GpgsmObject gpgsm = opaque;
int possibly_done = 0;
assert (fd != -1);
if (gpgsm->input_fd == fd)
gpgsm->input_fd = -1;
else if (gpgsm->output_fd == fd)
gpgsm->output_fd = -1;
else if (gpgsm->message_fd == fd)
gpgsm->message_fd = -1;
if (gpgsm->status_cb.fd == fd)
{
if (gpgsm->status_cb.tag)
{
(*gpgsm->io_cbs.remove) (gpgsm->status_cb.tag);
possibly_done = 1;
}
gpgsm->status_cb.fd = -1;
}
else if (gpgsm->input_cb.fd == fd)
{
if (gpgsm->input_cb.tag)
{
(*gpgsm->io_cbs.remove) (gpgsm->input_cb.tag);
possibly_done = 1;
}
gpgsm->input_cb.fd = -1;
}
else if (gpgsm->output_cb.fd == fd)
{
if (gpgsm->output_cb.tag)
{
(*gpgsm->io_cbs.remove) (gpgsm->output_cb.tag);
possibly_done = 1;
}
gpgsm->output_cb.fd = -1;
}
else if (gpgsm->message_cb.fd == fd)
{
if (gpgsm->message_cb.tag)
{
(*gpgsm->io_cbs.remove) (gpgsm->message_cb.tag);
possibly_done = 1;
}
gpgsm->message_cb.fd = -1;
}
if (possibly_done && gpgsm->io_cbs.event
&& gpgsm->status_cb.fd == -1 && gpgsm->input_cb.fd == -1
&& gpgsm->output_cb.fd == -1 && gpgsm->message_cb.fd == -1)
(*gpgsm->io_cbs.event) (gpgsm->io_cbs.event_priv, GPGME_EVENT_DONE, NULL);
}
@ -248,6 +295,8 @@ _gpgme_gpgsm_new (GpgsmObject *r_gpgsm)
char *old_lc = NULL;
char *dft_lc = NULL;
char *optstr;
int fdlist[5];
int nfds;
*r_gpgsm = NULL;
gpgsm = xtrycalloc (1, sizeof *gpgsm);
@ -257,11 +306,17 @@ _gpgme_gpgsm_new (GpgsmObject *r_gpgsm)
return err;
}
gpgsm->input_fd = -1;
gpgsm->status_cb.fd = -1;
gpgsm->status_cb.tag = 0;
gpgsm->input_cb.fd = -1;
gpgsm->input_cb.tag = 0;
gpgsm->input_fd_server = -1;
gpgsm->output_fd = -1;
gpgsm->output_cb.fd = -1;
gpgsm->output_cb.tag = 0;
gpgsm->output_fd_server = -1;
gpgsm->message_fd = -1;
gpgsm->message_cb.fd = -1;
gpgsm->message_cb.tag = 0;
gpgsm->message_fd_server = -1;
gpgsm->status.fnc = 0;
@ -270,12 +325,19 @@ _gpgme_gpgsm_new (GpgsmObject *r_gpgsm)
gpgsm->colon.attic.linesize = 0;
gpgsm->colon.attic.linelen = 0;
gpgsm->io_cbs.add = NULL;
gpgsm->io_cbs.add_priv = NULL;
gpgsm->io_cbs.remove = NULL;
gpgsm->io_cbs.event = NULL;
gpgsm->io_cbs.event_priv = NULL;
if (_gpgme_io_pipe (fds, 0) < 0)
{
err = mk_error (Pipe_Error);
goto leave;
}
gpgsm->input_fd = fds[1];
gpgsm->input_cb.fd = fds[1];
gpgsm->input_cb.dir = 0;
gpgsm->input_fd_server = fds[0];
if (_gpgme_io_pipe (fds, 1) < 0)
@ -283,7 +345,8 @@ _gpgme_gpgsm_new (GpgsmObject *r_gpgsm)
err = mk_error (Pipe_Error);
goto leave;
}
gpgsm->output_fd = fds[0];
gpgsm->output_cb.fd = fds[0];
gpgsm->output_cb.dir = 1;
gpgsm->output_fd_server = fds[1];
if (_gpgme_io_pipe (fds, 0) < 0)
@ -291,7 +354,8 @@ _gpgme_gpgsm_new (GpgsmObject *r_gpgsm)
err = mk_error (Pipe_Error);
goto leave;
}
gpgsm->message_fd = fds[1];
gpgsm->message_cb.fd = fds[1];
gpgsm->message_cb.dir = 0;
gpgsm->message_fd_server = fds[0];
child_fds[0] = gpgsm->input_fd_server;
@ -307,6 +371,20 @@ _gpgme_gpgsm_new (GpgsmObject *r_gpgsm)
_gpgme_get_gpgsm_path (), argv, child_fds,
1 /* dup stderr to /dev/null */);
/* We need to know the fd used by assuan for reads. We do this by
using the assumption that the first returned fd from
assuan_get_active_fds() is always this one. */
nfds = assuan_get_active_fds (gpgsm->assuan_ctx, 0 /* read fds */,
fdlist, DIM (fdlist));
if (nfds < 1)
{
err = mk_error (General_Error); /* FIXME */
goto leave;
}
gpgsm->status_cb.fd = fdlist[0];
gpgsm->status_cb.dir = 1;
gpgsm->status_cb.data = gpgsm;
dft_display = getenv ("DISPLAY");
if (dft_display)
{
@ -315,8 +393,8 @@ _gpgme_gpgsm_new (GpgsmObject *r_gpgsm)
err = mk_error (Out_Of_Core);
goto leave;
}
err = assuan_transact (gpgsm->assuan_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
NULL);
err = assuan_transact (gpgsm->assuan_ctx, optstr, NULL, NULL, NULL,
NULL, NULL, NULL);
free (optstr);
if (err)
{
@ -400,11 +478,13 @@ _gpgme_gpgsm_new (GpgsmObject *r_gpgsm)
}
if (!err &&
(_gpgme_io_set_close_notify (gpgsm->input_fd,
(_gpgme_io_set_close_notify (gpgsm->status_cb.fd,
close_notify_handler, gpgsm)
|| _gpgme_io_set_close_notify (gpgsm->output_fd,
|| _gpgme_io_set_close_notify (gpgsm->input_cb.fd,
close_notify_handler, gpgsm)
|| _gpgme_io_set_close_notify (gpgsm->output_cb.fd,
close_notify_handler, gpgsm)
|| _gpgme_io_set_close_notify (gpgsm->message_fd,
|| _gpgme_io_set_close_notify (gpgsm->message_cb.fd,
close_notify_handler, gpgsm)))
{
err = mk_error (General_Error);
@ -433,21 +513,15 @@ _gpgme_gpgsm_new (GpgsmObject *r_gpgsm)
void
_gpgme_gpgsm_release (GpgsmObject gpgsm)
{
pid_t pid;
if (!gpgsm)
return;
pid = assuan_get_pid (gpgsm->assuan_ctx);
if (pid != -1)
_gpgme_remove_proc_from_wait_queue (pid);
if (gpgsm->input_fd != -1)
_gpgme_io_close (gpgsm->input_fd);
if (gpgsm->output_fd != -1)
_gpgme_io_close (gpgsm->output_fd);
if (gpgsm->message_fd != -1)
_gpgme_io_close (gpgsm->message_fd);
if (gpgsm->input_cb.fd != -1)
_gpgme_io_close (gpgsm->input_cb.fd);
if (gpgsm->output_cb.fd != -1)
_gpgme_io_close (gpgsm->output_cb.fd);
if (gpgsm->message_cb.fd != -1)
_gpgme_io_close (gpgsm->message_cb.fd);
assuan_disconnect (gpgsm->assuan_ctx);
@ -512,12 +586,17 @@ map_input_enc (GpgmeData d)
{
switch (gpgme_data_get_encoding (d))
{
case GPGME_DATA_ENCODING_NONE: break;
case GPGME_DATA_ENCODING_BINARY: return "--binary";
case GPGME_DATA_ENCODING_BASE64: return "--base64";
case GPGME_DATA_ENCODING_ARMOR: return "--armor";
case GPGME_DATA_ENCODING_NONE:
break;
case GPGME_DATA_ENCODING_BINARY:
return "--binary";
case GPGME_DATA_ENCODING_BASE64:
return "--base64";
case GPGME_DATA_ENCODING_ARMOR:
return "--armor";
default:
break;
}
return NULL;
}
@ -534,16 +613,16 @@ _gpgme_gpgsm_op_decrypt (GpgsmObject gpgsm, GpgmeData ciph, GpgmeData plain)
if (!gpgsm->command)
return mk_error (Out_Of_Core);
gpgsm->input_data = ciph;
gpgsm->input_cb.data = ciph;
err = gpgsm_set_fd (gpgsm->assuan_ctx, "INPUT", gpgsm->input_fd_server,
map_input_enc (gpgsm->input_data));
map_input_enc (gpgsm->input_cb.data));
if (err)
return mk_error (General_Error); /* FIXME */
gpgsm->output_data = plain;
gpgsm->output_cb.data = plain;
err = gpgsm_set_fd (gpgsm->assuan_ctx, "OUTPUT", gpgsm->output_fd_server, 0);
if (err)
return mk_error (General_Error); /* FIXME */
_gpgme_io_close (gpgsm->message_fd);
_gpgme_io_close (gpgsm->message_cb.fd);
return 0;
}
@ -626,17 +705,17 @@ _gpgme_gpgsm_op_encrypt (GpgsmObject gpgsm, GpgmeRecipients recp,
if (!gpgsm->command)
return mk_error (Out_Of_Core);
gpgsm->input_data = plain;
gpgsm->input_cb.data = plain;
err = gpgsm_set_fd (gpgsm->assuan_ctx, "INPUT", gpgsm->input_fd_server,
map_input_enc (gpgsm->input_data));
map_input_enc (gpgsm->input_cb.data));
if (err)
return err;
gpgsm->output_data = ciph;
gpgsm->output_cb.data = ciph;
err = gpgsm_set_fd (gpgsm->assuan_ctx, "OUTPUT", gpgsm->output_fd_server,
use_armor ? "--armor" : 0);
if (err)
return err;
_gpgme_io_close (gpgsm->message_fd);
_gpgme_io_close (gpgsm->message_cb.fd);
err = gpgsm_set_recipients (gpgsm, recp);
if (err)
@ -668,17 +747,17 @@ _gpgme_gpgsm_op_genkey (GpgsmObject gpgsm, GpgmeData help_data, int use_armor,
if (!gpgsm->command)
return mk_error (Out_Of_Core);
gpgsm->input_data = help_data;
gpgsm->input_cb.data = help_data;
err = gpgsm_set_fd (gpgsm->assuan_ctx, "INPUT", gpgsm->input_fd_server,
map_input_enc (gpgsm->input_data));
map_input_enc (gpgsm->input_cb.data));
if (err)
return err;
gpgsm->output_data = pubkey;
gpgsm->output_cb.data = pubkey;
err = gpgsm_set_fd (gpgsm->assuan_ctx, "OUTPUT", gpgsm->output_fd_server,
use_armor ? "--armor" : 0);
if (err)
return err;
_gpgme_io_close (gpgsm->message_fd);
_gpgme_io_close (gpgsm->message_cb.fd);
return 0;
}
@ -696,13 +775,13 @@ _gpgme_gpgsm_op_import (GpgsmObject gpgsm, GpgmeData keydata)
if (!gpgsm->command)
return mk_error (Out_Of_Core);
gpgsm->input_data = keydata;
gpgsm->input_cb.data = keydata;
err = gpgsm_set_fd (gpgsm->assuan_ctx, "INPUT", gpgsm->input_fd_server,
map_input_enc (gpgsm->input_data));
map_input_enc (gpgsm->input_cb.data));
if (err)
return err;
_gpgme_io_close (gpgsm->output_fd);
_gpgme_io_close (gpgsm->message_fd);
_gpgme_io_close (gpgsm->output_cb.fd);
_gpgme_io_close (gpgsm->message_cb.fd);
return 0;
}
@ -740,9 +819,9 @@ _gpgme_gpgsm_op_keylist (GpgsmObject gpgsm, const char *pattern,
strcpy (&line[9], pattern);
}
_gpgme_io_close (gpgsm->input_fd);
_gpgme_io_close (gpgsm->output_fd);
_gpgme_io_close (gpgsm->message_fd);
_gpgme_io_close (gpgsm->input_cb.fd);
_gpgme_io_close (gpgsm->output_cb.fd);
_gpgme_io_close (gpgsm->message_cb.fd);
gpgsm->command = line;
return 0;
@ -839,9 +918,9 @@ _gpgme_gpgsm_op_keylist_ext (GpgsmObject gpgsm, const char *pattern[],
}
*linep = '\0';
_gpgme_io_close (gpgsm->input_fd);
_gpgme_io_close (gpgsm->output_fd);
_gpgme_io_close (gpgsm->message_fd);
_gpgme_io_close (gpgsm->input_cb.fd);
_gpgme_io_close (gpgsm->output_cb.fd);
_gpgme_io_close (gpgsm->message_cb.fd);
gpgsm->command = line;
return 0;
@ -872,17 +951,17 @@ _gpgme_gpgsm_op_sign (GpgsmObject gpgsm, GpgmeData in, GpgmeData out,
if (err)
return err;
gpgsm->input_data = in;
gpgsm->input_cb.data = in;
err = gpgsm_set_fd (gpgsm->assuan_ctx, "INPUT", gpgsm->input_fd_server,
map_input_enc (gpgsm->input_data));
map_input_enc (gpgsm->input_cb.data));
if (err)
return err;
gpgsm->output_data = out;
gpgsm->output_cb.data = out;
err = gpgsm_set_fd (gpgsm->assuan_ctx, "OUTPUT", gpgsm->output_fd_server,
use_armor ? "--armor" : 0);
if (err)
return err;
_gpgme_io_close (gpgsm->message_fd);
_gpgme_io_close (gpgsm->message_cb.fd);
return 0;
}
@ -908,26 +987,26 @@ _gpgme_gpgsm_op_verify (GpgsmObject gpgsm, GpgmeData sig, GpgmeData text)
if (!gpgsm->command)
return mk_error (Out_Of_Core);
gpgsm->input_data = sig;
gpgsm->input_cb.data = sig;
err = gpgsm_set_fd (gpgsm->assuan_ctx, "INPUT", gpgsm->input_fd_server,
map_input_enc (gpgsm->input_data));
map_input_enc (gpgsm->input_cb.data));
if (err)
return err;
if (_gpgme_data_get_mode (text) == GPGME_DATA_MODE_IN)
{
/* Normal or cleartext signature. */
gpgsm->output_data = text;
gpgsm->output_cb.data = text;
err = gpgsm_set_fd (gpgsm->assuan_ctx, "OUTPUT", gpgsm->output_fd_server,
0);
_gpgme_io_close (gpgsm->message_fd);
_gpgme_io_close (gpgsm->message_cb.fd);
}
else
{
/* Detached signature. */
gpgsm->message_data = text;
gpgsm->message_cb.data = text;
err = gpgsm_set_fd (gpgsm->assuan_ctx, "MESSAGE",
gpgsm->message_fd_server, 0);
_gpgme_io_close (gpgsm->output_fd);
_gpgme_io_close (gpgsm->output_cb.fd);
}
if (err)
return err;
@ -946,8 +1025,8 @@ status_cmp (const void *ap, const void *bp)
}
static int
gpgsm_status_handler (void *opaque, int pid, int fd)
static void
gpgsm_status_handler (void *opaque, int fd)
{
AssuanError err;
GpgsmObject gpgsm = opaque;
@ -966,8 +1045,9 @@ gpgsm_status_handler (void *opaque, int pid, int fd)
&& line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
&& (line[3] == '\0' || line[3] == ' ')))
{
/* XXX: If an error occured, find out what happened, then save the error value
before running the status handler (so it takes precedence). */
/* 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]));
@ -990,7 +1070,8 @@ gpgsm_status_handler (void *opaque, int pid, int fd)
if (err)
assuan_write_line (gpgsm->assuan_ctx, "BYE");
return 1;
_gpgme_io_close (gpgsm->status_cb.fd);
return;
}
if (linelen > 2
@ -1015,7 +1096,10 @@ gpgsm_status_handler (void *opaque, int pid, int fd)
unsigned char *newline = xtryrealloc (*aline,
*alinelen + linelen + 1);
if (!newline)
return mk_error (Out_Of_Core);
{
_gpgme_io_close (gpgsm->status_cb.fd);
return;
}
*aline = newline;
gpgsm->colon.attic.linesize += linelen + 1;
}
@ -1082,8 +1166,6 @@ gpgsm_status_handler (void *opaque, int pid, int fd)
}
}
while (assuan_pending_line (gpgsm->assuan_ctx));
return 0;
}
@ -1109,50 +1191,45 @@ _gpgme_gpgsm_set_colon_line_handler (GpgsmObject gpgsm,
}
static GpgmeError
_gpgme_gpgsm_add_io_cb (GpgsmObject gpgsm, iocb_data_t *iocbd,
GpgmeIOCb handler)
{
GpgmeError err = 0;
iocbd->tag = (*gpgsm->io_cbs.add) (gpgsm->io_cbs.add_priv,
iocbd->fd, iocbd->dir,
handler, iocbd->data);
if (!iocbd->tag)
err = mk_error (General_Error);
if (!err && !iocbd->dir)
/* FIXME Kludge around poll() problem. */
err = _gpgme_io_set_nonblocking (iocbd->fd);
return err;
}
GpgmeError
_gpgme_gpgsm_start (GpgsmObject gpgsm, void *opaque)
{
GpgmeError err = 0;
pid_t pid;
int fdlist[5];
int nfds;
if (!gpgsm)
return mk_error (Invalid_Value);
pid = assuan_get_pid (gpgsm->assuan_ctx);
/* We need to know the fd used by assuan for reads. We do this by
using the assumption that the first returned fd from
assuan_get_active_fds() is always this one. */
nfds = assuan_get_active_fds (gpgsm->assuan_ctx, 0 /* read fds */,
fdlist, DIM (fdlist));
if (nfds < 1)
return mk_error (General_Error); /* FIXME */
err = _gpgme_register_pipe_handler (opaque, gpgsm_status_handler, gpgsm, pid,
fdlist[0], 1);
if (gpgsm->input_fd != -1)
{
err = _gpgme_register_pipe_handler (opaque, _gpgme_data_outbound_handler,
gpgsm->input_data, pid,
gpgsm->input_fd, 0);
if (!err) /* FIXME Kludge around poll() problem. */
err = _gpgme_io_set_nonblocking (gpgsm->input_fd);
}
if (!err && gpgsm->output_fd != -1)
err = _gpgme_register_pipe_handler (opaque, _gpgme_data_inbound_handler,
gpgsm->output_data, pid,
gpgsm->output_fd, 1);
if (!err && gpgsm->message_fd != -1)
{
err = _gpgme_register_pipe_handler (opaque, _gpgme_data_outbound_handler,
gpgsm->message_data, pid,
gpgsm->message_fd, 0);
if (!err) /* FIXME Kludge around poll() problem. */
err = _gpgme_io_set_nonblocking (gpgsm->message_fd);
}
err = _gpgme_gpgsm_add_io_cb (gpgsm, &gpgsm->status_cb,
gpgsm_status_handler);
if (gpgsm->input_cb.fd != -1)
err = _gpgme_gpgsm_add_io_cb (gpgsm, &gpgsm->input_cb,
_gpgme_data_outbound_handler);
if (!err && gpgsm->output_cb.fd != -1)
err = _gpgme_gpgsm_add_io_cb (gpgsm, &gpgsm->output_cb,
_gpgme_data_inbound_handler);
if (!err && gpgsm->message_cb.fd != -1)
err = _gpgme_gpgsm_add_io_cb (gpgsm, &gpgsm->message_cb,
_gpgme_data_outbound_handler);
if (!err)
err = assuan_write_line (gpgsm->assuan_ctx, gpgsm->command);
@ -1160,6 +1237,12 @@ _gpgme_gpgsm_start (GpgsmObject gpgsm, void *opaque)
return err;
}
void
_gpgme_gpgsm_set_io_cbs (GpgsmObject gpgsm, struct GpgmeIOCbs *io_cbs)
{
gpgsm->io_cbs = *io_cbs;
}
#else /* ENABLE_GPGSM */
@ -1303,5 +1386,8 @@ _gpgme_gpgsm_start (GpgsmObject gpgsm, void *opaque)
return mk_error (Invalid_Engine);
}
void _gpgme_gpgsm_set_io_cbs (GpgsmObject gpgsm, GpgmeIOCbs io_cbs)
{
}
#endif /* ! ENABLE_GPGSM */

View File

@ -63,5 +63,6 @@ GpgmeError _gpgme_gpgsm_op_trustlist (GpgsmObject gpgsm, const char *pattern);
GpgmeError _gpgme_gpgsm_op_verify (GpgsmObject gpgsm, GpgmeData sig,
GpgmeData text);
GpgmeError _gpgme_gpgsm_start (GpgsmObject gpgsm, void *opaque);
void _gpgme_gpgsm_set_io_cbs (GpgsmObject gpgsm, struct GpgmeIOCbs *io_cbs);
#endif /* ENGINE_GPGSM_H */

View File

@ -567,6 +567,26 @@ _gpgme_engine_start (EngineObject engine, void *opaque)
return 0;
}
void
_gpgme_engine_set_io_cbs (EngineObject engine,
struct GpgmeIOCbs *io_cbs)
{
if (!engine)
return;
switch (engine->protocol)
{
case GPGME_PROTOCOL_OpenPGP:
_gpgme_gpg_set_io_cbs (engine->engine.gpg, io_cbs);
break;
case GPGME_PROTOCOL_CMS:
_gpgme_gpgsm_set_io_cbs (engine->engine.gpgsm, io_cbs);
break;
default:
break;
}
}
void
_gpgme_engine_add_child_to_reap_list (void *buf, int buflen, pid_t pid)

View File

@ -76,6 +76,9 @@ GpgmeError _gpgme_engine_op_verify (EngineObject engine, GpgmeData sig,
GpgmeData text);
GpgmeError _gpgme_engine_start (EngineObject engine, void *opaque);
void _gpgme_engine_set_io_cbs (EngineObject engine,
struct GpgmeIOCbs *io_cbs);
void _gpgme_engine_add_child_to_reap_list (void *buf, int buflen, pid_t pid);
void _gpgme_engine_housecleaning (void);

View File

@ -41,21 +41,13 @@ export_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
}
GpgmeError
gpgme_op_export_start (GpgmeCtx ctx, GpgmeRecipients recp, GpgmeData keydata)
static GpgmeError
_gpgme_op_export_start (GpgmeCtx ctx, int synchronous,
GpgmeRecipients recp, GpgmeData keydata)
{
GpgmeError err = 0;
fail_on_pending_request (ctx);
ctx->pending = 1;
_gpgme_engine_release (ctx->engine);
ctx->engine = NULL;
_gpgme_release_result (ctx);
err = _gpgme_engine_new (ctx->use_cms ? GPGME_PROTOCOL_CMS
: GPGME_PROTOCOL_OpenPGP, &ctx->engine);
err = _gpgme_op_reset (ctx, synchronous);
if (err)
goto leave;
@ -83,6 +75,11 @@ gpgme_op_export_start (GpgmeCtx ctx, GpgmeRecipients recp, GpgmeData keydata)
return err;
}
GpgmeError
gpgme_op_export_start (GpgmeCtx ctx, GpgmeRecipients recp, GpgmeData keydata)
{
return _gpgme_op_export_start (ctx, 0, recp, keydata);
}
/**
* gpgme_op_export:
@ -100,8 +97,8 @@ gpgme_op_export_start (GpgmeCtx ctx, GpgmeRecipients recp, GpgmeData keydata)
GpgmeError
gpgme_op_export (GpgmeCtx ctx, GpgmeRecipients recipients, GpgmeData keydata)
{
GpgmeError err = gpgme_op_export_start (ctx, recipients, keydata);
GpgmeError err = _gpgme_op_export_start (ctx, 1, recipients, keydata);
if (!err)
gpgme_wait (ctx, &err, 1);
err = _gpgme_wait_one (ctx);
return err;
}

View File

@ -78,66 +78,20 @@ genkey_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
}
}
/**
* gpgme_op_genkey:
* @c: the context
* @parms: XML string with the key parameters
* @pubkey: Returns the public key
* @seckey: Returns the secret key
*
* Generate a new key and store the key in the default keyrings if
* both @pubkey and @seckey are NULL. If @pubkey and @seckey are
* given, the newly created key will be returned in these data
* objects. This function just starts the gheneration and does not
* wait for completion.
*
* Here is an example on how @parms should be formatted; for deatils
* see the file doc/DETAILS from the GnuPG distribution.
*
* <literal>
* <![CDATA[
* <GnupgKeyParms format="internal">
* Key-Type: DSA
* Key-Length: 1024
* Subkey-Type: ELG-E
* Subkey-Length: 1024
* Name-Real: Joe Tester
* Name-Comment: with stupid passphrase
* Name-Email: joe@foo.bar
* Expire-Date: 0
* Passphrase: abc
* </GnupgKeyParms>
* ]]>
* </literal>
*
* Strings should be given in UTF-8 encoding. The format we support
* for now is only "internal". The content of the
* &lt;GnupgKeyParms&gt; container is passed verbatim to GnuPG.
* Control statements are not allowed.
*
* Return value: 0 for success or an error code
**/
GpgmeError
gpgme_op_genkey_start (GpgmeCtx ctx, const char *parms,
GpgmeData pubkey, GpgmeData seckey)
static GpgmeError
_gpgme_op_genkey_start (GpgmeCtx ctx, int synchronous, const char *parms,
GpgmeData pubkey, GpgmeData seckey)
{
int err = 0;
const char *s, *s2, *sx;
fail_on_pending_request (ctx);
ctx->pending = 1;
err = _gpgme_op_reset (ctx, synchronous);
if (err)
goto leave;
gpgme_data_release (ctx->help_data_1);
ctx->help_data_1 = NULL;
_gpgme_engine_release (ctx->engine);
ctx->engine = NULL;
err = _gpgme_engine_new (ctx->use_cms ? GPGME_PROTOCOL_CMS
: GPGME_PROTOCOL_OpenPGP, &ctx->engine);
if (err)
goto leave;
if (!pubkey && !seckey)
; /* okay: Add key to the keyrings */
else if (pubkey && gpgme_data_get_type (pubkey) != GPGME_DATA_TYPE_NONE)
@ -199,6 +153,53 @@ gpgme_op_genkey_start (GpgmeCtx ctx, const char *parms,
}
/**
* gpgme_op_genkey:
* @c: the context
* @parms: XML string with the key parameters
* @pubkey: Returns the public key
* @seckey: Returns the secret key
*
* Generate a new key and store the key in the default keyrings if
* both @pubkey and @seckey are NULL. If @pubkey and @seckey are
* given, the newly created key will be returned in these data
* objects. This function just starts the gheneration and does not
* wait for completion.
*
* Here is an example on how @parms should be formatted; for deatils
* see the file doc/DETAILS from the GnuPG distribution.
*
* <literal>
* <![CDATA[
* <GnupgKeyParms format="internal">
* Key-Type: DSA
* Key-Length: 1024
* Subkey-Type: ELG-E
* Subkey-Length: 1024
* Name-Real: Joe Tester
* Name-Comment: with stupid passphrase
* Name-Email: joe@foo.bar
* Expire-Date: 0
* Passphrase: abc
* </GnupgKeyParms>
* ]]>
* </literal>
*
* Strings should be given in UTF-8 encoding. The format we support
* for now is only "internal". The content of the
* &lt;GnupgKeyParms&gt; container is passed verbatim to GnuPG.
* Control statements are not allowed.
*
* Return value: 0 for success or an error code
**/
GpgmeError
gpgme_op_genkey_start (GpgmeCtx ctx, const char *parms,
GpgmeData pubkey, GpgmeData seckey)
{
return _gpgme_op_genkey_start (ctx, 0, parms, pubkey, seckey);
}
/**
* gpgme_op_genkey:
* @c: the context
@ -217,8 +218,8 @@ GpgmeError
gpgme_op_genkey (GpgmeCtx ctx, const char *parms,
GpgmeData pubkey, GpgmeData seckey)
{
GpgmeError err = gpgme_op_genkey_start (ctx, parms, pubkey, seckey);
GpgmeError err = _gpgme_op_genkey_start (ctx, 1, parms, pubkey, seckey);
if (!err)
gpgme_wait (ctx, &err, 1);
err = _gpgme_wait_one (ctx);
return err;
}

View File

@ -28,7 +28,7 @@
#include "util.h"
#include "context.h"
#include "ops.h"
#include "wait.h"
/**
* gpgme_new:
@ -53,8 +53,8 @@ gpgme_new (GpgmeCtx *r_ctx)
ctx->keylist_mode = GPGME_KEYLIST_MODE_LOCAL;
ctx->verbosity = 1;
ctx->include_certs = 1;
_gpgme_fd_table_init (&ctx->fdt);
*r_ctx = ctx;
return 0;
}
@ -71,6 +71,7 @@ gpgme_release (GpgmeCtx ctx)
if (!ctx)
return;
_gpgme_engine_release (ctx->engine);
_gpgme_fd_table_deinit (&ctx->fdt);
_gpgme_release_result (ctx);
gpgme_key_release (ctx->tmp_key);
gpgme_data_release (ctx->help_data_1);
@ -471,7 +472,8 @@ gpgme_set_progress_cb (GpgmeCtx ctx, GpgmeProgressCb cb, void *cb_value)
* @r_cb: The current callback function
* @r_cb_value: The current value passed to the callback function
*
* This function returns the callback function to be used as a progress indicator.
* This function returns the callback function to be used as a
* progress indicator.
**/
void
gpgme_get_progress_cb (GpgmeCtx ctx, GpgmeProgressCb *r_cb, void **r_cb_value)
@ -491,3 +493,59 @@ gpgme_get_progress_cb (GpgmeCtx ctx, GpgmeProgressCb *r_cb, void **r_cb_value)
*r_cb_value = NULL;
}
}
/**
* gpgme_set_io_cbs:
* @ctx: the context
* @register_io_cb: A callback function
* @register_hook_value: The value passed to the callback function
* @remove_io_cb: Another callback function
*
**/
void
gpgme_set_io_cbs (GpgmeCtx ctx, struct GpgmeIOCbs *io_cbs)
{
if (ctx && io_cbs)
ctx->io_cbs = *io_cbs;
else
{
ctx->io_cbs.add = NULL;
ctx->io_cbs.add_priv = NULL;
ctx->io_cbs.remove = NULL;
ctx->io_cbs.event = NULL;
ctx->io_cbs.event_priv = NULL;
}
}
/**
* gpgme_get_io_cbs:
* @ctx: the context
* @r_register_cb: The current register callback function
* @r_register_cb_value: The current value passed to the
* register callback function
* @r_remove_cb: The current remove callback function
*
* This function returns the callback function to be used to pass a passphrase
* to the crypto engine.
**/
void
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;
if (type == GPGME_EVENT_DONE)
ctx->pending = 0;
if (ctx->io_cbs.add && ctx->io_cbs.event)
(*ctx->io_cbs.event) (ctx->io_cbs.event_priv, type, type_data);
}

View File

@ -43,7 +43,7 @@ extern "C" {
AM_PATH_GPGME macro) check that this header matches the installed
library. Warning: Do not edit the next line. configure will do
that for you! */
#define GPGME_VERSION "0.3.7-cvs"
#define GPGME_VERSION "0.3.8-cvs"
/* The opaque data types used by GPGME. */
@ -316,6 +316,46 @@ 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);
/* The type of a function that can register FNC as the I/O callback
function for the file descriptor FD with direction dir (0: inbound,
1: outbound). FNC_DATA should be passed as DATA to FNC. The
function should return a TAG suitable for the corresponding
GpgmeRemoveIOCb. */
typedef void *(*GpgmeRegisterIOCb) (void *data, int fd, int dir,
GpgmeIOCb fnc, void *fnc_data);
/* The type of a function that can remove a previously registered I/O
callback function given TAG as returned by the register
function. */
typedef void (*GpgmeRemoveIOCb) (void *tag);
typedef enum { GPGME_EVENT_DONE,
GPGME_EVENT_NEXT_KEY,
GPGME_EVENT_NEXT_TRUSTITEM } GpgmeEventIO;
/* The type of a function that is called when a context finished an
operation. */
typedef void (*GpgmeEventIOCb) (void *data, GpgmeEventIO type,
void *type_data);
struct GpgmeIOCbs
{
GpgmeRegisterIOCb add;
void *add_priv;
GpgmeRemoveIOCb remove;
GpgmeEventIOCb event;
void *event_priv;
};
/* Set the I/O callback functions in CTX to IO_CBS. */
void gpgme_set_op_io_cbs (GpgmeCtx ctx, struct GpgmeIOCbs *io_cbs);
/* Get the current I/O callback functions. */
void gpgme_get_op_io_cbs (GpgmeCtx ctx, struct GpgmeIOCbs *io_cbs);
/* Cancel a pending operation in CTX. */
void gpgme_cancel (GpgmeCtx ctx);

View File

@ -162,18 +162,12 @@ import_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
}
GpgmeError
gpgme_op_import_start (GpgmeCtx ctx, GpgmeData keydata)
static GpgmeError
_gpgme_op_import_start (GpgmeCtx ctx, int synchronous, GpgmeData keydata)
{
int err = 0;
fail_on_pending_request (ctx);
ctx->pending = 1;
_gpgme_engine_release (ctx->engine);
ctx->engine = NULL;
err = _gpgme_engine_new (ctx->use_cms ? GPGME_PROTOCOL_CMS
: GPGME_PROTOCOL_OpenPGP, &ctx->engine);
err = _gpgme_op_reset (ctx, synchronous);
if (err)
goto leave;
@ -204,6 +198,12 @@ gpgme_op_import_start (GpgmeCtx ctx, GpgmeData keydata)
}
GpgmeError
gpgme_op_import_start (GpgmeCtx ctx, GpgmeData keydata)
{
return _gpgme_op_import_start (ctx, 0, keydata);
}
/**
* gpgme_op_import:
* @c: Context
@ -216,8 +216,8 @@ gpgme_op_import_start (GpgmeCtx ctx, GpgmeData keydata)
GpgmeError
gpgme_op_import (GpgmeCtx ctx, GpgmeData keydata)
{
GpgmeError err = gpgme_op_import_start (ctx, keydata);
GpgmeError err = _gpgme_op_import_start (ctx, 1, keydata);
if (!err)
gpgme_wait (ctx, &err, 1);
err = _gpgme_wait_one (ctx);
return err;
}

View File

@ -1,6 +1,6 @@
/* io.h - I/O functions
/* io.h - Interface to the I/O functions.
* Copyright (C) 2000 Werner Koch (dd9jn)
* Copyright (C) 2001 g10 Code GmbH
* Copyright (C) 2001, 2002 g10 Code GmbH
*
* This file is part of GPGME.
*
@ -24,48 +24,44 @@
#include "types.h"
struct spawn_fd_item_s {
int fd;
int dup_to;
/* A single file descriptor passed to spawn. For child fds, dup_to
specifies the fd it should become in the child. */
struct spawn_fd_item_s
{
int fd;
int dup_to;
};
struct io_select_fd_s {
int fd;
int is_closed;
int for_read;
int for_write;
int signaled;
int frozen;
void *opaque;
struct io_select_fd_s
{
int fd;
int for_read;
int for_write;
int signaled;
int frozen;
void *opaque;
};
/* These function are either defined in posix-io.c or w32-io.c. */
int _gpgme_io_read (int fd, void *buffer, size_t count);
int _gpgme_io_write (int fd, const void *buffer, size_t count);
int _gpgme_io_pipe (int filedes[2], int inherit_idx);
int _gpgme_io_close (int fd);
int _gpgme_io_set_close_notify (int fd, void (*handler) (int, void *),
void *value);
int _gpgme_io_set_nonblocking (int fd);
/* These function are either defined in posix-io.c or w32-io.c */
int _gpgme_io_read ( int fd, void *buffer, size_t count );
int _gpgme_io_write ( int fd, const void *buffer, size_t count );
int _gpgme_io_pipe ( int filedes[2], int inherit_idx );
int _gpgme_io_close ( int fd );
int _gpgme_io_set_close_notify (int fd,
void (*handler)(int, void*), void *value);
int _gpgme_io_set_nonblocking ( int fd );
int _gpgme_io_spawn ( const char *path, char **argv,
struct spawn_fd_item_s *fd_child_list,
struct spawn_fd_item_s *fd_parent_list );
int _gpgme_io_waitpid ( int pid, int hang, int *r_status, int *r_signal );
int _gpgme_io_kill ( int pid, int hard );
int _gpgme_io_select ( struct io_select_fd_s *fds, size_t nfds);
/* Spawn the executable PATH with ARGV as arguments, after forking
close all fds in FD_PARENT_LIST in the parent and close or dup all
fds in FD_CHILD_LIST in the child. */
int _gpgme_io_spawn (const char *path, char **argv,
struct spawn_fd_item_s *fd_child_list,
struct spawn_fd_item_s *fd_parent_list);
int _gpgme_io_waitpid (int pid, int hang, int *r_status, int *r_signal);
int _gpgme_io_kill (int pid, int hard);
int _gpgme_io_select (struct io_select_fd_s *fds, size_t nfds);
#endif /* IO_H */

View File

@ -236,47 +236,51 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
/* Start a new keyblock. */
if (_gpgme_key_new (&key))
{
ctx->error = mk_error (Out_Of_Core); /* the only kind of error we can get*/
/* The only kind of error we can get. */
ctx->error = mk_error (Out_Of_Core);
return;
}
rectype = RT_PUB;
finish_key (ctx);
assert (!ctx->tmp_key);
ctx->tmp_key = key;
rectype = RT_PUB;
finish_key (ctx);
assert (!ctx->tmp_key);
ctx->tmp_key = key;
}
else if (!strcmp (p, "sec"))
{
/* Start a new keyblock, */
if (_gpgme_key_new_secret (&key))
{
ctx->error = mk_error (Out_Of_Core); /* The only kind of error we can get*/
return;
}
rectype = RT_SEC;
finish_key (ctx);
assert (!ctx->tmp_key);
ctx->tmp_key = key;
else if (!strcmp (p, "sec"))
{
/* 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;
}
rectype = RT_SEC;
finish_key (ctx);
assert (!ctx->tmp_key);
ctx->tmp_key = key;
}
else if (!strcmp (p, "crt"))
{
/* Start a new certificate. */
if (_gpgme_key_new (&key))
{
ctx->error = mk_error (Out_Of_Core); /* The only kind of error we can get*/
return;
}
key->x509 = 1;
rectype = RT_CRT;
finish_key (ctx);
assert (!ctx->tmp_key);
ctx->tmp_key = key;
else if (!strcmp (p, "crt"))
{
/* 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;
}
key->x509 = 1;
rectype = RT_CRT;
finish_key (ctx);
assert (!ctx->tmp_key);
ctx->tmp_key = key;
}
else if (!strcmp (p, "crs"))
{
/* Start a new certificate. */
if (_gpgme_key_new_secret (&key))
{
ctx->error = mk_error (Out_Of_Core); /* The only kind of error we can get*/
/* The only kind of error we can get. */
ctx->error = mk_error (Out_Of_Core);
return;
}
key->x509 = 1;
@ -289,7 +293,6 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
rectype = RT_FPR;
else
rectype = RT_NONE;
}
else if (rectype == RT_PUB || rectype == RT_SEC
|| rectype == RT_CRT || rectype == RT_CRS)
@ -401,7 +404,8 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
break;
case 10: /* user ID */
if (_gpgme_key_append_name (key, p))
ctx->error = mk_error (Out_Of_Core); /* The only kind of error we can get*/
/* The only kind of error we can get*/
ctx->error = mk_error (Out_Of_Core);
else
{
if (trust_info)
@ -495,25 +499,13 @@ gpgme_op_keylist_start (GpgmeCtx ctx, const char *pattern, int secret_only)
{
GpgmeError err = 0;
if (!ctx)
return mk_error (Invalid_Value);
ctx->pending = 1;
err = _gpgme_op_reset (ctx, 0);
if (err)
goto leave;
_gpgme_release_result (ctx);
if (ctx->engine)
{
_gpgme_engine_release (ctx->engine);
ctx->engine = NULL;
}
gpgme_key_release (ctx->tmp_key);
ctx->tmp_key = NULL;
/* Fixme: Release key_queue. */
err = _gpgme_engine_new (ctx->use_cms ? GPGME_PROTOCOL_CMS
: GPGME_PROTOCOL_OpenPGP, &ctx->engine);
if (err)
goto leave;
_gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx);
err = _gpgme_engine_set_colon_line_handler (ctx->engine,
@ -526,7 +518,8 @@ gpgme_op_keylist_start (GpgmeCtx ctx, const char *pattern, int secret_only)
just ignore those lines - This should speed up things */
_gpgme_engine_set_verbosity (ctx->engine, 0);
err = _gpgme_engine_op_keylist (ctx->engine, pattern, secret_only, ctx->keylist_mode);
err = _gpgme_engine_op_keylist (ctx->engine, pattern, secret_only,
ctx->keylist_mode);
if (!err) /* And kick off the process. */
err = _gpgme_engine_start (ctx->engine, ctx);
@ -561,26 +554,12 @@ gpgme_op_keylist_ext_start (GpgmeCtx ctx, const char *pattern[],
{
GpgmeError err = 0;
if (!ctx)
return mk_error (Invalid_Value);
ctx->pending = 1;
_gpgme_release_result (ctx);
if (ctx->engine)
{
_gpgme_engine_release (ctx->engine);
ctx->engine = NULL;
}
gpgme_key_release (ctx->tmp_key);
ctx->tmp_key = NULL;
/* Fixme: Release key_queue. */
err = _gpgme_engine_new (ctx->use_cms ? GPGME_PROTOCOL_CMS
: GPGME_PROTOCOL_OpenPGP, &ctx->engine);
err = _gpgme_op_reset (ctx, 0);
if (err)
goto leave;
gpgme_key_release (ctx->tmp_key);
_gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx);
err = _gpgme_engine_set_colon_line_handler (ctx->engine,
keylist_colon_handler, ctx);

70
gpgme/op-support.c Normal file
View File

@ -0,0 +1,70 @@
/* 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
*/
#include <config.h>
#include "gpgme.h"
#include "context.h"
#include "ops.h"
GpgmeError
_gpgme_op_reset (GpgmeCtx ctx, int synchronous)
{
GpgmeError err = 0;
struct GpgmeIOCbs io_cbs;
fail_on_pending_request (ctx);
ctx->pending = 1;
_gpgme_release_result (ctx);
/* Create an engine object. */
_gpgme_engine_release (ctx->engine);
ctx->engine = NULL;
err = _gpgme_engine_new (ctx->use_cms ? GPGME_PROTOCOL_CMS
: GPGME_PROTOCOL_OpenPGP, &ctx->engine);
if (err)
return err;
if (synchronous)
{
io_cbs.add = _gpgme_add_io_cb;
io_cbs.add_priv = &ctx->fdt;
io_cbs.remove = _gpgme_remove_io_cb;
io_cbs.event = _gpgme_op_event_cb;
io_cbs.event_priv = ctx;
}
else if (! ctx->io_cbs.add)
{
io_cbs.add = _gpgme_add_io_cb;
io_cbs.add_priv = NULL;
io_cbs.remove = _gpgme_remove_io_cb;
io_cbs.event = _gpgme_wait_event_cb;
io_cbs.event_priv = ctx;
}
else
{
io_cbs = ctx->io_cbs;
io_cbs.event = _gpgme_op_event_cb;
io_cbs.event_priv = ctx;
}
_gpgme_engine_set_io_cbs (ctx->engine, &io_cbs);
return err;
}

View File

@ -46,12 +46,11 @@
void _gpgme_release_result ( GpgmeCtx c );
void _gpgme_set_op_info (GpgmeCtx c, GpgmeData info);
void _gpgme_op_event_cb (void *data, GpgmeEventIO type, void *type_data);
/*-- wait.c --*/
GpgmeCtx _gpgme_wait_on_condition ( GpgmeCtx c,
int hang, volatile int *cond );
void _gpgme_freeze_fd ( int fd );
void _gpgme_thaw_fd ( int fd );
/*-- recipient.c --*/
int _gpgme_recipients_all_valid ( const GpgmeRecipients rset );
@ -76,14 +75,15 @@ GpgmeError _gpgme_data_append_percentstring_for_xml ( GpgmeData dh,
GpgmeError _gpgme_data_unread (GpgmeData dh,
const char *buffer, size_t length );
int _gpgme_data_inbound_handler (void *opaque, int pid, int fd);
int _gpgme_data_outbound_handler (void *opaque, int pid, int fd);
void _gpgme_data_inbound_handler (void *opaque, int fd);
void _gpgme_data_outbound_handler (void *opaque, int fd);
/*-- key.c --*/
GpgmeError _gpgme_key_new ( GpgmeKey *r_key );
GpgmeError _gpgme_key_new_secret ( GpgmeKey *r_key );
/*-- op-support.c --*/
GpgmeError _gpgme_op_reset (GpgmeCtx ctx, int synchronous);
/*-- verify.c --*/
void _gpgme_release_verify_result (VerifyResult result);
@ -95,7 +95,8 @@ void _gpgme_verify_status_handler (GpgmeCtx ctx, GpgStatusCode code,
void _gpgme_release_decrypt_result (DecryptResult result);
void _gpgme_decrypt_status_handler (GpgmeCtx ctx, GpgStatusCode code,
char *args);
GpgmeError _gpgme_decrypt_start (GpgmeCtx ctx, GpgmeData ciph, GpgmeData plain,
GpgmeError _gpgme_decrypt_start (GpgmeCtx ctx, int synchronous,
GpgmeData ciph, GpgmeData plain,
void *status_handler);
GpgmeError _gpgme_decrypt_result (GpgmeCtx ctx);

File diff suppressed because it is too large Load Diff

View File

@ -159,5 +159,6 @@ GpgmeError _gpgme_gpg_op_sign (GpgObject gpg, GpgmeData in, GpgmeData out,
GpgmeError _gpgme_gpg_op_trustlist (GpgObject gpg, const char *pattern);
GpgmeError _gpgme_gpg_op_verify (GpgObject gpg, GpgmeData sig, GpgmeData text);
GpgmeError _gpgme_gpg_spawn (GpgObject gpg, void *opaque);
void _gpgme_gpg_set_io_cbs (GpgObject gpg, struct GpgmeIOCbs *io_cbs);
#endif /* RUNGPG_H */

View File

@ -168,27 +168,19 @@ _gpgme_sign_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
}
}
GpgmeError
gpgme_op_sign_start (GpgmeCtx ctx, GpgmeData in, GpgmeData out,
GpgmeSigMode mode)
static GpgmeError
_gpgme_op_sign_start (GpgmeCtx ctx, int synchronous,
GpgmeData in, GpgmeData out,
GpgmeSigMode mode)
{
GpgmeError err = 0;
fail_on_pending_request (ctx);
ctx->pending = 1;
_gpgme_release_result (ctx);
if (mode != GPGME_SIG_MODE_NORMAL
&& mode != GPGME_SIG_MODE_DETACH
&& mode != GPGME_SIG_MODE_CLEAR)
return mk_error (Invalid_Value);
/* Create a process object. */
_gpgme_engine_release (ctx->engine);
ctx->engine = NULL;
err = _gpgme_engine_new (ctx->use_cms ? GPGME_PROTOCOL_CMS
: GPGME_PROTOCOL_OpenPGP, &ctx->engine);
err = _gpgme_op_reset (ctx, synchronous);
if (err)
goto leave;
@ -231,6 +223,13 @@ gpgme_op_sign_start (GpgmeCtx ctx, GpgmeData in, GpgmeData out,
return err;
}
GpgmeError
gpgme_op_sign_start (GpgmeCtx ctx, GpgmeData in, GpgmeData out,
GpgmeSigMode mode)
{
return _gpgme_op_sign_start (ctx, 0, in, out, mode);
}
/**
* gpgme_op_sign:
* @ctx: The context
@ -255,8 +254,8 @@ gpgme_op_sign_start (GpgmeCtx ctx, GpgmeData in, GpgmeData out,
GpgmeError
gpgme_op_sign (GpgmeCtx ctx, GpgmeData in, GpgmeData out, GpgmeSigMode mode)
{
GpgmeError err = gpgme_op_sign_start (ctx, in, out, mode);
GpgmeError err = _gpgme_op_sign_start (ctx, 1, in, out, mode);
if (!err)
gpgme_wait (ctx, &err, 1);
err = _gpgme_wait_one (ctx);
return err;
}

View File

@ -164,26 +164,13 @@ gpgme_op_trustlist_start (GpgmeCtx ctx, const char *pattern, int max_level)
{
GpgmeError err = 0;
fail_on_pending_request (ctx);
if (!pattern || !*pattern)
return mk_error (Invalid_Value);
ctx->pending = 1;
if (ctx->engine)
{
_gpgme_engine_release (ctx->engine);
ctx->engine = NULL;
}
_gpgme_release_result (ctx);
err = _gpgme_engine_new (ctx->use_cms ? GPGME_PROTOCOL_CMS
: GPGME_PROTOCOL_OpenPGP, &ctx->engine);
err = _gpgme_op_reset (ctx, 0);
if (err)
goto leave;
_gpgme_engine_set_status_handler (ctx->engine, trustlist_status_handler, ctx);
err = _gpgme_engine_set_colon_line_handler (ctx->engine,
trustlist_colon_handler, ctx);
if (err)

View File

@ -282,26 +282,18 @@ _gpgme_verify_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
}
}
GpgmeError
gpgme_op_verify_start (GpgmeCtx ctx, GpgmeData sig, GpgmeData text)
static GpgmeError
_gpgme_op_verify_start (GpgmeCtx ctx, int synchronous,
GpgmeData sig, GpgmeData text)
{
int err = 0;
int pipemode = 0; /* !!text; use pipemode for detached sigs. */
fail_on_pending_request (ctx);
ctx->pending = 1;
_gpgme_release_result (ctx);
if (!pipemode)
{
_gpgme_engine_release (ctx->engine);
ctx->engine = NULL;
}
; /* XXX I am not sure what should happen/not happen in
pipemode. */
if (!ctx->engine)
err = _gpgme_engine_new (ctx->use_cms ? GPGME_PROTOCOL_CMS
: GPGME_PROTOCOL_OpenPGP, &ctx->engine);
err = _gpgme_op_reset (ctx, synchronous);
if (err)
goto leave;
@ -347,6 +339,12 @@ gpgme_op_verify_start (GpgmeCtx ctx, GpgmeData sig, GpgmeData text)
return err;
}
GpgmeError
gpgme_op_verify_start (GpgmeCtx ctx, GpgmeData sig, GpgmeData text)
{
return _gpgme_op_verify_start (ctx, 0, sig, text);
}
/*
* Figure out a common status value for all signatures
*/
@ -408,10 +406,10 @@ gpgme_op_verify (GpgmeCtx ctx, GpgmeData sig, GpgmeData text,
ctx->notation = NULL;
*r_stat = GPGME_SIG_STAT_NONE;
err = gpgme_op_verify_start (ctx, sig, text);
err = _gpgme_op_verify_start (ctx, 1, sig, text);
if (!err)
{
gpgme_wait (ctx, &err, 1);
err = _gpgme_wait_one (ctx);
if (!err)
*r_stat = _gpgme_intersect_stati (ctx->result.verify);
}

View File

@ -35,389 +35,84 @@
#include "io.h"
#include "engine.h"
struct wait_item_s;
struct proc_s;
struct fd_table fdt_global;
static struct proc_s *proc_queue;
DEFINE_STATIC_LOCK (proc_queue_lock);
static int fd_table_size;
static struct io_select_fd_s *fd_table;
DEFINE_STATIC_LOCK (fd_table_lock);
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 proc_s
struct wait_item_s
{
struct proc_s *next;
int pid;
GpgmeCtx ctx;
struct wait_item_s *handler_list;
/* Non-zero if the process has been completed. */
int done;
/* Non-zero if the status for this process has been returned
already. */
int reported;
struct wait_item_s *next;
GpgmeIOCb handler;
void *handler_value;
int dir;
};
struct wait_item_s {
struct wait_item_s *next;
int (*handler)(void*,int,int);
void *handler_value;
int inbound; /* this is an inbound data handler fd */
struct proc_s *proc; /* backlink */
int done;
int frozen; /* copy of the frozen flag from the fd_table */
};
static int do_select ( void );
static void run_idle (void);
/* only to be called with a locked proc_queue */
static int
count_running_fds (struct proc_s *proc)
void
_gpgme_fd_table_init (fd_table_t fdt)
{
struct wait_item_s *q;
int count = 0;
for (q = proc->handler_list; q; q=q->next)
{
if (!q->frozen && !q->done)
count++;
}
return count;
}
/* only to be called with a locked proc_queue */
static void
set_process_done (struct proc_s *proc)
{
struct wait_item_s *q, *q2;
int i;
assert (proc);
DEBUG2 ("set_process_done(%p) pid=%d", proc, proc->pid);
LOCK (fd_table_lock);
for (q = proc->handler_list; q; q=q2)
{
q2 = q->next;
for (i = 0; i < fd_table_size; i++)
{
if (fd_table[i].fd != -1 && q == fd_table[i].opaque)
{
fd_table[i].opaque = NULL;
fd_table[i].fd = -1;
}
}
xfree (q);
}
UNLOCK (fd_table_lock);
proc->handler_list = NULL;
proc->done = 1;
INIT_LOCK (fdt->lock);
fdt->fds = NULL;
fdt->size = 0;
}
void
_gpgme_remove_proc_from_wait_queue (int pid)
_gpgme_fd_table_deinit (fd_table_t fdt)
{
struct proc_s *proc, *last;
DEBUG1 ("removing process %d", pid);
LOCK (proc_queue_lock);
for (last = NULL, proc = proc_queue; proc; last = proc, proc = proc->next)
{
if (proc->pid == pid)
{
set_process_done (proc);
if (!last)
proc_queue = proc->next;
else
last->next = proc->next;
xfree (proc);
break;
}
}
UNLOCK (proc_queue_lock);
DESTROY_LOCK (fdt->lock);
if (fdt->fds)
xfree (fdt->fds);
}
/**
* 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 the given) request has finished.
**/
GpgmeCtx
gpgme_wait (GpgmeCtx ctx, GpgmeError *status, int hang)
{
GpgmeCtx retctx = _gpgme_wait_on_condition (ctx, hang, NULL);
if (status)
*status = retctx->error;
return retctx;
}
GpgmeCtx
_gpgme_wait_on_condition (GpgmeCtx ctx, int hang, volatile int *cond)
{
DEBUG3 ("waiting... ctx=%p hang=%d cond=%p", ctx, hang, cond);
do
{
int any = 0;
struct proc_s *proc;
do_select ();
if (cond && *cond)
hang = 0;
else
{
LOCK (proc_queue_lock);
for (proc = proc_queue; proc; proc = proc->next)
{
/* A process is done if it has completed voluntarily, or
if the context it lived in was canceled. */
if (!proc->done && !count_running_fds (proc))
set_process_done (proc);
else if (!proc->done && proc->ctx->cancel)
{
set_process_done (proc);
proc->ctx->cancel = 0;
proc->ctx->error = mk_error (Canceled);
}
/* A process that is done is eligible for election if it
is in the requested context or if it was not yet
reported. */
if (proc->done && (proc->ctx == ctx || (!ctx && !proc->reported)))
{
if (!ctx)
ctx = proc->ctx;
hang = 0;
ctx->pending = 0;
proc->reported = 1;
}
if (!proc->done)
any = 1;
}
UNLOCK (proc_queue_lock);
if (!any)
hang = 0;
}
/* fixme: We should check here for hanging processes. */
if (hang)
run_idle ();
}
while (hang && (!ctx || !ctx->cancel));
if (ctx && ctx->cancel)
{
/* FIXME: Paranoia? */
ctx->cancel = 0;
ctx->pending = 0;
ctx->error = mk_error (Canceled);
}
return ctx;
}
/*
* We use this function to do the select stuff for all running
* gpgs. A future version might provide a facility to delegate
* those selects to the GDK select stuff.
* This function must be called only by one thread!!
* Returns: 0 = nothing to run
* 1 = did run something
*/
static int
do_select (void)
{
int i, n;
int any = 0;
n = _gpgme_io_select (fd_table, fd_table_size);
if (n <= 0)
return 0; /* error or timeout */
for (i = 0; i < fd_table_size && n; i++)
{
if (fd_table[i].fd != -1 && fd_table[i].signaled
&& !fd_table[i].frozen)
{
struct wait_item_s *q;
assert (n);
n--;
q = fd_table[i].opaque;
assert (q);
assert (q->proc);
assert (!q->done);
any = 1;
if (q->handler (q->handler_value,
q->proc->pid, fd_table[i].fd))
{
DEBUG2 ("setting fd %d (q=%p) done", fd_table[i].fd, q);
q->done = 1;
/* Free the table entry. */
LOCK (fd_table_lock);
fd_table[i].for_read = 0;
fd_table[i].for_write = 0;
fd_table[i].fd = -1;
fd_table[i].opaque = NULL;
UNLOCK (fd_table_lock);
}
}
}
return any;
}
/*
* called by rungpg.c to register something for select()
*/
/* XXX We should keep a marker and roll over for speed. */
GpgmeError
_gpgme_register_pipe_handler (void *opaque,
int (*handler)(void*,int,int),
void *handler_value,
int pid, int fd, int inbound)
_gpgme_fd_table_put (fd_table_t fdt, int fd, int dir, void *opaque, int *idx)
{
GpgmeCtx ctx = opaque;
struct wait_item_s *q;
struct proc_s *proc;
int i;
int i, j;
struct io_select_fd_s *new_fds;
assert (opaque);
assert (handler);
/* Allocate a structure to hold info about the handler. */
q = xtrycalloc (1, sizeof *q);
if (!q)
return mk_error (Out_Of_Core);
q->inbound = inbound;
q->handler = handler;
q->handler_value = handler_value;
/* Put this into the process queue. */
LOCK (proc_queue_lock);
for (proc = proc_queue; proc && proc->pid != pid; proc = proc->next)
;
if (!proc)
LOCK (fdt->lock);
for (i = 0; i < fdt->size; i++)
{
/* A new process. */
proc = xtrycalloc (1, sizeof *proc);
if (!proc)
if (fdt->fds[i].fd == -1)
break;
}
if (i == fdt->size)
{
#define FDT_ALLOCSIZE 10
new_fds = xtryrealloc (fdt->fds, (fdt->size + FDT_ALLOCSIZE)
* sizeof (*new_fds));
if (!new_fds)
{
UNLOCK (proc_queue_lock);
UNLOCK (fdt->lock);
return mk_error (Out_Of_Core);
}
proc->pid = pid;
proc->ctx = ctx;
proc->next = proc_queue;
proc_queue = proc;
}
fdt->fds = new_fds;
fdt->size += FDT_ALLOCSIZE;
for (j = 0; j < FDT_ALLOCSIZE; j++)
fdt->fds[i + j].fd = -1;
}
assert (proc->ctx == ctx);
q->proc = proc;
q->next = proc->handler_list;
proc->handler_list = q;
UNLOCK (proc_queue_lock);
LOCK (fd_table_lock);
again:
for (i=0; i < fd_table_size; i++)
{
if (fd_table[i].fd == -1)
{
fd_table[i].fd = fd;
fd_table[i].for_read = inbound;
fd_table[i].for_write = !inbound;
fd_table[i].signaled = 0;
fd_table[i].frozen = 0;
fd_table[i].opaque = q;
UNLOCK (fd_table_lock);
return 0;
}
}
if ( fd_table_size < 50 ) {
/* FIXME: We have to wait until there are no other readers of the
* table, i.e that the io_select is not active in another thread */
struct io_select_fd_s *tmp;
tmp = xtryrealloc (fd_table, (fd_table_size + 10) * sizeof *tmp);
if (tmp)
{
for (i = 0; i < 10; i++)
tmp[fd_table_size+i].fd = -1;
fd_table_size += i;
fd_table = tmp;
goto again;
}
}
UNLOCK (fd_table_lock);
xfree (q);
/* FIXME: Remove the proc table entry. */
return mk_error (Too_Many_Procs);
fdt->fds[i].fd = fd;
fdt->fds[i].for_read = (dir == 1);
fdt->fds[i].for_write = (dir == 0);
fdt->fds[i].frozen = 0;
fdt->fds[i].signaled = 0;
fdt->fds[i].opaque = opaque;
UNLOCK (fdt->lock);
*idx = i;
return 0;
}
void
_gpgme_freeze_fd (int fd)
{
int i;
LOCK (fd_table_lock);
for (i = 0; i < fd_table_size; i++)
{
if (fd_table[i].fd == fd)
{
struct wait_item_s *q;
fd_table[i].frozen = 1;
q = fd_table[i].opaque;
if (q)
q->frozen = 1;
DEBUG2 ("fd %d frozen (q=%p)", fd, q);
break;
}
}
UNLOCK (fd_table_lock);
}
void
_gpgme_thaw_fd (int fd)
{
int i;
LOCK (fd_table_lock);
for (i = 0; i < fd_table_size; i++)
{
if (fd_table[i].fd == fd)
{
struct wait_item_s *q;
fd_table[i].frozen = 0;
q = fd_table[i].opaque;
if (q)
q->frozen = 0;
DEBUG2 ("fd %d thawed (q=%p)", fd, q);
break;
}
}
UNLOCK (fd_table_lock);
}
/**
* gpgme_register_idle:
* @fnc: Callers idle function
@ -438,7 +133,6 @@ gpgme_register_idle (GpgmeIdleFunc idle)
return old_idle;
}
static void
run_idle ()
{
@ -446,3 +140,233 @@ run_idle ()
if (idle_function)
idle_function ();
}
/* Wait on all file descriptors listed in FDT and process them using
the registered callbacks. Returns 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);
if (n <= 0)
{
UNLOCK (fdt->lock);
return 0; /* 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 = xtryrealloc (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)
{
ctx = _gpgme_wait_on_condition (ctx, hang, NULL);
if (ctx && status)
*status = ctx->error;
return ctx;
}
GpgmeError
_gpgme_wait_one (GpgmeCtx ctx)
{
int hang = 1;
DEBUG1 ("waiting... ctx=%p", ctx);
do
{
if (! do_select (&ctx->fdt))
hang = 0;
}
while (hang && !ctx->cancel);
if (ctx->cancel)
{
/* FIXME: Paranoia? */
ctx->cancel = 0;
ctx->pending = 0;
ctx->error = mk_error (Canceled);
}
return ctx->error;
}
GpgmeCtx
_gpgme_wait_on_condition (GpgmeCtx ctx, int hang, volatile int *cond)
{
DEBUG3 ("waiting... ctx=%p hang=%d cond=%p", ctx, hang, cond);
do
{
if (! do_select (&fdt_global))
hang = 0;
if (cond && *cond)
hang = 0;
else
{
int i;
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)
run_idle ();
}
while (hang && (!ctx || !ctx->cancel));
if (ctx && ctx->cancel)
{
/* FIXME: Paranoia? */
ctx->cancel = 0;
ctx->pending = 0;
ctx->error = mk_error (Canceled);
}
return ctx;
}
struct tag
{
fd_table_t fdt;
int idx;
};
void *
_gpgme_add_io_cb (void *data, int fd, int dir,
GpgmeIOCb fnc, void *fnc_data)
{
GpgmeError err;
fd_table_t fdt = (fd_table_t) (data ? data : &fdt_global);
struct wait_item_s *item;
struct tag *tag;
assert (fdt);
assert (fnc);
tag = xtrymalloc (sizeof *tag);
if (!tag)
return NULL;
tag->fdt = fdt;
/* Allocate a structure to hold info about the handler. */
item = xtrycalloc (1, sizeof *item);
if (!item)
{
xfree (tag);
return NULL;
}
item->dir = dir;
item->handler = fnc;
item->handler_value = fnc_data;
err = _gpgme_fd_table_put (fdt, fd, dir, item, &tag->idx);
if (err)
{
xfree (tag);
xfree (item);
errno = ENOMEM;
return 0;
}
return tag;
}
void
_gpgme_remove_io_cb (void *data)
{
struct tag *tag = data;
fd_table_t fdt = tag->fdt;
int idx = tag->idx;
LOCK (fdt->lock);
DEBUG2 ("setting fd %d (item=%p) done", fdt->fds[idx].fd,
fdt->fds[idx].opaque);
xfree (fdt->fds[idx].opaque);
xfree (tag);
/* Free the table entry. */
fdt->fds[idx].fd = -1;
fdt->fds[idx].for_read = 0;
fdt->fds[idx].for_write = 0;
fdt->fds[idx].opaque = NULL;
}

View File

@ -23,12 +23,24 @@
#define WAIT_H
#include "gpgme.h"
#include "sema.h"
void _gpgme_remove_proc_from_wait_queue (int pid);
struct fd_table
{
DECLARE_LOCK (lock);
struct io_select_fd_s *fds;
size_t size;
};
typedef struct fd_table *fd_table_t;
GpgmeError _gpgme_register_pipe_handler (void *opaque,
int (*handler) (void*, int, int),
void *handler_value,
int pid, int fd, int inbound);
void _gpgme_fd_table_init (fd_table_t fdt);
void _gpgme_fd_table_deinit (fd_table_t fdt);
void *_gpgme_add_io_cb (void *data, int fd, int dir,
GpgmeIOCb fnc, void *fnc_data);
void _gpgme_remove_io_cb (void *tag);
void _gpgme_wait_event_cb (void *data, GpgmeEventIO type, void *type_data);
GpgmeError _gpgme_wait_one (GpgmeCtx ctx);
#endif /* WAIT_H */