diff options
| author | Marcus Brinkmann <[email protected]> | 2009-03-06 22:29:49 +0000 | 
|---|---|---|
| committer | Marcus Brinkmann <[email protected]> | 2009-03-06 22:29:49 +0000 | 
| commit | 9ace1d56423f849b23fecdb77dd7ad6854975460 (patch) | |
| tree | 212cfbddf9a9a640d597f2b39c993b166852e811 | |
| parent | Chnaged the op-assuan interface. (diff) | |
| download | gpgme-9ace1d56423f849b23fecdb77dd7ad6854975460.tar.gz gpgme-9ace1d56423f849b23fecdb77dd7ad6854975460.zip | |
assuan/
2009-03-06  Marcus Brinkmann  <[email protected]>
	* assuan/: Update to libassuan SVN 2009-03-06.
src/
2009-03-06  Marcus Brinkmann  <[email protected]>
	* version.c (do_subsystem_inits): Do not set assuan log level.
	* debug.c (debug_init): Likewise.
| -rw-r--r-- | ChangeLog | 4 | ||||
| -rw-r--r-- | assuan/ChangeLog | 421 | ||||
| -rw-r--r-- | assuan/assuan-buffer.c | 60 | ||||
| -rw-r--r-- | assuan/assuan-client.c | 10 | ||||
| -rw-r--r-- | assuan/assuan-connect.c | 8 | ||||
| -rw-r--r-- | assuan/assuan-defs.h | 93 | ||||
| -rw-r--r-- | assuan/assuan-handler.c | 290 | ||||
| -rw-r--r-- | assuan/assuan-inquire.c | 158 | ||||
| -rw-r--r-- | assuan/assuan-io.c | 141 | ||||
| -rw-r--r-- | assuan/assuan-listen.c | 20 | ||||
| -rw-r--r-- | assuan/assuan-logging.c | 61 | ||||
| -rw-r--r-- | assuan/assuan-pipe-connect.c | 147 | ||||
| -rw-r--r-- | assuan/assuan-pipe-server.c | 24 | ||||
| -rw-r--r-- | assuan/assuan-socket-connect.c | 26 | ||||
| -rw-r--r-- | assuan/assuan-socket-server.c | 63 | ||||
| -rw-r--r-- | assuan/assuan-socket.c | 407 | ||||
| -rw-r--r-- | assuan/assuan-uds.c | 36 | ||||
| -rw-r--r-- | assuan/assuan-util.c | 25 | ||||
| -rw-r--r-- | assuan/assuan.h | 189 | ||||
| -rwxr-xr-x | assuan/mkerrors | 39 | ||||
| -rw-r--r-- | src/debug.c | 3 | ||||
| -rw-r--r-- | src/version.c | 1 | 
22 files changed, 1652 insertions, 574 deletions
| @@ -1,3 +1,7 @@ +2009-03-06  Marcus Brinkmann  <[email protected]> + +	* assuan/: Update to libassuan SVN 2009-03-06. +  2009-01-26  Werner Koch  <[email protected]>  	* configure.ac (AC_CONFIG_FILES): Add tests/opassuan/Makefile. diff --git a/assuan/ChangeLog b/assuan/ChangeLog index e620d205..3d875fb6 100644 --- a/assuan/ChangeLog +++ b/assuan/ChangeLog @@ -3,68 +3,262 @@  	* assuan-buffer.c (assuan_send_data): Add hack to optionally send  	a final "CAN". -2008-11-03  Marcus Brinkmann  <[email protected]> +2008-11-03  Marcus Brinkmann  <[email protected]> -	* Makefile.am (INCLUDES): Replace gpgme path with src. +	* assuan-handler.c (std_handler_help): Make I unsigned to silence +	gcc -W warning. +	* assuan-logging.c (_assuan_log_print_buffer): Likewise for N. +	* funopen.c (_assuan_funopen): Remove initializer to silence gcc +	-W warning. +	* assuan-handler.c (std_cmd_table): Add missing initializer to +	silence gcc -W warning. +	* assuan-socket-server.c (io): Likewise. +	* assuan-socket-connect.c (assuan_socket_connect_ext): Likewise. -2008-10-30  Marcus Brinkmann  <[email protected]> +2008-10-29  Marcus Brinkmann  <[email protected]> -	* assuan-pipe-connect.c: Fix prototype for _gpgme_io_spawn.  Cast -	second argument in its invocation to silence gcc warning. +	* assuan.h (assuan_error_t) (_ASSUAN_ONLY_GPG_ERRORS): Make +	unsigned int. +	(assuan_transact): Change return type of callback handlers to +	assuan_error_t. -2008-06-25  Marcus Brinkmann  <[email protected]> +2008-10-15  Werner Koch  <[email protected]> -	* assuan-pipe-connect.c (struct spawn_fd_item_s): Add new members. -	(HANDLE_TRANSLATION): New macro. -	(pipe_connect_gpgme): Adjust caller of _gpgme_io_spawn. -	[HANDLE_TRANSLATION]: Return translated handles. +	* assuan-logging.c (_assuan_log_printf): Flush if the format +	string ends with a LF. -2008-02-14  Werner Koch  <[email protected]> +2008-09-01  Werner Koch  <[email protected]> -	* assuan-pipe-connect.c (_gpgme_io_spawn): Adjust prototype. -	(pipe_connect_gpgme, pipe_connect_gpgme): Adjust call. +	* assuan-io.c: Include time.h.  Fixes bug#951. +	(_assuan_usleep): Use nanosleep only is available. -2008-01-04  Marcus Brinkmann  <[email protected]> +2008-03-25  Marcus Brinkmann  <[email protected]> -	* assuan-pipe-connect.c (_gpgme_io_pipe) -	(_gpgme_io_spawn) [_ASSUAN_IN_GPGME_BUILD_ASSUAN]: Add prototypes -	to silence compiler warning.  Reported by Alon Bar-Lev. +	* assuan-inquire.c (assuan_inquire): Loop over _assuan_read_line +	for EAGAIN. + +2008-03-21  Marcus Brinkmann  <[email protected]> + +	* assuan-defs.h (_assuan_usleep): New prototype. +	* assuan-io.c (_assuan_usleep): New function. +	* assuan-io-pth.c (_assuan_usleep): New function. +	* mkerrors: Do not incude <windows.h>, but assuan-defs.h. +	(_assuan_error_is_eagain): Call _assuan_usleep. + +	* mkerrors [HAVE_W32_SYSTEM]: Include <windows.h> +	(_assuan_error_is_eagain) [HAVE_W32_SYSTEM]: Wait the tenth of a +	second. + +2007-11-23  Marcus Brinkmann  <[email protected]> + +	* assuan-inquire.c (_assuan_inquire_ext_cb): Pass through return +	value from callback function. +	Suggested by Ben Kibbey <[email protected]>. + +2007-11-14  Werner Koch  <[email protected]> + +	* assuan-pipe-connect.c (pipe_connect_unix): Add dummy arg FLAGS. +	(pipe_connect_w32): Add arg FLAGS and start process detached if +	requested.  Changed callers to pass 0. +	(assuan_pipe_connect_ext): Pass FLAG. + +2007-11-12  Marcus Brinkmann  <[email protected]> + +	* assuan-inquire.c (_assuan_inquire_ext_cb): Clear +	CTX->inquire_membuf after deallocating it. + +2007-10-18  Marcus Brinkmann  <[email protected]> + +	* assuan-handler.c (std_handler_help): New function. +	(std_cmd_table): Add new command HELP. + +2007-10-08  Werner Koch  <[email protected]> + +	* assuan-util.c (assuan_set_io_hooks): New. +	* assuan.h (struct assuan_io_hooks): New. +	(assuan_set_io_hooks, _assuan_io_hooks): Add prefix macros. +	* assuan-defs.h (_assuan_io_hooks): New. +	* assuan-io.c (do_io_read): Take all code from _assuan_io_read. +	(_assuan_io_read, _assuan_simple_read): Add hook feature. +	(do_io_write): Take all code from _assuan_io_write. +	(_assuan_io_write, _assuan_simple_write): Add hook feature. +	* assuan-io-pth.c (_assuan_simple_read, _assuan_simple_write)  +	(_assuan_io_read, _assuan_io_write): Add hook feature. +	 +2007-10-05  Marcus Brinkmann  <[email protected]> + +	* assuan.h (_assuan_error_is_eagain): Add prefix macro. + +	* assuan-defs.h (_assuan_error_is_eagain): New prototype. +	* mkerrors (_assuan_error_is_eagain): New function. +	* assuan-handler.c (process_next): Leave on EAGAIN. +	* assuan-handler.c (process_request), +	assuan-client.c (_assuan_read_from_server), +	assuan-buffer.c (assuan_read_line): Busy loop over EAGAIN. + +2007-10-05  Werner Koch  <[email protected]> + +	* assuan-socket.c (_assuan_sock_wsa2errno): Map WSANOTINITIALISED. +	(_assuan_sock_new): Use assuan_fd_t. +	* assuan.h (_assuan_sock_wsa2errno): Add prefix macro. + +2007-10-05  Marcus Brinkmann  <[email protected]> + +	* assuan-defs.h (_assuan_sock_wsa2errno) [HAVE_W32_SYSTEM]: Add prototype. +	* assuan-uds.c (wsa2errno) [HAVE_W32_SYSTEM]: Move and rename to ... +	* assuan-socket.c (_assuan_sock_wsa2errno) [HAVE_W32_SYSTEM]: ... this. +	(_assuan_close, _assuan_sock_new, _assuan_sock_connect, _assuan_sock_bind): +	Always set errno on error. + +	* assuan-uds.c (wsa2errno) [HAVE_W32_SYSTEM]: New function. +	(uds_reader, uds_writer) [HAVE_W32_SYSTEM]: Set errno. + +2007-10-04  Werner Koch  <[email protected]> + +	* mkerrors: Map EAGAIN to GPG_ERR_EAGAIN for read and write +	errors.  + +2007-10-02  Werner Koch  <[email protected]> + +	* assuan-io.c (_assuan_io_read) [W32]: Map WSAEWOULDBLOCK to EAGAIN. +	* assuan-socket.c (_assuan_sock_check_nonce): N needs to be signed. + +	* assuan-defs.h (struct assuan_context_s): Add LISTEN_NONCE. +	* assuan-socket-server.c (assuan_set_sock_nonce): New. +	(accept_connection): Check the nonce. + +2007-10-01  Werner Koch  <[email protected]> + +	* assuan.h (ASSUAN_INT2FD, ASSUAN_FD2INT): New. + +	* assuan-socket.c: Rewritten. +	(assuan_sock_new, assuan_sock_connect, assuan_sock_bind)  +	(assuan_sock_get_nonce, assuan_sock_check_nonce): New APIs. + +	* assuan-io.c (_assuan_simple_read, _assuan_simple_write): +	Factored code out to ... +	(_assuan_io_read, _assuan_io_write): .. new. +	* assuan-io-pth.c (_assuan_io_read, _assuan_io_write): New.  2007-09-25  Werner Koch  <[email protected]>  	* assuan.h (_assuan_gpg_strerror_r, _assuan_gpg_strsource): Add -	new wrappers. +	wrappers for these new internal functions. + +2007-09-24  Marcus Brinkmann  <[email protected]> + +	* assuan-uds.c (uds_reader) [HAVE_W32_SYSTEM]: Do not touch the +	UDS structure in the context.  Reported by Frank Osterfeld. +	(uds_writer): Clarify code. + +2007-09-14  Marcus Brinkmann  <[email protected]> + +	* assuan-pipe-connect.c (do_finish) [HAVE_W32_SYSTEM]: Close +	ctx->pid as handle. +	(pipe_connect_w32): Save the spawned processes handle. + +2007-09-13  Werner Koch  <[email protected]> + +	* assuan-socket.c (_assuan_close): Add inactive debug outputs. + +2007-09-11  Marcus Brinkmann  <[email protected]> + +	* assuan.h: Use _WIN32 instead of HAVE_W32_SYSTEM. + +2007-09-07  Marcus Brinkmann  <[email protected]> + +	* assuan-inquire.c (assuan_inquire_ext): If MAXLEN is 0, still +	initialize MEMBUF. +	 +	* assuan-inquire.c (_assuan_inquire_ext_cb): Clear CTX->in_inquire +	before invoking callback and returning. + +2007-09-05  Marcus Brinkmann  <[email protected]> + +	* assuan-handler.c (dispatch_command): Return non-critical errors +	with PROCESS_DONE (). + +2007-09-03  Marcus Brinkmann  <[email protected]> + +	* assuan.h [_ASSUAN_EXT_SYM_PREFIX]: Add missing symbol renames +	with _ASSUAN_PREFIX.  2007-09-03  Marcus Brinkmann  <[email protected]>  	* assuan.h [_ASSUAN_EXT_SYM_PREFIX]: Add missing symbol renames  	with _ASSUAN_PREFIX. -2007-08-02  Werner Koch  <[email protected]> +	* assuan.h (assuan_inquire_ext): Move buffer and buffer_length +	arguments callback in prototype. +	* assuan-defs.h (struct assuan_context_s): Remove members +	inquire_r_buffer and inquire_r_buffer_len.  Add buffer and buffer +	length arguments to inquire_cb. +	* assuan-inquire.c (_assuan_inquire_ext_cb): Return buffer and +	buffer length via callback. +	(assuan_inquire_ext): Move buffer and buffer length arguments to +	callback. -	* assuan-pipe-connect.c (pipe_connect_w32): A bit more debug output. -	(pipe_connect_w32): Use DETACHED_PROCESS flag. -	* assuan-logging.c (log_level): New.  Use this to disable logging. -	(assuan_set_assuan_log_level): New. -	* assuan.h: Add prototype. +2007-08-24  Werner Koch  <[email protected]> -2007-07-12  Werner Koch  <[email protected]> +	Switched license to back to LGPLv2.1. -	* assuan-handler.c (assuan_get_active_fds): Use get_osfhandle for -	the data fp. -	* assuan-socket.c (_assuan_close) [W32]: Use CloseHandle and not close. +2007-08-09  Marcus Brinkmann  <[email protected]> -	* assuan-io.c (_assuan_simple_write, _assuan_simple_read): Map -	ERROR_BROKEN_PIPE to EPIPE. +	* assuan.h (assuan_process_done, assuan_inquire_ext): New +	prototypes. +	* assuan-defs.h (struct assuan_context_s): New members +	in_process_next, in_command, inquire_cb, inquire_cb_data, +	inquire_r_buffer, inquire_r_buffer_len, inquire_membuf. +	(_assuan_inquire_ext_cb, _assuan_inquire_release): New prototypes. +	* assuan-handler.c (PROCESS_DONE): New macro. +	(dummy_handler, std_handler_nop, std_handler_cancel) +	(std_handler_option, std_handler_bye, std_handler_auth) +	(std_handler_reset, std_handler_end): Use PROCESS_DONE to +	optionally call assuan_process_done if CTX->in_process_next is +	true. +	(assuan_process_done, process_next): New functions. +	(assuan_process_next): Rewritten to support external event +	handling. +	* mkerrors: Do not clear high bits of -1 for old style EOF. +	* assuan-inquire.c (_assuan_inquire_release) +	(_assuan_inquire_ext_cb, assuan_inquire_ext): New functions. +	* assuan-pipe-server.c (_assuan_release_context): Call +	_assuan_inquire_release. +	 +2007-07-12  Werner Koch  <[email protected]> +	* assuan.h (assuan_fd_t): New. +	(ASSUAN_INVALID_FD): New.  Use it everywhere. +	* assuan-defs.h (SOCKET2HANDLE, HANDLE2SOCKET) [W32]: New.  Use +	them to cast descriptors for socket fucntions. +	* assuan-pipe-connect.c (fd_to_handle, handle_to_fd): Remove +	definition and all uses. +	(pid_to_handle, handle_to_pid): Remove as they are ununsed. +	* assuan-io.c (_assuan_simple_write, _assuan_simple_read) [W32]: +	Make use of HANDLE2SOCKET. +	* assuan-socket.c (_assuan_close) [W32]: Use CloseHandle and not +	close. +	* assuan-handler.c (assuan_get_active_fds) [W32]: Use +	_get_osfhandle for the data fp. + +	* assuan-io.c (_assuan_simple_write): Return EPIPE on a closed pipe. +	(_assuan_simple_read): Likewise +	  2007-07-08  Marcus Brinkmann  <[email protected]> -	* assuan-defs.h (struct assuan_context_s): Have partial peercred -	structure even if HAVE_W32_SYSTEM, and have full peercred -	structure only if HAVE_SO_PEERCRED. +	* assuan-defs.h (struct assuan_context_s): Have full peercred +	structure for HAVE_SO_PEERCRED.  	* assuan-connect.c (assuan_get_peercred) [!HAVE_SO_PEERCRED]: Do  	not try to set PID, UID and GID. +2007-07-05  Werner Koch  <[email protected]> + +	* assuan-defs.h (struct assuan_context_s): Have peercred.valid +	even for Windows.  This makes some other code cleaner. + +	* assuan.h (ASSUAN_CONFIDENTIAL): New flag. +	* assuan-util.c (assuan_set_flag, assuan_get_flag): Support flag. +  2007-07-04  Marcus Brinkmann  <[email protected]>  	Change _WIN32 to HAVE_W32_SYSTEM for consistency. @@ -382,28 +576,63 @@  	to silence gcc warning.  	* assuan-inquire.c (assuan_inquire): Likewise. -2005-08-19  Werner Koch  <[email protected]> +2005-09-08  Marcus Brinkmann  <[email protected]> -	* funopen.c, assuan-socket.c: Copied from libassuan CVS.  	* assuan-pipe-connect.c (assuan_pipe_connect2): Add missing  	declaration of PID.  2005-08-09  Werner Koch  <[email protected]> -	* README.1st: Adjusted to cope with changes done in upstream Assuan. +	* mkerrors: Include config.h into assuan-errors.c.  This is +	required so that assuan.h knows about the W32 macro. -	Merged changes for W32 support from libassuan. -	  	* assuan.h [_ASSUAN_EXT_SYM_PREFIX]: New.  	* assuan-io.c [_ASSUAN_NO_PTH]: New.  	* assuan-pipe-connect.c (fix_signals) [_ASSUAN_NO_FIXED_SIGNALS]: New.  	(assuan_pipe_connect2) [_ASSUAN_USE_DOUBLE_FORK]: Use double fork.  	(fix_signals) [_ASSUAN_USE_DOUBLE_FORK]: Do not wait.. -	* assuan-logging.c, assuan-io.c: Include config.h -	Replaced all usages of _WIN32 by the new HAVE_W32_SYSTEM because -	there is nothing winning in this API. -	* assuan-pipe-connect.c (assuan_pipe_connect2) [_WIN32]: Return -	error Not Imlemented. +	 +2005-05-21  Werner Koch  <[email protected]> + +	* assuan-util.c (assuan_set_flag, assuan_get_flag): New. +	* assuan-defs.h (struct assuan_context_s): New field flags. +	* assuan.h (assuan_flag_t): New with one flag value +	ASSUAN_NO_WAITPID for now. +	* assuan-pipe-connect.c (do_finish): Take care of the no_waitpid +	flag. + +2005-04-04  Werner Koch  <[email protected]> + +	* assuan-util.c (_assuan_calloc): Avoid integer overflow. + +2005-03-22  Werner Koch  <[email protected]> + +	* assuan-defs.h (struct assuan_io): Renamed elements READ and +	WRITE to READFNC and WRITEFNC to avoid problems with read defined +	as macros.  Changed callers.  Noted by Ville Skyttä. + +2005-02-24  Werner Koch  <[email protected]> + +	* assuan-client.c (assuan_transact): Handle empty and comment +	commands correctly. + +2004-12-20  Werner Koch  <[email protected]> + +	* assuan-socket-connect.c (assuan_socket_connect) [W32]: Allow for +	a drive letter in the path. + +2004-12-19  Werner Koch  <[email protected]> + +	* assuan-pipe-server.c (assuan_init_pipe_server) [W32]: Map file +	descriptors using _get_osfhandle. + +2004-12-19  Moritz Schulte  <[email protected]> + +	* assuan-pipe-connect.c (assuan_pipe_connect2): Removed "`" +	character at beginning of line 532. + +2004-12-18  Werner Koch  <[email protected]> +  	* assuan-logging.c (_assuan_w32_strerror): New.   	* assuan-defs.h (w32_strerror): new.  	* assuan-pipe-connect.c (assuan_pipe_connect2, fix_signals): @@ -411,57 +640,95 @@  	(build_w32_commandline, create_inheritable_pipe): New.  Taken  	from gnupg 1.9.  	(assuan_pipe_connect2) [W32]: Implemented for W32. -	* assuan-pipe-server.c (assuan_init_pipe_server) [W32]: Map file -	descriptors using _get_osfhandle. -	* assuan-socket-connect.c (assuan_socket_connect) [W32]: Allow for -	a drive letter in the path. -	* assuan-client.c (assuan_transact): Handle empty and comment -	commands correctly. -	* assuan-util.c (_assuan_calloc): Avoid integer overflow. -	* assuan-util.c (assuan_set_flag, assuan_get_flag): New. -	* assuan-defs.h (struct assuan_context_s): New field flags. -	* assuan.h (assuan_flag_t): New with one flag value -	ASSUAN_NO_WAITPID for now. -	* assuan-pipe-connect.c (do_finish): Take care of the no_waitpid -	flag. -	* mkerrors: Include config.h into assuan-errors.c.  This is -	required so that assuan.h knows about the W32 macro. -2005-08-09 Timo Schulz  <[email protected]> (ported from libassuan by wk) +2004-12-14  Werner Koch  <[email protected]> + +	* assuan-socket-connect.c (assuan_socket_connect): Always allow +	NAME to start with a froward slash. + +2004-12-07  Werner Koch  <[email protected]> + +	* assuan-logging.c, assuan-io.c: Include config.h + +	Replaced all usages of _WIN32 by the new HAVE_W32_SYSTEM because +	there is nothing winning in this API. + +	* assuan-pipe-connect.c (assuan_pipe_connect2) [_WIN32]: Return +	error Not Imlemented. + +2004-11-27  Werner Koch  <[email protected]> + +	* assuan-socket.c: Include sys/types.h.  Noted by Michael +	Nottebrock. + +2004-11-26  Werner Koch  <[email protected]> + +	* assuan-io.c [_WIN32]: Avoid warnings about unknown pragmas. + +2004-11-24  Werner Koch  <[email protected]> + +	* assuan-logging.c (_assuan_log_printf): New. +	* assuan-domain-connect.c (LOG): Removed and replaced all callers +	by _assuan_log_printf.  This is needed for C89 and gcc 2.95 which +	both don't have C99 style variable arg macros. +	* assuan-pipe-connect.c (LOG): Ditto. +	* assuan-socket-connect.c (LOG): Ditto. + +	* assuan-socket.c[!_WIN32]: Fixed includes. + +2004-11-23  Timo Schulz  <[email protected]> + +	* assuan-socket.c (_assuan_sock_connect): Get local port from +	the sun_path[] file. +	(_assuan_sock_bind): Write local port to the sun_path[] file. +	* assuan-socket-connect.c (assuan_socket_connect): Use DIRSEP_C +	for a better portability. +	(assuan-defs.h): Define DIRSEP_C. +2004-11-19  Werner Koch  <[email protected]> + +	* assuan-handler.c (assuan_write_status): Return an error code. + +2004-11-22  Timo Schulz  <[email protected]> +  	* assuan-io.c (_assuan_simple_read, _assuan_simple_write): W32  	support.  	* assuan-socket.c (_assuan_close): New.  	(_assuan_sock_new): New.  	(_assuan_sock_bind): New. +	 +2004-11-16  Werner Koch  <[email protected]> -2005-03-22  Werner Koch  <[email protected]> +	* assuan-socket-connect.c (LOG): Fixed macro to print not only the +	prefix. +	* assuan-domain-connect.c, assuan-socket-connect.c (LOG): Ditto. -	* assuan-defs.h (struct assuan_io): Renamed elements READ and -	WRITE to READFNC and WRITEFNC to avoid problems with read defined -	as macro.  Changed callers.  Noted by Ville Skyttä. +2004-10-02  Werner Koch  <[email protected]> + +	* assuan-socket-connect.c: Define SUN_LEN, AF_LOCAL and PF_LOCAL +	if they are not available. +	* assuan-domain-connect.c: Define PF_LOCAL and AF_LOCAL if needed. -2004-12-16  Marcus Brinkmann  <[email protected]> +2004-06-23  Marcus Brinkmann  <[email protected]> -	* assuan-pipe-connect.c (do_finish): Do not wait for child to finish. -	(assuan_pipe_connect): Use double-fork approach. -	* assuan-connect.c (assuan_disconnect): Do not write BYE to the -	status line. +	* assuan-domain-connect.c [HAVE_SYS_UIO_H]: Include <sys/uio.h>. -2004-12-07  Marcus Brinkmann  <[email protected]> +2004-05-11  Werner Koch  <[email protected]> -	* README.1st: Add copyright notice. +	* assuan-listen.c (assuan_set_hello_line, assuan_accept): Allow +	for multi line hello strings. -2004-06-23  Marcus Brinkmann  <[email protected]> +	* assuan-buffer.c (_assuan_write_line): New with parts of .. +	(assuan_write_line): .. factored out. -	* assuan-domain-connect.c [HAVE_SYS_UIO_H]: Include <sys/uio.h>. +2004-04-29  Werner Koch  <[email protected]> -	* assuan-handler.c: Include <errno.h>. +	* assuan-socket-connect.c: Include string.h. +	* assuan-logging.c: Ditto. -2004-06-08  Marcus Brinkmann  <[email protected]> +2004-04-22  Marcus Brinkmann  <[email protected]> -	* assuan-buffer.c (assuan_write_line): If the line is longer than -	the maximum line length, bail out early. +	* libassuan.m4: Quote first argument to AC_DEFUN.  2004-04-21  Werner Koch  <[email protected]> @@ -1039,7 +1306,7 @@  	* assuan-defs.h: Add space in the context for this. - Copyright 2001, 2002, 2006 Free Software Foundation, Inc. + Copyright 2001, 2002, 2006, 2007 Free Software Foundation, Inc.   This file is free software; as a special exception the author gives   unlimited permission to copy and/or distribute it, with or without diff --git a/assuan/assuan-buffer.c b/assuan/assuan-buffer.c index 31f33945..b9e35721 100644 --- a/assuan/assuan-buffer.c +++ b/assuan/assuan-buffer.c @@ -14,9 +14,7 @@   * Lesser General Public License for more details.   *   * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA.  + * License along with this program; if not, see <http://www.gnu.org/licenses/>.   */  #include <config.h> @@ -53,9 +51,10 @@ writen (assuan_context_t ctx, const char *buffer, size_t length)    return 0;  /* okay */  } -/* Read an entire line. Returns 0 on success or -1 and ERRNo on +/* Read an entire line. Returns 0 on success or -1 and ERRNO on     failure.  EOF is indictated by setting the integer at address -   R_EOF.  */ +   R_EOF.  Note: BUF, R_NREAD and R_EOF contain a valid result even if +   an error is returned.  */  static int  readline (assuan_context_t ctx, char *buf, size_t buflen,  	  int *r_nread, int *r_eof) @@ -94,7 +93,7 @@ readline (assuan_context_t ctx, char *buf, size_t buflen,  } -/* Function returns an Assuan error. */ +/* Function returns an Assuan error.  */  assuan_error_t  _assuan_read_line (assuan_context_t ctx)  { @@ -134,11 +133,23 @@ _assuan_read_line (assuan_context_t ctx)                     &nread, &ctx->inbound.eof);    if (rc)      { +      int saved_errno = errno; +        if (ctx->log_fp) -	fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- [Error: %s (%d)]\n", -		 assuan_get_assuan_log_prefix (), -                 (unsigned int)getpid (), ctx->inbound.fd, -                 strerror (errno), errno); +	fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- [Error: %s]\n", +                 assuan_get_assuan_log_prefix (), +                 (unsigned int)getpid (), (int)ctx->inbound.fd, +                 strerror (errno)); + +      if (saved_errno == EAGAIN) +        { +          /* We have to save a partial line.  */ +          memcpy (ctx->inbound.attic.line, line, atticlen + nread); +          ctx->inbound.attic.pending = 0; +          ctx->inbound.attic.linelen = atticlen + nread; +        } + +      errno = saved_errno;        return _assuan_error (ASSUAN_Read_Error);      }    if (!nread) @@ -147,7 +158,7 @@ _assuan_read_line (assuan_context_t ctx)        if (ctx->log_fp)  	fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- [EOF]\n",  		 assuan_get_assuan_log_prefix (), -                 (unsigned int)getpid (), ctx->inbound.fd); +                 (unsigned int)getpid (), (int)ctx->inbound.fd);        return _assuan_error (-1);      } @@ -191,7 +202,7 @@ _assuan_read_line (assuan_context_t ctx)  	{  	  fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- ",  		   assuan_get_assuan_log_prefix (), -                   (unsigned int)getpid (), ctx->inbound.fd); +                   (unsigned int)getpid (), (int)ctx->inbound.fd);  	  if (ctx->confidential)  	    fputs ("[Confidential data not shown]", ctx->log_fp);  	  else @@ -207,7 +218,7 @@ _assuan_read_line (assuan_context_t ctx)        if (ctx->log_fp)  	fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- [Invalid line]\n",  		 assuan_get_assuan_log_prefix (), -                 (unsigned int)getpid (), ctx->inbound.fd); +                 (unsigned int)getpid (), (int)ctx->inbound.fd);        *line = 0;        ctx->inbound.linelen = 0;        return _assuan_error (ctx->inbound.eof  @@ -234,7 +245,12 @@ assuan_read_line (assuan_context_t ctx, char **line, size_t *linelen)    if (!ctx)      return _assuan_error (ASSUAN_Invalid_Value); -  err = _assuan_read_line (ctx); +  do +    { +      err = _assuan_read_line (ctx); +    } +  while (_assuan_error_is_eagain (err)); +    *line = ctx->inbound.line;    *linelen = ctx->inbound.linelen;    return err; @@ -265,7 +281,7 @@ _assuan_write_line (assuan_context_t ctx, const char *prefix,          fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> "                   "[supplied line too long -truncated]\n",                   assuan_get_assuan_log_prefix (), -                 (unsigned int)getpid (), ctx->inbound.fd); +                 (unsigned int)getpid (), (int)ctx->inbound.fd);        if (prefixlen > 5)          prefixlen = 5;        if (len > ASSUAN_LINELENGTH - prefixlen - 2) @@ -281,7 +297,7 @@ _assuan_write_line (assuan_context_t ctx, const char *prefix,      {        fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> ",  	       assuan_get_assuan_log_prefix (), -               (unsigned int)getpid (), ctx->inbound.fd); +               (unsigned int)getpid (), (int)ctx->inbound.fd);        if (ctx->confidential)  	fputs ("[Confidential data not shown]", ctx->log_fp);        else @@ -333,7 +349,7 @@ assuan_write_line (assuan_context_t ctx, const char *line)      fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> "               "[supplied line contained a LF - truncated]\n",               assuan_get_assuan_log_prefix (), -             (unsigned int)getpid (), ctx->inbound.fd); +             (unsigned int)getpid (), (int)ctx->inbound.fd);    return _assuan_write_line (ctx, NULL, line, len);  } @@ -398,7 +414,7 @@ _assuan_cookie_write_data (void *cookie, const char *buffer, size_t orig_size)              {  	      fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> ",  		       assuan_get_assuan_log_prefix (), -                       (unsigned int)getpid (), ctx->inbound.fd); +                       (unsigned int)getpid (), (int)ctx->inbound.fd);                if (ctx->confidential)                  fputs ("[Confidential data not shown]", ctx->log_fp); @@ -454,7 +470,7 @@ _assuan_cookie_write_flush (void *cookie)  	{  	  fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> ",  		   assuan_get_assuan_log_prefix (), -                   (unsigned int)getpid (), ctx->inbound.fd); +                   (unsigned int)getpid (), (int)ctx->inbound.fd);  	  if (ctx->confidential)  	    fputs ("[Confidential data not shown]", ctx->log_fp);  	  else @@ -524,11 +540,11 @@ assuan_send_data (assuan_context_t ctx, const void *buffer, size_t length)  }  assuan_error_t -assuan_sendfd (assuan_context_t ctx, int fd) +assuan_sendfd (assuan_context_t ctx, assuan_fd_t fd)  {    /* It is explicitly allowed to use (NULL, -1) as a runtime test to       check whether descriptor passing is available. */ -  if (!ctx && fd == -1) +  if (!ctx && fd == ASSUAN_INVALID_FD)  #ifdef USE_DESCRIPTOR_PASSING      return 0;  #else @@ -543,7 +559,7 @@ assuan_sendfd (assuan_context_t ctx, int fd)  }  assuan_error_t -assuan_receivefd (assuan_context_t ctx, int *fd) +assuan_receivefd (assuan_context_t ctx, assuan_fd_t *fd)  {    if (! ctx->io->receivefd)      return set_error (ctx, Not_Implemented, diff --git a/assuan/assuan-client.c b/assuan/assuan-client.c index 7b3d2662..15f4f1cd 100644 --- a/assuan/assuan-client.c +++ b/assuan/assuan-client.c @@ -14,9 +14,7 @@   * Lesser General Public License for more details.   *   * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA.  + * License along with this program; if not, see <http://www.gnu.org/licenses/>.   */  #include <config.h> @@ -44,7 +42,11 @@ _assuan_read_from_server (assuan_context_t ctx, int *okay, int *off)    *off = 0;    do       { -      rc = _assuan_read_line (ctx); +      do +	{ +	  rc = _assuan_read_line (ctx); +	} +      while (_assuan_error_is_eagain (rc));        if (rc)          return rc;        line = ctx->inbound.line; diff --git a/assuan/assuan-connect.c b/assuan/assuan-connect.c index b50b17bd..2106ac30 100644 --- a/assuan/assuan-connect.c +++ b/assuan/assuan-connect.c @@ -14,9 +14,7 @@   * Lesser General Public License for more details.   *   * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA.  + * License along with this program; if not, see <http://www.gnu.org/licenses/>.   */  #ifdef HAVE_CONFIG_H @@ -60,8 +58,8 @@ assuan_get_pid (assuan_context_t ctx)  #ifndef HAVE_W32_SYSTEM -/* Return user credentials. PID, UID and GID amy be gived as NULL if -   you are not interested in this value.  For getting the pid of the +/* Return user credentials. PID, UID and GID may be given as NULL if +   you are not interested in a value.  For getting the pid of the     peer the assuan_get_pid is usually better suited. */  assuan_error_t  assuan_get_peercred (assuan_context_t ctx, pid_t *pid, uid_t *uid, gid_t *gid) diff --git a/assuan/assuan-defs.h b/assuan/assuan-defs.h index b1d9f3ef..e2d0f52b 100644 --- a/assuan/assuan-defs.h +++ b/assuan/assuan-defs.h @@ -1,5 +1,5 @@  /* assuan-defs.c - Internal definitions to Assuan - *	Copyright (C) 2001, 2002, 2004, 2005 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2004, 2005, 2007, 2008 Free Software Foundation, Inc.   *   * This file is part of Assuan.   * @@ -40,17 +40,6 @@  #endif  #ifdef HAVE_W32_SYSTEM -#define AF_LOCAL AF_UNIX -/* We need to prefix the structure with a sockaddr_in header so we can -   use it later for sendto and recvfrom. */ -struct sockaddr_un -{ -  short          sun_family; -  unsigned short sun_port; -  struct         in_addr sun_addr; -  char           sun_path[108-2-4]; /* Path name.  */ -}; -  /* Not needed anymore because the current mingw32 defines this in     sys/types.h */  /* typedef int ssize_t; */ @@ -80,12 +69,16 @@ struct assuan_io    /* Routine to write to output_fd.  */    ssize_t (*writefnc) (assuan_context_t, const void *, size_t);    /* Send a file descriptor.  */ -  assuan_error_t (*sendfd) (assuan_context_t, int); +  assuan_error_t (*sendfd) (assuan_context_t, assuan_fd_t);    /* Receive a file descriptor.  */ -  assuan_error_t (*receivefd) (assuan_context_t, int *); +  assuan_error_t (*receivefd) (assuan_context_t, assuan_fd_t *);  }; +/* The global variable with the optional hook fucntions.  */ +extern struct assuan_io_hooks _assuan_io_hooks; + +  /* The context we use with most functions. */  struct assuan_context_s  { @@ -103,6 +96,14 @@ struct assuan_context_s    int confidential;    int is_server;      /* Set if this is context belongs to a server */    int in_inquire; +  int in_process_next; +  int in_command; + +  /* The following members are used by assuan_inquire_ext.  */ +  int (*inquire_cb) (void *cb_data, int rc, unsigned char *buf, size_t len); +  void *inquire_cb_data; +  void *inquire_membuf; +    char *hello_line;    char *okay_line;    /* See assuan_set_okay_line() */ @@ -111,7 +112,7 @@ struct assuan_context_s    FILE *log_fp;    struct { -    int fd; +    assuan_fd_t fd;      int eof;      char line[LINELENGTH];      int linelen;  /* w/o CR, LF - might not be the same as @@ -125,7 +126,7 @@ struct assuan_context_s    } inbound;    struct { -    int fd; +    assuan_fd_t fd;      struct {        FILE *fp;        char line[LINELENGTH]; @@ -137,8 +138,10 @@ struct assuan_context_s    int pipe_mode;  /* We are in pipe mode, i.e. we can handle just one                       connection and must terminate then. */    pid_t pid;	  /* The pid of the peer. */ -  int listen_fd;  /* The fd we are listening on (used by socket servers) */ -  int connected_fd; /* helper */ +  assuan_fd_t listen_fd;  /* The fd we are listening on (used by +                             socket servers) */ +  assuan_sock_nonce_t listen_nonce; /* Used with LISTEN_FD.  */ +  assuan_fd_t connected_fd; /* helper */    struct {      int valid;   /* Whether this structure has valid information. */ @@ -162,7 +165,7 @@ struct assuan_context_s      int bufferoffset;     /* Offset of start of buffer.  */      int buffersize;       /* Bytes buffered.  */ -    int pendingfds[5];    /* Array to save received descriptors.  */ +    assuan_fd_t pendingfds[5]; /* Array to save received descriptors.  */      int pendingfdscount;  /* Number of received descriptors. */    } uds; @@ -188,15 +191,15 @@ struct assuan_context_s    /* If set, this is called right before logging an I/O line.  With       DIRECTION set to 1 it is called for an output oeration; 0 means       an input operation. If bit 0 is set in the return value, the -     logging of the will be suppressed.  With bit 1 set, the entire -     line will be ignored. */ +     logging of the line will be suppressed.  With bit 1 set, the +     entire line will be ignored. */    unsigned int (*io_monitor)(assuan_context_t ctx,                               int direction,                               const char *line,                               size_t linelen); -  int input_fd;   /* set by INPUT command */ -  int output_fd;  /* set by OUTPUT command */ +  assuan_fd_t input_fd;   /* Set by the INPUT command.  */ +  assuan_fd_t output_fd;  /* Set by the OUTPUT command.  */    /* io routines.  */    struct assuan_io *io; @@ -228,17 +231,22 @@ assuan_error_t _assuan_read_from_server (assuan_context_t ctx,  /*-- assuan-error.c --*/ +/*-- assuan-inquire.c --*/ +int _assuan_inquire_ext_cb (assuan_context_t ctx); +void _assuan_inquire_release (assuan_context_t ctx); -/* Map error codes as used in this implementaion to the libgpg-error +/* Map error codes as used in this implementation to the libgpg-error     codes. */  assuan_error_t _assuan_error (int oldcode); +/* Check if ERR means EAGAIN.  */ +int _assuan_error_is_eagain (assuan_error_t err); -/* Extrac the erro code from A.  This works for both the old and the -   new style error codes. This needs to be whenever an error code is -   compared. */ +/* Extract the error code from A.  This works for both the old and the +   new style error codes.  This needs to be used whenever an error +   code is compared. */  #define err_code(a) ((a) & 0x00ffffff) -/* Check whether A is the erro code for EOF.  We allow forold and new +/* Check whether A is the erro code for EOF.  We allow for old and new     style EOF error codes here.  */  #define err_is_eof(a) ((a) == (-1) || err_code (a) == 16383) @@ -284,6 +292,8 @@ pid_t _assuan_waitpid (pid_t pid, int *status, int options);  ssize_t _assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size);  ssize_t _assuan_simple_write (assuan_context_t ctx, const void *buffer,  			      size_t size); +ssize_t _assuan_io_read (assuan_fd_t fd, void *buffer, size_t size); +ssize_t _assuan_io_write (assuan_fd_t fd, const void *buffer, size_t size);  #ifdef HAVE_W32_SYSTEM  int _assuan_simple_sendmsg (assuan_context_t ctx, void *msg);  int _assuan_simple_recvmsg (assuan_context_t ctx, void *msg); @@ -292,11 +302,21 @@ ssize_t _assuan_simple_sendmsg (assuan_context_t ctx, struct msghdr *msg);  ssize_t _assuan_simple_recvmsg (assuan_context_t ctx, struct msghdr *msg);  #endif +void _assuan_usleep (unsigned int usec); + +  /*-- assuan-socket.c --*/ -int _assuan_close (int fd); -int _assuan_sock_new (int domain, int type, int proto); -int _assuan_sock_bind (int sockfd, struct sockaddr *addr, int addrlen); -int _assuan_sock_connect (int sockfd, struct sockaddr *addr, int addrlen); +int _assuan_close (assuan_fd_t fd); +assuan_fd_t _assuan_sock_new (int domain, int type, int proto); +int _assuan_sock_connect (assuan_fd_t sockfd, +                          struct sockaddr *addr, int addrlen); +int _assuan_sock_bind (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen); +int _assuan_sock_get_nonce (struct sockaddr *addr, int addrlen,  +                            assuan_sock_nonce_t *nonce); +int _assuan_sock_check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce); +#ifdef HAVE_W32_SYSTEM +int _assuan_sock_wsa2errno (int err); +#endif  #ifdef HAVE_FOPENCOOKIE  /* We have to implement funopen in terms of glibc's fopencookie. */ @@ -329,4 +349,13 @@ int putc_unlocked (int c, FILE *stream);  #define DIMof(type,member)   DIM(((type *)0)->member) +#if HAVE_W32_SYSTEM +#define SOCKET2HANDLE(s) ((void *)(s)) +#define HANDLE2SOCKET(h) ((unsigned int)(h)) +#else +#define SOCKET2HANDLE(s) (s) +#define HANDLE2SOCKET(h) (h) +#endif + +  #endif /*ASSUAN_DEFS_H*/ diff --git a/assuan/assuan-handler.c b/assuan/assuan-handler.c index d1b29cff..b940bfd4 100644 --- a/assuan/assuan-handler.c +++ b/assuan/assuan-handler.c @@ -1,5 +1,5 @@  /* assuan-handler.c - dispatch commands  - *	Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2007 Free Software Foundation, Inc.   *   * This file is part of Assuan.   * @@ -14,9 +14,7 @@   * Lesser General Public License for more details.   *   * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA.  + * License along with this program; if not, see <http://www.gnu.org/licenses/>.   */  #include <config.h> @@ -35,18 +33,21 @@  static int my_strcasecmp (const char *a, const char *b); +#define PROCESS_DONE(ctx, rc) \ +  ((ctx)->in_process_next ? assuan_process_done ((ctx), (rc)) : (rc))  static int  dummy_handler (assuan_context_t ctx, char *line)  { -  return set_error (ctx, Server_Fault, "no handler registered"); +  return +    PROCESS_DONE (ctx, set_error (ctx, Server_Fault, "no handler registered"));  }  static int  std_handler_nop (assuan_context_t ctx, char *line)  { -  return 0; /* okay */ +  return PROCESS_DONE (ctx, 0); /* okay */  }  static int @@ -54,7 +55,7 @@ std_handler_cancel (assuan_context_t ctx, char *line)  {    if (ctx->cancel_notify_fnc)      ctx->cancel_notify_fnc (ctx); -  return set_error (ctx, Not_Implemented, NULL);  +  return PROCESS_DONE (ctx, set_error (ctx, Not_Implemented, NULL));  }  static int @@ -65,9 +66,12 @@ std_handler_option (assuan_context_t ctx, char *line)    for (key=line; spacep (key); key++)      ;    if (!*key) -    return set_error (ctx, Syntax_Error, "argument required"); +    return +      PROCESS_DONE (ctx, set_error (ctx, Syntax_Error, "argument required"));    if (*key == '=') -    return set_error (ctx, Syntax_Error, "no option name given"); +    return +      PROCESS_DONE (ctx, set_error (ctx, Syntax_Error, +				    "no option name given"));    for (value=key; *value && !spacep (value) && *value != '='; value++)      ;    if (*value) @@ -82,7 +86,9 @@ std_handler_option (assuan_context_t ctx, char *line)            for (; spacep (value); value++)              ;            if (!*value) -            return set_error (ctx, Syntax_Error, "option argument expected"); +            return +	      PROCESS_DONE (ctx, set_error (ctx, Syntax_Error, +					    "option argument expected"));          }        if (*value)          { @@ -96,12 +102,13 @@ std_handler_option (assuan_context_t ctx, char *line)    if (*key == '-' && key[1] == '-' && key[2])      key += 2; /* the double dashes are optional */    if (*key == '-') -    return set_error (ctx, Syntax_Error, -                      "option should not begin with one dash"); +    return PROCESS_DONE (ctx, +			 set_error (ctx, Syntax_Error, +				    "option should not begin with one dash"));    if (ctx->option_handler_fnc) -    return ctx->option_handler_fnc (ctx, key, value); -  return 0; +    return PROCESS_DONE (ctx, ctx->option_handler_fnc (ctx, key, value)); +  return PROCESS_DONE (ctx, 0);  }  static int @@ -111,13 +118,13 @@ std_handler_bye (assuan_context_t ctx, char *line)      ctx->bye_notify_fnc (ctx);    assuan_close_input_fd (ctx);    assuan_close_output_fd (ctx); -  return -1; /* pretty simple :-) */ +  return PROCESS_DONE (ctx, _assuan_error (-1)); /* pretty simple :-) */  }  static int  std_handler_auth (assuan_context_t ctx, char *line)  { -  return set_error (ctx, Not_Implemented, NULL);  +  return PROCESS_DONE (ctx, set_error (ctx, Not_Implemented, NULL));  }  static int @@ -128,17 +135,35 @@ std_handler_reset (assuan_context_t ctx, char *line)    assuan_close_input_fd (ctx);    assuan_close_output_fd (ctx);    _assuan_uds_close_fds (ctx); -  return 0; +  return PROCESS_DONE (ctx, 0);  }  static int +std_handler_help (assuan_context_t ctx, char *line) +{ +  unsigned int i; +  char buf[ASSUAN_LINELENGTH]; + +  for (i = 0; i < ctx->cmdtbl_used; i++) +    { +      snprintf (buf, sizeof (buf), "# %s", ctx->cmdtbl[i].name); +      buf[ASSUAN_LINELENGTH - 1] = '\0'; +      assuan_write_line (ctx, buf); +    } + +  return PROCESS_DONE (ctx, 0); +} + + +static int  std_handler_end (assuan_context_t ctx, char *line)  { -  return set_error (ctx, Not_Implemented, NULL);  +  return PROCESS_DONE (ctx, set_error (ctx, Not_Implemented, NULL));  } +  assuan_error_t -assuan_command_parse_fd (assuan_context_t ctx, char *line, int *rfd) +assuan_command_parse_fd (assuan_context_t ctx, char *line, assuan_fd_t *rfd)  {    char *endp; @@ -151,7 +176,13 @@ assuan_command_parse_fd (assuan_context_t ctx, char *line, int *rfd)        line ++;        if (!digitp (*line))  	return set_error (ctx, Syntax_Error, "number required"); +#ifdef HAVE_W32_SYSTEM +      /* Fixme: For a W32/64bit system we will need to change the cast +         and the conversion fucntion.  */ +      *rfd = (void*)strtoul (line, &endp, 10); +#else        *rfd = strtoul (line, &endp, 10); +#endif        /* Remove that argument so that a notify handler won't see it. */        memset (line, ' ', endp? (endp-line):strlen(line)); @@ -166,34 +197,37 @@ assuan_command_parse_fd (assuan_context_t ctx, char *line, int *rfd)      return assuan_receivefd (ctx, rfd);  } +  /* Format is INPUT FD=<n> */  static int  std_handler_input (assuan_context_t ctx, char *line)  { -  int rc, fd; +  int rc; +  assuan_fd_t fd;    rc = assuan_command_parse_fd (ctx, line, &fd);    if (rc) -    return rc; +    return PROCESS_DONE (ctx, rc);    ctx->input_fd = fd;    if (ctx->input_notify_fnc)      ctx->input_notify_fnc (ctx, line); -  return 0; +  return PROCESS_DONE (ctx, 0);  }  /* Format is OUTPUT FD=<n> */  static int  std_handler_output (assuan_context_t ctx, char *line)  { -  int rc, fd; +  int rc; +  assuan_fd_t fd;    rc = assuan_command_parse_fd (ctx, line, &fd);    if (rc) -    return rc; +    return PROCESS_DONE (ctx, rc);    ctx->output_fd = fd;    if (ctx->output_notify_fnc)      ctx->output_notify_fnc (ctx, line); -  return 0; +  return PROCESS_DONE (ctx, 0);  } @@ -215,11 +249,12 @@ static struct {    { "AUTH",   std_handler_auth, 1 },    { "RESET",  std_handler_reset, 1 },    { "END",    std_handler_end, 1 }, +  { "HELP",   std_handler_help, 1 }, -  { "INPUT",  std_handler_input }, -  { "OUTPUT", std_handler_output }, +  { "INPUT",  std_handler_input, 0 }, +  { "OUTPUT", std_handler_output, 0 },    { "OPTION", std_handler_option, 1 }, -  { NULL } +  { NULL, NULL, 0 }  }; @@ -406,9 +441,10 @@ my_strcasecmp (const char *a, const char *b)      return *a == *b? 0 : (((*a >= 'a' && *a <= 'z')? (*a&~0x20):*a) - *b);  } +  /* Parse the line, break out the command, find it in the command     table, remove leading and white spaces from the arguments, call the -   handler with the argument line and return the error */ +   handler with the argument line and return the error.  */  static int   dispatch_command (assuan_context_t ctx, char *line, int linelen)  { @@ -416,13 +452,21 @@ dispatch_command (assuan_context_t ctx, char *line, int linelen)    const char *s;    int shift, i; +  /* Note that as this function is invoked by assuan_process_next as +     well, we need to hide non-critical errors with PROCESS_DONE.  */ +    if (*line == 'D' && line[1] == ' ') /* divert to special handler */ -    return handle_data_line (ctx, line+2, linelen-2); +    /* FIXME: Depending on the final implementation of +       handle_data_line, this may be wrong here.  For example, if a +       user callback is invoked, and that callback is responsible for +       calling assuan_process_done, then this is wrong.  */ +    return PROCESS_DONE (ctx, handle_data_line (ctx, line+2, linelen-2));    for (p=line; *p && *p != ' ' && *p != '\t'; p++)      ;    if (p==line) -    return set_error (ctx, Syntax_Error, "leading white-space");  +    return PROCESS_DONE +      (ctx, set_error (ctx, Syntax_Error, "leading white-space"));     if (*p)       { /* Skip over leading WS after the keyword */        *p++ = 0; @@ -445,7 +489,7 @@ dispatch_command (assuan_context_t ctx, char *line, int linelen)          }      }    if (!s) -    return set_error (ctx, Unknown_Command, NULL); +    return PROCESS_DONE (ctx, set_error (ctx, Unknown_Command, NULL));    line += shift;    linelen -= shift; @@ -453,42 +497,34 @@ dispatch_command (assuan_context_t ctx, char *line, int linelen)    return ctx->cmdtbl[i].handler (ctx, line);  } - - -static int -process_request (assuan_context_t ctx) +/* Call this to acknowledge the current command.  */ +int +assuan_process_done (assuan_context_t ctx, int rc)  { -  int rc; - -  if (ctx->in_inquire) -    return _assuan_error (ASSUAN_Nested_Commands); +  if (!ctx->in_command) +    return _assuan_error (ASSUAN_General_Error); -  rc = _assuan_read_line (ctx); -  if (rc) -    return rc; -  if (*ctx->inbound.line == '#' || !ctx->inbound.linelen) -    return 0; /* comment line - ignore */ +  ctx->in_command = 0; -  ctx->outbound.data.error = 0; -  ctx->outbound.data.linelen = 0; -  /* dispatch command and return reply */ -  rc = dispatch_command (ctx, ctx->inbound.line, ctx->inbound.linelen); -  /* check from data write errors */ +  /* Check for data write errors.  */    if (ctx->outbound.data.fp) -    { /* Flush the data lines */ +    { +      /* Flush the data lines.  */        fclose (ctx->outbound.data.fp);        ctx->outbound.data.fp = NULL;        if (!rc && ctx->outbound.data.error) -        rc = ctx->outbound.data.error; +	rc = ctx->outbound.data.error;      } -  else /* flush any data send w/o using the data fp */ +  else      { +      /* Flush any data send without using the data FP.  */        assuan_send_data (ctx, NULL, 0);        if (!rc && ctx->outbound.data.error) -        rc = ctx->outbound.data.error; +	rc = ctx->outbound.data.error;      } -  /* Error handling */ +   +  /* Error handling.  */    if (!rc)      {        rc = assuan_write_line (ctx, ctx->okay_line? ctx->okay_line : "OK"); @@ -501,26 +537,26 @@ process_request (assuan_context_t ctx)    else       {        char errline[300]; - +              if (rc < 100)          sprintf (errline, "ERR %d server fault (%.50s)",                   _assuan_error (ASSUAN_Server_Fault), assuan_strerror (rc));        else          {            const char *text = ctx->err_no == rc? ctx->err_str:NULL; - +	    #if defined(HAVE_W32_SYSTEM)            unsigned int source, code;            char ebuf[50];            const char *esrc; - +	              source = ((rc >> 24) & 0xff);            code = (rc & 0x00ffffff);            if (source                && !_assuan_gpg_strerror_r (rc, ebuf, sizeof ebuf)                && (esrc=_assuan_gpg_strsource (rc)))              { -              /* Assume this is an libgpg-error. */ +              /* Assume this is an libgpg-error.  */                sprintf (errline, "ERR %d %.50s <%.30s>%s%.100s",                         rc, ebuf, esrc,                         text? " - ":"", text?text:""); @@ -554,7 +590,7 @@ process_request (assuan_context_t ctx)              {                /* Assume this is an libgpg-error. */                char ebuf[50]; - +	                      gpg_strerror_r (rc, ebuf, sizeof ebuf );                sprintf (errline, "ERR %d %.50s <%.30s>%s%.100s",                         rc, @@ -569,19 +605,123 @@ process_request (assuan_context_t ctx)          }        rc = assuan_write_line (ctx, errline);      } - +      if (ctx->post_cmd_notify_fnc)      ctx->post_cmd_notify_fnc (ctx, rc); - +      ctx->confidential = 0;    if (ctx->okay_line)      {        xfree (ctx->okay_line);        ctx->okay_line = NULL;      } + +  return rc; +} + + +static int  +process_next (assuan_context_t ctx) +{ +  int rc; + +  /* What the next thing to do is depends on the current state. +     However, we will always first read the next line.  The client is +     required to write full lines without blocking long after starting +     a partial line.  */ +  rc = _assuan_read_line (ctx); +  if (_assuan_error_is_eagain (rc)) +    return 0; +  if (rc) +    return rc; +  if (*ctx->inbound.line == '#' || !ctx->inbound.linelen) +     /* Comment lines are ignored.  */ +    return 0; + +  /* Now we have a line that really means something.  It could be one +     of the following things: First, if we are not in a command +     already, it is the next command to dispatch.  Second, if we are +     in a command, it can only be the response to an INQUIRE +     reply.  */ + +  if (!ctx->in_command) +    { +      ctx->in_command = 1; + +      ctx->outbound.data.error = 0; +      ctx->outbound.data.linelen = 0; +      /* Dispatch command and return reply.  */ +      ctx->in_process_next = 1; +      rc = dispatch_command (ctx, ctx->inbound.line, ctx->inbound.linelen); +      ctx->in_process_next = 0; +    } +  else if (ctx->in_inquire) +    { +      /* FIXME: Pick up the continuation.  */ +      rc = _assuan_inquire_ext_cb (ctx); +    } +  else +    { +      /* Should not happen.  The client is sending data while we are +	 in a command and not waiting for an inquire.  We log an error +	 and discard it.  */ +      _assuan_log_printf ("unexpected client data\n"); +      rc = 0; +    } +    return rc;  } + +/* This function should be invoked when the assuan connected FD is +   ready for reading.  If the equivalent to EWOULDBLOCK is returned +   (this should be done by the command handler), assuan_process_next +   should be invoked the next time the connected FD is readable. +   Eventually, the caller will finish by invoking +   assuan_process_done.  */ +int  +assuan_process_next (assuan_context_t ctx) +{ +  int rc; + +  do +    { +      rc = process_next (ctx); +    } +  while (!rc && assuan_pending_line (ctx)); + +  return rc; +} + + + +static int +process_request (assuan_context_t ctx) +{ +  int rc; + +  if (ctx->in_inquire) +    return _assuan_error (ASSUAN_Nested_Commands); + +  do +    { +      rc = _assuan_read_line (ctx); +    } +  while (_assuan_error_is_eagain (rc)); +  if (rc) +    return rc; +  if (*ctx->inbound.line == '#' || !ctx->inbound.linelen) +    return 0; /* comment line - ignore */ + +  ctx->in_command = 1; +  ctx->outbound.data.error = 0; +  ctx->outbound.data.linelen = 0; +  /* dispatch command and return reply */ +  rc = dispatch_command (ctx, ctx->inbound.line, ctx->inbound.linelen); + +  return assuan_process_done (ctx, rc); +} +  /**   * assuan_process:   * @ctx: assuan context @@ -610,24 +750,6 @@ assuan_process (assuan_context_t ctx)  /** - * assuan_process_next: - * @ctx: Assuan context - *  - * Same as assuan_process() but the user has to provide the outer - * loop.  He should loop as long as the return code is zero and stop - * otherwise; -1 is regular end. - *  - * See also: assuan_get_active_fds() - * Return value: -1 for end of server, 0 on success or an error code - **/ -int  -assuan_process_next (assuan_context_t ctx) -{ -  return process_request (ctx); -} - - -/**   * assuan_get_active_fds:   * @ctx: Assuan context   * @what: 0 for read fds, 1 for write fds @@ -646,7 +768,7 @@ assuan_process_next (assuan_context_t ctx)   **/  int   assuan_get_active_fds (assuan_context_t ctx, int what, -                       int *fdarray, int fdarraysize) +                       assuan_fd_t *fdarray, int fdarraysize)  {    int n = 0; @@ -655,16 +777,16 @@ assuan_get_active_fds (assuan_context_t ctx, int what,    if (!what)      { -      if (ctx->inbound.fd != -1) +      if (ctx->inbound.fd != ASSUAN_INVALID_FD)          fdarray[n++] = ctx->inbound.fd;      }    else      { -      if (ctx->outbound.fd != -1) +      if (ctx->outbound.fd != ASSUAN_INVALID_FD)          fdarray[n++] = ctx->outbound.fd;        if (ctx->outbound.data.fp)  #ifdef HAVE_W32_SYSTEM -        fdarray[n++] = _get_osfhandle (fileno (ctx->outbound.data.fp)); +        fdarray[n++] = (void*)_get_osfhandle (fileno (ctx->outbound.data.fp));  #else          fdarray[n++] = fileno (ctx->outbound.data.fp);  #endif diff --git a/assuan/assuan-inquire.c b/assuan/assuan-inquire.c index d8c52d09..58b9f029 100644 --- a/assuan/assuan-inquire.c +++ b/assuan/assuan-inquire.c @@ -1,5 +1,5 @@  /* assuan-inquire.c - handle inquire stuff - *	Copyright (C) 2001, 2002, 2003, 2005  Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2005, 2007 Free Software Foundation, Inc.   *   * This file is part of Assuan.   * @@ -14,9 +14,7 @@   * Lesser General Public License for more details.   *   * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA.  + * License along with this program; if not, see <http://www.gnu.org/licenses/>.   */  #include <config.h> @@ -44,7 +42,7 @@ struct membuf -/* A simple implemnation of a dynamic buffer.  Use init_membuf() to +/* A simple implementation of a dynamic buffer.  Use init_membuf() to     create a buffer, put_membuf to append bytes and get_membuf to     release and return the buffer.  Allocation errors are detected but     only returned at the final get_membuf(), this helps not to clutter @@ -171,7 +169,9 @@ assuan_inquire (assuan_context_t ctx, const char *keyword,      {        do           { -          rc = _assuan_read_line (ctx); +	  do +	    rc = _assuan_read_line (ctx); +	  while (_assuan_error_is_eagain (rc));            if (rc)              goto leave;            line = (unsigned char *) ctx->inbound.line; @@ -234,8 +234,154 @@ assuan_inquire (assuan_context_t ctx, const char *keyword,    return rc;  } + +void +_assuan_inquire_release (assuan_context_t ctx) +{ +  if (ctx->in_inquire) +    { +      if (ctx->inquire_membuf) +	{ +	  free_membuf (ctx->inquire_membuf); +	  free (ctx->inquire_membuf); +	} +      ctx->in_inquire = 0; +    } +} + + +int +_assuan_inquire_ext_cb (assuan_context_t ctx) +{ +  int rc; +  unsigned char *line; +  int linelen; +  struct membuf *mb; +  unsigned char *p; + +  line = (unsigned char *) ctx->inbound.line; +  linelen = ctx->inbound.linelen; +  mb = ctx->inquire_membuf; + +  if (line[0] == 'C' && line[1] == 'A' && line[2] == 'N') +    { +      rc = _assuan_error (ASSUAN_Canceled); +      goto leave; +    } +  if (line[0] == 'E' && line[1] == 'N' && line[2] == 'D' +      && (!line[3] || line[3] == ' ')) +    { +      rc = 0; +      goto leave; +    } + +  if (line[0] != 'D' || line[1] != ' ' || mb == NULL) +    { +      rc = _assuan_error (ASSUAN_Unexpected_Command); +      goto leave; +    } +   +  if (linelen < 3) +    return 0; +  line += 2; +  linelen -= 2; +   +  p = line; +  while (linelen) +    { +      for (;linelen && *p != '%'; linelen--, p++) +	; +      put_membuf (mb, line, p-line); +      if (linelen > 2) +	{ /* handle escaping */ +	  unsigned char tmp[1]; +	  p++; +	  *tmp = xtoi_2 (p); +	  p += 2; +	  linelen -= 3; +	  put_membuf (mb, tmp, 1); +	} +      line = p; +    } +  if (mb->too_large) +    { +      rc = _assuan_error (ASSUAN_Too_Much_Data); +      goto leave; +    } + +  return 0; + + leave: +  { +    size_t buf_len = 0; +    unsigned char *buf = NULL; + +    if (mb) +      { +	buf = get_membuf (mb, &buf_len); +	if (!buf) +	  rc = _assuan_error (ASSUAN_Out_Of_Core); +	free_membuf (mb); +	free (mb); +	ctx->inquire_membuf = NULL; +      } +    ctx->in_inquire = 0; +    rc = (ctx->inquire_cb) (ctx->inquire_cb_data, rc, buf, buf_len); +  } +  return rc; +} + +/** + * assuan_inquire_ext: + * @ctx: An assuan context + * @keyword: The keyword used for the inquire + * @maxlen: If not 0, the size limit of the inquired data. + * @cb: A callback handler which is invoked after the operation completed. + * @cb_data: A user-provided value passed to the callback handler. + *  + * A Server may use this to Send an inquire.  r_buffer, r_length and + * maxlen may all be NULL/0 to indicate that no real data is expected. + * When this function returns,  + * + * Return value: 0 on success or an ASSUAN error code + **/ +assuan_error_t +assuan_inquire_ext (assuan_context_t ctx, const char *keyword, size_t maxlen, +		    int (*cb) (void *cb_data, int rc, unsigned char *buf, +			       size_t len), +		    void *cb_data) +{ +  assuan_error_t rc; +  struct membuf *mb = NULL; +  char cmdbuf[LINELENGTH-10]; /* (10 = strlen ("INQUIRE ")+CR,LF) */ +  if (!ctx || !keyword || (10 + strlen (keyword) >= sizeof (cmdbuf))) +    return _assuan_error (ASSUAN_Invalid_Value); +  if (!ctx->is_server) +    return _assuan_error (ASSUAN_Not_A_Server); +  if (ctx->in_inquire) +    return _assuan_error (ASSUAN_Nested_Commands); +  mb = malloc (sizeof (struct membuf)); +  if (!mb) +    return _assuan_error (ASSUAN_Out_Of_Core); +  init_membuf (mb, maxlen ? maxlen : 1024, maxlen); +  strcpy (stpcpy (cmdbuf, "INQUIRE "), keyword); +  rc = assuan_write_line (ctx, cmdbuf); +  if (rc) +    { +      free_membuf (mb);  +      free (mb); +      return rc; +    } +  ctx->in_inquire = 1; + +  /* Set up the continuation.  */ +  ctx->inquire_cb = cb; +  ctx->inquire_cb_data = cb_data; +  ctx->inquire_membuf = mb; +  return 0; +} diff --git a/assuan/assuan-io.c b/assuan/assuan-io.c index a7f84492..8d4cbb8e 100644 --- a/assuan/assuan-io.c +++ b/assuan/assuan-io.c @@ -1,5 +1,5 @@  /* assuan-io.c - Wraps the read and write functions. - *	Copyright (C) 2002, 2004, 2006 Free Software Foundation, Inc. + * Copyright (C) 2002, 2004, 2006, 2007, 2008 Free Software Foundation, Inc.   *   * This file is part of Assuan.   * @@ -14,15 +14,14 @@   * Lesser General Public License for more details.   *   * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA.  + * License along with this program; if not, see <http://www.gnu.org/licenses/>.   */  #ifdef HAVE_CONFIG_H  #include <config.h>  #endif +#include <time.h>  #include <sys/time.h>  #include <sys/types.h>  #ifdef HAVE_SYS_SOCKET_H @@ -48,8 +47,8 @@ _assuan_waitpid (pid_t pid, int *status, int options)  #endif -ssize_t -_assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size) +static ssize_t +do_io_read (assuan_fd_t fd, void *buffer, size_t size)  {  #if defined(HAVE_W32_SYSTEM) && !defined(_ASSUAN_IN_GPGME_BUILD_ASSUAN)    /* Due to the peculiarities of the W32 API we can't use read for a @@ -57,32 +56,71 @@ _assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size)       read if recv detects that it is not a network socket.  */    int n; -  n = recv (ctx->inbound.fd, buffer, size, 0); -  if (n == -1 && WSAGetLastError () == WSAENOTSOCK) +  n = recv (HANDLE2SOCKET(fd), buffer, size, 0); +  if (n == -1)      { -      DWORD nread = 0; - -      n = ReadFile ((HANDLE)ctx->inbound.fd, buffer, size, &nread, NULL); -      if (!n) +      switch (WSAGetLastError ())          { -          switch (GetLastError()) -            { -            case ERROR_BROKEN_PIPE: errno = EPIPE; break; -            default: errno = EIO;  -            } -          n = -1; +        case WSAENOTSOCK: +          { +            DWORD nread = 0; +             +            n = ReadFile (fd, buffer, size, &nread, NULL); +            if (!n) +              { +                switch (GetLastError()) +                  { +                  case ERROR_BROKEN_PIPE: errno = EPIPE; break; +                  default: errno = EIO;  +                  } +                n = -1; +              } +            else +              n = (int)nread; +          } +          break; +           +        case WSAEWOULDBLOCK: errno = EAGAIN; break; +        case ERROR_BROKEN_PIPE: errno = EPIPE; break; +        default: errno = EIO; break;          } -      else -        n = (int)nread;      }    return n;  #else /*!HAVE_W32_SYSTEM*/ -  return read (ctx->inbound.fd, buffer, size); +  return read (fd, buffer, size);  #endif /*!HAVE_W32_SYSTEM*/  } +  ssize_t -_assuan_simple_write (assuan_context_t ctx, const void *buffer, size_t size) +_assuan_io_read (assuan_fd_t fd, void *buffer, size_t size) +{ +  ssize_t retval; +   +  if (_assuan_io_hooks.read_hook +      && _assuan_io_hooks.read_hook (NULL, fd, buffer, size, &retval) == 1) +    return retval; + +  return do_io_read (fd, buffer, size); +} + +ssize_t +_assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size) +{ +  ssize_t retval; +   +  if (_assuan_io_hooks.read_hook +      && _assuan_io_hooks.read_hook (ctx, ctx->inbound.fd,  +                                     buffer, size, &retval) == 1) +    return retval; + +  return do_io_read (ctx->inbound.fd, buffer, size); +} + + + +static ssize_t +do_io_write (assuan_fd_t fd, const void *buffer, size_t size)  {  #if defined(HAVE_W32_SYSTEM) && !defined(_ASSUAN_IN_GPGME_BUILD_ASSUAN)    /* Due to the peculiarities of the W32 API we can't use write for a @@ -90,12 +128,12 @@ _assuan_simple_write (assuan_context_t ctx, const void *buffer, size_t size)       write if send detects that it is not a network socket.  */    int n; -  n = send (ctx->outbound.fd, buffer, size, 0); +  n = send (HANDLE2SOCKET(fd), buffer, size, 0);    if (n == -1 && WSAGetLastError () == WSAENOTSOCK)      {        DWORD nwrite; -      n = WriteFile ((HANDLE)ctx->outbound.fd, buffer, size, &nwrite, NULL); +      n = WriteFile (fd, buffer, size, &nwrite, NULL);        if (!n)          {            switch (GetLastError ()) @@ -111,10 +149,34 @@ _assuan_simple_write (assuan_context_t ctx, const void *buffer, size_t size)      }    return n;  #else /*!HAVE_W32_SYSTEM*/ -  return write (ctx->outbound.fd, buffer, size); +  return write (fd, buffer, size);  #endif /*!HAVE_W32_SYSTEM*/  } +ssize_t +_assuan_io_write (assuan_fd_t fd, const void *buffer, size_t size) +{ +  ssize_t retval; +   +  if (_assuan_io_hooks.write_hook +      && _assuan_io_hooks.write_hook (NULL, fd, buffer, size, &retval) == 1) +    return retval; +  return do_io_write (fd, buffer, size); +} + +ssize_t +_assuan_simple_write (assuan_context_t ctx, const void *buffer, size_t size) +{ +  ssize_t retval; +   +  if (_assuan_io_hooks.write_hook +      && _assuan_io_hooks.write_hook (ctx, ctx->outbound.fd,  +                                      buffer, size, &retval) == 1) +    return retval; + +  return do_io_write (ctx->outbound.fd, buffer, size); +} +  #ifdef HAVE_W32_SYSTEM  int @@ -152,3 +214,32 @@ _assuan_simple_recvmsg (assuan_context_t ctx, struct msghdr *msg)    return ret;  #endif  } + + +void +_assuan_usleep (unsigned int usec) +{ +  if (usec) +    { +#ifdef HAVE_NANOSLEEP +      struct timespec req; +      struct timespec rem; +       +      req.tv_sec = 0; +      req.tv_nsec = usec * 1000; +       +      while (nanosleep (&req, &rem) < 0 && errno == EINTR) +        req = rem; + +#elif defined(HAVE_W32_SYSTEM) +      Sleep (usec / 1000); +#else +      struct timeval tv; + +      tv.tv_sec  = usec / 1000000; +      tv.tv_usec = usec % 1000000; +      select (0, NULL, NULL, NULL, &tv); +#endif +    } +} + diff --git a/assuan/assuan-listen.c b/assuan/assuan-listen.c index 04db68ce..2ef93340 100644 --- a/assuan/assuan-listen.c +++ b/assuan/assuan-listen.c @@ -14,9 +14,7 @@   * Lesser General Public License for more details.   *   * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA.  + * License along with this program; if not, see <http://www.gnu.org/licenses/>.   */  #include <config.h> @@ -116,17 +114,17 @@ assuan_accept (assuan_context_t ctx) -int +assuan_fd_t  assuan_get_input_fd (assuan_context_t ctx)  { -  return ctx? ctx->input_fd : -1; +  return ctx? ctx->input_fd : ASSUAN_INVALID_FD;  } -int +assuan_fd_t  assuan_get_output_fd (assuan_context_t ctx)  { -  return ctx? ctx->output_fd : -1; +  return ctx? ctx->output_fd : ASSUAN_INVALID_FD;  } @@ -135,10 +133,10 @@ assuan_get_output_fd (assuan_context_t ctx)  assuan_error_t  assuan_close_input_fd (assuan_context_t ctx)  { -  if (!ctx || ctx->input_fd == -1) +  if (!ctx || ctx->input_fd == ASSUAN_INVALID_FD)      return _assuan_error (ASSUAN_Invalid_Value);    _assuan_close (ctx->input_fd); -  ctx->input_fd = -1; +  ctx->input_fd = ASSUAN_INVALID_FD;    return 0;  } @@ -147,11 +145,11 @@ assuan_close_input_fd (assuan_context_t ctx)  assuan_error_t  assuan_close_output_fd (assuan_context_t ctx)  { -  if (!ctx || ctx->output_fd == -1) +  if (!ctx || ctx->output_fd == ASSUAN_INVALID_FD)      return _assuan_error (ASSUAN_Invalid_Value);    _assuan_close (ctx->output_fd); -  ctx->output_fd = -1; +  ctx->output_fd = ASSUAN_INVALID_FD;    return 0;  } diff --git a/assuan/assuan-logging.c b/assuan/assuan-logging.c index 41ada915..2ebd6678 100644 --- a/assuan/assuan-logging.c +++ b/assuan/assuan-logging.c @@ -14,9 +14,7 @@   * Lesser General Public License for more details.   *   * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA.  + * License along with this program; if not, see <http://www.gnu.org/licenses/>.   */  #ifdef HAVE_CONFIG_H @@ -37,23 +35,6 @@  static char prefix_buffer[80];  static FILE *_assuan_log;  static int full_logging; -static int log_level = 1;  /* Defaults to logging enabled.  */ - - -/* Set the log level for general assuan commands.  0 is no logging at -   all, 1 is the standard logging and the default. Higher leveles may -   be defined in the future.  Passing a level of -1 will not change -   the current log level.  Returns previosu log level.  */ -int -assuan_set_assuan_log_level (int level) -{ -  int old = log_level; - -  if (level != -1) -    log_level = level; -  return old; -} -  void  _assuan_set_default_log_stream (FILE *fp) @@ -122,9 +103,6 @@ _assuan_log_printf (const char *format, ...)    FILE *fp;    const char *prf;    int save_errno = errno; - -  if (!log_level) -    return;    fp = assuan_get_assuan_log_stream ();    prf = assuan_get_assuan_log_prefix (); @@ -134,29 +112,31 @@ _assuan_log_printf (const char *format, ...)    va_start (arg_ptr, format);    vfprintf (fp, format, arg_ptr );    va_end (arg_ptr); +  /* If the log stream is a file, the output would be buffered.  This +     is bad for debugging, thus we flush the stream if FORMAT ends +     with a LF.  */  +  if (format && *format && format[strlen(format)-1] == '\n') +    fflush (fp);    errno = save_errno;  }  /* Dump a possibly binary string (used for debugging).  Distinguish     ascii text from binary and print it accordingly.  This function -   takes FILE pointer arg becuase logging may be enabled on a per -   context basis. */ +   takes FILE pointer arg because logging may be enabled on a per +   context basis.  */  void  _assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length)  {    const unsigned char *s; -  int n; - -  if (!log_level) -    return; +  unsigned int n; -  for (n=length,s=buffer; n; n--, s++) -    if  ((!isascii (*s) || iscntrl (*s) || !isprint (*s)) && !(*s >= 0x80)) +  for (n = length, s = buffer; n; n--, s++) +    if  ((! isascii (*s) || iscntrl (*s) || ! isprint (*s)) && !(*s >= 0x80))        break;    s = buffer; -  if (!n && *s != '[') +  if (! n && *s != '[')      fwrite (buffer, length, 1, fp);    else      { @@ -164,15 +144,15 @@ _assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length)        flockfile (fp);  #endif        putc_unlocked ('[', fp); -      if ( length > 16 && !full_logging) +      if (length > 16 && ! full_logging)          { -          for (n=0; n < 12; n++, s++) +          for (n = 0; n < 12; n++, s++)              fprintf (fp, " %02x", *s); -          fprintf (fp, " ...(%d bytes skipped)", (int)length - 12); +          fprintf (fp, " ...(%d bytes skipped)", (int) length - 12);          }        else          { -          for (n=0; n < length; n++, s++) +          for (n = 0; n < length; n++, s++)              fprintf (fp, " %02x", *s);          }        putc_unlocked (' ', fp); @@ -189,16 +169,11 @@ void  _assuan_log_sanitized_string (const char *string)  {    const unsigned char *s = (const unsigned char *) string; -  FILE *fp; +  FILE *fp = assuan_get_assuan_log_stream (); -  if (!log_level) +  if (! *s)      return; -  if (!*s) -    return; - -  fp = assuan_get_assuan_log_stream (); -  #ifdef HAVE_FLOCKFILE    flockfile (fp);  #endif diff --git a/assuan/assuan-pipe-connect.c b/assuan/assuan-pipe-connect.c index e3555325..7fdfe74f 100644 --- a/assuan/assuan-pipe-connect.c +++ b/assuan/assuan-pipe-connect.c @@ -1,5 +1,6 @@  /* assuan-pipe-connect.c - Establish a pipe connection (client)  - * Copyright (C) 2001, 2002, 2003, 2005, 2006 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2005, 2006, + *               2007 Free Software Foundation, Inc.   *   * This file is part of Assuan.   * @@ -14,9 +15,7 @@   * Lesser General Public License for more details.   *   * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA.  + * License along with this program; if not, see <http://www.gnu.org/licenses/>.   */  #ifdef HAVE_CONFIG_H @@ -75,17 +74,6 @@ int _gpgme_io_spawn (const char *path, char *const argv[],  #define MAX_OPEN_FDS 20  #endif -#ifdef HAVE_W32_SYSTEM -/* We assume that a HANDLE can be represented by an int which should -   be true for all i386 systems (HANDLE is defined as void *) and -   these are the only systems for which Windows is available.  Further -   we assume that -1 denotes an invalid handle.  */ -#define fd_to_handle(a)  ((HANDLE)(a)) -#define handle_to_fd(a)  ((int)(a)) -#define pid_to_handle(a) ((HANDLE)(a)) -#define handle_to_pid(a) ((int)(a)) -#endif /*HAVE_W32_SYSTEM*/ -  /* This should be called to make sure that SIGPIPE gets ignored.  */  static void @@ -139,31 +127,35 @@ writen (int fd, const char *buffer, size_t length)  static int  do_finish (assuan_context_t ctx)  { -  if (ctx->inbound.fd != -1) +  if (ctx->inbound.fd != ASSUAN_INVALID_FD)      {        _assuan_close (ctx->inbound.fd);        if (ctx->inbound.fd == ctx->outbound.fd) -        ctx->outbound.fd = -1; -      ctx->inbound.fd = -1; +        ctx->outbound.fd = ASSUAN_INVALID_FD; +      ctx->inbound.fd = ASSUAN_INVALID_FD;      } -  if (ctx->outbound.fd != -1) +  if (ctx->outbound.fd != ASSUAN_INVALID_FD)      {        _assuan_close (ctx->outbound.fd); -      ctx->outbound.fd = -1; +      ctx->outbound.fd = ASSUAN_INVALID_FD;      } -  if (ctx->pid != -1 && ctx->pid) +  if (ctx->pid != (pid_t)(-1) && ctx->pid)      {  #ifndef HAVE_W32_SYSTEM  #ifndef _ASSUAN_USE_DOUBLE_FORK        if (!ctx->flags.no_waitpid)          _assuan_waitpid (ctx->pid, NULL, 0);  -      ctx->pid = -1; +      ctx->pid =(pid_t)(-1);  #endif -#endif /*!HAVE_W32_SYSTEM*/ +#else /*!HAVE_W32_SYSTEM*/ +      CloseHandle ((HANDLE) ctx->pid); +      ctx->pid = (pid_t) INVALID_HANDLE_VALUE; +#endif /*HAVE_W32_SYSTEM*/      }    return 0;  } +  static void  do_deinit (assuan_context_t ctx)  { @@ -209,13 +201,15 @@ pipe_connect_unix (assuan_context_t *ctx,                     const char *name, const char *const argv[],                     int *fd_child_list,                     void (*atfork) (void *opaque, int reserved), -                   void *atforkvalue) +                   void *atforkvalue, unsigned int flags)  {    assuan_error_t err;    int rp[2];    int wp[2];    char mypidstr[50]; +  (void)flags; +    if (!ctx || !name || !argv || !argv[0])      return _assuan_error (ASSUAN_Invalid_Value); @@ -581,7 +575,7 @@ pipe_connect_gpgme (assuan_context_t *ctx,  		    const char *name, const char *const argv[],  		    int *fd_child_list,  		    void (*atfork) (void *opaque, int reserved), -		    void *atforkvalue) +		    void *atforkvalue, unsigned int flags)  {    assuan_error_t err;    int res; @@ -744,9 +738,9 @@ build_w32_commandline (const char * const *argv, char **cmdline)  #ifdef HAVE_W32_SYSTEM -/* Create pipe where one end is inheritable.  */ +/* Create pipe where one end end is inheritable.  */  static int -create_inheritable_pipe (int filedes[2], int for_write) +create_inheritable_pipe (assuan_fd_t filedes[2], int for_write)  {    HANDLE r, w, h;    SECURITY_ATTRIBUTES sec_attr; @@ -781,14 +775,12 @@ create_inheritable_pipe (int filedes[2], int for_write)        w = h;      } -  _assuan_log_printf ("created pipe: read=%p%s, write=%p%s\n", -                      r, for_write? " (inherit)":"", -                      w, for_write? "":" (inherit)"); -  filedes[0] = handle_to_fd (r); -  filedes[1] = handle_to_fd (w); +  filedes[0] = r; +  filedes[1] = w;    return 0;  } -#endif /* HAVE_W32_SYSTEM */ +#endif /*HAVE_W32_SYSTEM*/ +  #ifdef HAVE_W32_SYSTEM  #define pipe_connect pipe_connect_w32 @@ -798,11 +790,11 @@ pipe_connect_w32 (assuan_context_t *ctx,                    const char *name, const char *const argv[],                    int *fd_child_list,                    void (*atfork) (void *opaque, int reserved), -                  void *atforkvalue) +                  void *atforkvalue, unsigned int flags)  {    assuan_error_t err; -  int rp[2]; -  int wp[2]; +  assuan_fd_t rp[2]; +  assuan_fd_t wp[2];    char mypidstr[50];    char *cmdline;    SECURITY_ATTRIBUTES sec_attr; @@ -837,8 +829,8 @@ pipe_connect_w32 (assuan_context_t *ctx,    if (create_inheritable_pipe (wp, 1))      { -      CloseHandle (fd_to_handle (rp[0])); -      CloseHandle (fd_to_handle (rp[1])); +      CloseHandle (rp[0]); +      CloseHandle (rp[1]);        xfree (cmdline);        return _assuan_error (ASSUAN_General_Error);      } @@ -847,10 +839,10 @@ pipe_connect_w32 (assuan_context_t *ctx,    err = _assuan_new_context (ctx);    if (err)      { -      CloseHandle (fd_to_handle (rp[0])); -      CloseHandle (fd_to_handle (rp[1])); -      CloseHandle (fd_to_handle (wp[0])); -      CloseHandle (fd_to_handle (wp[1])); +      CloseHandle (rp[0]); +      CloseHandle (rp[1]); +      CloseHandle (wp[0]); +      CloseHandle (wp[1]);        xfree (cmdline);        return _assuan_error (ASSUAN_General_Error);      } @@ -877,8 +869,8 @@ pipe_connect_w32 (assuan_context_t *ctx,    memset (&si, 0, sizeof si);    si.cb = sizeof (si);    si.dwFlags = STARTF_USESTDHANDLES; -  si.hStdInput  = fd_to_handle (wp[0]); -  si.hStdOutput = fd_to_handle (rp[1]); +  si.hStdInput  = wp[0]; +  si.hStdOutput = rp[1];    /* Dup stderr to /dev/null unless it is in the list of FDs to be       passed to the child. */ @@ -894,14 +886,13 @@ pipe_connect_w32 (assuan_context_t *ctx,        nullfd = CreateFile ("nul", GENERIC_WRITE,                             FILE_SHARE_READ | FILE_SHARE_WRITE,                             NULL, OPEN_EXISTING, 0, NULL); -      _assuan_log_printf ("created nul device, hd=%p\n", nullfd);        if (nullfd == INVALID_HANDLE_VALUE)          {            _assuan_log_printf ("can't open `nul': %s\n", w32_strerror (-1)); -          CloseHandle (fd_to_handle (rp[0])); -          CloseHandle (fd_to_handle (rp[1])); -          CloseHandle (fd_to_handle (wp[0])); -          CloseHandle (fd_to_handle (wp[1])); +          CloseHandle (rp[0]); +          CloseHandle (rp[1]); +          CloseHandle (wp[0]); +          CloseHandle (wp[1]);            xfree (cmdline);            _assuan_release_context (*ctx);             return -1; @@ -909,23 +900,21 @@ pipe_connect_w32 (assuan_context_t *ctx,        si.hStdError = nullfd;      }    else -    si.hStdError = fd_to_handle (_get_osfhandle (fd)); +    si.hStdError = (void*)_get_osfhandle (fd);    /* Note: We inherit all handles flagged as inheritable.  This seems       to be a security flaw but there seems to be no way of selecting       handles to inherit. */ -  _assuan_log_printf ("CreateProcess, path=`%s' cmdline=`%s'\n", -                      name, cmdline); -  _assuan_log_printf ("        stdin=%p stdout=%p stderr=%p\n", -                      si.hStdInput, si.hStdOutput, si.hStdError); +  /*   _assuan_log_printf ("CreateProcess, path=`%s' cmdline=`%s'\n", */ +  /*                       name, cmdline); */    if (!CreateProcess (name,                 /* Program to start.  */                        cmdline,              /* Command line arguments.  */                        &sec_attr,            /* Process security attributes.  */                        &sec_attr,            /* Thread security attributes.  */                        TRUE,                 /* Inherit handles.  */                        (CREATE_DEFAULT_ERROR_MODE -                       | DETACHED_PROCESS +                       | ((flags & 128)? DETACHED_PROCESS : 0)                         | GetPriorityClass (GetCurrentProcess ())                         | CREATE_SUSPENDED), /* Creation flags.  */                        NULL,                 /* Environment.  */ @@ -935,10 +924,10 @@ pipe_connect_w32 (assuan_context_t *ctx,                        ))      {        _assuan_log_printf ("CreateProcess failed: %s\n", w32_strerror (-1)); -      CloseHandle (fd_to_handle (rp[0])); -      CloseHandle (fd_to_handle (rp[1])); -      CloseHandle (fd_to_handle (wp[0])); -      CloseHandle (fd_to_handle (wp[1])); +      CloseHandle (rp[0]); +      CloseHandle (rp[1]); +      CloseHandle (wp[0]); +      CloseHandle (wp[1]);        if (nullfd != INVALID_HANDLE_VALUE)          CloseHandle (nullfd);        xfree (cmdline); @@ -953,20 +942,17 @@ pipe_connect_w32 (assuan_context_t *ctx,        nullfd = INVALID_HANDLE_VALUE;      } -  _assuan_log_printf ("closing handles %p and %p\n",  -                      fd_to_handle (rp[1]), fd_to_handle (wp[0]) ); -  CloseHandle (fd_to_handle (rp[1])); -  CloseHandle (fd_to_handle (wp[0])); +  CloseHandle (rp[1]); +  CloseHandle (wp[0]); -  _assuan_log_printf ("CreateProcess ready: hProcess=%p hThread=%p" -                      " dwProcessID=%d dwThreadId=%d\n", -                      pi.hProcess, pi.hThread, -                      (int) pi.dwProcessId, (int) pi.dwThreadId); +  /*   _assuan_log_printf ("CreateProcess ready: hProcess=%p hThread=%p" */ +  /*                       " dwProcessID=%d dwThreadId=%d\n", */ +  /*                       pi.hProcess, pi.hThread, */ +  /*                       (int) pi.dwProcessId, (int) pi.dwThreadId); */    ResumeThread (pi.hThread);    CloseHandle (pi.hThread);  -  (*ctx)->pid = 0;  /* We don't use the PID. */ -  CloseHandle (pi.hProcess); /* We don't need to wait for the process. */ +  (*ctx)->pid = (pid_t) pi.hProcess;    return initial_handshake (ctx);  } @@ -982,7 +968,7 @@ assuan_error_t  assuan_pipe_connect (assuan_context_t *ctx, const char *name,  		     const char *const argv[], int *fd_child_list)  { -  return pipe_connect (ctx, name, argv, fd_child_list, NULL, NULL); +  return pipe_connect (ctx, name, argv, fd_child_list, NULL, NULL, 0);  } @@ -994,7 +980,7 @@ assuan_pipe_connect2 (assuan_context_t *ctx,                        void (*atfork) (void *opaque, int reserved),                        void *atforkvalue)  { -  return pipe_connect (ctx, name, argv, fd_child_list, atfork, atforkvalue); +  return pipe_connect (ctx, name, argv, fd_child_list, atfork, atforkvalue, 0);  } @@ -1007,9 +993,19 @@ assuan_pipe_connect2 (assuan_context_t *ctx,     as the second argument. The ATFORK function should only act if the     second value is 0. -   For now FLAGS may either take the value 0 to behave like -   assuan_pipe_connect2 or 1 to enable the described full-duplex -   socket behaviour. +   FLAGS is a bit vector and controls how the function acts: +   Bit 0: If cleared a simple pipe based server is expected and the +          function behaves similar to `assuan_pipe_connect'. + +          If set a server based on full-duplex pipes is expected. Such +          pipes are usually created using the `socketpair' function. +          It also enables features only available with such servers. + +   Bit 7: If set and there is a need to start ther server it will be +          started as a background process.  This flag is useful under +          W32 systems, so that no new console is created and pops up a +          console window when starting the server +     If NAME as well as ARGV are NULL, no exec is done but the same     process is continued.  However all file descriptors are closed and @@ -1033,6 +1029,7 @@ assuan_pipe_connect_ext (assuan_context_t *ctx,  #endif      }    else -    return pipe_connect (ctx, name, argv, fd_child_list, atfork, atforkvalue); +    return pipe_connect (ctx, name, argv, fd_child_list, atfork, atforkvalue, +                         flags);  } diff --git a/assuan/assuan-pipe-server.c b/assuan/assuan-pipe-server.c index 1b47def5..70404144 100644 --- a/assuan/assuan-pipe-server.c +++ b/assuan/assuan-pipe-server.c @@ -14,9 +14,7 @@   * Lesser General Public License for more details.   *   * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA.  + * License along with this program; if not, see <http://www.gnu.org/licenses/>.   */  #include <config.h> @@ -69,14 +67,14 @@ _assuan_new_context (assuan_context_t *r_ctx)    ctx = xtrycalloc (1, sizeof *ctx);    if (!ctx)      return _assuan_error (ASSUAN_Out_Of_Core); -  ctx->input_fd = -1; -  ctx->output_fd = -1; +  ctx->input_fd = ASSUAN_INVALID_FD; +  ctx->output_fd = ASSUAN_INVALID_FD; -  ctx->inbound.fd = -1; -  ctx->outbound.fd = -1; +  ctx->inbound.fd = ASSUAN_INVALID_FD; +  ctx->outbound.fd = ASSUAN_INVALID_FD;    ctx->io = &io; -  ctx->listen_fd = -1; +  ctx->listen_fd = ASSUAN_INVALID_FD;    /* Use the pipe server handler as a default.  */    ctx->deinit_handler = deinit_pipe_server;    ctx->accept_handler = accept_connection; @@ -121,11 +119,11 @@ assuan_init_pipe_server (assuan_context_t *r_ctx, int filedes[2])  #ifdef HAVE_W32_SYSTEM        /* MS Windows has so many different types of handle that one           needs to tranlsate them at many place forth and back.  Also -         make sure that the fiel descriptos are in binary mode.  */ +         make sure that the file descriptors are in binary mode.  */        setmode (filedes[0], O_BINARY);        setmode (filedes[1], O_BINARY); -      ctx->inbound.fd  = _get_osfhandle (filedes[0]); -      ctx->outbound.fd = _get_osfhandle (filedes[1]); +      ctx->inbound.fd  = (void*)_get_osfhandle (filedes[0]); +      ctx->outbound.fd = (void*)_get_osfhandle (filedes[1]);  #else        s = getenv ("_assuan_connection_fd");        if (s && *s && is_valid_socket (s) ) @@ -137,7 +135,8 @@ assuan_init_pipe_server (assuan_context_t *r_ctx, int filedes[2])            _assuan_init_uds_io (ctx);            ctx->deinit_handler = _assuan_uds_deinit;          } -      else if (filedes && filedes[0] != -1 && filedes[1] != -1 ) +      else if (filedes && filedes[0] != ASSUAN_INVALID_FD  +               && filedes[1] != ASSUAN_INVALID_FD )          {            /* Standard pipe server. */            ctx->inbound.fd  = filedes[0]; @@ -168,6 +167,7 @@ _assuan_release_context (assuan_context_t ctx)  {    if (ctx)      { +      _assuan_inquire_release (ctx);        xfree (ctx->hello_line);        xfree (ctx->okay_line);        xfree (ctx->cmdtbl); diff --git a/assuan/assuan-socket-connect.c b/assuan/assuan-socket-connect.c index 5953f1c3..8eb6d828 100644 --- a/assuan/assuan-socket-connect.c +++ b/assuan/assuan-socket-connect.c @@ -14,9 +14,7 @@   * Lesser General Public License for more details.   *   * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA.  + * License along with this program; if not, see <http://www.gnu.org/licenses/>.   */  #include <config.h> @@ -57,12 +55,12 @@  static int  do_finish (assuan_context_t ctx)  { -  if (ctx->inbound.fd != -1) +  if (ctx->inbound.fd != ASSUAN_INVALID_FD)      {        _assuan_close (ctx->inbound.fd);      } -  ctx->inbound.fd = -1; -  ctx->outbound.fd = -1; +  ctx->inbound.fd = ASSUAN_INVALID_FD; +  ctx->outbound.fd = ASSUAN_INVALID_FD;    return 0;  } @@ -87,18 +85,17 @@ assuan_socket_connect (assuan_context_t *r_ctx,  /* Make a connection to the Unix domain socket NAME and return a new     Assuan context in CTX.  SERVER_PID is currently not used but may     become handy in the future.  With flags set to 1 sendmsg and -   recvmesg are used. */ +   recvmsg are used. */  assuan_error_t  assuan_socket_connect_ext (assuan_context_t *r_ctx,                             const char *name, pid_t server_pid,                             unsigned int flags)  { -  static struct assuan_io io = { _assuan_simple_read, -				 _assuan_simple_write }; - +  static struct assuan_io io = { _assuan_simple_read, _assuan_simple_write, +				 NULL, NULL };    assuan_error_t err;    assuan_context_t ctx; -  int fd; +  assuan_fd_t fd;    struct sockaddr_un srvr_addr;    size_t len;    const char *s; @@ -109,7 +106,7 @@ assuan_socket_connect_ext (assuan_context_t *r_ctx,    /* We require that the name starts with a slash, so that we       eventually can reuse this function for other socket types.  To -     make things easier we allow an optional dirver prefix.  */ +     make things easier we allow an optional driver prefix.  */    s = name;    if (*s && s[1] == ':')      s += 2; @@ -126,7 +123,7 @@ assuan_socket_connect_ext (assuan_context_t *r_ctx,    ctx->finish_handler = do_finish;    fd = _assuan_sock_new (PF_LOCAL, SOCK_STREAM, 0); -  if (fd == -1) +  if (fd == ASSUAN_INVALID_FD)      {        _assuan_log_printf ("can't create socket: %s\n", strerror (errno));        _assuan_release_context (ctx); @@ -139,8 +136,7 @@ assuan_socket_connect_ext (assuan_context_t *r_ctx,    srvr_addr.sun_path[sizeof (srvr_addr.sun_path) - 1] = 0;    len = SUN_LEN (&srvr_addr); - -  if (_assuan_sock_connect (fd, (struct sockaddr *) &srvr_addr, len) == -1) +  if ( _assuan_sock_connect (fd, (struct sockaddr *) &srvr_addr, len) == -1 )      {        _assuan_log_printf ("can't connect to `%s': %s\n",                            name, strerror (errno)); diff --git a/assuan/assuan-socket-server.c b/assuan/assuan-socket-server.c index 5c461644..c536dba4 100644 --- a/assuan/assuan-socket-server.c +++ b/assuan/assuan-socket-server.c @@ -1,5 +1,5 @@  /* assuan-socket-server.c - Assuan socket based server - *	Copyright (C) 2002 Free Software Foundation, Inc. + *	Copyright (C) 2002, 2007 Free Software Foundation, Inc.   *   * This file is part of Assuan.   * @@ -14,9 +14,7 @@   * Lesser General Public License for more details.   *   * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA.  + * License along with this program; if not, see <http://www.gnu.org/licenses/>.   */  #include <config.h> @@ -40,14 +38,13 @@  #include "assuan-defs.h" -static struct assuan_io io = { _assuan_simple_read, -			       _assuan_simple_write }; - +static struct assuan_io io = { _assuan_simple_read, _assuan_simple_write, +			       NULL, NULL };  static int  accept_connection_bottom (assuan_context_t ctx)  { -  int fd = ctx->connected_fd; +  assuan_fd_t fd = ctx->connected_fd;    ctx->peercred.valid = 0;  #ifdef HAVE_SO_PEERCRED @@ -89,16 +86,23 @@ accept_connection_bottom (assuan_context_t ctx)  static int  accept_connection (assuan_context_t ctx)  { -  int fd; +  assuan_fd_t fd;    struct sockaddr_un clnt_addr;    socklen_t len = sizeof clnt_addr; -  fd = accept (ctx->listen_fd, (struct sockaddr*)&clnt_addr, &len ); -  if (fd == -1) +  fd = SOCKET2HANDLE(accept (HANDLE2SOCKET(ctx->listen_fd),  +                             (struct sockaddr*)&clnt_addr, &len )); +  if (fd == ASSUAN_INVALID_FD)      {        ctx->os_errno = errno;        return _assuan_error (ASSUAN_Accept_Failed);      } +  if (_assuan_sock_check_nonce (fd, &ctx->listen_nonce)) +    { +      _assuan_close (fd); +      ctx->os_errno = EACCES; +      return _assuan_error (ASSUAN_Accept_Failed); +    }    ctx->connected_fd = fd;    return accept_connection_bottom (ctx); @@ -107,12 +111,12 @@ accept_connection (assuan_context_t ctx)  static int  finish_connection (assuan_context_t ctx)  { -  if (ctx->inbound.fd != -1) +  if (ctx->inbound.fd != ASSUAN_INVALID_FD)      {        _assuan_close (ctx->inbound.fd);      } -  ctx->inbound.fd = -1; -  ctx->outbound.fd = -1; +  ctx->inbound.fd = ASSUAN_INVALID_FD; +  ctx->outbound.fd = ASSUAN_INVALID_FD;    return 0;  } @@ -126,15 +130,15 @@ deinit_socket_server (assuan_context_t ctx)  /* Initialize a server for the socket LISTEN_FD which has already be     put into listen mode */  int -assuan_init_socket_server (assuan_context_t *r_ctx, int listen_fd) +assuan_init_socket_server (assuan_context_t *r_ctx, assuan_fd_t listen_fd)  {    return assuan_init_socket_server_ext (r_ctx, listen_fd, 0);  }  /* Initialize a server using the already accepted socket FD.  This -   fucntion is deprecated. */ +   function is deprecated. */  int -assuan_init_connected_socket_server (assuan_context_t *r_ctx, int fd) +assuan_init_connected_socket_server (assuan_context_t *r_ctx, assuan_fd_t fd)  {    return assuan_init_socket_server_ext (r_ctx, fd, 2);  } @@ -145,7 +149,7 @@ assuan_init_connected_socket_server (assuan_context_t *r_ctx, int fd)                1 - FD has already been accepted.  */  int -assuan_init_socket_server_ext (assuan_context_t *r_ctx, int fd, +assuan_init_socket_server_ext (assuan_context_t *r_ctx, assuan_fd_t fd,                                 unsigned int flags)  {    assuan_context_t ctx; @@ -158,21 +162,21 @@ assuan_init_socket_server_ext (assuan_context_t *r_ctx, int fd,    ctx->is_server = 1;    if ((flags & 2))      ctx->pipe_mode = 1; /* We want a second accept to indicate EOF. */ -  ctx->input_fd = -1; -  ctx->output_fd = -1; +  ctx->input_fd = ASSUAN_INVALID_FD; +  ctx->output_fd = ASSUAN_INVALID_FD; -  ctx->inbound.fd = -1; -  ctx->outbound.fd = -1; +  ctx->inbound.fd = ASSUAN_INVALID_FD; +  ctx->outbound.fd = ASSUAN_INVALID_FD;    if ((flags & 2))      { -      ctx->listen_fd = -1; +      ctx->listen_fd = ASSUAN_INVALID_FD;        ctx->connected_fd = fd;      }    else      {        ctx->listen_fd = fd; -      ctx->connected_fd = -1; +      ctx->connected_fd = ASSUAN_INVALID_FD;      }    ctx->deinit_handler = (flags & 1)? _assuan_uds_deinit:deinit_socket_server;    ctx->accept_handler = ((flags & 2) @@ -191,3 +195,14 @@ assuan_init_socket_server_ext (assuan_context_t *r_ctx, int fd,      *r_ctx = ctx;    return rc;  } + + +/* Save a copy of NONCE in context CTX.  This should be used to +   register the server's nonce with an context established by +   assuan_init_socket_server.  */ +void +assuan_set_sock_nonce (assuan_context_t ctx, assuan_sock_nonce_t *nonce) +{ +  if (ctx && nonce) +    ctx->listen_nonce = *nonce; +} diff --git a/assuan/assuan-socket.c b/assuan/assuan-socket.c index 5566fdea..02a62253 100644 --- a/assuan/assuan-socket.c +++ b/assuan/assuan-socket.c @@ -14,20 +14,26 @@   * Lesser General Public License for more details.   *   * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA.  + * License along with this program; if not, see <http://www.gnu.org/licenses/>.   */  #include <config.h>  #include <stdio.h> +#include <stdlib.h>  #ifdef HAVE_W32_SYSTEM +#define WIN32_LEAN_AND_MEAN  #include <windows.h> +#include <wincrypt.h>  #include <io.h>  #else  #include <sys/types.h>  #include <sys/socket.h>  #endif +#include <errno.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <assert.h> +  #include "assuan-defs.h"  /* Hacks for Slowaris.  */ @@ -42,13 +48,114 @@  # define AF_LOCAL AF_UNIX  #endif +#ifdef HAVE_W32_SYSTEM +#ifndef S_IRGRP +# define S_IRGRP 0 +# define S_IWGRP 0 +#endif +#endif + + +#ifdef HAVE_W32_SYSTEM +int +_assuan_sock_wsa2errno (int err) +{ +  switch (err) +    { +    case WSAENOTSOCK: +      return EINVAL; +    case WSAEWOULDBLOCK: +      return EAGAIN; +    case ERROR_BROKEN_PIPE: +      return EPIPE; +    case WSANOTINITIALISED: +      return ENOSYS; +    default: +      return EIO; +    } +} + + +/* W32: Fill BUFFER with LENGTH bytes of random.  Returns -1 on +   failure, 0 on success.  Sets errno on failure.  */ +static int +get_nonce (char *buffer, size_t nbytes)  +{ +  HCRYPTPROV prov; +  int ret = -1; + +  if (!CryptAcquireContext (&prov, NULL, NULL, PROV_RSA_FULL,  +                            (CRYPT_VERIFYCONTEXT|CRYPT_SILENT)) ) +    errno = ENODEV; +  else  +    { +      if (!CryptGenRandom (prov, nbytes, buffer)) +        errno = ENODEV; +      else +        ret = 0; +      CryptReleaseContext (prov, 0); +    } +  return ret; +} + + +/* W32: The buffer for NONCE needs to be at least 16 bytes.  Returns 0 on +   success and sets errno on failure. */ +static int +read_port_and_nonce (const char *fname, unsigned short *port, char *nonce) +{ +  FILE *fp; +  char buffer[50], *p; +  size_t nread; +  int aval; + +  fp = fopen (fname, "rb"); +  if (!fp) +    return -1; +  nread = fread (buffer, 1, sizeof buffer - 1, fp); +  fclose (fp); +  if (!nread) +    { +      errno = ENOFILE; +      return -1; +    } +  buffer[nread] = 0; +  aval = atoi (buffer); +  if (aval < 1 || aval > 65535) +    { +      errno = EINVAL; +      return -1; +    } +  *port = (unsigned int)aval; +  for (p=buffer; nread && *p != '\n'; p++, nread--) +    ; +  if (*p != '\n' || nread != 17) +    { +      errno = EINVAL; +      return -1; +    } +  p++; nread--; +  memcpy (nonce, p, 16); +  return 0; +} +#endif /*HAVE_W32_SYSTEM*/ + + +  int -_assuan_close (int fd) +_assuan_close (assuan_fd_t fd)  {  #if defined (HAVE_W32_SYSTEM) && !defined(_ASSUAN_IN_GPGME_BUILD_ASSUAN) -  int rc = closesocket (fd); +  int rc = closesocket (HANDLE2SOCKET(fd)); +  if (rc) +    errno = _assuan_sock_wsa2errno (WSAGetLastError ());    if (rc && WSAGetLastError () == WSAENOTSOCK) -    rc = CloseHandle (fd); +    { +      rc = CloseHandle (fd); +      if (rc) +	/* FIXME. */ +	errno = EIO; +    }    return rc;  #else    return close (fd); @@ -56,93 +163,277 @@ _assuan_close (int fd)  } -int +/* Return a new socket.  Note that under W32 we consider a socket the +   same as an System Handle; all functions using such a handle know +   about this dual use and act accordingly. */  +assuan_fd_t  _assuan_sock_new (int domain, int type, int proto)  { -#ifndef HAVE_W32_SYSTEM -  return socket (domain, type, proto); -#else +#ifdef HAVE_W32_SYSTEM +  assuan_fd_t res;    if (domain == AF_UNIX || domain == AF_LOCAL)      domain = AF_INET; +  res = SOCKET2HANDLE(socket (domain, type, proto)); +  if (res == ASSUAN_INVALID_FD) +    errno = _assuan_sock_wsa2errno (WSAGetLastError ()); +  return res; +#else    return socket (domain, type, proto);  #endif  }  int -_assuan_sock_connect (int sockfd, struct sockaddr * addr, int addrlen) +_assuan_sock_connect (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)  { -#ifndef HAVE_W32_SYSTEM -  return connect (sockfd, addr, addrlen); -#else -  struct sockaddr_in myaddr; -  struct sockaddr_un * unaddr; -  FILE * fp; -  int port = 0; -   -  unaddr = (struct sockaddr_un *)addr; -  fp = fopen (unaddr->sun_path, "rb"); -  if (!fp) -      return -1; -  fscanf (fp, "%d", &port); -  fclose (fp); -  /* XXX: set errno in this case */ -  if (port < 0 || port > 65535) -      return -1; +#ifdef HAVE_W32_SYSTEM +  if (addr->sa_family == AF_LOCAL || addr->sa_family == AF_UNIX) +    { +      struct sockaddr_in myaddr; +      struct sockaddr_un *unaddr; +      unsigned short port; +      char nonce[16]; +      int ret; +       +      unaddr = (struct sockaddr_un *)addr; +      if (read_port_and_nonce (unaddr->sun_path, &port, nonce)) +        return -1; +       +      myaddr.sin_family = AF_INET; +      myaddr.sin_port = htons (port);  +      myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); -  myaddr.sin_family = AF_INET; -  myaddr.sin_port = port;  -  myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); - -  /* we need this later. */ -  unaddr->sun_family = myaddr.sin_family; -  unaddr->sun_port = myaddr.sin_port; -  unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr; +      /* Set return values.  */ +      unaddr->sun_family = myaddr.sin_family; +      unaddr->sun_port = myaddr.sin_port; +      unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr; -  return connect (sockfd, (struct sockaddr *)&myaddr, sizeof myaddr); +      ret = connect (HANDLE2SOCKET(sockfd),  +                     (struct sockaddr *)&myaddr, sizeof myaddr); +      if (!ret) +        { +          /* Send the nonce. */ +          ret = _assuan_io_write (sockfd, nonce, 16); +          if (ret >= 0 && ret != 16) +            { +              errno = EIO; +              ret = -1; +            } +        } +      return ret; +    } +  else +    { +      int res; +      res = connect (HANDLE2SOCKET (sockfd), addr, addrlen); +      if (res < 0) +	errno = _assuan_sock_wsa2errno (WSAGetLastError ()); +      return res; +    }       +#else +  return connect (sockfd, addr, addrlen);  #endif  }  int -_assuan_sock_bind (int sockfd, struct sockaddr * addr, int addrlen) +_assuan_sock_bind (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)  { -#ifndef HAVE_W32_SYSTEM -  return bind (sockfd, addr, addrlen); -#else +#ifdef HAVE_W32_SYSTEM    if (addr->sa_family == AF_LOCAL || addr->sa_family == AF_UNIX)      {        struct sockaddr_in myaddr; -      struct sockaddr_un * unaddr; -      FILE * fp; +      struct sockaddr_un *unaddr; +      int filefd; +      FILE *fp;        int len = sizeof myaddr;        int rc; +      char nonce[16]; + +      if (get_nonce (nonce, 16)) +        return -1; + +      unaddr = (struct sockaddr_un *)addr;        myaddr.sin_port = 0;        myaddr.sin_family = AF_INET;        myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); -      rc = bind (sockfd, (struct sockaddr *)&myaddr, len); -      if (rc) -        return rc; -      rc = getsockname (sockfd, (struct sockaddr *)&myaddr, &len); -      if (rc) -        return rc; -      unaddr = (struct sockaddr_un *)addr; -      fp = fopen (unaddr->sun_path, "wb"); +      filefd = open (unaddr->sun_path,  +                     (O_WRONLY|O_CREAT|O_EXCL|O_BINARY),  +                     (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)); +      if (filefd == -1) +        { +          if (errno == EEXIST) +            errno = WSAEADDRINUSE; +          return -1; +        } +      fp = fdopen (filefd, "wb");        if (!fp) -        return -1; -      fprintf (fp, "%d", myaddr.sin_port); +        {  +          int save_e = errno; +          close (filefd); +          errno = save_e; +          return -1; +        } + +      rc = bind (HANDLE2SOCKET (sockfd), (struct sockaddr *)&myaddr, len); +      if (!rc) +        rc = getsockname (HANDLE2SOCKET (sockfd),  +                          (struct sockaddr *)&myaddr, &len); +      if (rc) +        { +          int save_e = errno; +          fclose (fp); +          remove (unaddr->sun_path); +          errno = save_e; +          return rc; +        } +      fprintf (fp, "%d\n", ntohs (myaddr.sin_port)); +      fwrite (nonce, 16, 1, fp);        fclose (fp); -      /* we need this later. */ -      unaddr->sun_family = myaddr.sin_family; -      unaddr->sun_port = myaddr.sin_port; -      unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr; -              return 0;      } +  else +    { +      int res = bind (HANDLE2SOCKET(sockfd), addr, addrlen); +      if (res < 0) +	errno = _assuan_sock_wsa2errno (WSAGetLastError ()); +      return res; +    } +#else    return bind (sockfd, addr, addrlen);  #endif  } + +int +_assuan_sock_get_nonce (struct sockaddr *addr, int addrlen,  +                        assuan_sock_nonce_t *nonce) +{ +#ifdef HAVE_W32_SYSTEM +  if (addr->sa_family == AF_LOCAL || addr->sa_family == AF_UNIX) +    { +      struct sockaddr_un *unaddr; +      unsigned short port; + +      if (sizeof nonce->nonce != 16) +        { +          errno = EINVAL; +          return -1; +        } +      nonce->length = 16; +      unaddr = (struct sockaddr_un *)addr; +      if (read_port_and_nonce (unaddr->sun_path, &port, nonce->nonce)) +        return -1; +    } +  else +    { +      nonce->length = 42; /* Arbitrary valuie to detect unitialized nonce. */ +      nonce->nonce[0] = 42; +    } +#else +  (void)addr; +  (void)addrlen; +  nonce->length = 0; +#endif +  return 0; +} +  +  +int +_assuan_sock_check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce) +{ +#ifdef HAVE_W32_SYSTEM +  char buffer[16], *p; +  size_t nleft; +  int n; + +  if (sizeof nonce->nonce != 16) +    { +      errno = EINVAL; +      return -1; +    } + +  if (nonce->length == 42 && nonce->nonce[0] == 42) +    return 0; /* Not a Unix domain socket.  */ + +  if (nonce->length != 16) +    { +      errno = EINVAL; +      return -1; +    } +       +  p = buffer; +  nleft = 16; +  while (nleft) +    { +      n = _assuan_io_read (SOCKET2HANDLE(fd), p, nleft); +      if (n < 0 && errno == EINTR) +        ; +      else if (n < 0 && errno == EAGAIN) +        Sleep (100); +      else if (n < 0) +        return -1; +      else if (!n) +        { +          errno = EIO; +          return -1; +        } +      else +        { +          p += n; +          nleft -= n; +        } +    } +  if (memcmp (buffer, nonce->nonce, 16)) +    { +      errno = EACCES; +      return -1; +    } +#else +  (void)fd; +  (void)nonce; +#endif +  return 0; +} + + +/* Public API.  */ +int +assuan_sock_close (assuan_fd_t fd) +{ +  return _assuan_close (fd); +} + +assuan_fd_t  +assuan_sock_new (int domain, int type, int proto) +{ +  return _assuan_sock_new (domain, type, proto); +} + +int +assuan_sock_connect (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen) +{ +  return _assuan_sock_connect (sockfd, addr, addrlen); +} + +int +assuan_sock_bind (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen) +{ +  return _assuan_sock_bind (sockfd, addr, addrlen); +} + +int +assuan_sock_get_nonce (struct sockaddr *addr, int addrlen,  +                       assuan_sock_nonce_t *nonce) +{      +  return _assuan_sock_get_nonce (addr, addrlen, nonce); +} + +int +assuan_sock_check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce) +{ +  return _assuan_sock_check_nonce (fd, nonce); +} diff --git a/assuan/assuan-uds.c b/assuan/assuan-uds.c index 70ec8ccc..02f77a52 100644 --- a/assuan/assuan-uds.c +++ b/assuan/assuan-uds.c @@ -14,9 +14,7 @@   * Lesser General Public License for more details.   *   * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA.  + * License along with this program; if not, see <http://www.gnu.org/licenses/>.   */  #ifdef HAVE_CONFIG_H @@ -72,9 +70,9 @@  static ssize_t  uds_reader (assuan_context_t ctx, void *buf, size_t buflen)  { +#ifndef HAVE_W32_SYSTEM    int len = ctx->uds.buffersize; -#ifndef HAVE_W32_SYSTEM    if (!ctx->uds.bufferallocated)      {        ctx->uds.buffer = xtrymalloc (2048); @@ -141,12 +139,6 @@ uds_reader (assuan_context_t ctx, void *buf, size_t buflen)  #endif /*USE_DESCRIPTOR_PASSING*/      } -#else /*HAVE_W32_SYSTEM*/ - -  len = recvfrom (ctx->inbound.fd, buf, buflen, 0, NULL, NULL); - -#endif /*HAVE_W32_SYSTEM*/ -    /* Return some data to the user.  */    if (len > buflen) /* We have more than the user requested.  */ @@ -159,6 +151,12 @@ uds_reader (assuan_context_t ctx, void *buf, size_t buflen)    assert (ctx->uds.bufferoffset <= ctx->uds.bufferallocated);    return len; +#else /*HAVE_W32_SYSTEM*/ +  int res = recvfrom (HANDLE2SOCKET(ctx->inbound.fd), buf, buflen, 0, NULL, NULL); +  if (res < 0) +    errno = _assuan_sock_wsa2errno (WSAGetLastError ()); +  return res; +#endif /*HAVE_W32_SYSTEM*/  } @@ -181,19 +179,21 @@ uds_writer (assuan_context_t ctx, const void *buf, size_t buflen)    iovec.iov_len = buflen;    len = _assuan_simple_sendmsg (ctx, &msg); + +  return len;  #else /*HAVE_W32_SYSTEM*/ -  int len; -   -  len = sendto (ctx->outbound.fd, buf, buflen, 0, -                (struct sockaddr *)&ctx->serveraddr, -                sizeof (struct sockaddr_in)); +  int res = sendto (HANDLE2SOCKET(ctx->outbound.fd), buf, buflen, 0, +		    (struct sockaddr *)&ctx->serveraddr, +		    sizeof (struct sockaddr_in)); +  if (res < 0) +    errno = _assuan_sock_wsa2errno (WSAGetLastError ()); +  return res;  #endif /*HAVE_W32_SYSTEM*/ -  return len;  }  static assuan_error_t -uds_sendfd (assuan_context_t ctx, int fd) +uds_sendfd (assuan_context_t ctx, assuan_fd_t fd)  {  #ifdef USE_DESCRIPTOR_PASSING    struct msghdr msg; @@ -243,7 +243,7 @@ uds_sendfd (assuan_context_t ctx, int fd)  static assuan_error_t -uds_receivefd (assuan_context_t ctx, int *fd) +uds_receivefd (assuan_context_t ctx, assuan_fd_t *fd)  {  #ifdef USE_DESCRIPTOR_PASSING    int i; diff --git a/assuan/assuan-util.c b/assuan/assuan-util.c index d12277fc..cefefcb2 100644 --- a/assuan/assuan-util.c +++ b/assuan/assuan-util.c @@ -14,9 +14,7 @@   * Lesser General Public License for more details.   *   * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA.  + * License along with this program; if not, see <http://www.gnu.org/licenses/>.   */  #include <config.h> @@ -32,6 +30,10 @@ static void *(*alloc_func)(size_t n) = malloc;  static void *(*realloc_func)(void *p, size_t n) = realloc;  static void (*free_func)(void*) = free; +struct assuan_io_hooks _assuan_io_hooks; + + +  void  assuan_set_malloc_hooks ( void *(*new_alloc_func)(size_t n),                            void *(*new_realloc_func)(void *p, size_t n), @@ -42,6 +44,20 @@ assuan_set_malloc_hooks ( void *(*new_alloc_func)(size_t n),    free_func	    = new_free_func;  } + +void +assuan_set_io_hooks (assuan_io_hooks_t io_hooks) +{ +  _assuan_io_hooks.read_hook = NULL; +  _assuan_io_hooks.write_hook = NULL; +  if (io_hooks) +    { +      _assuan_io_hooks.read_hook = io_hooks->read_hook; +      _assuan_io_hooks.write_hook = io_hooks->write_hook; +    } +} + +  void *  _assuan_malloc (size_t n)  { @@ -152,6 +168,7 @@ assuan_set_flag (assuan_context_t ctx, assuan_flag_t flag, int value)    switch (flag)      {      case ASSUAN_NO_WAITPID: ctx->flags.no_waitpid = value; break; +    case ASSUAN_CONFIDENTIAL: ctx->confidential = value; break;      }  } @@ -164,8 +181,8 @@ assuan_get_flag (assuan_context_t ctx, assuan_flag_t flag)    switch (flag)      {      case ASSUAN_NO_WAITPID: return ctx->flags.no_waitpid; +    case ASSUAN_CONFIDENTIAL: return ctx->confidential;      }    return 0;  } - diff --git a/assuan/assuan.h b/assuan/assuan.h index 6df01667..0e5c7413 100644 --- a/assuan/assuan.h +++ b/assuan/assuan.h @@ -1,5 +1,6 @@  /* assuan.h - Definitions for the Assuan IPC library - * Copyright (C) 2001, 2002, 2003, 2005, 2007 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2005, 2007,  + *               2008 Free Software Foundation, Inc.   *   * This file is part of Assuan.   * @@ -14,9 +15,7 @@   * Lesser General Public License for more details.   *   * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA.  + * License along with this program; if not, see <http://www.gnu.org/licenses/>.   */  #ifndef ASSUAN_H @@ -25,18 +24,28 @@  #include <stdio.h>  #include <sys/types.h>  #include <unistd.h> - +#ifndef _ASSUAN_NO_SOCKET_WRAPPER +#ifdef _WIN32 +#include <ws2tcpip.h>  +#else +#include <sys/socket.h> +#endif +#endif /*!_ASSUAN_NO_SOCKET_WRAPPER*/  /* To use this file with libraries the following macros are useful:       #define _ASSUAN_EXT_SYM_PREFIX _foo_ -     This prefixes all external symbols with "_foo_". +       This prefixes all external symbols with "_foo_".       #define _ASSUAN_ONLY_GPG_ERRORS -     If this is defined all old-style Assuan error codes are made -     inactive as well as other dereacted stuff. +       If this is defined all old-style Assuan error codes are made +       inactive as well as other deprecated stuff. + +     #define _ASSUAN_NO_SOCKET_WRAPPER + +       Do not include the definitions for the socket wrapper feature.     The follwing macros are used internally in the implementation of     libassuan: @@ -69,6 +78,8 @@ int _gpgme_io_write (int fd, const void *buffer, size_t count);  int _gpgme_io_sendmsg (int sock, const struct msghdr *msg, int flags);  int _gpgme_io_recvmsg (int sock, struct msghdr *msg, int flags); +#define _assuan_funopen _gpgme_funopen +  #define close         _gpgme_io_close  #define read          _gpgme_io_read  #define write         _gpgme_io_write @@ -103,6 +114,7 @@ int _gpgme_io_recvmsg (int sock, struct msghdr *msg, int flags);    _ASSUAN_PREFIX(assuan_register_option_handler)  #define assuan_process _ASSUAN_PREFIX(assuan_process)  #define assuan_process_next _ASSUAN_PREFIX(assuan_process_next) +#define assuan_process_done _ASSUAN_PREFIX(assuan_process_done)  #define assuan_get_active_fds _ASSUAN_PREFIX(assuan_get_active_fds)  #define assuan_get_data_fp _ASSUAN_PREFIX(assuan_get_data_fp)  #define assuan_set_okay_line _ASSUAN_PREFIX(assuan_set_okay_line) @@ -130,6 +142,7 @@ int _gpgme_io_recvmsg (int sock, struct msghdr *msg, int flags);  #define assuan_get_peercred _ASSUAN_PREFIX(assuan_get_peercred)  #define assuan_transact _ASSUAN_PREFIX(assuan_transact)  #define assuan_inquire _ASSUAN_PREFIX(assuan_inquire) +#define assuan_inquire_ext _ASSUAN_PREFIX(assuan_inquire_ext)  #define assuan_read_line _ASSUAN_PREFIX(assuan_read_line)  #define assuan_pending_line _ASSUAN_PREFIX(assuan_pending_line)  #define assuan_write_line _ASSUAN_PREFIX(assuan_write_line) @@ -137,7 +150,7 @@ int _gpgme_io_recvmsg (int sock, struct msghdr *msg, int flags);  #define assuan_sendfd _ASSUAN_PREFIX(assuan_sendfd)  #define assuan_receivefd _ASSUAN_PREFIX(assuan_receivefd)  #define assuan_set_malloc_hooks _ASSUAN_PREFIX(assuan_set_malloc_hooks) -#define assuan_set_assuan_log_level _ASSUAN_PREFIX(assuan_set_assuan_log_level) +#define assuan_set_io_hooks _ASSUAN_PREFIX(assuan_set_io_hooks)  #define assuan_set_log_stream _ASSUAN_PREFIX(assuan_set_log_stream)  #define assuan_set_error _ASSUAN_PREFIX(assuan_set_error)  #define assuan_set_pointer _ASSUAN_PREFIX(assuan_set_pointer) @@ -159,6 +172,13 @@ int _gpgme_io_recvmsg (int sock, struct msghdr *msg, int flags);  #define assuan_pipe_connect2 _ASSUAN_PREFIX(assuan_pipe_connect2)  #define assuan_set_assuan_log_prefix \    _ASSUAN_PREFIX(assuan_set_assuan_log_prefix) +#define assuan_sock_close       _ASSUAN_PREFIX(assuan_sock_close)       +#define assuan_sock_new         _ASSUAN_PREFIX(assuan_sock_new)         +#define assuan_sock_connect     _ASSUAN_PREFIX(assuan_sock_connect)     +#define assuan_sock_bind        _ASSUAN_PREFIX(assuan_sock_bind)        +#define assuan_sock_get_nonce   _ASSUAN_PREFIX(assuan_sock_get_nonce) +#define assuan_sock_check_nonce _ASSUAN_PREFIX(assuan_sock_check_nonce) +  /* And now the internal functions, argh...  */  #define _assuan_read_line _ASSUAN_PREFIX(_assuan_read_line) @@ -170,8 +190,9 @@ int _gpgme_io_recvmsg (int sock, struct msghdr *msg, int flags);    _ASSUAN_PREFIX(_assuan_register_std_commands)  #define _assuan_simple_read _ASSUAN_PREFIX(_assuan_simple_read)  #define _assuan_simple_write _ASSUAN_PREFIX(_assuan_simple_write) -#define _assuan_simple_read _ASSUAN_PREFIX(_assuan_simple_read) -#define _assuan_simple_write _ASSUAN_PREFIX(_assuan_simple_write) +#define _assuan_io_read _ASSUAN_PREFIX(_assuan_io_read) +#define _assuan_io_write _ASSUAN_PREFIX(_assuan_io_write) +#define _assuan_io_hooks _ASSUAN_PREFIX(_assuan_io_hooks)  #define _assuan_new_context _ASSUAN_PREFIX(_assuan_new_context)  #define _assuan_release_context _ASSUAN_PREFIX(_assuan_release_context)  #define _assuan_malloc _ASSUAN_PREFIX(_assuan_malloc) @@ -188,19 +209,22 @@ int _gpgme_io_recvmsg (int sock, struct msghdr *msg, int flags);  #define _assuan_gpg_strerror_r _ASSUAN_PREFIX(_assuan_gpg_strerror_r)  #define _assuan_gpg_strsource  _ASSUAN_PREFIX(_assuan_gpg_strsource)  #define _assuan_write_line _ASSUAN_PREFIX(_assuan_write_line) -#define _assuan_close _ASSUAN_PREFIX(_assuan_close)    -#define _assuan_sock_new _ASSUAN_PREFIX(_assuan_sock_new)   -#define _assuan_sock_bind _ASSUAN_PREFIX(_assuan_sock_bind) -#define _assuan_sock_connect _ASSUAN_PREFIX(_assuan_sock_connect)  #define _assuan_error _ASSUAN_PREFIX(_assuan_error) +#define _assuan_error_is_eagain   _ASSUAN_PREFIX(_assuan_error_is_eagain)  #define _assuan_init_uds_io _ASSUAN_PREFIX(_assuan_init_uds_io)  #define _assuan_uds_close_fds _ASSUAN_PREFIX(_assuan_uds_close_fds)  #define _assuan_uds_deinit _ASSUAN_PREFIX(_assuan_uds_deinit)  #define _assuan_simple_recvmsg _ASSUAN_PREFIX(_assuan_simple_recvmsg)  #define _assuan_simple_sendmsg _ASSUAN_PREFIX(_assuan_simple_sendmsg)  #define _assuan_waitpid _ASSUAN_PREFIX(_assuan_waitpid) +#define _assuan_sock_wsa2errno   _ASSUAN_PREFIX(_assuan_sock_wsa2errno) +#define _assuan_sock_close       _ASSUAN_PREFIX(_assuan_sock_close)       +#define _assuan_sock_new         _ASSUAN_PREFIX(_assuan_sock_new)         +#define _assuan_sock_connect     _ASSUAN_PREFIX(_assuan_sock_connect)     +#define _assuan_sock_bind        _ASSUAN_PREFIX(_assuan_sock_bind)        +#define _assuan_sock_get_nonce   _ASSUAN_PREFIX(_assuan_sock_get_nonce) +#define _assuan_sock_check_nonce _ASSUAN_PREFIX(_assuan_sock_check_nonce) -#define _assuan_funopen _gpgme_funopen  #endif /*_ASSUAN_EXT_SYM_PREFIX*/ @@ -350,7 +374,8 @@ typedef enum  #else  /*!_ASSUAN_ONLY_GPG_ERRORS*/ -typedef int assuan_error_t; +/* Choose a type compatible with gpg_error_t.  */ +typedef unsigned int assuan_error_t;  #endif /*!_ASSUAN_ONLY_GPG_ERRORS*/ @@ -363,7 +388,11 @@ typedef enum         this is not desirable.  By setting this flag, the waitpid will         be skipped and the caller is responsible to cleanup a forked         process. */ -    ASSUAN_NO_WAITPID = 1 +    ASSUAN_NO_WAITPID = 1, +    /* This flag indicates whether Assuan logging is in confidential +       mode. Use assuan_{begin,end}_condidential to change the +       mode.  */ +    ASSUAN_CONFIDENTIAL = 2    }   assuan_flag_t; @@ -375,6 +404,66 @@ typedef struct assuan_context_s *assuan_context_t;  typedef struct assuan_context_s *ASSUAN_CONTEXT _ASSUAN_DEPRECATED;  #endif /*_ASSUAN_ONLY_GPG_ERRORS*/ +/* Because we use system handles and not libc low level file +   descriptors on W32, we need to declare them as HANDLE (which +   actually is a plain pointer).  This is required to eventually +   support 64 bit Windows systems.  */ +#ifdef _WIN32 +typedef void *assuan_fd_t; +#define ASSUAN_INVALID_FD ((void*)(-1)) +#define ASSUAN_INT2FD(s)  ((void *)(s)) +#define ASSUAN_FD2INT(h)  ((unsigned int)(h)) +#else +typedef int assuan_fd_t; +#define ASSUAN_INVALID_FD (-1) +#define ASSUAN_INT2FD(s)  ((s)) +#define ASSUAN_FD2INT(h)  ((h)) +#endif + + +/* Assuan features an emulation of Unix domain sockets based on a +   local TCP connections.  To implement access permissions based on +   file permissions a nonce is used which is expected by th server as +   the first bytes received.  This structure is used by the server to +   save the nonce created initially by bind.  On POSIX systems this is +   a dummy operation. */   +struct assuan_sock_nonce_s +{ +  size_t length; +#ifdef _WIN32 +  char nonce[16]; +#endif +}; +typedef struct assuan_sock_nonce_s assuan_sock_nonce_t; + +/* Define the Unix domain socket structure for Windows.  */ +#if defined(_WIN32) && !defined(_ASSUAN_NO_SOCKET_WRAPPER) +#ifndef AF_LOCAL +#define AF_LOCAL AF_UNIX +#endif +#define EADDRINUSE WSAEADDRINUSE +struct sockaddr_un +{ +  short          sun_family; +  unsigned short sun_port; +  struct         in_addr sun_addr; +  char           sun_path[108-2-4];  +}; +#endif + + +/* Definition of hook functions used to conditionally replace the +   default I/O functions. */ +struct assuan_io_hooks +{ +  int (*read_hook)(assuan_context_t, assuan_fd_t, void *, size_t, ssize_t *); +  int (*write_hook)(assuan_context_t, assuan_fd_t fd, +                    const void *, size_t, ssize_t *); +}; +typedef struct assuan_io_hooks *assuan_io_hooks_t; + + +  /*-- assuan-handler.c --*/  int assuan_register_command (assuan_context_t ctx,                               const char *cmd_string, @@ -398,8 +487,9 @@ int assuan_register_option_handler (assuan_context_t ctx,  int assuan_process (assuan_context_t ctx);  int assuan_process_next (assuan_context_t ctx); +int assuan_process_done (assuan_context_t ctx, int rc);  int assuan_get_active_fds (assuan_context_t ctx, int what, -                           int *fdarray, int fdarraysize); +                           assuan_fd_t *fdarray, int fdarraysize);  FILE *assuan_get_data_fp (assuan_context_t ctx); @@ -410,15 +500,17 @@ assuan_error_t assuan_write_status (assuan_context_t ctx,  /* Negotiate a file descriptor.  If LINE contains "FD=N", returns N     assuming a local file descriptor.  If LINE contains "FD" reads a     file descriptor via CTX and stores it in *RDF (the CTX must be -   capable of passing file descriptors).  */ +   capable of passing file descriptors).  Under W32 the returned FD is +   a libc-type one.  */  assuan_error_t assuan_command_parse_fd (assuan_context_t ctx, char *line, -                                        int *rfd); +                                        assuan_fd_t *rfd); +  /*-- assuan-listen.c --*/  assuan_error_t assuan_set_hello_line (assuan_context_t ctx, const char *line);  assuan_error_t assuan_accept (assuan_context_t ctx); -int assuan_get_input_fd (assuan_context_t ctx); -int assuan_get_output_fd (assuan_context_t ctx); +assuan_fd_t assuan_get_input_fd (assuan_context_t ctx); +assuan_fd_t assuan_get_output_fd (assuan_context_t ctx);  assuan_error_t assuan_close_input_fd (assuan_context_t ctx);  assuan_error_t assuan_close_output_fd (assuan_context_t ctx); @@ -428,11 +520,12 @@ int assuan_init_pipe_server (assuan_context_t *r_ctx, int filedes[2]);  void assuan_deinit_server (assuan_context_t ctx);  /*-- assuan-socket-server.c --*/ -int assuan_init_socket_server (assuan_context_t *r_ctx, int listen_fd); +int assuan_init_socket_server (assuan_context_t *r_ctx, assuan_fd_t listen_fd);  int assuan_init_connected_socket_server (assuan_context_t *r_ctx,  -                                         int fd) _ASSUAN_DEPRECATED; -int assuan_init_socket_server_ext (assuan_context_t *r_ctx, int fd, +                                         assuan_fd_t fd) _ASSUAN_DEPRECATED; +int assuan_init_socket_server_ext (assuan_context_t *r_ctx, assuan_fd_t fd,                                     unsigned int flags); +void assuan_set_sock_nonce (assuan_context_t ctx, assuan_sock_nonce_t *nonce);  /*-- assuan-pipe-connect.c --*/  assuan_error_t assuan_pipe_connect (assuan_context_t *ctx, @@ -465,7 +558,7 @@ assuan_error_t assuan_socket_connect_ext (assuan_context_t *ctx,  /*-- assuan-connect.c --*/  void assuan_disconnect (assuan_context_t ctx);  pid_t assuan_get_pid (assuan_context_t ctx); -#ifndef HAVE_W32_SYSTEM +#ifndef _WIN32  assuan_error_t assuan_get_peercred (assuan_context_t ctx,                                      pid_t *pid, uid_t *uid, gid_t *gid);  #endif @@ -474,11 +567,11 @@ assuan_error_t assuan_get_peercred (assuan_context_t ctx,  assuan_error_t   assuan_transact (assuan_context_t ctx,                   const char *command, -                 int (*data_cb)(void *, const void *, size_t), +                 assuan_error_t (*data_cb)(void *, const void *, size_t),                   void *data_cb_arg, -                 int (*inquire_cb)(void*, const char *), +                 assuan_error_t (*inquire_cb)(void*, const char *),                   void *inquire_cb_arg, -                 int (*status_cb)(void*, const char *), +                 assuan_error_t (*status_cb)(void*, const char *),                   void *status_cb_arg); @@ -486,7 +579,12 @@ assuan_transact (assuan_context_t ctx,  assuan_error_t assuan_inquire (assuan_context_t ctx, const char *keyword,                                 unsigned char **r_buffer, size_t *r_length,                                 size_t maxlen); - +assuan_error_t assuan_inquire_ext (assuan_context_t ctx, const char *keyword, +				   size_t maxlen, +				   int (*cb) (void *cb_data, int rc, +					      unsigned char *buf, +					      size_t buf_len), +				   void *cb_data);  /*-- assuan-buffer.c --*/  assuan_error_t assuan_read_line (assuan_context_t ctx,                                char **line, size_t *linelen); @@ -498,13 +596,15 @@ assuan_error_t assuan_send_data (assuan_context_t ctx,  /* The file descriptor must be pending before assuan_receivefd is     called.  This means that assuan_sendfd should be called *before* the     trigger is sent (normally via assuan_write_line ("INPUT FD")).  */ -assuan_error_t assuan_sendfd (assuan_context_t ctx, int fd); -assuan_error_t assuan_receivefd (assuan_context_t ctx, int *fd); +assuan_error_t assuan_sendfd (assuan_context_t ctx, assuan_fd_t fd); +assuan_error_t assuan_receivefd (assuan_context_t ctx, assuan_fd_t *fd); +  /*-- assuan-util.c --*/  void assuan_set_malloc_hooks ( void *(*new_alloc_func)(size_t n),                                 void *(*new_realloc_func)(void *p, size_t n),                                 void (*new_free_func)(void*) ); +void assuan_set_io_hooks (assuan_io_hooks_t io_hooks);  void assuan_set_log_stream (assuan_context_t ctx, FILE *fp);  int assuan_set_error (assuan_context_t ctx, int err, const char *text);  void assuan_set_pointer (assuan_context_t ctx, void *pointer); @@ -545,14 +645,6 @@ void assuan_set_assuan_err_source (int errsource);  /*-- assuan-logging.c --*/ -/* Set the log level for general assuan commands.  0 is no logging at -   all, 1 is the standard logging and the default. Higher leveles may -   be defined in the future.  Passing a level of -1 will not change -   the current log level.  Returns previous log level.  Note, that -   this function is not thread-safe and should in general be used -   right at startup. */ -int assuan_set_assuan_log_level (int level); -  /* Set the stream to which assuan should log message not associated     with a context.  By default, this is stderr.  The default value     will be changed when the first log stream is associated with a @@ -574,6 +666,21 @@ void assuan_set_assuan_log_prefix (const char *text);     string, i.e. ""  */  const char *assuan_get_assuan_log_prefix (void); + +/*-- assuan-socket.c --*/ + +/* These are socket wrapper functions to support an emulation of Unix +   domain sockets on Windows W32.  */ +int assuan_sock_close (assuan_fd_t fd); +assuan_fd_t assuan_sock_new (int domain, int type, int proto); +int assuan_sock_connect (assuan_fd_t sockfd,  +                         struct sockaddr *addr, int addrlen); +int assuan_sock_bind (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen); +int assuan_sock_get_nonce (struct sockaddr *addr, int addrlen,  +                           assuan_sock_nonce_t *nonce); +int assuan_sock_check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce); + +  #ifdef __cplusplus  }  #endif diff --git a/assuan/mkerrors b/assuan/mkerrors index 28451f63..79ac23b6 100755 --- a/assuan/mkerrors +++ b/assuan/mkerrors @@ -31,6 +31,7 @@ cat <<EOF  #undef _ASSUAN_IN_LIBASSUAN /* undef to get all error codes. */  #include "assuan.h" +#include "assuan-defs.h"  /* If true the modern gpg-error style error codes are used in the     API. */ @@ -94,11 +95,8 @@ _assuan_error (int oldcode)          {          case 0: n = 16381; /*GPG_ERR_MISSING_ERRNO*/  break;          case EAGAIN: -          if (errno > 0 && errno < 4096) -            { -              n = (EAGAIN | (1 << 15));  -              break; -            } +          n = (6 | (1 << 15)); +          break;          default: n = 270;  /*GPG_ERR_ASS_READ_ERROR*/ break;          }        break; @@ -108,11 +106,8 @@ _assuan_error (int oldcode)          {          case 0: n = 16381; /*GPG_ERR_MISSING_ERRNO*/  break;          case EAGAIN: -          if (errno > 0 && errno < 4096) -            { -              n = (EAGAIN | (1 << 15));  -              break; -            } +          n = (6 | (1 << 15)); +          break;          default: n = 271;  /*GPG_ERR_ASS_WRITE_ERROR*/ break;          }        break; @@ -127,11 +122,8 @@ _assuan_error (int oldcode)            n = 16381; /*GPG_ERR_MISSING_ERRNO*/            break;          case ENOMEM: -          if (errno > 0 && errno < 4096) -            { -              n = (ENOMEM | (1 << 15)); -              break; -            } +          n = (86 | (1 << 15)); +          break;          default:              n = 16382; /*GPG_ERR_UNKNOWN_ERRNO*/            break; @@ -150,6 +142,23 @@ _assuan_error (int oldcode)  } +/* A small helper function to treat EAGAIN transparently to the +   caller.  */ +int +_assuan_error_is_eagain (assuan_error_t err) +{ +  if ((!err_source && err == ASSUAN_Read_Error && errno == EAGAIN) +      || (err_source && (err & ((1 << 24) - 1)) == (6 | (1 << 15)))) +    { +      /* Avoid spinning by sleeping for one tenth of a second.  */ +       _assuan_usleep (100000); +       return 1; +    } +  else +    return 0; +} +    +  /**   * assuan_strerror:   * @err:  Error code  diff --git a/src/debug.c b/src/debug.c index bf1ca18c..d529653a 100644 --- a/src/debug.c +++ b/src/debug.c @@ -145,8 +145,7 @@ debug_init (void)          fprintf (errfp, "gpgme_debug: level=%d\n", debug_level);  #ifdef HAVE_ASSUAN_H        assuan_set_assuan_log_prefix ("gpgme-assuan"); -      assuan_set_assuan_log_stream (errfp); -      assuan_set_assuan_log_level (debug_level >= 0? debug_level:0); +      assuan_set_assuan_log_stream (debug_level > 0 ? errfp : NULL);  #endif /* HAVE_ASSUAN_H*/      }    UNLOCK (debug_lock); diff --git a/src/version.c b/src/version.c index 879e2f3e..03d9e9ae 100644 --- a/src/version.c +++ b/src/version.c @@ -56,7 +56,6 @@ do_subsystem_inits (void)    _gpgme_sema_subsystem_init ();  #ifdef HAVE_ASSUAN_H -  assuan_set_assuan_log_level (0);    assuan_set_assuan_err_source (GPG_ERR_SOURCE_GPGME);  #endif /*HAVE_ASSUAN_H*/    _gpgme_debug_subsystem_init (); | 
