assuan/
authorMarcus Brinkmann <mb@g10code.com>
Fri, 6 Mar 2009 22:29:49 +0000 (22:29 +0000)
committerMarcus Brinkmann <mb@g10code.com>
Fri, 6 Mar 2009 22:29:49 +0000 (22:29 +0000)
2009-03-06  Marcus Brinkmann  <marcus@g10code.de>

* assuan/: Update to libassuan SVN 2009-03-06.

src/
2009-03-06  Marcus Brinkmann  <marcus@g10code.de>

* version.c (do_subsystem_inits): Do not set assuan log level.
* debug.c (debug_init): Likewise.

22 files changed:
ChangeLog
assuan/ChangeLog
assuan/assuan-buffer.c
assuan/assuan-client.c
assuan/assuan-connect.c
assuan/assuan-defs.h
assuan/assuan-handler.c
assuan/assuan-inquire.c
assuan/assuan-io.c
assuan/assuan-listen.c
assuan/assuan-logging.c
assuan/assuan-pipe-connect.c
assuan/assuan-pipe-server.c
assuan/assuan-socket-connect.c
assuan/assuan-socket-server.c
assuan/assuan-socket.c
assuan/assuan-uds.c
assuan/assuan-util.c
assuan/assuan.h
assuan/mkerrors
src/debug.c
src/version.c

index 40966da..fecb981 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2009-03-06  Marcus Brinkmann  <marcus@g10code.de>
+
+       * assuan/: Update to libassuan SVN 2009-03-06.
+
 2009-01-26  Werner Koch  <wk@g10code.com>
 
        * configure.ac (AC_CONFIG_FILES): Add tests/opassuan/Makefile.
index e620d20..3d875fb 100644 (file)
        * assuan-buffer.c (assuan_send_data): Add hack to optionally send
        a final "CAN".
 
-2008-11-03  Marcus Brinkmann  <marcus@g10code.com>
+2008-11-03  Marcus Brinkmann  <marcus@g10code.de>
 
-       * 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  <marcus@g10code.de>
+2008-10-29  Marcus Brinkmann  <marcus@g10code.de>
 
-       * 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  <marcus@g10code.de>
+2008-10-15  Werner Koch  <wk@g10code.com>
 
-       * 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  <wk@g10code.com>
+2008-09-01  Werner Koch  <wk@g10code.com>
 
-       * 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  <marcus@g10code.de>
+2008-03-25  Marcus Brinkmann  <marcus@g10code.de>
 
-       * 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  <marcus@g10code.de>
+
+       * 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  <marcus@g10code.de>
+
+       * assuan-inquire.c (_assuan_inquire_ext_cb): Pass through return
+       value from callback function.
+       Suggested by Ben Kibbey <bjk@luxsci.net>.
+
+2007-11-14  Werner Koch  <wk@g10code.com>
+
+       * 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  <marcus@g10code.de>
+
+       * assuan-inquire.c (_assuan_inquire_ext_cb): Clear
+       CTX->inquire_membuf after deallocating it.
+
+2007-10-18  Marcus Brinkmann  <marcus@g10code.de>
+
+       * assuan-handler.c (std_handler_help): New function.
+       (std_cmd_table): Add new command HELP.
+
+2007-10-08  Werner Koch  <wk@g10code.com>
+
+       * 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  <marcus@g10code.de>
+
+       * 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  <wk@g10code.com>
+
+       * 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  <marcus@g10code.de>
+
+       * 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  <wk@g10code.com>
+
+       * mkerrors: Map EAGAIN to GPG_ERR_EAGAIN for read and write
+       errors. 
+
+2007-10-02  Werner Koch  <wk@g10code.com>
+
+       * 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  <wk@g10code.com>
+
+       * 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  <wk@g10code.com>
 
        * assuan.h (_assuan_gpg_strerror_r, _assuan_gpg_strsource): Add
-       new wrappers.
+       wrappers for these new internal functions.
+
+2007-09-24  Marcus Brinkmann  <marcus@g10code.de>
+
+       * 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  <marcus@g10code.de>
+
+       * 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  <wk@g10code.com>
+
+       * assuan-socket.c (_assuan_close): Add inactive debug outputs.
+
+2007-09-11  Marcus Brinkmann  <marcus@g10code.de>
+
+       * assuan.h: Use _WIN32 instead of HAVE_W32_SYSTEM.
+
+2007-09-07  Marcus Brinkmann  <marcus@g10code.de>
+
+       * 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  <marcus@g10code.de>
+
+       * assuan-handler.c (dispatch_command): Return non-critical errors
+       with PROCESS_DONE ().
+
+2007-09-03  Marcus Brinkmann  <marcus@g10code.de>
+
+       * assuan.h [_ASSUAN_EXT_SYM_PREFIX]: Add missing symbol renames
+       with _ASSUAN_PREFIX.
 
 2007-09-03  Marcus Brinkmann  <marcus@g10code.de>
 
        * assuan.h [_ASSUAN_EXT_SYM_PREFIX]: Add missing symbol renames
        with _ASSUAN_PREFIX.
 
-2007-08-02  Werner Koch  <wk@g10code.com>
+       * 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  <wk@g10code.com>
 
-2007-07-12  Werner Koch  <wk@g10code.com>
+       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  <marcus@g10code.de>
 
-       * 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  <wk@g10code.com>
 
