+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.
* 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
* 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>
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)
}
-/* Function returns an Assuan error. */
+/* Function returns an Assuan error. */
assuan_error_t
_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)
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);
}
{
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
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
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;
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)
{
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
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);
}
{
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);
{
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
}
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
}
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,
* 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>
*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;
* 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
#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)
/* 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; */
/* 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
{
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() */
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
} inbound;
struct {
- int fd;
+ assuan_fd_t fd;
struct {
FILE *fp;
char line[LINELENGTH];
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. */
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;
/* 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;
/*-- 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)
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);
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. */
#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*/
/* 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.
*
* 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
{
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
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)
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)
{
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
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
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;
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));
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);
}
{ "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 }
};
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)
{
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;
}
}
if (!s)
- return set_error (ctx, Unknown_Command, NULL);
+ return PROCESS_DONE (ctx, set_error (ctx, Unknown_Command, NULL));
line += shift;
linelen -= shift;
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");
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:"");
{
/* 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,
}
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
}
-/**
- * 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
**/
int
assuan_get_active_fds (assuan_context_t ctx, int what,
- int *fdarray, int fdarraysize)
+ assuan_fd_t *fdarray, int fdarraysize)
{
int n = 0;
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
/* 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.
*
* 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>
\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
{
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;
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;
+}
/* 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
#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
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
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 ())
}
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
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
+ }
+}
+
* 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>
-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;
}
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;
}
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;
}
* 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)
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 ();
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
{
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);
_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
/* 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.
*
* 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
#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
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)
{
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);
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;
#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;
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
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;
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);
}
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);
}
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. */
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;
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. */
))
{
_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);
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);
}
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);
}
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);
}
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
#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);
}
* 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>
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;
#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) )
_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];
{
if (ctx)
{
+ _assuan_inquire_release (ctx);
xfree (ctx->hello_line);
xfree (ctx->okay_line);
xfree (ctx->cmdtbl);
* 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;
}
/* 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;
/* 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;
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);
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));
/* 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.
*
* 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
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);
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;
}
/* 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);
}
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;
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)
*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;
+}
* 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);
}
-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);
+}
* 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 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);
#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. */
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*/
}
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;
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;
* 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 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),
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)
{
switch (flag)
{
case ASSUAN_NO_WAITPID: ctx->flags.no_waitpid = value; break;
+ case ASSUAN_CONFIDENTIAL: ctx->confidential = value; break;
}
}
switch (flag)
{
case ASSUAN_NO_WAITPID: return ctx->flags.no_waitpid;
+ case ASSUAN_CONFIDENTIAL: return ctx->confidential;
}
return 0;
}
-
/* 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.
*
* 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:
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
_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)
#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)
#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)
#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)
_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)
#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*/
#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*/
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;
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,
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);
/* 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);
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,
/*-- 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
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);
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);
/* 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);
/*-- 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
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
#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. */
{
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;
{
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;
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;
}
+/* 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
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);
_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 ();