+       * 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  <marcus@g10code.de>
 
-       * 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  <wk@g10code.com>
+
+       * 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  <marcus@g10code.de>
 
        Change _WIN32 to HAVE_W32_SYSTEM for consistency.
        to silence gcc warning.
        * assuan-inquire.c (assuan_inquire): Likewise.
 
-2005-08-19  Werner Koch  <wk@g10code.com>
+2005-09-08  Marcus Brinkmann  <marcus@g10code.com>
 
-       * 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  <wk@g10code.com>
 
-       * 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  <wk@g10code.com>
+
+       * 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  <wk@g10code.com>
+
+       * assuan-util.c (_assuan_calloc): Avoid integer overflow.
+
+2005-03-22  Werner Koch  <wk@g10code.com>
+
+       * 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  <wk@g10code.com>
+
+       * assuan-client.c (assuan_transact): Handle empty and comment
+       commands correctly.
+
+2004-12-20  Werner Koch  <wk@g10code.com>
+
+       * assuan-socket-connect.c (assuan_socket_connect) [W32]: Allow for
+       a drive letter in the path.
+
+2004-12-19  Werner Koch  <wk@g10code.com>
+
+       * assuan-pipe-server.c (assuan_init_pipe_server) [W32]: Map file
+       descriptors using _get_osfhandle.
+
+2004-12-19  Moritz Schulte  <moritz@g10code.com>
+
+       * assuan-pipe-connect.c (assuan_pipe_connect2): Removed "`"
+       character at beginning of line 532.
+
+2004-12-18  Werner Koch  <wk@g10code.com>
+
        * assuan-logging.c (_assuan_w32_strerror): New. 
        * assuan-defs.h (w32_strerror): new.
        * assuan-pipe-connect.c (assuan_pipe_connect2, fix_signals):
        (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  <twoaday@g10code.com> (ported from libassuan by wk)
+2004-12-14  Werner Koch  <wk@g10code.com>
+
+       * assuan-socket-connect.c (assuan_socket_connect): Always allow
+       NAME to start with a froward slash.
+
+2004-12-07  Werner Koch  <wk@g10code.com>
+
+       * 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  <wk@g10code.com>
+
+       * assuan-socket.c: Include sys/types.h.  Noted by Michael
+       Nottebrock.
+
+2004-11-26  Werner Koch  <wk@g10code.com>
+
+       * assuan-io.c [_WIN32]: Avoid warnings about unknown pragmas.
+
+2004-11-24  Werner Koch  <wk@g10code.com>
+
+       * 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  <twoaday@g10code.com>
+
+       * 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  <wk@g10code.com>
+
+       * assuan-handler.c (assuan_write_status): Return an error code.
+
+2004-11-22  Timo Schulz  <twoaday@g10code.com>
+
        * 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  <wk@g10code.com>
 
-2005-03-22  Werner Koch  <wk@g10code.com>
+       * 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  <wk@g10code.com>
+
+       * 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  <marcus@g10code.de>
+2004-06-23  Marcus Brinkmann  <marcus@g10code.de>
 
-       * 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  <marcus@g10code.de>
+2004-05-11  Werner Koch  <wk@gnupg.org>
 
-       * 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  <marcus@g10code.de>
+       * 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  <wk@gnupg.org>
 
-       * assuan-handler.c: Include <errno.h>.
+       * assuan-socket-connect.c: Include string.h.
+       * assuan-logging.c: Ditto.
 
-2004-06-08  Marcus Brinkmann  <marcus@g10code.de>
+2004-04-22  Marcus Brinkmann  <marcus@g10code.de>
 
-       * 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  <wk@gnupg.org>
 
        * 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
index 31f3394..b9e3572 100644 (file)
@@ -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,
index 7b3d266..15f4f1c 100644 (file)
@@ -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;
index b50b17b..2106ac3 100644 (file)
@@ -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)
index b1d9f3e..e2d0f52 100644 (file)
@@ -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.
  *
 #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*/
index d1b29cf..b940bfd 100644 (file)
@@ -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>
 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);
 }
 
-
-
 \f
-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;
+}
+
+
+\f
+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
index d8c52d0..58b9f02 100644 (file)
@@ -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
 
 
 \f
-/* 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;
 }
 
+\f
+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;
+}
index a7f8449..8d4cbb8 100644 (file)
@@ -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.
  *
  * 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
+    }
+}
+
index 04db68c..2ef9334 100644 (file)
@@ -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;
 }
 
index 41ada91..2ebd667 100644 (file)
@@ -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
 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
index e355532..7fdfe74 100644 (file)
@@ -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);
 }
 
index 1b47def..7040414 100644 (file)
@@ -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);
index 5953f1c..8eb6d82 100644 (file)
@@ -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>
 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));
index 5c46164..c536dba 100644 (file)
@@ -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>
 
 #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;
+}
index 5566fde..02a6225 100644 (file)
  * 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.  */
 # 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);
+}
index 70ec8cc..02f77a5 100644 (file)
@@ -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;
index d12277f..cefefcb 100644 (file)
@@ -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;
 }
 
-
index 6df0166..0e5c741 100644 (file)
@@ -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
 #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
index 28451f6..79ac23b 100755 (executable)
@@ -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 
index bf1ca18..d529653 100644 (file)
@@ -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);
index 879e2f3..03d9e9a 100644 (file)
@@ -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 ();