aboutsummaryrefslogtreecommitdiffstats
path: root/branches/gpgme-1-0-branch/assuan
diff options
context:
space:
mode:
Diffstat (limited to 'branches/gpgme-1-0-branch/assuan')
-rw-r--r--branches/gpgme-1-0-branch/assuan/ChangeLog510
-rw-r--r--branches/gpgme-1-0-branch/assuan/Makefile.am53
-rw-r--r--branches/gpgme-1-0-branch/assuan/README.1st25
-rw-r--r--branches/gpgme-1-0-branch/assuan/assuan-buffer.c451
-rw-r--r--branches/gpgme-1-0-branch/assuan/assuan-client.c225
-rw-r--r--branches/gpgme-1-0-branch/assuan/assuan-connect.c54
-rw-r--r--branches/gpgme-1-0-branch/assuan/assuan-defs.h194
-rw-r--r--branches/gpgme-1-0-branch/assuan/assuan-domain-connect.c476
-rw-r--r--branches/gpgme-1-0-branch/assuan/assuan-domain-server.c46
-rw-r--r--branches/gpgme-1-0-branch/assuan/assuan-handler.c691
-rw-r--r--branches/gpgme-1-0-branch/assuan/assuan-inquire.c240
-rw-r--r--branches/gpgme-1-0-branch/assuan/assuan-io.c58
-rw-r--r--branches/gpgme-1-0-branch/assuan/assuan-listen.c132
-rw-r--r--branches/gpgme-1-0-branch/assuan/assuan-logging.c42
-rw-r--r--branches/gpgme-1-0-branch/assuan/assuan-pipe-connect.c285
-rw-r--r--branches/gpgme-1-0-branch/assuan/assuan-pipe-server.c129
-rw-r--r--branches/gpgme-1-0-branch/assuan/assuan-socket-connect.c138
-rw-r--r--branches/gpgme-1-0-branch/assuan/assuan-socket-server.c175
-rw-r--r--branches/gpgme-1-0-branch/assuan/assuan-util.c219
-rw-r--r--branches/gpgme-1-0-branch/assuan/assuan.h394
-rwxr-xr-xbranches/gpgme-1-0-branch/assuan/mkerrors82
21 files changed, 4619 insertions, 0 deletions
diff --git a/branches/gpgme-1-0-branch/assuan/ChangeLog b/branches/gpgme-1-0-branch/assuan/ChangeLog
new file mode 100644
index 00000000..f740e95e
--- /dev/null
+++ b/branches/gpgme-1-0-branch/assuan/ChangeLog
@@ -0,0 +1,510 @@
+2004-06-23 Marcus Brinkmann <[email protected]>
+
+ * assuan-domain-connect.c [HAVE_SYS_UIO_H]: Include <sys/uio.h>.
+
+ * assuan-handler.c: Include <errno.h>.
+
+2004-06-08 Marcus Brinkmann <[email protected]>
+
+ * assuan-buffer.c (assuan_write_line): If the line is longer than
+ the maximum line length, bail out early.
+
+2004-04-19 Werner Koch <[email protected]>
+
+ * assuan-socket-connect.c: Include sys/types.h
+ * assuan-socket-server.c: Ditto
+ * assuan-domain-connect.c: Ditto.
+
+2004-02-18 Werner Koch <[email protected]>
+
+ * assuan-handler.c (assuan_get_data_fp): Fail with ENOSYS if we
+ can't implement this.
+
+2004-02-13 Werner Koch <[email protected]>
+
+ * assuan-domain-connect.c: Removed the unneeded alloca.h
+
+2003-08-13 Werner Koch <[email protected]>
+
+ * assuan-inquire.c (assuan_inquire): Increase length of cmdbuf to
+ the Assuan limit.
+
+2003-06-24 Werner Koch <[email protected]>
+
+ * mkerrors: Kludge to print libgpg-error values in an easier
+ readable way.
+
+2003-04-29 Werner Koch <[email protected]>
+
+ * libassuan.m4: New. Based on libgrypt.m4.
+ * Makefile.am (m4data_DATA): New.
+
+ * assuan.h (AssuanCommand): Removed.
+
+ * assuan-handler.c: Remove the cmd_id element,
+ (assuan_register_command): Likewise. Note that semantics changed.
+ (_assuan_register_std_commands): Adjusted.
+
+2003-02-22 Neal H. Walfield <[email protected]>
+
+ * Makefile.am (bin_SCRIPTS): Renamed from bin_PROGRAMS.
+
+2003-02-18 Neal H. Walfield <[email protected]>
+
+ * Makefile.am (libassuan_a_LIBADD): New variable.
+ * funopen.c: Move from ../common.
+ * isascii.c: Likewise.
+ * memrchr.c: Likewise.
+ * putc_unlocked.c: Likewise.
+
+2003-02-18 Neal H. Walfield <[email protected]>
+
+ * assuan-handler.c (_IO_cookie_io_functions_t): Remove.
+ (cookie_io_functions_t): Remove.
+ (fopencookie): Remove prototype.
+ (assuan_get_data_fp): Use funopen, not fopencookie.
+
+2003-02-18 Neal H. Walfield <[email protected]>
+
+ * libassuan-config.in: New file.
+ * Makefile.am (bin_PROGRAMS): New variable.
+
+2003-02-17 Neal H. Walfield <[email protected]>
+
+ * .cvsignore: New file.
+
+2003-02-17 Neal H. Walfield <[email protected]>
+
+ * Makefile.am (lib_LIBRARIES): Use this instead of . . .
+ (noinst_LIBRARIES): . . . this.
+ (include_HEADERS): New variable.
+ (libassuan_a_SOURCES): Remove assuan.h, add assuan-logging.c.
+
+ * assuan.h (assuan_set_assuan_log_stream): New prototype.
+ (assuan_get_assuan_log_stream): Likewise.
+ (assuan_get_assuan_log_prefix): Likewise.
+ * assuan-logging.c: New file.
+
+ * assuan-buffer.c [HAVE_JNLIB_LOGGIN]: Do not include
+ "../jnlib/logging.h".
+ (my_log_prefix): Remove function.
+ (_assuan_read_line): Use assuan_get_assuan_log_prefix in lieu of
+ my_log_prefix.
+ (assuan_write_line): Likewise.
+ (_assuan_cookie_write_data): Likewise.
+ (_assuan_cookie_write_flush): Likewise.
+ * assuan-domain-connect.c (LOGERROR, LOGERROR1, LOGERROR2,
+ LOGERRORX): Remove.
+ (LOG): New macro.
+ (domain_reader): Use it.
+ (domain_writer): Likewise.
+ (domain_sendfd): Likewise.
+ (domain_receivefd): Likewise.
+ (_assuan_domain_init): Likewise.
+ (assuan_domain_connect): Likewise.
+ * assuan-pipe-connect.c [HAVE_JNLIB_LOGGIN]: Do not include
+ "../jnlib/logging.h".
+ (LOGERROR, LOGERROR1, LOGERROR2, LOGERRORX): Remove.
+ (LOG): New macro.
+ (assuan_pipe_connect): Use it.
+ * assuan-socket-connect.c [HAVE_JNLIB_LOGGIN]: Do not include
+ "../jnlib/logging.h".
+ (LOGERROR, LOGERROR1, LOGERROR2, LOGERRORX): Remove.
+ (LOG): New macro.
+ (assuan_socket_connect): Use it.
+ (socket_reader): Remove dead code.
+ (socket_writer): Likewise.
+ * assuan-util.c [HAVE_JNLIB_LOGGIN]: Do not include
+ "../jnlib/logging.h".
+ (_assuan_log_sanitized_string): Use assuan_get_assuan_log_stream,
+ not jnlib.
+
+2002-11-24 Neal H. Walfield <[email protected]>
+
+ * assuan.h (assuan_command_parse_fd): New prototype.
+ * assuan-handler.c (assuan_command_parse_fd): Rename from
+ parse_cmd_input_output. Export.
+ (std_handler_input): Update to use assuan_command_parse_fd.
+ (std_handler_output): Likewise.
+
+2002-11-24 Neal H. Walfield <[email protected]>
+
+ * assuan.h (assuan_sendfd): New prototype.
+ (assuan_receivefd): New prototype.
+ * assuan-buffer.c (assuan_sendfd): New function.
+ (assuan_receivefd): New function.
+ * assuan-handler.c (parse_cmd_input_output): Recognize incoming
+ file descriptors and act appropriately.
+ * assuan-defs.h (struct assuan_io): Add fields sendfd and
+ receivefd.
+ (struct assuan_context_s): Add fields pendingfds and
+ pendingfdscount.
+ * assuan-pipe-server.c (_assuan_new_context): Update IO to reflect
+ new features.
+ * assuan-domain-connect.c (do_deinit): Cleanup any unreceived file
+ descriptors.
+ (domain_reader): Receive file descriptors.
+ (domain_sendfd): New function.
+ (domain_receivefd): New function.
+ (_assuan_domain_init): Update initialization code to reflect new
+ features.
+
+2002-11-24 Neal H. Walfield <[email protected]>
+
+ * assuan-domain-connect.c (do_finish): Remove.
+ (_assuan_domain_init): Use default handlers where possible.
+ Add an assert and update comments.
+ * assuan-domain-server.c (accept_connection): Remove.
+ (assuan_init_domain_server): Use default handlers where possible.
+ Put the server in pipe mode: it can only be used by a single
+ client.
+
+2002-11-24 Neal H. Walfield <[email protected]>
+
+ * assuan.h: Add prototype for assuan_domain_connect and
+ assuan_init_domain_server.
+ * assuan-defs.h: Include <unistd.h>.
+ Add prototype for _assuan_domain_init.
+ * assuan-domain-connect.c: New file.
+ * assuan-domain-server.c: New file.
+ * Makefile.am (libassuan_a_SOURCES): Add assuan-domain-connect.c
+ and assuan-domain-server.c
+
+2002-11-23 Neal H. Walfield <[email protected]>
+
+ * Makefile.am (libassuan_a_SOURCES): Add assuan-io.c.
+ * assuan-io.c: Restore.
+ (_assuan_simple_read): Rename from _assuan_read.
+ (_assuan_simple_write): Rename from _assuan_write.
+ * assuan-defs.h (_assuan_simple_read): New prototype.
+ (_assuan_simple_write): Likewise.
+ * assuan-pipe-server.c (pipe_reader): Remove.
+ (pipe_writer): Remove.
+ (_assuan_new_context): Initialize IO is with _assuan_simple_read
+ and _assuan_simple_write.
+ * assuan-socket-connect.c (socket_reader): Remove.
+ (socket_writer): Remove.
+ (assuan_socket_connect): Initialize IO is with _assuan_simple_read
+ and _assuan_simple_write.
+ * assuan-socket-server.c (io): New local variable.
+ (assuan_init_socket_server): Initialize CTX->io.
+ (assuan_init_connected_socket_server): Likewise.
+
+2002-11-23 Neal H. Walfield <[email protected]>
+
+ * assuan-buffer.c (readline): Use memrchr.
+ (_assuan_read_line): Rewritten to use the string functions.
+
+2002-11-20 Neal H. Walfield <[email protected]>
+
+ * assuan-socket-connect.c (assuan_socket_connect): Pass PF_LOCAL
+ to socket(), not AF_UNIX: it expects a PF_* macro and the former
+ is more portable.
+ (assuan_socket_connect): Use AF_LOCAL, not AF_UNIX which is more
+ POSIXy.
+
+2002-11-20 Neal H. Walfield <[email protected]>
+
+ * assuan-defs.h (struct assuan_io): New structure.
+ (struct assuan_context_s): New field, io.
+ (_assuan_read): Depreciated.
+ (_assuan_write): Likewise.
+ * assuan-pipe-server.c: Include <unistd.h>.
+ (pipe_reader): New function.
+ (pipe_writer): Likewise.
+ (_assuan_new_context.IO): New local static. Set to pipe_reader
+ and pipe_writer. Use it to initialize new context.
+ * assuan-socket-connect.c (socket_reader): New function.
+ (socket_writer): New function.
+ (assuan_socket_connect.IO): New local static. Set to socket_reader
+ and socket_writer. Use it to initialize new context.
+ * assuan-buffer.c (writen): Take an ASSUAN_CONTEXT rather than a
+ file descriptor. Do not use _assuan_write but the write method
+ in the supplied context.
+ (readline): Likewise for _assuan_read.
+ (assuan_write_line): When calling writen, pass CTX; not the file
+ descriptor directly.
+ (_assuan_cookie_write_data): Likewise.
+ (_assuan_cookie_write_flush): Likewise.
+ (_assuan_read_line): Likewise for readline.
+ * Makefile.am (libassuan_a_SOURCES): Remove assuan-io.c.
+ * assuan-io.c: Removed.
+
+2002-11-10 Werner Koch <[email protected]>
+
+ * assuan-pipe-connect.c (assuan_pipe_connect): Changed the order
+ of the dups to handle cases where we have already used fd 2 for
+ other things.
+
+2002-10-31 Neal H. Walfield <[email protected]>
+
+ * assuan-util.c: Include <ctype.h>.
+ (_assuan_log_print_buffer): Elide the magic numbers preferring the
+ standard isfoo functions. Use putc_unlocked where possible.
+ (_assuan_log_sanitized_string): Rewrite to use putc_unlocked and
+ the isfoo functions.
+
+2002-09-05 Neal H. Walfield <[email protected]>
+
+ * assuan-defs.h (_assuan_read_wrapper): Depreciated.
+ * assuan-util.c (_assuan_read_wrapper): Removed.
+ * assuan-defs.h (_assuan_write_wrapper): Depreciated.
+ * assuan-util.c (_assuan_write_wrapper): Removed.
+ * assuan.h (assuan_set_io_fun): Depreciated.
+ * assuan-util.c (assuan_set_io_fun): Removed.
+
+ * assuan-defs.h (_assuan_read): New function.
+ (_assuan_write): Likewise.
+ * assuan-io.c: New file.
+
+ * assuan-buffer.c (writen): Use _assuan_write rather than doing
+ the work here.
+ (readline): Likewise for _assuan_read.
+
+ * Makefile.am (libassuan_a_SOURCES): Add assuan-io.c.
+
+2002-08-16 Werner Koch <[email protected]>
+
+ * assuan.h: Renamed Bad_Certificate_Path to Bad_Certificate_Chain.
+
+2002-07-30 Werner Koch <[email protected]>
+
+ Changed the license from GPL to LGPL.
+
+2002-07-23 Werner Koch <[email protected]>
+
+ * assuan-handler.c (_IO_cookie_io_functions_t): Define it here if
+ it does not exists.
+
+2002-06-27 Werner Koch <[email protected]>
+
+ * assuan-pipe-connect.c (assuan_pipe_connect): No special handling
+ for the log_fd and stderr. Connect stderr to /dev/null if it
+ should not be retained.
+
+2002-06-26 Werner Koch <[email protected]>
+
+ * assuan-buffer.c (assuan_write_line): Make sure we never
+ accidently print an extra LF.
+
+2002-05-23 Werner Koch <[email protected]>
+
+ * assuan-util.c (assuan_set_io_func): New.
+ * assuan-buffer.c (writen, readline): Use the new functions
+ instead of pth.
+ * assuan-socket-server.c (accept_connection): Don't use the
+ pth_accept - using the assuan included accept code would be a bad
+ idea within Pth so we don't need a replacement function.
+
+2002-05-22 Werner Koch <[email protected]>
+
+ * assuan-socket-server.c (assuan_init_connected_socket_server): New.
+ (accept_connection): Factored most code out to..
+ (accept_connection_bottom): .. new function.
+
+2002-04-04 Werner Koch <[email protected]>
+
+ * assuan-buffer.c (my_log_prefix): New. Use it for all i/o debug
+ output.
+
+2002-03-06 Werner Koch <[email protected]>
+
+ * assuan-client.c (_assuan_read_from_server): Detect END.
+ (assuan_transact): Pass it to the data callback.
+
+2002-02-27 Werner Koch <[email protected]>
+
+ * assuan-client.c (assuan_transact): Add 2 more arguments to
+ support status lines. Passing NULL yields the old behaviour.
+
+ * assuan-handler.c (process_request): Flush data lines send
+ without using the data fp.
+
+2002-02-14 Werner Koch <[email protected]>
+
+ * assuan-inquire.c (assuan_inquire): Check for a cancel command
+ and return ASSUAN_Canceled. Allow for non-data inquiry.
+
+ * assuan.h: Add a few token specific error codes.
+
+2002-02-13 Werner Koch <[email protected]>
+
+ * assuan-defs.h (assuan_context_s): New var CLIENT_PID.
+ * assuan-pipe-server.c (_assuan_new_context): set default value.
+ * assuan-socket-server.c (accept_connection): get the actual pid.
+
+2002-02-12 Werner Koch <[email protected]>
+
+ * assuan-buffer.c (writen,readline) [USE_GNU_PT]: Use pth_read/write.
+ * assuan-socket-server.c (accept_connection) [USE_GNU_PTH]: Ditto.
+
+2002-02-01 Marcus Brinkmann <[email protected]>
+
+ * Makefile.am (MOSTLYCLEANFILES): New variable.
+
+2002-01-23 Werner Koch <[email protected]>
+
+ * assuan-socket-connect.c (LOGERRORX): and removed typo.
+
+2002-01-22 Marcus Brinkmann <[email protected]>
+
+ * assuan-socket-connect.c (LOGERRORX): Reverse arguments to fputs.
+
+2002-01-21 Werner Koch <[email protected]>
+
+ * assuan-connect.c: Move all except assuan_get_pid to...
+ * assuan-pipe-connect.c: this.
+ (assuan_pipe_disconnect): Removed.
+ (do_finish, do_deinit): New
+ (assuan_pipe_connect): and set them into the context.
+ * assuan-socket-connect.c: New.
+
+ * assuan-util.c (_assuan_log_sanitized_string): New.
+
+ * assuan-pipe-server.c (assuan_init_pipe_server): Factored most
+ code out to ...
+ (_assuan_new_context): new func.
+ (_assuan_release_context): New
+ * assuan-connect.c (assuan_pipe_connect): Use the new functions.
+
+2002-01-20 Werner Koch <[email protected]>
+
+ * assuan.h: Added Invalid Option error code.
+
+ * assuan-handler.c (std_handler_option): New.
+ (std_cmd_tbl): Add OPTION as standard command.
+ (assuan_register_option_handler): New.
+ (dispatch_command): Use case insensitive matching as a fallback.
+ (my_strcasecmp): New.
+
+2002-01-19 Werner Koch <[email protected]>
+
+ * assuan-buffer.c (_assuan_read_line): Add output logging.
+ (assuan_write_line): Ditto.
+ (_assuan_cookie_write_data): Ditto.
+ (_assuan_cookie_write_flush): Ditto.
+ * assuan-util.c (_assuan_log_print_buffer): New.
+ (assuan_set_log_stream): New.
+ (assuan_begin_confidential): New.
+ (assuan_end_confidential): New.
+
+ * assuan-defs.h: Add a few handler variables.
+ * assuan-pipe-server.c (assuan_deinit_pipe_server): Removed.
+ (deinit_pipe_server): New.
+ (assuan_deinit_server): New. Changed all callers to use this.
+ * assuan-listen.c (assuan_accept): Use the accept handler.
+ * assuan-handler.c (process_request): Use the close Handler.
+ * assuan-socket-server.c: New.
+
+2002-01-14 Werner Koch <[email protected]>
+
+ * assuan-client.c (_assuan_read_from_server): Skip spaces after
+ the keyword.
+
+2002-01-03 Werner Koch <[email protected]>
+
+ * assuan-handler.c (assuan_set_okay_line): New.
+ (process_request): And use it here.
+
+2002-01-02 Werner Koch <[email protected]>
+
+ * assuan-inquire.c (init_membuf,put_membuf,get_membuf): Apply a
+ hidden 0 behind the buffer so that the buffer can be used as a
+ string in certain contexts.
+
+2001-12-14 Marcus Brinkmann <[email protected]>
+
+ * assuan-connect.c (assuan_pipe_connect): New argument
+ FD_CHILD_LIST. Don't close those fds.
+ * assuan.h: Likewise for prototype.
+
+2001-12-14 Werner Koch <[email protected]>
+
+ * assuan-listen.c (assuan_close_input_fd): New.
+ (assuan_close_output_fd): New.
+ * assuan-handler.c (std_handler_reset): Always close them after a
+ reset command.
+ (std_handler_bye): Likewise.
+
+2001-12-14 Marcus Brinkmann <[email protected]>
+
+ * assuan-buffer.c (_assuan_read_line): New variable ATTICLEN, use
+ it to save the length of the attic line.
+ Rediddle the code a bit to make it more clear what happens.
+
+2001-12-14 Marcus Brinkmann <[email protected]>
+
+ * assuan-defs.h (LINELENGTH): Define as ASSUAN_LINELENGTH.
+ assuan.h: Define ASSUAN_LINELENGTH.
+
+2001-12-13 Marcus Brinkmann <[email protected]>
+
+ * assuan-buffer.c (assuan_read_line): Fix order of execution to
+ get correct return values.
+
+2001-12-13 Werner Koch <[email protected]>
+
+ * assuan-handler.c (assuan_get_active_fds): Fixed silly bug,
+ pretty obvious that nobody ever tested this function.
+
+2001-12-12 Werner Koch <[email protected]>
+
+ * assuan-connect.c (assuan_pipe_connect): Implemented the inital
+ handshake.
+ * assuan-client.c (read_from_server): Renamed to
+ (_assuan_read_from_server): this and made external.
+
+ * assuan-listen.c (assuan_set_hello_line): New.
+ (assuan_accept): Use a custom hello line is available.
+
+ * assuan-buffer.c (assuan_read_line): New.
+ (assuan_pending_line): New.
+ (_assuan_write_line): Renamed to ..
+ (assuan_write_line): this, made public and changed all callers.
+
+2001-12-04 Werner Koch <[email protected]>
+
+ * assuan-connect.c (assuan_pipe_connect): Add more error reporting.
+ * assuan-client.c: New.
+
+ * assuan-inquire.c: New.
+ * assuan-handler.c (process_request): Check for nested invocations.
+
+2001-11-27 Werner Koch <[email protected]>
+
+ * assuan-handler.c (assuan_register_input_notify): New.
+ (assuan_register_output_notify): New.
+
+2001-11-26 Werner Koch <[email protected]>
+
+ * assuan.h: Added more status codes.
+
+2001-11-25 Werner Koch <[email protected]>
+
+ * assuan-handler.c (assuan_register_bye_notify)
+ (assuan_register_reset_notify)
+ (assuan_register_cancel_notify): New and call them from the
+ standard handlers.
+ (assuan_process): Moved bulk of function to ..
+ (process_request): .. new.
+ (assuan_process_next): One shot version of above.
+ (assuan_get_active_fds): New.
+
+2001-11-24 Werner Koch <[email protected]>
+
+ * assuan-connect.c (assuan_get_pid): New.
+
+ * assuan-buffer.c (_assuan_read_line): Deal with reads of more
+ than a line.
+ * assuan-defs.h: Add space in the context for this.
+
+
+ Copyright 2001, 2002 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
+ modifications, as long as this notice is preserved.
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/branches/gpgme-1-0-branch/assuan/Makefile.am b/branches/gpgme-1-0-branch/assuan/Makefile.am
new file mode 100644
index 00000000..8c4d88cf
--- /dev/null
+++ b/branches/gpgme-1-0-branch/assuan/Makefile.am
@@ -0,0 +1,53 @@
+# Assuan Makefile
+# Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+#
+# This file is part of Assuan.
+#
+# Assuan is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+#
+# Assuan is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+
+## Process this file with automake to produce Makefile.in
+
+EXTRA_DIST = mkerrors
+INCLUDES = -I.. -I$(top_srcdir)/include
+BUILT_SOURCES = assuan-errors.c
+MOSTLYCLEANFILES = assuan-errors.c
+
+noinst_LTLIBRARIES = libassuan.la
+
+AM_CPPFLAGS = -D_ASSUAN_IN_GPGME_BUILD_ASSUAN
+
+#libassuan_la_LDFLAGS =
+libassuan_la_SOURCES = \
+ assuan.h \
+ assuan-defs.h \
+ assuan-util.c \
+ assuan-errors.c \
+ assuan-buffer.c \
+ assuan-handler.c \
+ assuan-inquire.c \
+ assuan-listen.c \
+ assuan-connect.c \
+ assuan-client.c \
+ assuan-pipe-server.c \
+ assuan-socket-server.c \
+ assuan-pipe-connect.c \
+ assuan-socket-connect.c \
+ assuan-io.c \
+ assuan-domain-connect.c \
+ assuan-domain-server.c \
+ assuan-logging.c
+
+assuan-errors.c : assuan.h
+ $(srcdir)/mkerrors < $(srcdir)/assuan.h > assuan-errors.c
diff --git a/branches/gpgme-1-0-branch/assuan/README.1st b/branches/gpgme-1-0-branch/assuan/README.1st
new file mode 100644
index 00000000..6e8d4ec8
--- /dev/null
+++ b/branches/gpgme-1-0-branch/assuan/README.1st
@@ -0,0 +1,25 @@
+This is a modified copy of the libassuan library. Don't modify it,
+but instead modify the original Assuan library and merge the changes
+back into this copy.
+
+The changes to the original libassuan, that have to preserved when
+updating this directory, are:
+
+* Makefile.am
+** Build the library with libtool as a convenience library, which can
+ be linked into the shared library GPGME.
+** Do not install the library or the header file.
+** Define -D_ASSUAN_IN_GPGME_BUILD_ASSUAN to wrap some POSIX functions
+ with ATH replacements.
+
+* assuan.h
+** Define _ASSUAN_IN_GPGME to enable GPGME specific code.
+** Put all exported Assuan functions in the _gpgme namespace.
+** Also wrap all system functions that are wrapped by GNU Pth to
+ _gpgme wrappers.
+
+* assuan-io.c
+** Don't try to support GNU Pth here.
+
+* assuan-pipe-connect.c
+** Do not install SIGPIPE signal handler here.
diff --git a/branches/gpgme-1-0-branch/assuan/assuan-buffer.c b/branches/gpgme-1-0-branch/assuan/assuan-buffer.c
new file mode 100644
index 00000000..01e77001
--- /dev/null
+++ b/branches/gpgme-1-0-branch/assuan/assuan-buffer.c
@@ -0,0 +1,451 @@
+/* assuan-buffer.c - read and send data
+ * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Assuan is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <assert.h>
+#include "assuan-defs.h"
+
+static int
+writen (ASSUAN_CONTEXT ctx, const char *buffer, size_t length)
+{
+ while (length)
+ {
+ ssize_t nwritten = ctx->io->write (ctx, buffer, length);
+
+ if (nwritten < 0)
+ {
+ if (errno == EINTR)
+ continue;
+ return -1; /* write error */
+ }
+ length -= nwritten;
+ buffer += nwritten;
+ }
+ return 0; /* okay */
+}
+
+/* Read an entire line. */
+static int
+readline (ASSUAN_CONTEXT ctx, char *buf, size_t buflen,
+ int *r_nread, int *eof)
+{
+ size_t nleft = buflen;
+ char *p;
+
+ *eof = 0;
+ *r_nread = 0;
+ while (nleft > 0)
+ {
+ ssize_t n = ctx->io->read (ctx, buf, nleft);
+
+ if (n < 0)
+ {
+ if (errno == EINTR)
+ continue;
+ return -1; /* read error */
+ }
+ else if (!n)
+ {
+ *eof = 1;
+ break; /* allow incomplete lines */
+ }
+ p = buf;
+ nleft -= n;
+ buf += n;
+ *r_nread += n;
+
+ p = memrchr (p, '\n', n);
+ if (p)
+ break; /* at least one full line available - that's enough for now */
+ }
+
+ return 0;
+}
+
+
+int
+_assuan_read_line (ASSUAN_CONTEXT ctx)
+{
+ char *line = ctx->inbound.line;
+ int nread, atticlen;
+ int rc;
+ char *endp = 0;
+
+ if (ctx->inbound.eof)
+ return -1;
+
+ atticlen = ctx->inbound.attic.linelen;
+ if (atticlen)
+ {
+ memcpy (line, ctx->inbound.attic.line, atticlen);
+ ctx->inbound.attic.linelen = 0;
+
+ endp = memchr (line, '\n', atticlen);
+ if (endp)
+ /* Found another line in the attic. */
+ {
+ rc = 0;
+ nread = atticlen;
+ atticlen = 0;
+ }
+ else
+ /* There is pending data but not a full line. */
+ {
+ assert (atticlen < LINELENGTH);
+ rc = readline (ctx, line + atticlen,
+ LINELENGTH - atticlen, &nread, &ctx->inbound.eof);
+ }
+ }
+ else
+ /* No pending data. */
+ rc = readline (ctx, line, LINELENGTH,
+ &nread, &ctx->inbound.eof);
+ if (rc)
+ {
+ if (ctx->log_fp)
+ fprintf (ctx->log_fp, "%s[%p] <- [Error: %s]\n",
+ assuan_get_assuan_log_prefix (), ctx, strerror (errno));
+ return ASSUAN_Read_Error;
+ }
+ if (!nread)
+ {
+ assert (ctx->inbound.eof);
+ if (ctx->log_fp)
+ fprintf (ctx->log_fp, "%s[%p] <- [EOF]\n",
+ assuan_get_assuan_log_prefix (), ctx);
+ return -1;
+ }
+
+ ctx->inbound.attic.pending = 0;
+ nread += atticlen;
+
+ if (! endp)
+ endp = memchr (line, '\n', nread);
+
+ if (endp)
+ {
+ int n = endp - line + 1;
+ if (n < nread)
+ /* LINE contains more than one line. We copy it to the attic
+ now as handlers are allowed to modify the passed
+ buffer. */
+ {
+ int len = nread - n;
+ memcpy (ctx->inbound.attic.line, endp + 1, len);
+ ctx->inbound.attic.pending = memrchr (endp + 1, '\n', len) ? 1 : 0;
+ ctx->inbound.attic.linelen = len;
+ }
+
+ if (endp != line && endp[-1] == '\r')
+ endp --;
+ *endp = 0;
+
+ ctx->inbound.linelen = endp - line;
+ if (ctx->log_fp)
+ {
+ fprintf (ctx->log_fp, "%s[%p] <- ",
+ assuan_get_assuan_log_prefix (), ctx);
+ if (ctx->confidential)
+ fputs ("[Confidential data not shown]", ctx->log_fp);
+ else
+ _assuan_log_print_buffer (ctx->log_fp,
+ ctx->inbound.line,
+ ctx->inbound.linelen);
+ putc ('\n', ctx->log_fp);
+ }
+ return 0;
+ }
+ else
+ {
+ if (ctx->log_fp)
+ fprintf (ctx->log_fp, "%s[%p] <- [Invalid line]\n",
+ assuan_get_assuan_log_prefix (), ctx);
+ *line = 0;
+ ctx->inbound.linelen = 0;
+ return ctx->inbound.eof ? ASSUAN_Line_Not_Terminated
+ : ASSUAN_Line_Too_Long;
+ }
+}
+
+
+/* Read the next line from the client or server and return a pointer
+ in *LINE to a buffer holding the line. LINELEN is the length of
+ *LINE. The buffer is valid until the next read operation on it.
+ The caller may modify the buffer. The buffer is invalid (i.e. must
+ not be used) if an error is returned.
+
+ Returns 0 on success or an assuan error code.
+ See also: assuan_pending_line().
+*/
+AssuanError
+assuan_read_line (ASSUAN_CONTEXT ctx, char **line, size_t *linelen)
+{
+ AssuanError err;
+
+ if (!ctx)
+ return ASSUAN_Invalid_Value;
+
+ err = _assuan_read_line (ctx);
+ *line = ctx->inbound.line;
+ *linelen = ctx->inbound.linelen;
+ return err;
+}
+
+
+/* Return true if a full line is buffered (i.e. an entire line may be
+ read without any I/O). */
+int
+assuan_pending_line (ASSUAN_CONTEXT ctx)
+{
+ return ctx && ctx->inbound.attic.pending;
+}
+
+
+AssuanError
+assuan_write_line (ASSUAN_CONTEXT ctx, const char *line)
+{
+ int rc;
+ size_t len;
+ const char *s;
+
+ if (!ctx)
+ return ASSUAN_Invalid_Value;
+
+ /* Make sure that we never take a LF from the user - this might
+ violate the protocol. */
+ s = strchr (line, '\n');
+ len = s? (s-line) : strlen (line);
+
+ if (len > LINELENGTH - 2)
+ return ASSUAN_Line_Too_Long;
+
+ /* fixme: we should do some kind of line buffering. */
+ if (ctx->log_fp)
+ {
+ fprintf (ctx->log_fp, "%s[%p] -> ",
+ assuan_get_assuan_log_prefix (), ctx);
+ if (s)
+ fputs ("[supplied line contained a LF]", ctx->log_fp);
+ if (ctx->confidential)
+ fputs ("[Confidential data not shown]", ctx->log_fp);
+ else
+ _assuan_log_print_buffer (ctx->log_fp, line, len);
+ putc ('\n', ctx->log_fp);
+ }
+
+ rc = writen (ctx, line, len);
+ if (rc)
+ rc = ASSUAN_Write_Error;
+ if (!rc)
+ {
+ rc = writen (ctx, "\n", 1);
+ if (rc)
+ rc = ASSUAN_Write_Error;
+ }
+
+ return rc;
+}
+
+
+
+/* Write out the data in buffer as datalines with line wrapping and
+ percent escaping. This fucntion is used for GNU's custom streams */
+int
+_assuan_cookie_write_data (void *cookie, const char *buffer, size_t size)
+{
+ ASSUAN_CONTEXT ctx = cookie;
+ char *line;
+ size_t linelen;
+
+ if (ctx->outbound.data.error)
+ return 0;
+
+ line = ctx->outbound.data.line;
+ linelen = ctx->outbound.data.linelen;
+ line += linelen;
+ while (size)
+ {
+ /* insert data line header */
+ if (!linelen)
+ {
+ *line++ = 'D';
+ *line++ = ' ';
+ linelen += 2;
+ }
+
+ /* copy data, keep some space for the CRLF and to escape one character */
+ while (size && linelen < LINELENGTH-2-2)
+ {
+ if (*buffer == '%' || *buffer == '\r' || *buffer == '\n')
+ {
+ sprintf (line, "%%%02X", *(unsigned char*)buffer);
+ line += 3;
+ linelen += 3;
+ buffer++;
+ }
+ else
+ {
+ *line++ = *buffer++;
+ linelen++;
+ }
+ size--;
+ }
+
+ if (linelen >= LINELENGTH-2-2)
+ {
+ if (ctx->log_fp)
+ {
+ fprintf (ctx->log_fp, "%s[%p] -> ",
+ assuan_get_assuan_log_prefix (), ctx);
+
+ if (ctx->confidential)
+ fputs ("[Confidential data not shown]", ctx->log_fp);
+ else
+ _assuan_log_print_buffer (ctx->log_fp,
+ ctx->outbound.data.line,
+ linelen);
+ putc ('\n', ctx->log_fp);
+ }
+ *line++ = '\n';
+ linelen++;
+ if (writen (ctx, ctx->outbound.data.line, linelen))
+ {
+ ctx->outbound.data.error = ASSUAN_Write_Error;
+ return 0;
+ }
+ line = ctx->outbound.data.line;
+ linelen = 0;
+ }
+ }
+
+ ctx->outbound.data.linelen = linelen;
+ return 0;
+}
+
+
+/* Write out any buffered data
+ This fucntion is used for GNU's custom streams */
+int
+_assuan_cookie_write_flush (void *cookie)
+{
+ ASSUAN_CONTEXT ctx = cookie;
+ char *line;
+ size_t linelen;
+
+ if (ctx->outbound.data.error)
+ return 0;
+
+ line = ctx->outbound.data.line;
+ linelen = ctx->outbound.data.linelen;
+ line += linelen;
+ if (linelen)
+ {
+ if (ctx->log_fp)
+ {
+ fprintf (ctx->log_fp, "%s[%p] -> ",
+ assuan_get_assuan_log_prefix (), ctx);
+ if (ctx->confidential)
+ fputs ("[Confidential data not shown]", ctx->log_fp);
+ else
+ _assuan_log_print_buffer (ctx->log_fp,
+ ctx->outbound.data.line, linelen);
+ putc ('\n', ctx->log_fp);
+ }
+ *line++ = '\n';
+ linelen++;
+ if (writen (ctx, ctx->outbound.data.line, linelen))
+ {
+ ctx->outbound.data.error = ASSUAN_Write_Error;
+ return 0;
+ }
+ ctx->outbound.data.linelen = 0;
+ }
+ return 0;
+}
+
+
+/**
+ * assuan_send_data:
+ * @ctx: An assuan context
+ * @buffer: Data to send or NULL to flush
+ * @length: length of the data to send/
+ *
+ * This function may be used by the server or the client to send data
+ * lines. The data will be escaped as required by the Assuan protocol
+ * and may get buffered until a line is full. To force sending the
+ * data out @buffer may be passed as NULL (in which case @length must
+ * also be 0); however when used by a client this flush operation does
+ * also send the terminating "END" command to terminate the reponse on
+ * a INQUIRE response. However, when assuan_transact() is used, this
+ * function takes care of sending END itself.
+ *
+ * Return value: 0 on success or an error code
+ **/
+
+AssuanError
+assuan_send_data (ASSUAN_CONTEXT ctx, const void *buffer, size_t length)
+{
+ if (!ctx)
+ return ASSUAN_Invalid_Value;
+ if (!buffer && length)
+ return ASSUAN_Invalid_Value;
+
+ if (!buffer)
+ { /* flush what we have */
+ _assuan_cookie_write_flush (ctx);
+ if (ctx->outbound.data.error)
+ return ctx->outbound.data.error;
+ if (!ctx->is_server)
+ return assuan_write_line (ctx, "END");
+ }
+ else
+ {
+ _assuan_cookie_write_data (ctx, buffer, length);
+ if (ctx->outbound.data.error)
+ return ctx->outbound.data.error;
+ }
+
+ return 0;
+}
+
+AssuanError
+assuan_sendfd (ASSUAN_CONTEXT ctx, int fd)
+{
+ if (! ctx->io->sendfd)
+ return set_error (ctx, Not_Implemented,
+ "server does not support sending and receiving "
+ "of file descriptors");
+ return ctx->io->sendfd (ctx, fd);
+}
+
+AssuanError
+assuan_receivefd (ASSUAN_CONTEXT ctx, int *fd)
+{
+ if (! ctx->io->receivefd)
+ return set_error (ctx, Not_Implemented,
+ "server does not support sending and receiving "
+ "of file descriptors");
+ return ctx->io->receivefd (ctx, fd);
+}
diff --git a/branches/gpgme-1-0-branch/assuan/assuan-client.c b/branches/gpgme-1-0-branch/assuan/assuan-client.c
new file mode 100644
index 00000000..d5c0ec81
--- /dev/null
+++ b/branches/gpgme-1-0-branch/assuan/assuan-client.c
@@ -0,0 +1,225 @@
+/* assuan-client.c - client functions
+ * Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Assuan is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <assert.h>
+
+#include "assuan-defs.h"
+
+#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
+ *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
+#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
+
+
+AssuanError
+_assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off)
+{
+ char *line;
+ int linelen;
+ AssuanError rc;
+
+ *okay = 0;
+ *off = 0;
+ do
+ {
+ rc = _assuan_read_line (ctx);
+ if (rc)
+ return rc;
+ line = ctx->inbound.line;
+ linelen = ctx->inbound.linelen;
+ }
+ while (*line == '#' || !linelen);
+
+ if (linelen >= 1
+ && line[0] == 'D' && line[1] == ' ')
+ {
+ *okay = 2; /* data line */
+ *off = 2;
+ }
+ else if (linelen >= 1
+ && line[0] == 'S'
+ && (line[1] == '\0' || line[1] == ' '))
+ {
+ *okay = 4;
+ *off = 1;
+ while (line[*off] == ' ')
+ ++*off;
+ }
+ else if (linelen >= 2
+ && line[0] == 'O' && line[1] == 'K'
+ && (line[2] == '\0' || line[2] == ' '))
+ {
+ *okay = 1;
+ *off = 2;
+ while (line[*off] == ' ')
+ ++*off;
+ }
+ else if (linelen >= 3
+ && line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
+ && (line[3] == '\0' || line[3] == ' '))
+ {
+ *okay = 0;
+ *off = 3;
+ while (line[*off] == ' ')
+ ++*off;
+ }
+ else if (linelen >= 7
+ && line[0] == 'I' && line[1] == 'N' && line[2] == 'Q'
+ && line[3] == 'U' && line[4] == 'I' && line[5] == 'R'
+ && line[6] == 'E'
+ && (line[7] == '\0' || line[7] == ' '))
+ {
+ *okay = 3;
+ *off = 7;
+ while (line[*off] == ' ')
+ ++*off;
+ }
+ else if (linelen >= 3
+ && line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
+ && (line[3] == '\0' || line[3] == ' '))
+ {
+ *okay = 5; /* end line */
+ *off = 3;
+ }
+ else
+ rc = ASSUAN_Invalid_Response;
+ return rc;
+}
+
+
+
+/**
+ * assuan_transact:
+ * @ctx: The Assuan context
+ * @command: Coimmand line to be send to server
+ * @data_cb: Callback function for data lines
+ * @data_cb_arg: first argument passed to @data_cb
+ * @inquire_cb: Callback function for a inquire response
+ * @inquire_cb_arg: first argument passed to @inquire_cb
+ * @status_cb: Callback function for a status response
+ * @status_cb_arg: first argument passed to @status_cb
+ *
+ * FIXME: Write documentation
+ *
+ * Return value: 0 on success or error code. The error code may be
+ * the one one returned by the server in error lines or from the
+ * callback functions.
+ **/
+AssuanError
+assuan_transact (ASSUAN_CONTEXT ctx,
+ const char *command,
+ AssuanError (*data_cb)(void *, const void *, size_t),
+ void *data_cb_arg,
+ AssuanError (*inquire_cb)(void*, const char *),
+ void *inquire_cb_arg,
+ AssuanError (*status_cb)(void*, const char *),
+ void *status_cb_arg)
+{
+ int rc, okay, off;
+ unsigned char *line;
+ int linelen;
+
+ rc = assuan_write_line (ctx, command);
+ if (rc)
+ return rc;
+
+ again:
+ rc = _assuan_read_from_server (ctx, &okay, &off);
+ if (rc)
+ return rc; /* error reading from server */
+
+ line = ctx->inbound.line + off;
+ linelen = ctx->inbound.linelen - off;
+
+ if (!okay)
+ {
+ rc = atoi (line);
+ if (rc < 100)
+ rc = ASSUAN_Server_Fault;
+ }
+ else if (okay == 2)
+ {
+ if (!data_cb)
+ rc = ASSUAN_No_Data_Callback;
+ else
+ {
+ unsigned char *s, *d;
+
+ for (s=d=line; linelen; linelen--)
+ {
+ if (*s == '%' && linelen > 2)
+ { /* handle escaping */
+ s++;
+ *d++ = xtoi_2 (s);
+ s += 2;
+ linelen -= 2;
+ }
+ else
+ *d++ = *s++;
+ }
+ *d = 0; /* add a hidden string terminator */
+ rc = data_cb (data_cb_arg, line, d - line);
+ if (!rc)
+ goto again;
+ }
+ }
+ else if (okay == 3)
+ {
+ if (!inquire_cb)
+ {
+ assuan_write_line (ctx, "END"); /* get out of inquire mode */
+ _assuan_read_from_server (ctx, &okay, &off); /* dummy read */
+ rc = ASSUAN_No_Inquire_Callback;
+ }
+ else
+ {
+ rc = inquire_cb (inquire_cb_arg, line);
+ if (!rc)
+ rc = assuan_send_data (ctx, NULL, 0); /* flush and send END */
+ if (!rc)
+ goto again;
+ }
+ }
+ else if (okay == 4)
+ {
+ if (status_cb)
+ rc = status_cb (status_cb_arg, line);
+ if (!rc)
+ goto again;
+ }
+ else if (okay == 5)
+ {
+ if (!data_cb)
+ rc = ASSUAN_No_Data_Callback;
+ else
+ {
+ rc = data_cb (data_cb_arg, NULL, 0);
+ if (!rc)
+ goto again;
+ }
+ }
+
+ return rc;
+}
+
diff --git a/branches/gpgme-1-0-branch/assuan/assuan-connect.c b/branches/gpgme-1-0-branch/assuan/assuan-connect.c
new file mode 100644
index 00000000..009aaab4
--- /dev/null
+++ b/branches/gpgme-1-0-branch/assuan/assuan-connect.c
@@ -0,0 +1,54 @@
+/* assuan-connect.c - Establish a connection (client)
+ * Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Assuan is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "assuan-defs.h"
+
+/* Disconnect and release the context CTX. */
+void
+assuan_disconnect (ASSUAN_CONTEXT ctx)
+{
+ if (ctx)
+ {
+ assuan_write_line (ctx, "BYE");
+ ctx->finish_handler (ctx);
+ ctx->deinit_handler (ctx);
+ ctx->deinit_handler = NULL;
+ _assuan_release_context (ctx);
+ }
+}
+
+pid_t
+assuan_get_pid (ASSUAN_CONTEXT ctx)
+{
+ return ctx ? ctx->pid : -1;
+}
diff --git a/branches/gpgme-1-0-branch/assuan/assuan-defs.h b/branches/gpgme-1-0-branch/assuan/assuan-defs.h
new file mode 100644
index 00000000..1f7f1f03
--- /dev/null
+++ b/branches/gpgme-1-0-branch/assuan/assuan-defs.h
@@ -0,0 +1,194 @@
+/* assuan-defs.c - Internal definitions to Assuan
+ * Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Assuan is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifndef ASSUAN_DEFS_H
+#define ASSUAN_DEFS_H
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include "assuan.h"
+
+#define LINELENGTH ASSUAN_LINELENGTH
+
+struct cmdtbl_s
+{
+ const char *name;
+ int (*handler)(ASSUAN_CONTEXT, char *line);
+};
+
+struct assuan_io
+{
+ /* Routine to read from input_fd. */
+ ssize_t (*read) (ASSUAN_CONTEXT, void *, size_t);
+ /* Routine to write to output_fd. */
+ ssize_t (*write) (ASSUAN_CONTEXT, const void *, size_t);
+ /* Send a file descriptor. */
+ AssuanError (*sendfd) (ASSUAN_CONTEXT, int);
+ /* Receive a file descriptor. */
+ AssuanError (*receivefd) (ASSUAN_CONTEXT, int *);
+};
+
+struct assuan_context_s
+{
+ AssuanError err_no;
+ const char *err_str;
+ int os_errno; /* last system error number used with certain error codes*/
+
+ int confidential;
+ int is_server; /* set if this is context belongs to a server */
+ int in_inquire;
+ char *hello_line;
+ char *okay_line; /* see assan_set_okay_line() */
+
+ void *user_pointer; /* for assuan_[gs]et_pointer () */
+
+ FILE *log_fp;
+
+ struct {
+ int fd;
+ int eof;
+ char line[LINELENGTH];
+ int linelen; /* w/o CR, LF - might not be the same as
+ strlen(line) due to embedded nuls. However a nul
+ is always written at this pos */
+ struct {
+ char line[LINELENGTH];
+ int linelen ;
+ int pending; /* i.e. at least one line is available in the attic */
+ } attic;
+ } inbound;
+
+ struct {
+ int fd;
+ struct {
+ FILE *fp;
+ char line[LINELENGTH];
+ int linelen;
+ int error;
+ } data;
+ } outbound;
+
+ int pipe_mode; /* We are in pipe mode, i.e. we can handle just one
+ connection and must terminate then */
+ pid_t pid; /* In pipe mode, the pid of the child server process.
+ In socket mode, the pid of the server */
+ int listen_fd; /* The fd we are listening on (used by socket servers) */
+ int connected_fd; /* helper */
+
+ pid_t client_pid; /* for a socket server the PID of the client or -1
+ if not available */
+
+ /* Used for Unix domain sockets. */
+ struct sockaddr_un myaddr;
+ struct sockaddr_un serveraddr;
+ /* When reading from datagram sockets, we must read an entire
+ message at a time. This means that we have to do our own
+ buffering to be able to get the semantics of read. */
+ void *domainbuffer;
+ /* Offset of start of buffer. */
+ int domainbufferoffset;
+ /* Bytes buffered. */
+ int domainbuffersize;
+ /* Memory allocated. */
+ int domainbufferallocated;
+
+ int *pendingfds;
+ int pendingfdscount;
+
+ void (*deinit_handler)(ASSUAN_CONTEXT);
+ int (*accept_handler)(ASSUAN_CONTEXT);
+ int (*finish_handler)(ASSUAN_CONTEXT);
+
+ struct cmdtbl_s *cmdtbl;
+ size_t cmdtbl_used; /* used entries */
+ size_t cmdtbl_size; /* allocated size of table */
+
+ void (*bye_notify_fnc)(ASSUAN_CONTEXT);
+ void (*reset_notify_fnc)(ASSUAN_CONTEXT);
+ void (*cancel_notify_fnc)(ASSUAN_CONTEXT);
+ int (*option_handler_fnc)(ASSUAN_CONTEXT,const char*, const char*);
+ void (*input_notify_fnc)(ASSUAN_CONTEXT, const char *);
+ void (*output_notify_fnc)(ASSUAN_CONTEXT, const char *);
+
+ int input_fd; /* set by INPUT command */
+ int output_fd; /* set by OUTPUT command */
+
+ /* io routines. */
+ struct assuan_io *io;
+};
+
+/*-- assuan-pipe-server.c --*/
+int _assuan_new_context (ASSUAN_CONTEXT *r_ctx);
+void _assuan_release_context (ASSUAN_CONTEXT ctx);
+
+/*-- assuan-domain-connect.c --*/
+/* 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. */
+AssuanError _assuan_domain_init (ASSUAN_CONTEXT *r_ctx,
+ int rendezvousfd,
+ pid_t peer);
+
+/*-- assuan-handler.c --*/
+int _assuan_register_std_commands (ASSUAN_CONTEXT ctx);
+
+/*-- assuan-buffer.c --*/
+int _assuan_read_line (ASSUAN_CONTEXT ctx);
+int _assuan_cookie_write_data (void *cookie, const char *buffer, size_t size);
+int _assuan_cookie_write_flush (void *cookie);
+
+/*-- assuan-client.c --*/
+AssuanError _assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off);
+
+
+/*-- assuan-util.c --*/
+void *_assuan_malloc (size_t n);
+void *_assuan_calloc (size_t n, size_t m);
+void *_assuan_realloc (void *p, size_t n);
+void _assuan_free (void *p);
+
+#define xtrymalloc(a) _assuan_malloc ((a))
+#define xtrycalloc(a,b) _assuan_calloc ((a),(b))
+#define xtryrealloc(a,b) _assuan_realloc((a),(b))
+#define xfree(a) _assuan_free ((a))
+
+#define set_error(c,e,t) assuan_set_error ((c), ASSUAN_ ## e, (t))
+
+void _assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length);
+void _assuan_log_sanitized_string (const char *string);
+
+/*-- assuan-io.c --*/
+ssize_t _assuan_simple_read (ASSUAN_CONTEXT ctx, void *buffer, size_t size);
+ssize_t _assuan_simple_write (ASSUAN_CONTEXT ctx, const void *buffer,
+ size_t size);
+
+#ifdef HAVE_FOPENCOOKIE
+/* We have to implement funopen in terms of glibc's fopencookie. */
+FILE *funopen(const void *cookie, cookie_read_function_t *readfn,
+ cookie_write_function_t *writefn,
+ cookie_seek_function_t *seekfn,
+ cookie_close_function_t *closefn);
+#endif /*HAVE_FOPENCOOKIE*/
+
+#endif /*ASSUAN_DEFS_H*/
+
diff --git a/branches/gpgme-1-0-branch/assuan/assuan-domain-connect.c b/branches/gpgme-1-0-branch/assuan/assuan-domain-connect.c
new file mode 100644
index 00000000..b92be3b8
--- /dev/null
+++ b/branches/gpgme-1-0-branch/assuan/assuan-domain-connect.c
@@ -0,0 +1,476 @@
+/* assuan-domain-connect.c - Assuan unix domain socket based client
+ * Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Assuan is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#if HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+
+#include "assuan-defs.h"
+
+#define LOG(format, args...) \
+ fprintf (assuan_get_assuan_log_stream (), \
+ assuan_get_assuan_log_prefix (), \
+ "%s" format , ## args)
+
+
+static void
+do_deinit (ASSUAN_CONTEXT ctx)
+{
+ if (ctx->inbound.fd != -1)
+ close (ctx->inbound.fd);
+ ctx->inbound.fd = -1;
+ ctx->outbound.fd = -1;
+
+ if (ctx->domainbuffer)
+ {
+ assert (ctx->domainbufferallocated);
+ free (ctx->domainbuffer);
+ }
+
+ if (ctx->pendingfds)
+ {
+ int i;
+
+ assert (ctx->pendingfdscount > 0);
+ for (i = 0; i < ctx->pendingfdscount; i ++)
+ close (ctx->pendingfds[i]);
+
+ free (ctx->pendingfds);
+ }
+
+ unlink (ctx->myaddr.sun_path);
+}
+
+
+/* Read from the socket server. */
+static ssize_t
+domain_reader (ASSUAN_CONTEXT ctx, void *buf, size_t buflen)
+{
+ int len = ctx->domainbuffersize;
+
+ start:
+ if (len == 0)
+ /* No data is buffered. */
+ {
+ struct msghdr msg;
+ struct iovec iovec;
+ struct sockaddr_un sender;
+ struct
+ {
+ struct cmsghdr hdr;
+ int fd;
+ }
+ cmsg;
+
+ memset (&msg, 0, sizeof (msg));
+
+ for (;;)
+ {
+ msg.msg_name = &sender;
+ msg.msg_namelen = sizeof (struct sockaddr_un);
+ msg.msg_iov = &iovec;
+ msg.msg_iovlen = 1;
+ iovec.iov_base = ctx->domainbuffer;
+ iovec.iov_len = ctx->domainbufferallocated;
+ msg.msg_control = &cmsg;
+ msg.msg_controllen = sizeof cmsg;
+
+ /* Peek first: if the buffer we have is too small then it
+ will be truncated. */
+ len = recvmsg (ctx->inbound.fd, &msg, MSG_PEEK);
+ if (len < 0)
+ {
+ printf ("domain_reader: %m\n");
+ return -1;
+ }
+
+ if (strcmp (ctx->serveraddr.sun_path,
+ ((struct sockaddr_un *) msg.msg_name)->sun_path) != 0)
+ {
+ /* XXX: Arg. Not from whom we expected! What do we
+ want to do? Should we just ignore it? Either way,
+ we still need to consume the message. */
+ break;
+ }
+
+ if (msg.msg_flags & MSG_TRUNC)
+ /* Enlarge the buffer and try again. */
+ {
+ int size = ctx->domainbufferallocated;
+ void *tmp;
+
+ if (size == 0)
+ size = 4 * 1024;
+ else
+ size *= 2;
+
+ tmp = malloc (size);
+ if (! tmp)
+ return -1;
+
+ free (ctx->domainbuffer);
+ ctx->domainbuffer = tmp;
+ ctx->domainbufferallocated = size;
+ }
+ else
+ /* We have enough space! */
+ break;
+ }
+
+ /* Now we have to actually consume it (remember, we only
+ peeked). */
+ msg.msg_name = &sender;
+ msg.msg_namelen = sizeof (struct sockaddr_un);
+ msg.msg_iov = &iovec;
+ msg.msg_iovlen = 1;
+ iovec.iov_base = ctx->domainbuffer;
+ iovec.iov_len = ctx->domainbufferallocated;
+ msg.msg_control = &cmsg;
+ msg.msg_controllen = sizeof cmsg;
+
+ if (strcmp (ctx->serveraddr.sun_path,
+ ((struct sockaddr_un *) msg.msg_name)->sun_path) != 0)
+ {
+ /* XXX: Arg. Not from whom we expected! What do we want to
+ do? Should we just ignore it? We shall do the latter
+ for the moment. */
+ LOG ("Not setup to receive messages from: `%s'.",
+ ((struct sockaddr_un *) msg.msg_name)->sun_path);
+ goto start;
+ }
+
+ len = recvmsg (ctx->inbound.fd, &msg, 0);
+ if (len < 0)
+ {
+ LOG ("domain_reader: %s\n", strerror (errno));
+ return -1;
+ }
+
+ ctx->domainbuffersize = len;
+ ctx->domainbufferoffset = 0;
+
+ if (sizeof (cmsg) == msg.msg_controllen)
+ /* We received a file descriptor. */
+ {
+ void *tmp;
+
+ tmp = realloc (ctx->pendingfds,
+ sizeof (int) * (ctx->pendingfdscount + 1));
+ if (! tmp)
+ {
+ LOG ("domain_reader: %s\n", strerror (errno));
+ return -1;
+ }
+
+ ctx->pendingfds = tmp;
+ ctx->pendingfds[ctx->pendingfdscount++]
+ = *(int *) CMSG_DATA (&cmsg.hdr);
+
+ LOG ("Received file descriptor %d from peer.\n",
+ ctx->pendingfds[ctx->pendingfdscount - 1]);
+ }
+
+ if (len == 0)
+ goto start;
+ }
+
+ /* Return some data to the user. */
+
+ if (len > buflen)
+ /* We have more than the user requested. */
+ len = buflen;
+
+ memcpy (buf, ctx->domainbuffer + ctx->domainbufferoffset, len);
+ ctx->domainbuffersize -= len;
+ assert (ctx->domainbuffersize >= 0);
+ ctx->domainbufferoffset += len;
+ assert (ctx->domainbufferoffset <= ctx->domainbufferallocated);
+
+ return len;
+}
+
+/* Write to the domain server. */
+static ssize_t
+domain_writer (ASSUAN_CONTEXT ctx, const void *buf, size_t buflen)
+{
+ struct msghdr msg;
+ struct iovec iovec;
+ ssize_t len;
+
+ memset (&msg, 0, sizeof (msg));
+
+ msg.msg_name = &ctx->serveraddr;
+ msg.msg_namelen = offsetof (struct sockaddr_un, sun_path)
+ + strlen (ctx->serveraddr.sun_path) + 1;
+
+ msg.msg_iovlen = 1;
+ msg.msg_iov = &iovec;
+ iovec.iov_base = (void *) buf;
+ iovec.iov_len = buflen;
+ msg.msg_control = 0;
+ msg.msg_controllen = 0;
+
+ len = sendmsg (ctx->outbound.fd, &msg, 0);
+ if (len < 0)
+ LOG ("domain_writer: %s\n", strerror (errno));
+
+ return len;
+}
+
+static AssuanError
+domain_sendfd (ASSUAN_CONTEXT ctx, int fd)
+{
+ struct msghdr msg;
+ struct
+ {
+ struct cmsghdr hdr;
+ int fd;
+ }
+ cmsg;
+ int len;
+
+ memset (&msg, 0, sizeof (msg));
+
+ msg.msg_name = &ctx->serveraddr;
+ msg.msg_namelen = offsetof (struct sockaddr_un, sun_path)
+ + strlen (ctx->serveraddr.sun_path) + 1;
+
+ msg.msg_iovlen = 0;
+ msg.msg_iov = 0;
+
+ cmsg.hdr.cmsg_level = SOL_SOCKET;
+ cmsg.hdr.cmsg_type = SCM_RIGHTS;
+ cmsg.hdr.cmsg_len = sizeof (cmsg);
+
+ msg.msg_control = &cmsg;
+ msg.msg_controllen = sizeof (cmsg);
+
+ *(int *) CMSG_DATA (&cmsg.hdr) = fd;
+
+ len = sendmsg (ctx->outbound.fd, &msg, 0);
+ if (len < 0)
+ {
+ LOG ("domain_sendfd: %s\n", strerror (errno));
+ return ASSUAN_General_Error;
+ }
+ else
+ return 0;
+}
+
+static AssuanError
+domain_receivefd (ASSUAN_CONTEXT ctx, int *fd)
+{
+ if (ctx->pendingfds == 0)
+ {
+ LOG ("No pending file descriptors!\n");
+ return ASSUAN_General_Error;
+ }
+
+ *fd = ctx->pendingfds[0];
+ if (-- ctx->pendingfdscount == 0)
+ {
+ free (ctx->pendingfds);
+ ctx->pendingfds = 0;
+ }
+ else
+ /* Fix the array. */
+ {
+ memmove (ctx->pendingfds, ctx->pendingfds + 1,
+ ctx->pendingfdscount * sizeof (int));
+ ctx->pendingfds = realloc (ctx->pendingfds,
+ ctx->pendingfdscount * sizeof (int));
+ }
+
+ 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. */
+AssuanError
+_assuan_domain_init (ASSUAN_CONTEXT *r_ctx, int rendezvousfd, pid_t peer)
+{
+ static struct assuan_io io = { domain_reader, domain_writer,
+ domain_sendfd, domain_receivefd };
+
+ AssuanError err;
+ ASSUAN_CONTEXT ctx;
+ int fd;
+ size_t len;
+ int tries;
+
+ if (!r_ctx)
+ return ASSUAN_Invalid_Value;
+ *r_ctx = NULL;
+
+ err = _assuan_new_context (&ctx);
+ if (err)
+ return err;
+
+ /* Save it in case we need it later. */
+ ctx->pid = peer;
+
+ /* Override the default (NOP) handlers. */
+ ctx->deinit_handler = do_deinit;
+
+ /* Setup the socket. */
+
+ fd = socket (PF_LOCAL, SOCK_DGRAM, 0);
+ if (fd == -1)
+ {
+ LOG ("can't create socket: %s\n", strerror (errno));
+ _assuan_release_context (ctx);
+ return ASSUAN_General_Error;
+ }
+
+ ctx->inbound.fd = fd;
+ ctx->outbound.fd = fd;
+
+ /* And the io buffers. */
+
+ ctx->io = &io;
+ ctx->domainbuffer = 0;
+ ctx->domainbufferoffset = 0;
+ ctx->domainbuffersize = 0;
+ ctx->domainbufferallocated = 0;
+ ctx->pendingfds = 0;
+ ctx->pendingfdscount = 0;
+
+ /* Get usable name and bind to it. */
+
+ for (tries = 0; tries < TMP_MAX; tries ++)
+ {
+ char *p;
+ char buf[L_tmpnam];
+
+ /* XXX: L_tmpnam must be shorter than sizeof (sun_path)! */
+ assert (L_tmpnam < sizeof (ctx->myaddr.sun_path));
+
+ p = tmpnam (buf);
+ if (! p)
+ {
+ LOG ("cannot determine an appropriate temporary file "
+ "name. DOS in progress?\n");
+ _assuan_release_context (ctx);
+ close (fd);
+ return ASSUAN_General_Error;
+ }
+
+ memset (&ctx->myaddr, 0, sizeof ctx->myaddr);
+ ctx->myaddr.sun_family = AF_LOCAL;
+ len = strlen (buf) + 1;
+ memcpy (ctx->myaddr.sun_path, buf, len);
+ len += offsetof (struct sockaddr_un, sun_path);
+
+ err = bind (fd, (struct sockaddr *) &ctx->myaddr, len);
+ if (! err)
+ break;
+ }
+
+ if (err)
+ {
+ LOG ("can't bind to `%s': %s\n", ctx->myaddr.sun_path,
+ strerror (errno));
+ _assuan_release_context (ctx);
+ close (fd);
+ return ASSUAN_Connect_Failed;
+ }
+
+ /* Rendezvous with our peer. */
+ {
+ FILE *fp;
+ char *p;
+
+ fp = fdopen (rendezvousfd, "w+");
+ if (! fp)
+ {
+ LOG ("can't open rendezvous port: %s\n", strerror (errno));
+ return ASSUAN_Connect_Failed;
+ }
+
+ /* Send our address. */
+ fprintf (fp, "%s\n", ctx->myaddr.sun_path);
+ fflush (fp);
+
+ /* And receive our peer's. */
+ memset (&ctx->serveraddr, 0, sizeof ctx->serveraddr);
+ for (p = ctx->serveraddr.sun_path;
+ p < (ctx->serveraddr.sun_path
+ + sizeof ctx->serveraddr.sun_path - 1);
+ p ++)
+ {
+ *p = fgetc (fp);
+ if (*p == '\n')
+ break;
+ }
+ *p = '\0';
+ fclose (fp);
+
+ ctx->serveraddr.sun_family = AF_LOCAL;
+ }
+
+ *r_ctx = ctx;
+ return 0;
+}
+
+AssuanError
+assuan_domain_connect (ASSUAN_CONTEXT * r_ctx, int rendezvousfd, pid_t peer)
+{
+ AssuanError aerr;
+ int okay, off;
+
+ aerr = _assuan_domain_init (r_ctx, rendezvousfd, peer);
+ if (aerr)
+ return aerr;
+
+ /* Initial handshake. */
+ aerr = _assuan_read_from_server (*r_ctx, &okay, &off);
+ if (aerr)
+ LOG ("can't connect to server: %s\n", assuan_strerror (aerr));
+ else if (okay != 1)
+ {
+ LOG ("can't connect to server: `");
+ _assuan_log_sanitized_string ((*r_ctx)->inbound.line);
+ fprintf (assuan_get_assuan_log_stream (), "'\n");
+ aerr = ASSUAN_Connect_Failed;
+ }
+
+ if (aerr)
+ assuan_disconnect (*r_ctx);
+
+ return aerr;
+}
diff --git a/branches/gpgme-1-0-branch/assuan/assuan-domain-server.c b/branches/gpgme-1-0-branch/assuan/assuan-domain-server.c
new file mode 100644
index 00000000..b62b140d
--- /dev/null
+++ b/branches/gpgme-1-0-branch/assuan/assuan-domain-server.c
@@ -0,0 +1,46 @@
+/* assuan-socket-server.c - Assuan socket based server
+ * Copyright (C) 2002 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Assuan is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <unistd.h>
+
+#include "assuan-defs.h"
+
+/* Initialize a server. */
+AssuanError
+assuan_init_domain_server (ASSUAN_CONTEXT *r_ctx,
+ int rendezvousfd,
+ pid_t peer)
+{
+ AssuanError err;
+
+ err = _assuan_domain_init (r_ctx, rendezvousfd, peer);
+ if (err)
+ return err;
+
+ (*r_ctx)->is_server = 1;
+ /* A domain server can only be used once. */
+ (*r_ctx)->pipe_mode = 1;
+
+ return 0;
+}
diff --git a/branches/gpgme-1-0-branch/assuan/assuan-handler.c b/branches/gpgme-1-0-branch/assuan/assuan-handler.c
new file mode 100644
index 00000000..7a774cb6
--- /dev/null
+++ b/branches/gpgme-1-0-branch/assuan/assuan-handler.c
@@ -0,0 +1,691 @@
+/* assuan-handler.c - dispatch commands
+ * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Assuan is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "assuan-defs.h"
+
+
+
+#define spacep(p) (*(p) == ' ' || *(p) == '\t')
+#define digitp(a) ((a) >= '0' && (a) <= '9')
+
+static int my_strcasecmp (const char *a, const char *b);
+
+
+
+static int
+dummy_handler (ASSUAN_CONTEXT ctx, char *line)
+{
+ return set_error (ctx, Server_Fault, "no handler registered");
+}
+
+
+static int
+std_handler_nop (ASSUAN_CONTEXT ctx, char *line)
+{
+ return 0; /* okay */
+}
+
+static int
+std_handler_cancel (ASSUAN_CONTEXT ctx, char *line)
+{
+ if (ctx->cancel_notify_fnc)
+ ctx->cancel_notify_fnc (ctx);
+ return set_error (ctx, Not_Implemented, NULL);
+}
+
+static int
+std_handler_option (ASSUAN_CONTEXT ctx, char *line)
+{
+ char *key, *value, *p;
+
+ for (key=line; spacep (key); key++)
+ ;
+ if (!*key)
+ return set_error (ctx, Syntax_Error, "argument required");
+ if (*key == '=')
+ return set_error (ctx, Syntax_Error, "no option name given");
+ for (value=key; *value && !spacep (value) && *value != '='; value++)
+ ;
+ if (*value)
+ {
+ if (spacep (value))
+ *value++ = 0; /* terminate key */
+ for (; spacep (value); value++)
+ ;
+ if (*value == '=')
+ {
+ *value++ = 0; /* terminate key */
+ for (; spacep (value); value++)
+ ;
+ if (!*value)
+ return set_error (ctx, Syntax_Error, "option argument expected");
+ }
+ if (*value)
+ {
+ for (p = value + strlen(value) - 1; p > value && spacep (p); p--)
+ ;
+ if (p > value)
+ *++p = 0; /* strip trailing spaces */
+ }
+ }
+
+ 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");
+
+ if (ctx->option_handler_fnc)
+ return ctx->option_handler_fnc (ctx, key, value);
+ return 0;
+}
+
+static int
+std_handler_bye (ASSUAN_CONTEXT ctx, char *line)
+{
+ if (ctx->bye_notify_fnc)
+ ctx->bye_notify_fnc (ctx);
+ assuan_close_input_fd (ctx);
+ assuan_close_output_fd (ctx);
+ return -1; /* pretty simple :-) */
+}
+
+static int
+std_handler_auth (ASSUAN_CONTEXT ctx, char *line)
+{
+ return set_error (ctx, Not_Implemented, NULL);
+}
+
+static int
+std_handler_reset (ASSUAN_CONTEXT ctx, char *line)
+{
+ if (ctx->reset_notify_fnc)
+ ctx->reset_notify_fnc (ctx);
+ assuan_close_input_fd (ctx);
+ assuan_close_output_fd (ctx);
+ return 0;
+}
+
+static int
+std_handler_end (ASSUAN_CONTEXT ctx, char *line)
+{
+ return set_error (ctx, Not_Implemented, NULL);
+}
+
+AssuanError
+assuan_command_parse_fd (ASSUAN_CONTEXT ctx, char *line, int *rfd)
+{
+ char *endp;
+
+ if (strncmp (line, "FD", 2) != 0 || (line[2] != '=' && line[2] != '\0'))
+ return set_error (ctx, Syntax_Error, "FD[=<n>] expected");
+ line += 2;
+ if (*line == '=')
+ {
+ line ++;
+ if (!digitp (*line))
+ return set_error (ctx, Syntax_Error, "number required");
+ *rfd = strtoul (line, &endp, 10);
+ /* remove that argument so that a notify handler won't see it */
+ memset (line, ' ', endp? (endp-line):strlen(line));
+
+ if (*rfd == ctx->inbound.fd)
+ return set_error (ctx, Parameter_Conflict, "fd same as inbound fd");
+ if (*rfd == ctx->outbound.fd)
+ return set_error (ctx, Parameter_Conflict, "fd same as outbound fd");
+ return 0;
+ }
+ else
+ /* Our peer has sent the file descriptor. */
+ return assuan_receivefd (ctx, rfd);
+}
+
+/* Format is INPUT FD=<n> */
+static int
+std_handler_input (ASSUAN_CONTEXT ctx, char *line)
+{
+ int rc, fd;
+
+ rc = assuan_command_parse_fd (ctx, line, &fd);
+ if (rc)
+ return rc;
+ ctx->input_fd = fd;
+ if (ctx->input_notify_fnc)
+ ctx->input_notify_fnc (ctx, line);
+ return 0;
+}
+
+/* Format is OUTPUT FD=<n> */
+static int
+std_handler_output (ASSUAN_CONTEXT ctx, char *line)
+{
+ int rc, fd;
+
+ rc = assuan_command_parse_fd (ctx, line, &fd);
+ if (rc)
+ return rc;
+ ctx->output_fd = fd;
+ if (ctx->output_notify_fnc)
+ ctx->output_notify_fnc (ctx, line);
+ return 0;
+}
+
+
+
+
+
+/* This is a table with the standard commands and handler for them.
+ The table is used to initialize a new context and associate strings
+ with default handlers */
+static struct {
+ const char *name;
+ int (*handler)(ASSUAN_CONTEXT, char *line);
+ int always; /* always initialize this command */
+} std_cmd_table[] = {
+ { "NOP", std_handler_nop, 1 },
+ { "CANCEL", std_handler_cancel, 1 },
+ { "OPTION", std_handler_option, 1 },
+ { "BYE", std_handler_bye, 1 },
+ { "AUTH", std_handler_auth, 1 },
+ { "RESET", std_handler_reset, 1 },
+ { "END", std_handler_end, 1 },
+
+ { "INPUT", std_handler_input },
+ { "OUTPUT", std_handler_output },
+ { "OPTION", std_handler_option, 1 },
+ { NULL }
+};
+
+
+/**
+ * assuan_register_command:
+ * @ctx: the server context
+ * @cmd_name: A string with the command name
+ * @handler: The handler function to be called or NULL to use a default
+ * handler.
+ *
+ * Register a handler to be used for a given command. Note that
+ * several default handlers are already regsitered with a new context.
+ * This function however allows to override them.
+ *
+ * Return value: 0 on success or an error code
+ **/
+int
+assuan_register_command (ASSUAN_CONTEXT ctx,
+ const char *cmd_name,
+ int (*handler)(ASSUAN_CONTEXT, char *))
+{
+ int i;
+ const char *s;
+
+ if (cmd_name && !*cmd_name)
+ cmd_name = NULL;
+
+ if (!cmd_name)
+ return ASSUAN_Invalid_Value;
+
+ if (!handler)
+ { /* find a default handler. */
+ for (i=0; (s=std_cmd_table[i].name) && strcmp (cmd_name, s); i++)
+ ;
+ if (!s)
+ { /* Try again but case insensitive. */
+ for (i=0; (s=std_cmd_table[i].name)
+ && my_strcasecmp (cmd_name, s); i++)
+ ;
+ }
+ if (s)
+ handler = std_cmd_table[i].handler;
+ if (!handler)
+ handler = dummy_handler; /* Last resort is the dummy handler. */
+ }
+
+ if (!ctx->cmdtbl)
+ {
+ ctx->cmdtbl_size = 50;
+ ctx->cmdtbl = xtrycalloc ( ctx->cmdtbl_size, sizeof *ctx->cmdtbl);
+ if (!ctx->cmdtbl)
+ return ASSUAN_Out_Of_Core;
+ ctx->cmdtbl_used = 0;
+ }
+ else if (ctx->cmdtbl_used >= ctx->cmdtbl_size)
+ {
+ struct cmdtbl_s *x;
+
+ x = xtryrealloc ( ctx->cmdtbl, (ctx->cmdtbl_size+10) * sizeof *x);
+ if (!x)
+ return ASSUAN_Out_Of_Core;
+ ctx->cmdtbl = x;
+ ctx->cmdtbl_size += 50;
+ }
+
+ ctx->cmdtbl[ctx->cmdtbl_used].name = cmd_name;
+ ctx->cmdtbl[ctx->cmdtbl_used].handler = handler;
+ ctx->cmdtbl_used++;
+ return 0;
+}
+
+int
+assuan_register_bye_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT))
+{
+ if (!ctx)
+ return ASSUAN_Invalid_Value;
+ ctx->bye_notify_fnc = fnc;
+ return 0;
+}
+
+int
+assuan_register_reset_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT))
+{
+ if (!ctx)
+ return ASSUAN_Invalid_Value;
+ ctx->reset_notify_fnc = fnc;
+ return 0;
+}
+
+int
+assuan_register_cancel_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT))
+{
+ if (!ctx)
+ return ASSUAN_Invalid_Value;
+ ctx->cancel_notify_fnc = fnc;
+ return 0;
+}
+
+int
+assuan_register_option_handler (ASSUAN_CONTEXT ctx,
+ int (*fnc)(ASSUAN_CONTEXT,
+ const char*, const char*))
+{
+ if (!ctx)
+ return ASSUAN_Invalid_Value;
+ ctx->option_handler_fnc = fnc;
+ return 0;
+}
+
+int
+assuan_register_input_notify (ASSUAN_CONTEXT ctx,
+ void (*fnc)(ASSUAN_CONTEXT, const char *))
+{
+ if (!ctx)
+ return ASSUAN_Invalid_Value;
+ ctx->input_notify_fnc = fnc;
+ return 0;
+}
+
+int
+assuan_register_output_notify (ASSUAN_CONTEXT ctx,
+ void (*fnc)(ASSUAN_CONTEXT, const char *))
+{
+ if (!ctx)
+ return ASSUAN_Invalid_Value;
+ ctx->output_notify_fnc = fnc;
+ return 0;
+}
+
+
+/* Helper to register the standards commands */
+int
+_assuan_register_std_commands (ASSUAN_CONTEXT ctx)
+{
+ int i, rc;
+
+ for (i=0; std_cmd_table[i].name; i++)
+ {
+ if (std_cmd_table[i].always)
+ {
+ rc = assuan_register_command (ctx, std_cmd_table[i].name, NULL);
+ if (rc)
+ return rc;
+ }
+ }
+ return 0;
+}
+
+
+
+/* Process the special data lines. The "D " has already been removed
+ from the line. As all handlers this function may modify the line. */
+static int
+handle_data_line (ASSUAN_CONTEXT ctx, char *line, int linelen)
+{
+ return set_error (ctx, Not_Implemented, NULL);
+}
+
+/* like ascii_strcasecmp but assume that B is already uppercase */
+static int
+my_strcasecmp (const char *a, const char *b)
+{
+ if (a == b)
+ return 0;
+
+ for (; *a && *b; a++, b++)
+ {
+ if (((*a >= 'a' && *a <= 'z')? (*a&~0x20):*a) != *b)
+ break;
+ }
+ 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, all the
+ handler with the argument line and return the error */
+static int
+dispatch_command (ASSUAN_CONTEXT ctx, char *line, int linelen)
+{
+ char *p;
+ const char *s;
+ int shift, i;
+
+ if (*line == 'D' && line[1] == ' ') /* divert to special handler */
+ return handle_data_line (ctx, line+2, linelen-2);
+
+ for (p=line; *p && *p != ' ' && *p != '\t'; p++)
+ ;
+ if (p==line)
+ return set_error (ctx, Invalid_Command, "leading white-space");
+ if (*p)
+ { /* Skip over leading WS after the keyword */
+ *p++ = 0;
+ while ( *p == ' ' || *p == '\t')
+ p++;
+ }
+ shift = p - line;
+
+ for (i=0; (s=ctx->cmdtbl[i].name); i++)
+ {
+ if (!strcmp (line, s))
+ break;
+ }
+ if (!s)
+ { /* and try case insensitive */
+ for (i=0; (s=ctx->cmdtbl[i].name); i++)
+ {
+ if (!my_strcasecmp (line, s))
+ break;
+ }
+ }
+ if (!s)
+ return set_error (ctx, Unknown_Command, NULL);
+ line += shift;
+ linelen -= shift;
+
+/* fprintf (stderr, "DBG-assuan: processing %s `%s'\n", s, line); */
+ return ctx->cmdtbl[i].handler (ctx, line);
+}
+
+
+
+
+static int
+process_request (ASSUAN_CONTEXT ctx)
+{
+ int rc;
+
+ if (ctx->in_inquire)
+ return ASSUAN_Nested_Commands;
+
+ rc = _assuan_read_line (ctx);
+ if (rc)
+ return rc;
+ if (*ctx->inbound.line == '#' || !ctx->inbound.linelen)
+ return 0; /* comment line - ignore */
+
+ 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 */
+ if (ctx->outbound.data.fp)
+ { /* 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;
+ }
+ else /* flush any data send w/o using the data fp */
+ {
+ assuan_send_data (ctx, NULL, 0);
+ if (!rc && ctx->outbound.data.error)
+ rc = ctx->outbound.data.error;
+ }
+ /* Error handling */
+ if (!rc)
+ {
+ rc = assuan_write_line (ctx, ctx->okay_line? ctx->okay_line : "OK");
+ }
+ else if (rc == -1)
+ { /* No error checking because the peer may have already disconnect */
+ assuan_write_line (ctx, "OK closing connection");
+ ctx->finish_handler (ctx);
+ }
+ else
+ {
+ char errline[256];
+
+ if (rc < 100)
+ sprintf (errline, "ERR %d server fault (%.50s)",
+ ASSUAN_Server_Fault, assuan_strerror (rc));
+ else
+ {
+ const char *text = ctx->err_no == rc? ctx->err_str:NULL;
+
+ sprintf (errline, "ERR %d %.50s%s%.100s",
+ rc, assuan_strerror (rc), text? " - ":"", text?text:"");
+ }
+ rc = assuan_write_line (ctx, errline);
+ }
+
+ ctx->confidential = 0;
+ if (ctx->okay_line)
+ {
+ xfree (ctx->okay_line);
+ ctx->okay_line = NULL;
+ }
+ return rc;
+}
+
+/**
+ * assuan_process:
+ * @ctx: assuan context
+ *
+ * This fucntion is used to handle the assuan protocol after a
+ * connection has been established using assuan_accept(). This is the
+ * main protocol handler.
+ *
+ * Return value: 0 on success or an error code if the assuan operation
+ * failed. Note, that no error is returned for operational errors.
+ **/
+int
+assuan_process (ASSUAN_CONTEXT ctx)
+{
+ int rc;
+
+ do {
+ rc = process_request (ctx);
+ } while (!rc);
+
+ if (rc == -1)
+ rc = 0;
+
+ return rc;
+}
+
+
+/**
+ * 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 ctx)
+{
+ return process_request (ctx);
+}
+
+
+/**
+ * assuan_get_active_fds:
+ * @ctx: Assuan context
+ * @what: 0 for read fds, 1 for write fds
+ * @fdarray: Caller supplied array to store the FDs
+ * @fdarraysize: size of that array
+ *
+ * Return all active filedescriptors for the given context. This
+ * function can be used to select on the fds and call
+ * assuan_process_next() if there is an active one. The first fd in
+ * the array is the one used for the command connection.
+ *
+ * Note, that write FDs are not yet supported.
+ *
+ * Return value: number of FDs active and put into @fdarray or -1 on
+ * error which is most likely a too small fdarray.
+ **/
+int
+assuan_get_active_fds (ASSUAN_CONTEXT ctx, int what,
+ int *fdarray, int fdarraysize)
+{
+ int n = 0;
+
+ if (!ctx || fdarraysize < 2 || what < 0 || what > 1)
+ return -1;
+
+ if (!what)
+ {
+ if (ctx->inbound.fd != -1)
+ fdarray[n++] = ctx->inbound.fd;
+ }
+ else
+ {
+ if (ctx->outbound.fd != -1)
+ fdarray[n++] = ctx->outbound.fd;
+ if (ctx->outbound.data.fp)
+ fdarray[n++] = fileno (ctx->outbound.data.fp);
+ }
+
+ return n;
+}
+
+/* Return a FP to be used for data output. The FILE pointer is valid
+ until the end of a handler. So a close is not needed. Assuan does
+ all the buffering needed to insert the status line as well as the
+ required line wappping and quoting for data lines.
+
+ We use GNU's custom streams here. There should be an alternative
+ implementaion for systems w/o a glibc, a simple implementation
+ could use a child process */
+FILE *
+assuan_get_data_fp (ASSUAN_CONTEXT ctx)
+{
+#if defined (HAVE_FOPENCOOKIE) || defined (HAVE_FUNOPEN)
+ if (ctx->outbound.data.fp)
+ return ctx->outbound.data.fp;
+
+
+ ctx->outbound.data.fp = funopen (ctx, 0,
+ _assuan_cookie_write_data,
+ 0, _assuan_cookie_write_flush);
+ ctx->outbound.data.error = 0;
+ return ctx->outbound.data.fp;
+#else
+ errno = ENOSYS;
+ return NULL;
+#endif
+}
+
+
+/* Set the text used for the next OK reponse. This string is
+ automatically reset to NULL after the next command. */
+AssuanError
+assuan_set_okay_line (ASSUAN_CONTEXT ctx, const char *line)
+{
+ if (!ctx)
+ return ASSUAN_Invalid_Value;
+ if (!line)
+ {
+ xfree (ctx->okay_line);
+ ctx->okay_line = NULL;
+ }
+ else
+ {
+ /* FIXME: we need to use gcry_is_secure() to test whether
+ we should allocate the entire line in secure memory */
+ char *buf = xtrymalloc (3+strlen(line)+1);
+ if (!buf)
+ return ASSUAN_Out_Of_Core;
+ strcpy (buf, "OK ");
+ strcpy (buf+3, line);
+ xfree (ctx->okay_line);
+ ctx->okay_line = buf;
+ }
+ return 0;
+}
+
+
+
+void
+assuan_write_status (ASSUAN_CONTEXT ctx, const char *keyword, const char *text)
+{
+ char buffer[256];
+ char *helpbuf;
+ size_t n;
+
+ if ( !ctx || !keyword)
+ return;
+ if (!text)
+ text = "";
+
+ n = 2 + strlen (keyword) + 1 + strlen (text) + 1;
+ if (n < sizeof (buffer))
+ {
+ strcpy (buffer, "S ");
+ strcat (buffer, keyword);
+ if (*text)
+ {
+ strcat (buffer, " ");
+ strcat (buffer, text);
+ }
+ assuan_write_line (ctx, buffer);
+ }
+ else if ( (helpbuf = xtrymalloc (n)) )
+ {
+ strcpy (helpbuf, "S ");
+ strcat (helpbuf, keyword);
+ if (*text)
+ {
+ strcat (helpbuf, " ");
+ strcat (helpbuf, text);
+ }
+ assuan_write_line (ctx, helpbuf);
+ xfree (helpbuf);
+ }
+}
diff --git a/branches/gpgme-1-0-branch/assuan/assuan-inquire.c b/branches/gpgme-1-0-branch/assuan/assuan-inquire.c
new file mode 100644
index 00000000..ec9d8e65
--- /dev/null
+++ b/branches/gpgme-1-0-branch/assuan/assuan-inquire.c
@@ -0,0 +1,240 @@
+/* assuan-inquire.c - handle inquire stuff
+ * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Assuan is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "assuan-defs.h"
+
+#define digitp(a) ((a) >= '0' && (a) <= '9')
+#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
+ *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
+#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
+
+
+struct membuf
+{
+ size_t len;
+ size_t size;
+ char *buf;
+ int out_of_core;
+ int too_large;
+ size_t maxlen;
+};
+
+
+
+/* A simple implemnation 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
+ the code with out of core checks. */
+
+static void
+init_membuf (struct membuf *mb, int initiallen, size_t maxlen)
+{
+ mb->len = 0;
+ mb->size = initiallen;
+ mb->out_of_core = 0;
+ mb->too_large = 0;
+ mb->maxlen = maxlen;
+ /* we need to allocate one byte more for get_membuf */
+ mb->buf = xtrymalloc (initiallen+1);
+ if (!mb->buf)
+ mb->out_of_core = 1;
+}
+
+static void
+put_membuf (struct membuf *mb, const void *buf, size_t len)
+{
+ if (mb->out_of_core || mb->too_large)
+ return;
+
+ if (mb->maxlen && mb->len + len > mb->maxlen)
+ {
+ mb->too_large = 1;
+ return;
+ }
+
+ if (mb->len + len >= mb->size)
+ {
+ char *p;
+
+ mb->size += len + 1024;
+ /* we need to allocate one byte more for get_membuf */
+ p = xtryrealloc (mb->buf, mb->size+1);
+ if (!p)
+ {
+ mb->out_of_core = 1;
+ return;
+ }
+ mb->buf = p;
+ }
+ memcpy (mb->buf + mb->len, buf, len);
+ mb->len += len;
+}
+
+static void *
+get_membuf (struct membuf *mb, size_t *len)
+{
+ char *p;
+
+ if (mb->out_of_core || mb->too_large)
+ {
+ xfree (mb->buf);
+ mb->buf = NULL;
+ return NULL;
+ }
+
+ mb->buf[mb->len] = 0; /* there is enough space for the hidden eos */
+ p = mb->buf;
+ *len = mb->len;
+ mb->buf = NULL;
+ mb->out_of_core = 1; /* don't allow a reuse */
+ return p;
+}
+
+static void
+free_membuf (struct membuf *mb)
+{
+ xfree (mb->buf);
+ mb->buf = NULL;
+}
+
+
+/**
+ * assuan_inquire:
+ * @ctx: An assuan context
+ * @keyword: The keyword used for the inquire
+ * @r_buffer: Returns an allocated buffer
+ * @r_length: Returns the length of this buffer
+ * @maxlen: If not 0, the size limit of the inquired data.
+ *
+ * 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.
+ *
+ * Return value: 0 on success or an ASSUAN error code
+ **/
+AssuanError
+assuan_inquire (ASSUAN_CONTEXT ctx, const char *keyword,
+ char **r_buffer, size_t *r_length, size_t maxlen)
+{
+ AssuanError rc;
+ struct membuf mb;
+ char cmdbuf[LINELENGTH-10]; /* (10 = strlen ("INQUIRE ")+CR,LF) */
+ unsigned char *line, *p;
+ int linelen;
+ int nodataexpected;
+
+ if (!ctx || !keyword || (10 + strlen (keyword) >= sizeof (cmdbuf)))
+ return ASSUAN_Invalid_Value;
+ nodataexpected = !r_buffer && !r_length && !maxlen;
+ if (!nodataexpected && (!r_buffer || !r_length))
+ return ASSUAN_Invalid_Value;
+ if (!ctx->is_server)
+ return ASSUAN_Not_A_Server;
+ if (ctx->in_inquire)
+ return ASSUAN_Nested_Commands;
+
+ ctx->in_inquire = 1;
+ if (nodataexpected)
+ memset (&mb, 0, sizeof mb); /* avoid compiler warnings */
+ else
+ init_membuf (&mb, maxlen? maxlen:1024, maxlen);
+
+ strcpy (stpcpy (cmdbuf, "INQUIRE "), keyword);
+ rc = assuan_write_line (ctx, cmdbuf);
+ if (rc)
+ goto leave;
+
+ for (;;)
+ {
+ do
+ {
+ rc = _assuan_read_line (ctx);
+ if (rc)
+ goto leave;
+ line = ctx->inbound.line;
+ linelen = ctx->inbound.linelen;
+ }
+ while (*line == '#' || !linelen);
+ if (line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
+ && (!line[3] || line[3] == ' '))
+ break; /* END command received*/
+ if (line[0] == 'C' && line[1] == 'A' && line[2] == 'N')
+ {
+ rc = ASSUAN_Canceled;
+ goto leave;
+ }
+ if (line[0] != 'D' || line[1] != ' ' || nodataexpected)
+ {
+ rc = ASSUAN_Unexpected_Command;
+ goto leave;
+ }
+ if (linelen < 3)
+ continue;
+ 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_Too_Much_Data;
+ goto leave;
+ }
+ }
+
+ if (!nodataexpected)
+ {
+ *r_buffer = get_membuf (&mb, r_length);
+ if (!*r_buffer)
+ rc = ASSUAN_Out_Of_Core;
+ }
+
+ leave:
+ if (!nodataexpected)
+ free_membuf (&mb);
+ ctx->in_inquire = 0;
+ return rc;
+}
+
+
+
+
+
+
diff --git a/branches/gpgme-1-0-branch/assuan/assuan-io.c b/branches/gpgme-1-0-branch/assuan/assuan-io.c
new file mode 100644
index 00000000..5dca009d
--- /dev/null
+++ b/branches/gpgme-1-0-branch/assuan/assuan-io.c
@@ -0,0 +1,58 @@
+/* assuan-io.c - Wraps the read and write functions.
+ * Copyright (C) 2002 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Assuan is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "assuan-defs.h"
+#include <sys/types.h>
+#include <unistd.h>
+
+#ifdef _ASSUAN_IN_GPGME
+ssize_t
+_assuan_simple_read (ASSUAN_CONTEXT ctx, void *buffer, size_t size)
+{
+ return read (ctx->inbound.fd, buffer, size);
+}
+
+ssize_t
+_assuan_simple_write (ASSUAN_CONTEXT ctx, const void *buffer, size_t size)
+{
+ return write (ctx->outbound.fd, buffer, size);
+}
+
+#else
+
+extern ssize_t pth_read (int fd, void *buffer, size_t size);
+extern ssize_t pth_write (int fd, const void *buffer, size_t size);
+
+#pragma weak pth_read
+#pragma weak pth_write
+
+ssize_t
+_assuan_simple_read (ASSUAN_CONTEXT ctx, void *buffer, size_t size)
+{
+ return (pth_read ? pth_read : read) (ctx->inbound.fd, buffer, size);
+}
+
+ssize_t
+_assuan_simple_write (ASSUAN_CONTEXT ctx, const void *buffer, size_t size)
+{
+ return (pth_write ? pth_write : write) (ctx->outbound.fd, buffer, size);
+}
+
+#endif
diff --git a/branches/gpgme-1-0-branch/assuan/assuan-listen.c b/branches/gpgme-1-0-branch/assuan/assuan-listen.c
new file mode 100644
index 00000000..aae3f7b7
--- /dev/null
+++ b/branches/gpgme-1-0-branch/assuan/assuan-listen.c
@@ -0,0 +1,132 @@
+/* assuan-listen.c - Wait for a connection (server)
+ * Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Assuan is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "assuan-defs.h"
+
+AssuanError
+assuan_set_hello_line (ASSUAN_CONTEXT ctx, const char *line)
+{
+ if (!ctx)
+ return ASSUAN_Invalid_Value;
+ if (!line)
+ {
+ xfree (ctx->hello_line);
+ ctx->hello_line = NULL;
+ }
+ else
+ {
+ char *buf = xtrymalloc (3+strlen(line)+1);
+ if (!buf)
+ return ASSUAN_Out_Of_Core;
+ strcpy (buf, "OK ");
+ strcpy (buf+3, line);
+ xfree (ctx->hello_line);
+ ctx->hello_line = buf;
+ }
+ return 0;
+}
+
+
+/**
+ * assuan_accept:
+ * @ctx: context
+ *
+ * Cancel any existing connection and wait for a connection from a
+ * client. The initial handshake is performed which may include an
+ * initial authentication or encryption negotiation.
+ *
+ * Return value: 0 on success or an error if the connection could for
+ * some reason not be established.
+ **/
+AssuanError
+assuan_accept (ASSUAN_CONTEXT ctx)
+{
+ int rc;
+
+ if (!ctx)
+ return ASSUAN_Invalid_Value;
+
+ if (ctx->pipe_mode > 1)
+ return -1; /* second invocation for pipemode -> terminate */
+ ctx->finish_handler (ctx);
+
+ rc = ctx->accept_handler (ctx);
+ if (rc)
+ return rc;
+
+ /* send the hello */
+ rc = assuan_write_line (ctx, ctx->hello_line? ctx->hello_line
+ : "OK Your orders please");
+ if (rc)
+ return rc;
+
+ if (ctx->pipe_mode)
+ ctx->pipe_mode = 2;
+
+ return 0;
+}
+
+
+
+int
+assuan_get_input_fd (ASSUAN_CONTEXT ctx)
+{
+ return ctx? ctx->input_fd : -1;
+}
+
+
+int
+assuan_get_output_fd (ASSUAN_CONTEXT ctx)
+{
+ return ctx? ctx->output_fd : -1;
+}
+
+
+/* Close the fd descriptor set by the command INPUT FD=n. We handle
+ this fd inside assuan so that we can do some initial checks */
+AssuanError
+assuan_close_input_fd (ASSUAN_CONTEXT ctx)
+{
+ if (!ctx || ctx->input_fd == -1)
+ return ASSUAN_Invalid_Value;
+ close (ctx->input_fd);
+ ctx->input_fd = -1;
+ return 0;
+}
+
+/* Close the fd descriptor set by the command OUTPUT FD=n. We handle
+ this fd inside assuan so that we can do some initial checks */
+AssuanError
+assuan_close_output_fd (ASSUAN_CONTEXT ctx)
+{
+ if (!ctx || ctx->output_fd == -1)
+ return ASSUAN_Invalid_Value;
+
+ close (ctx->output_fd);
+ ctx->output_fd = -1;
+ return 0;
+}
+
diff --git a/branches/gpgme-1-0-branch/assuan/assuan-logging.c b/branches/gpgme-1-0-branch/assuan/assuan-logging.c
new file mode 100644
index 00000000..340ce724
--- /dev/null
+++ b/branches/gpgme-1-0-branch/assuan/assuan-logging.c
@@ -0,0 +1,42 @@
+/* assuan-logging.c - Default logging function.
+ * Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Assuan is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "assuan-defs.h"
+#include <stdio.h>
+
+static FILE *_assuan_log;
+
+void
+assuan_set_assuan_log_stream (FILE *fp)
+{
+ _assuan_log = fp;
+}
+
+FILE *
+assuan_get_assuan_log_stream (void)
+{
+ return _assuan_log ? _assuan_log : stderr;
+}
+
+const char *
+assuan_get_assuan_log_prefix (void)
+{
+ return "";
+}
diff --git a/branches/gpgme-1-0-branch/assuan/assuan-pipe-connect.c b/branches/gpgme-1-0-branch/assuan/assuan-pipe-connect.c
new file mode 100644
index 00000000..a3ddc224
--- /dev/null
+++ b/branches/gpgme-1-0-branch/assuan/assuan-pipe-connect.c
@@ -0,0 +1,285 @@
+/* assuan-pipe-connect.c - Establish a pipe connection (client)
+ * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Assuan is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "assuan-defs.h"
+
+#ifdef _POSIX_OPEN_MAX
+#define MAX_OPEN_FDS _POSIX_OPEN_MAX
+#else
+#define MAX_OPEN_FDS 20
+#endif
+
+#define LOG(format, args...) \
+ fprintf (assuan_get_assuan_log_stream (), \
+ assuan_get_assuan_log_prefix (), \
+ "%s" format , ## args)
+
+static int
+writen (int fd, const char *buffer, size_t length)
+{
+ while (length)
+ {
+ int nwritten = write (fd, buffer, length);
+
+ if (nwritten < 0)
+ {
+ if (errno == EINTR)
+ continue;
+ return -1; /* write error */
+ }
+ length -= nwritten;
+ buffer += nwritten;
+ }
+ return 0; /* okay */
+}
+
+
+static int
+do_finish (ASSUAN_CONTEXT ctx)
+{
+ if (ctx->inbound.fd != -1)
+ {
+ close (ctx->inbound.fd);
+ ctx->inbound.fd = -1;
+ }
+ if (ctx->outbound.fd != -1)
+ {
+ close (ctx->outbound.fd);
+ ctx->outbound.fd = -1;
+ }
+ if (ctx->pid != -1)
+ {
+ waitpid (ctx->pid, NULL, 0); /* FIXME Check return value. */
+ ctx->pid = -1;
+ }
+ return 0;
+}
+
+static void
+do_deinit (ASSUAN_CONTEXT ctx)
+{
+ do_finish (ctx);
+}
+
+
+
+/* Connect to a server over a pipe, creating the assuan context and
+ returning it in CTX. The server filename is NAME, the argument
+ vector in ARGV. FD_CHILD_LIST is a -1 terminated list of file
+ descriptors not to close in the child. */
+AssuanError
+assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, char *const argv[],
+ int *fd_child_list)
+{
+#ifndef _ASSUAN_IN_GPGME
+ static int fixed_signals = 0;
+#endif
+ AssuanError err;
+ int rp[2];
+ int wp[2];
+
+ if (!ctx || !name || !argv || !argv[0])
+ return ASSUAN_Invalid_Value;
+
+#ifndef _ASSUAN_IN_GPGME
+ if (!fixed_signals)
+ {
+ struct sigaction act;
+
+ sigaction (SIGPIPE, NULL, &act);
+ if (act.sa_handler == SIG_DFL)
+ {
+ act.sa_handler = SIG_IGN;
+ sigemptyset (&act.sa_mask);
+ act.sa_flags = 0;
+ sigaction (SIGPIPE, &act, NULL);
+ }
+ fixed_signals = 1;
+ /* FIXME: This is not MT safe */
+ }
+#endif
+
+ if (pipe (rp) < 0)
+ return ASSUAN_General_Error;
+
+ if (pipe (wp) < 0)
+ {
+ close (rp[0]);
+ close (rp[1]);
+ return ASSUAN_General_Error;
+ }
+
+ err = _assuan_new_context (ctx);
+ if (err)
+ {
+ close (rp[0]);
+ close (rp[1]);
+ close (wp[0]);
+ close (wp[1]);
+ return err;
+ }
+ (*ctx)->pipe_mode = 1;
+ (*ctx)->inbound.fd = rp[0]; /* Our inbound is read end of read pipe. */
+ (*ctx)->outbound.fd = wp[1]; /* Our outbound is write end of write pipe. */
+ (*ctx)->deinit_handler = do_deinit;
+ (*ctx)->finish_handler = do_finish;
+
+ (*ctx)->pid = fork ();
+ if ((*ctx)->pid < 0)
+ {
+ close (rp[0]);
+ close (rp[1]);
+ close (wp[0]);
+ close (wp[1]);
+ _assuan_release_context (*ctx);
+ return ASSUAN_General_Error;
+ }
+
+ if ((*ctx)->pid == 0)
+ {
+ int i, n;
+ char errbuf[512];
+ int *fdp;
+
+ /* Dup handles to stdin/stdout. */
+ if (rp[1] != STDOUT_FILENO)
+ {
+ if (dup2 (rp[1], STDOUT_FILENO) == -1)
+ {
+ LOG ("dup2 failed in child: %s\n", strerror (errno));
+ _exit (4);
+ }
+ }
+ if (wp[0] != STDIN_FILENO)
+ {
+ if (dup2 (wp[0], STDIN_FILENO) == -1)
+ {
+ LOG ("dup2 failed in child: %s\n", strerror (errno));
+ _exit (4);
+ }
+ }
+
+ /* Dup stderr to /dev/null unless it is in the list of FDs to be
+ passed to the child. */
+ fdp = fd_child_list;
+ if (fdp)
+ {
+ for (; *fdp != -1 && *fdp != STDERR_FILENO; fdp++)
+ ;
+ }
+ if (!fdp || *fdp == -1)
+ {
+ int fd = open ("/dev/null", O_WRONLY);
+ if (fd == -1)
+ {
+ LOG ("can't open `/dev/null': %s\n", strerror (errno));
+ _exit (4);
+ }
+ if (dup2 (fd, STDERR_FILENO) == -1)
+ {
+ LOG ("dup2(dev/null, 2) failed: %s\n", strerror (errno));
+ _exit (4);
+ }
+ }
+
+
+ /* Close all files which will not be duped and are not in the
+ fd_child_list. */
+ n = sysconf (_SC_OPEN_MAX);
+ if (n < 0)
+ n = MAX_OPEN_FDS;
+ for (i=0; i < n; i++)
+ {
+ if ( i == STDIN_FILENO || i == STDOUT_FILENO || i == STDERR_FILENO)
+ continue;
+ fdp = fd_child_list;
+ if (fdp)
+ {
+ while (*fdp != -1 && *fdp != i)
+ fdp++;
+ }
+
+ if (!(fdp && *fdp != -1))
+ close(i);
+ }
+ errno = 0;
+
+ execv (name, argv);
+ /* oops - use the pipe to tell the parent about it */
+ snprintf (errbuf, sizeof(errbuf)-1, "ERR %d can't exec `%s': %.50s\n",
+ ASSUAN_Problem_Starting_Server, name, strerror (errno));
+ errbuf[sizeof(errbuf)-1] = 0;
+ writen (1, errbuf, strlen (errbuf));
+ _exit (4);
+ }
+
+ close (rp[1]);
+ close (wp[0]);
+
+ /* initial handshake */
+ {
+ int okay, off;
+
+ err = _assuan_read_from_server (*ctx, &okay, &off);
+ if (err)
+ LOG ("can't connect server: %s\n", assuan_strerror (err));
+ else if (okay != 1)
+ {
+ LOG ("can't connect server: `%s'\n", (*ctx)->inbound.line);
+ err = ASSUAN_Connect_Failed;
+ }
+ }
+
+ if (err)
+ {
+ assuan_disconnect (*ctx);
+ *ctx = NULL;
+ }
+
+ return err;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/branches/gpgme-1-0-branch/assuan/assuan-pipe-server.c b/branches/gpgme-1-0-branch/assuan/assuan-pipe-server.c
new file mode 100644
index 00000000..ba269b04
--- /dev/null
+++ b/branches/gpgme-1-0-branch/assuan/assuan-pipe-server.c
@@ -0,0 +1,129 @@
+/* assuan-pipe-server.c - Assuan server working over a pipe
+ * Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Assuan is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "assuan-defs.h"
+
+static void
+deinit_pipe_server (ASSUAN_CONTEXT ctx)
+{
+ /* nothing to do for this simple server */
+}
+
+static int
+accept_connection (ASSUAN_CONTEXT ctx)
+{
+ /* This is a NOP for a pipe server */
+ return 0;
+}
+
+static int
+finish_connection (ASSUAN_CONTEXT ctx)
+{
+ /* This is a NOP for a pipe server */
+ return 0;
+}
+
+/* Create a new context. Note that the handlers are set up for a pipe
+ server/client - this way we don't need extra dummy functions */
+int
+_assuan_new_context (ASSUAN_CONTEXT *r_ctx)
+{
+ static struct assuan_io io = { _assuan_simple_read,
+ _assuan_simple_write,
+ 0, 0 };
+
+ ASSUAN_CONTEXT ctx;
+ int rc;
+
+ *r_ctx = NULL;
+ ctx = xtrycalloc (1, sizeof *ctx);
+ if (!ctx)
+ return ASSUAN_Out_Of_Core;
+ ctx->input_fd = -1;
+ ctx->output_fd = -1;
+
+ ctx->inbound.fd = -1;
+ ctx->outbound.fd = -1;
+ ctx->io = &io;
+
+ ctx->listen_fd = -1;
+ ctx->client_pid = (pid_t)-1;
+ /* Use the pipe server handler as a default. */
+ ctx->deinit_handler = deinit_pipe_server;
+ ctx->accept_handler = accept_connection;
+ ctx->finish_handler = finish_connection;
+
+ rc = _assuan_register_std_commands (ctx);
+ if (rc)
+ xfree (ctx);
+ else
+ *r_ctx = ctx;
+ return rc;
+}
+
+
+
+int
+assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2])
+{
+ int rc;
+
+ rc = _assuan_new_context (r_ctx);
+ if (!rc)
+ {
+ ASSUAN_CONTEXT ctx = *r_ctx;
+
+ ctx->is_server = 1;
+ ctx->inbound.fd = filedes[0];
+ ctx->outbound.fd = filedes[1];
+ ctx->pipe_mode = 1;
+ }
+ return rc;
+}
+
+
+void
+_assuan_release_context (ASSUAN_CONTEXT ctx)
+{
+ if (ctx)
+ {
+ xfree (ctx->hello_line);
+ xfree (ctx->okay_line);
+ xfree (ctx);
+ }
+}
+
+void
+assuan_deinit_server (ASSUAN_CONTEXT ctx)
+{
+ if (ctx)
+ {
+ /* We use this function pointer to avoid linking other server
+ when not needed but still allow for a generic deinit function. */
+ ctx->deinit_handler (ctx);
+ ctx->deinit_handler = NULL;
+ _assuan_release_context (ctx);
+ }
+}
diff --git a/branches/gpgme-1-0-branch/assuan/assuan-socket-connect.c b/branches/gpgme-1-0-branch/assuan/assuan-socket-connect.c
new file mode 100644
index 00000000..cd963ed2
--- /dev/null
+++ b/branches/gpgme-1-0-branch/assuan/assuan-socket-connect.c
@@ -0,0 +1,138 @@
+/* assuan-socket-connect.c - Assuan socket based client
+ * Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Assuan is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include "assuan-defs.h"
+
+#define LOG(format, args...) \
+ fprintf (assuan_get_assuan_log_stream (), \
+ assuan_get_assuan_log_prefix (), \
+ "%s" format , ## args)
+
+static int
+do_finish (ASSUAN_CONTEXT ctx)
+{
+ if (ctx->inbound.fd != -1)
+ {
+ close (ctx->inbound.fd);
+ }
+ ctx->inbound.fd = -1;
+ ctx->outbound.fd = -1;
+ return 0;
+}
+
+static void
+do_deinit (ASSUAN_CONTEXT ctx)
+{
+ do_finish (ctx);
+}
+/* Make a connection to the Unix domain socket NAME and return a new
+ Assuan context in CTX. SERVER_PID is currently not used but may
+ become handy in the future. */
+AssuanError
+assuan_socket_connect (ASSUAN_CONTEXT *r_ctx,
+ const char *name, pid_t server_pid)
+{
+ static struct assuan_io io = { _assuan_simple_read,
+ _assuan_simple_write };
+
+ AssuanError err;
+ ASSUAN_CONTEXT ctx;
+ int fd;
+ struct sockaddr_un srvr_addr;
+ size_t len;
+
+ if (!r_ctx || !name)
+ return ASSUAN_Invalid_Value;
+ *r_ctx = NULL;
+
+ /* we require that the name starts with a slash, so that we can
+ alter reuse this function for other socket types */
+ if (*name != '/')
+ return ASSUAN_Invalid_Value;
+ if (strlen (name)+1 >= sizeof srvr_addr.sun_path)
+ return ASSUAN_Invalid_Value;
+
+ err = _assuan_new_context (&ctx);
+ if (err)
+ return err;
+ ctx->pid = server_pid; /* save it in case we need it later */
+ ctx->deinit_handler = do_deinit;
+ ctx->finish_handler = do_finish;
+
+ fd = socket (PF_LOCAL, SOCK_STREAM, 0);
+ if (fd == -1)
+ {
+ LOG ("can't create socket: %s\n", strerror (errno));
+ _assuan_release_context (ctx);
+ return ASSUAN_General_Error;
+ }
+
+ memset (&srvr_addr, 0, sizeof srvr_addr);
+ srvr_addr.sun_family = AF_LOCAL;
+ len = strlen (srvr_addr.sun_path) + 1;
+ memcpy (srvr_addr.sun_path, name, len);
+ len += (offsetof (struct sockaddr_un, sun_path));
+
+ if (connect (fd, (struct sockaddr *) &srvr_addr, len) == -1)
+ {
+ LOG ("can't connect to `%s': %s\n", name, strerror (errno));
+ _assuan_release_context (ctx);
+ close (fd);
+ return ASSUAN_Connect_Failed;
+ }
+
+ ctx->inbound.fd = fd;
+ ctx->outbound.fd = fd;
+ ctx->io = &io;
+
+ /* initial handshake */
+ {
+ int okay, off;
+
+ err = _assuan_read_from_server (ctx, &okay, &off);
+ if (err)
+ LOG ("can't connect to server: %s\n", assuan_strerror (err));
+ else if (okay != 1)
+ {
+ LOG ("can't connect to server: `");
+ _assuan_log_sanitized_string (ctx->inbound.line);
+ fprintf (assuan_get_assuan_log_stream (), "'\n");
+ err = ASSUAN_Connect_Failed;
+ }
+ }
+
+ if (err)
+ {
+ assuan_disconnect (ctx);
+ }
+ else
+ *r_ctx = ctx;
+ return 0;
+}
diff --git a/branches/gpgme-1-0-branch/assuan/assuan-socket-server.c b/branches/gpgme-1-0-branch/assuan/assuan-socket-server.c
new file mode 100644
index 00000000..d92e6e42
--- /dev/null
+++ b/branches/gpgme-1-0-branch/assuan/assuan-socket-server.c
@@ -0,0 +1,175 @@
+/* assuan-socket-server.c - Assuan socket based server
+ * Copyright (C) 2002 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Assuan is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include "assuan-defs.h"
+
+static int
+accept_connection_bottom (ASSUAN_CONTEXT ctx)
+{
+ int fd = ctx->connected_fd;
+
+ ctx->client_pid = (pid_t)-1;
+#ifdef HAVE_SO_PEERCRED
+ {
+ struct ucred cr;
+ int cl = sizeof cr;
+
+ if ( !getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl) )
+ ctx->client_pid = cr.pid;
+ }
+#endif
+
+ ctx->inbound.fd = fd;
+ ctx->inbound.eof = 0;
+ ctx->inbound.linelen = 0;
+ ctx->inbound.attic.linelen = 0;
+ ctx->inbound.attic.pending = 0;
+
+ ctx->outbound.fd = fd;
+ ctx->outbound.data.linelen = 0;
+ ctx->outbound.data.error = 0;
+
+ ctx->confidential = 0;
+
+ return 0;
+}
+
+
+static int
+accept_connection (ASSUAN_CONTEXT ctx)
+{
+ int fd;
+ struct sockaddr_un clnt_addr;
+ size_t len = sizeof clnt_addr;
+
+ ctx->client_pid = (pid_t)-1;
+ fd = accept (ctx->listen_fd, (struct sockaddr*)&clnt_addr, &len );
+ if (fd == -1)
+ {
+ ctx->os_errno = errno;
+ return ASSUAN_Accept_Failed;
+ }
+
+ ctx->connected_fd = fd;
+ return accept_connection_bottom (ctx);
+}
+
+static int
+finish_connection (ASSUAN_CONTEXT ctx)
+{
+ if (ctx->inbound.fd != -1)
+ {
+ close (ctx->inbound.fd);
+ }
+ ctx->inbound.fd = -1;
+ ctx->outbound.fd = -1;
+ return 0;
+}
+
+
+static void
+deinit_socket_server (ASSUAN_CONTEXT ctx)
+{
+ finish_connection (ctx);
+}
+
+static struct assuan_io io = { _assuan_simple_read,
+ _assuan_simple_write };
+
+/* Initialize a server for the socket LISTEN_FD which has already be
+ put into listen mode */
+int
+assuan_init_socket_server (ASSUAN_CONTEXT *r_ctx, int listen_fd)
+{
+ ASSUAN_CONTEXT ctx;
+ int rc;
+
+ *r_ctx = NULL;
+ ctx = xtrycalloc (1, sizeof *ctx);
+ if (!ctx)
+ return ASSUAN_Out_Of_Core;
+ ctx->is_server = 1;
+ ctx->input_fd = -1;
+ ctx->output_fd = -1;
+
+ ctx->inbound.fd = -1;
+ ctx->outbound.fd = -1;
+
+ ctx->listen_fd = listen_fd;
+ ctx->connected_fd = -1;
+ ctx->deinit_handler = deinit_socket_server;
+ ctx->accept_handler = accept_connection;
+ ctx->finish_handler = finish_connection;
+
+ ctx->io = &io;
+
+ rc = _assuan_register_std_commands (ctx);
+ if (rc)
+ xfree (ctx);
+ else
+ *r_ctx = ctx;
+ return rc;
+}
+
+/* Initialize a server using the already accepted socket FD. */
+int
+assuan_init_connected_socket_server (ASSUAN_CONTEXT *r_ctx, int fd)
+{
+ ASSUAN_CONTEXT ctx;
+ int rc;
+
+ *r_ctx = NULL;
+ ctx = xtrycalloc (1, sizeof *ctx);
+ if (!ctx)
+ return ASSUAN_Out_Of_Core;
+ ctx->is_server = 1;
+ ctx->pipe_mode = 1; /* we want a second accept to indicate EOF */
+ ctx->input_fd = -1;
+ ctx->output_fd = -1;
+
+ ctx->inbound.fd = -1;
+ ctx->outbound.fd = -1;
+
+ ctx->io = &io;
+
+ ctx->listen_fd = -1;
+ ctx->connected_fd = fd;
+ ctx->deinit_handler = deinit_socket_server;
+ ctx->accept_handler = accept_connection_bottom;
+ ctx->finish_handler = finish_connection;
+
+ rc = _assuan_register_std_commands (ctx);
+ if (rc)
+ xfree (ctx);
+ else
+ *r_ctx = ctx;
+ return rc;
+}
+
+
diff --git a/branches/gpgme-1-0-branch/assuan/assuan-util.c b/branches/gpgme-1-0-branch/assuan/assuan-util.c
new file mode 100644
index 00000000..fc0beedb
--- /dev/null
+++ b/branches/gpgme-1-0-branch/assuan/assuan-util.c
@@ -0,0 +1,219 @@
+/* assuan-util.c - Utility functions for Assuan
+ * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Assuan is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "assuan-defs.h"
+
+static void *(*alloc_func)(size_t n) = malloc;
+static void *(*realloc_func)(void *p, size_t n) = realloc;
+static void (*free_func)(void*) = free;
+
+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*) )
+{
+ alloc_func = new_alloc_func;
+ realloc_func = new_realloc_func;
+ free_func = new_free_func;
+}
+
+void *
+_assuan_malloc (size_t n)
+{
+ return alloc_func (n);
+}
+
+void *
+_assuan_realloc (void *a, size_t n)
+{
+ return realloc_func (a, n);
+}
+
+void *
+_assuan_calloc (size_t n, size_t m)
+{
+ void *p = _assuan_malloc (n*m);
+ if (p)
+ memset (p, 0, n* m);
+ return p;
+}
+
+void
+_assuan_free (void *p)
+{
+ if (p)
+ free_func (p);
+}
+
+
+/* Store the error in the context so that the error sending function
+ can take out a descriptive text. Inside the assuan code, use the
+ macro set_error instead of this function. */
+int
+assuan_set_error (ASSUAN_CONTEXT ctx, int err, const char *text)
+{
+ ctx->err_no = err;
+ ctx->err_str = text;
+ return err;
+}
+
+void
+assuan_set_pointer (ASSUAN_CONTEXT ctx, void *pointer)
+{
+ if (ctx)
+ ctx->user_pointer = pointer;
+}
+
+void *
+assuan_get_pointer (ASSUAN_CONTEXT ctx)
+{
+ return ctx? ctx->user_pointer : NULL;
+}
+
+
+void
+assuan_set_log_stream (ASSUAN_CONTEXT ctx, FILE *fp)
+{
+ if (ctx)
+ {
+ if (ctx->log_fp)
+ fflush (ctx->log_fp);
+ ctx->log_fp = fp;
+ }
+}
+
+
+void
+assuan_begin_confidential (ASSUAN_CONTEXT ctx)
+{
+ if (ctx)
+ {
+ ctx->confidential = 1;
+ }
+}
+
+void
+assuan_end_confidential (ASSUAN_CONTEXT ctx)
+{
+ if (ctx)
+ {
+ ctx->confidential = 0;
+ }
+}
+
+/* Dump a possibly binary string (used for debugging). Distinguish
+ ascii text from binary and print it accordingly. */
+void
+_assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length)
+{
+ const unsigned char *s;
+ int n;
+
+ for (n=length,s=buffer; n; n--, s++)
+ if (!isascii (*s) || iscntrl (*s) || !isprint (*s))
+ break;
+
+ s = buffer;
+ if (!n && *s != '[')
+ fwrite (buffer, length, 1, fp);
+ else
+ {
+#ifdef HAVE_FLOCKFILE
+ flockfile (fp);
+#endif
+ putc_unlocked ('[', fp);
+ for (n=0; n < length; n++, s++)
+ fprintf (fp, " %02x", *s);
+ putc_unlocked (' ', fp);
+ putc_unlocked (']', fp);
+#ifdef HAVE_FUNLOCKFILE
+ funlockfile (fp);
+#endif
+ }
+}
+
+/* Log a user supplied string. Escapes non-printable before
+ printing. */
+void
+_assuan_log_sanitized_string (const char *string)
+{
+ const unsigned char *s = string;
+ FILE *fp = assuan_get_assuan_log_stream ();
+
+ if (! *s)
+ return;
+
+#ifdef HAVE_FLOCKFILE
+ flockfile (fp);
+#endif
+
+ for (; *s; s++)
+ {
+ int c = 0;
+
+ switch (*s)
+ {
+ case '\r':
+ c = 'r';
+ break;
+
+ case '\n':
+ c = 'n';
+ break;
+
+ case '\f':
+ c = 'f';
+ break;
+
+ case '\v':
+ c = 'v';
+ break;
+
+ case '\b':
+ c = 'b';
+ break;
+
+ default:
+ if (isascii (*s) && isprint (*s))
+ putc_unlocked (*s, fp);
+ else
+ {
+ putc_unlocked ('\\', fp);
+ fprintf (fp, "x%02x", *s);
+ }
+ }
+
+ if (c)
+ {
+ putc_unlocked ('\\', fp);
+ putc_unlocked (c, fp);
+ }
+ }
+
+#ifdef HAVE_FUNLOCKFILE
+ funlockfile (fp);
+#endif
+}
diff --git a/branches/gpgme-1-0-branch/assuan/assuan.h b/branches/gpgme-1-0-branch/assuan/assuan.h
new file mode 100644
index 00000000..05f02126
--- /dev/null
+++ b/branches/gpgme-1-0-branch/assuan/assuan.h
@@ -0,0 +1,394 @@
+/* assuan.c - Definitions for the Assuan protocol
+ * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Assuan is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifndef ASSUAN_H
+#define ASSUAN_H
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <sys/socket.h>
+
+#define _ASSUAN_IN_GPGME
+#ifdef _ASSUAN_IN_GPGME
+#define _ASSUAN_EXT_SYM_PREFIX _gpgme_
+
+#ifdef _ASSUAN_IN_GPGME_BUILD_ASSUAN
+int _gpgme_io_read (int fd, void *buffer, size_t count);
+int _gpgme_io_write (int fd, const void *buffer, size_t count);
+ssize_t _gpgme_ath_select (int nfd, fd_set *rset, fd_set *wset, fd_set *eset,
+ struct timeval *timeout);
+ssize_t _gpgme_ath_waitpid (pid_t pid, int *status, int options);
+int _gpgme_ath_accept (int s, struct sockaddr *addr, socklen_t *length_ptr);
+int _gpgme_ath_connect (int s, struct sockaddr *addr, socklen_t length);
+int _gpgme_ath_sendmsg (int s, const struct msghdr *msg, int flags);
+int _gpgme_ath_recvmsg (int s, struct msghdr *msg, int flags);
+
+#define read _gpgme_io_read
+#define write _gpgme_io_write
+#define waitpid _gpgme_ath_waitpid
+#define select _gpgme_ath_select
+#define accept _gpgme_ath_accept
+#define connect _gpgme_ath_connect
+#define sendmsg _gpgme_ath_sendmsg
+#define recvmsg _gpgme_ath_recvmsg
+#endif
+#endif
+
+#ifdef _ASSUAN_EXT_SYM_PREFIX
+#define _ASSUAN_PREFIX1(x,y) x ## y
+#define _ASSUAN_PREFIX2(x,y) _ASSUAN_PREFIX1(x,y)
+#define _ASSUAN_PREFIX(x) _ASSUAN_PREFIX2(_ASSUAN_EXT_SYM_PREFIX,x)
+#define assuan_ _ASSUAN_PREFIX(assuan_)
+#define assuan_register_command _ASSUAN_PREFIX(assuan_register_command)
+#define assuan_register_bye_notify _ASSUAN_PREFIX(assuan_register_bye_notify)
+#define assuan_register_reset_notify \
+ _ASSUAN_PREFIX(assuan_register_reset_notify)
+#define assuan_register_cancel_notify \
+ _ASSUAN_PREFIX(assuan_register_cancel_notify)
+#define assuan_register_input_notify \
+ _ASSUAN_PREFIX(assuan_register_input_notify)
+#define assuan_register_output_notify \
+ _ASSUAN_PREFIX(assuan_register_output_notify)
+#define assuan_register_option_handler \
+ _ASSUAN_PREFIX(assuan_register_option_handler)
+#define assuan_process _ASSUAN_PREFIX(assuan_process)
+#define assuan_process_next _ASSUAN_PREFIX(assuan_process_next)
+#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_write_status _ASSUAN_PREFIX(assuan_write_status)
+#define assuan_command_parse_fd _ASSUAN_PREFIX(assuan_command_parse_fd)
+#define assuan_set_hello_line _ASSUAN_PREFIX(assuan_set_hello_line)
+#define assuan_accept _ASSUAN_PREFIX(assuan_accept)
+#define assuan_get_input_fd _ASSUAN_PREFIX(assuan_get_input_fd)
+#define assuan_get_output_fd _ASSUAN_PREFIX(assuan_get_output_fd)
+#define assuan_close_input_fd _ASSUAN_PREFIX(assuan_close_input_fd)
+#define assuan_close_output_fd _ASSUAN_PREFIX(assuan_close_output_fd)
+#define assuan_init_pipe_server _ASSUAN_PREFIX(assuan_init_pipe_server)
+#define assuan_deinit_server _ASSUAN_PREFIX(assuan_deinit_server)
+#define assuan_init_socket_server _ASSUAN_PREFIX(assuan_init_socket_server)
+#define assuan_init_connected_socket_server \
+ _ASSUAN_PREFIX(assuan_init_connected_socket_server)
+#define assuan_pipe_connect _ASSUAN_PREFIX(assuan_pipe_connect)
+#define assuan_socket_connect _ASSUAN_PREFIX(assuan_socket_connect)
+#define assuan_domain_connect _ASSUAN_PREFIX(assuan_domain_connect)
+#define assuan_init_domain_server _ASSUAN_PREFIX(assuan_init_domain_server)
+#define assuan_disconnect _ASSUAN_PREFIX(assuan_disconnect)
+#define assuan_get_pid _ASSUAN_PREFIX(assuan_get_pid)
+#define assuan_transact _ASSUAN_PREFIX(assuan_transact)
+#define assuan_inquire _ASSUAN_PREFIX(assuan_inquire)
+#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_send_data _ASSUAN_PREFIX(assuan_send_data)
+#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_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_get_pointer _ASSUAN_PREFIX(assuan_get_pointer)
+#define assuan_begin_confidential _ASSUAN_PREFIX(assuan_begin_confidential)
+#define assuan_end_confidential _ASSUAN_PREFIX(assuan_end_confidential)
+#define assuan_strerror _ASSUAN_PREFIX(assuan_strerror)
+#define assuan_set_assuan_log_stream \
+ _ASSUAN_PREFIX(assuan_set_assuan_log_stream)
+#define assuan_get_assuan_log_stream \
+ _ASSUAN_PREFIX(assuan_get_assuan_log_stream)
+#define assuan_get_assuan_log_prefix \
+ _ASSUAN_PREFIX(assuan_get_assuan_log_prefix)
+
+/* And now the internal functions, argh... */
+#define _assuan_read_line _ASSUAN_PREFIX(_assuan_read_line)
+#define _assuan_cookie_write_data _ASSUAN_PREFIX(_assuan_cookie_write_data)
+#define _assuan_cookie_write_flush _ASSUAN_PREFIX(_assuan_cookie_write_flush)
+#define _assuan_read_from_server _ASSUAN_PREFIX(_assuan_read_from_server)
+#define _assuan_domain_init _ASSUAN_PREFIX(_assuan_domain_init)
+#define _assuan_register_std_commands \
+ _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_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_realloc _ASSUAN_PREFIX(_assuan_realloc)
+#define _assuan_calloc _ASSUAN_PREFIX(_assuan_calloc)
+#define _assuan_free _ASSUAN_PREFIX(_assuan_free)
+#define _assuan_log_print_buffer _ASSUAN_PREFIX(_assuan_log_print_buffer)
+#define _assuan_log_sanitized_string \
+ _ASSUAN_PREFIX(_assuan_log_sanitized_string)
+
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+typedef enum
+{
+ ASSUAN_No_Error = 0,
+ ASSUAN_General_Error = 1,
+ ASSUAN_Out_Of_Core = 2,
+ ASSUAN_Invalid_Value = 3,
+ ASSUAN_Timeout = 4,
+ ASSUAN_Read_Error = 5,
+ ASSUAN_Write_Error = 6,
+ ASSUAN_Problem_Starting_Server = 7,
+ ASSUAN_Not_A_Server = 8,
+ ASSUAN_Not_A_Client = 9,
+ ASSUAN_Nested_Commands = 10,
+ ASSUAN_Invalid_Response = 11,
+ ASSUAN_No_Data_Callback = 12,
+ ASSUAN_No_Inquire_Callback = 13,
+ ASSUAN_Connect_Failed = 14,
+ ASSUAN_Accept_Failed = 15,
+
+ /* error codes above 99 are meant as status codes */
+ ASSUAN_Not_Implemented = 100,
+ ASSUAN_Server_Fault = 101,
+ ASSUAN_Invalid_Command = 102,
+ ASSUAN_Unknown_Command = 103,
+ ASSUAN_Syntax_Error = 104,
+ ASSUAN_Parameter_Error = 105,
+ ASSUAN_Parameter_Conflict = 106,
+ ASSUAN_Line_Too_Long = 107,
+ ASSUAN_Line_Not_Terminated = 108,
+ ASSUAN_No_Input = 109,
+ ASSUAN_No_Output = 110,
+ ASSUAN_Canceled = 111,
+ ASSUAN_Unsupported_Algorithm = 112,
+ ASSUAN_Server_Resource_Problem = 113,
+ ASSUAN_Server_IO_Error = 114,
+ ASSUAN_Server_Bug = 115,
+ ASSUAN_No_Data_Available = 116,
+ ASSUAN_Invalid_Data = 117,
+ ASSUAN_Unexpected_Command = 118,
+ ASSUAN_Too_Much_Data = 119,
+ ASSUAN_Inquire_Unknown = 120,
+ ASSUAN_Inquire_Error = 121,
+ ASSUAN_Invalid_Option = 122,
+ ASSUAN_Invalid_Index = 123,
+ ASSUAN_Unexpected_Status = 124,
+ ASSUAN_Unexpected_Data = 125,
+ ASSUAN_Invalid_Status = 126,
+
+ ASSUAN_Not_Confirmed = 128,
+
+ ASSUAN_Bad_Certificate = 201,
+ ASSUAN_Bad_Certificate_Chain = 202,
+ ASSUAN_Missing_Certificate = 203,
+ ASSUAN_Bad_Signature = 204,
+ ASSUAN_No_Agent = 205,
+ ASSUAN_Agent_Error = 206,
+ ASSUAN_No_Public_Key = 207,
+ ASSUAN_No_Secret_Key = 208,
+ ASSUAN_Invalid_Name = 209,
+
+ ASSUAN_Cert_Revoked = 301,
+ ASSUAN_No_CRL_For_Cert = 302,
+ ASSUAN_CRL_Too_Old = 303,
+ ASSUAN_Not_Trusted = 304,
+
+ ASSUAN_Card_Error = 401,
+ ASSUAN_Invalid_Card = 402,
+ ASSUAN_No_PKCS15_App = 403,
+ ASSUAN_Card_Not_Present = 404,
+ ASSUAN_Invalid_Id = 405
+
+} AssuanError;
+
+/* This is a list of pre-registered ASSUAN commands */
+typedef enum
+{
+ ASSUAN_CMD_NOP = 0,
+ ASSUAN_CMD_CANCEL, /* cancel the current request */
+ ASSUAN_CMD_BYE,
+ ASSUAN_CMD_AUTH,
+ ASSUAN_CMD_RESET,
+ ASSUAN_CMD_OPTION,
+ ASSUAN_CMD_DATA,
+ ASSUAN_CMD_END,
+ ASSUAN_CMD_INPUT,
+ ASSUAN_CMD_OUTPUT,
+
+ ASSUAN_CMD_USER = 256 /* Other commands should be used with this offset*/
+} AssuanCommand;
+
+#define ASSUAN_LINELENGTH 1002 /* 1000 + [CR,]LF */
+
+struct assuan_context_s;
+typedef struct assuan_context_s *ASSUAN_CONTEXT;
+
+/*-- assuan-handler.c --*/
+int assuan_register_command (ASSUAN_CONTEXT ctx,
+ const char *cmd_string,
+ int (*handler)(ASSUAN_CONTEXT, char *));
+int assuan_register_bye_notify (ASSUAN_CONTEXT ctx,
+ void (*fnc)(ASSUAN_CONTEXT));
+int assuan_register_reset_notify (ASSUAN_CONTEXT ctx,
+ void (*fnc)(ASSUAN_CONTEXT));
+int assuan_register_cancel_notify (ASSUAN_CONTEXT ctx,
+ void (*fnc)(ASSUAN_CONTEXT));
+int assuan_register_input_notify (ASSUAN_CONTEXT ctx,
+ void (*fnc)(ASSUAN_CONTEXT, const char *));
+int assuan_register_output_notify (ASSUAN_CONTEXT ctx,
+ void (*fnc)(ASSUAN_CONTEXT, const char *));
+
+int assuan_register_option_handler (ASSUAN_CONTEXT ctx,
+ int (*fnc)(ASSUAN_CONTEXT,
+ const char*, const char*));
+
+int assuan_process (ASSUAN_CONTEXT ctx);
+int assuan_process_next (ASSUAN_CONTEXT ctx);
+int assuan_get_active_fds (ASSUAN_CONTEXT ctx, int what,
+ int *fdarray, int fdarraysize);
+
+
+FILE *assuan_get_data_fp (ASSUAN_CONTEXT ctx);
+AssuanError assuan_set_okay_line (ASSUAN_CONTEXT ctx, const char *line);
+void assuan_write_status (ASSUAN_CONTEXT ctx,
+ const char *keyword, const char *text);
+
+/* 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). */
+AssuanError assuan_command_parse_fd (ASSUAN_CONTEXT ctx, char *line,
+ int *rfd);
+
+/*-- assuan-listen.c --*/
+AssuanError assuan_set_hello_line (ASSUAN_CONTEXT ctx, const char *line);
+AssuanError assuan_accept (ASSUAN_CONTEXT ctx);
+int assuan_get_input_fd (ASSUAN_CONTEXT ctx);
+int assuan_get_output_fd (ASSUAN_CONTEXT ctx);
+AssuanError assuan_close_input_fd (ASSUAN_CONTEXT ctx);
+AssuanError assuan_close_output_fd (ASSUAN_CONTEXT ctx);
+
+
+/*-- assuan-pipe-server.c --*/
+int assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2]);
+void assuan_deinit_server (ASSUAN_CONTEXT ctx);
+
+/*-- assuan-socket-server.c --*/
+int assuan_init_socket_server (ASSUAN_CONTEXT *r_ctx, int listen_fd);
+int assuan_init_connected_socket_server (ASSUAN_CONTEXT *r_ctx, int fd);
+
+
+/*-- assuan-pipe-connect.c --*/
+AssuanError assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name,
+ char *const argv[], int *fd_child_list);
+/*-- assuan-socket-connect.c --*/
+AssuanError assuan_socket_connect (ASSUAN_CONTEXT *ctx, const char *name,
+ pid_t server_pid);
+
+/*-- assuan-domain-connect.c --*/
+
+/* Connect to a Unix domain socket server. RENDEZVOUSFD is
+ bidirectional file descriptor (normally returned via socketpair)
+ which the client can use to rendezvous with the server. SERVER s
+ the server's pid. */
+AssuanError assuan_domain_connect (ASSUAN_CONTEXT *r_ctx,
+ int rendezvousfd,
+ pid_t server);
+
+/*-- assuan-domain-server.c --*/
+
+/* RENDEZVOUSFD is a bidirectional file descriptor (normally returned
+ via socketpair) that the domain server can use to rendezvous with
+ the client. CLIENT is the client's pid. */
+AssuanError assuan_init_domain_server (ASSUAN_CONTEXT *r_ctx,
+ int rendezvousfd,
+ pid_t client);
+
+
+/*-- assuan-connect.c --*/
+void assuan_disconnect (ASSUAN_CONTEXT ctx);
+pid_t assuan_get_pid (ASSUAN_CONTEXT ctx);
+
+/*-- assuan-client.c --*/
+AssuanError
+assuan_transact (ASSUAN_CONTEXT ctx,
+ const char *command,
+ AssuanError (*data_cb)(void *, const void *, size_t),
+ void *data_cb_arg,
+ AssuanError (*inquire_cb)(void*, const char *),
+ void *inquire_cb_arg,
+ AssuanError (*status_cb)(void*, const char *),
+ void *status_cb_arg);
+
+
+/*-- assuan-inquire.c --*/
+AssuanError assuan_inquire (ASSUAN_CONTEXT ctx, const char *keyword,
+ char **r_buffer, size_t *r_length, size_t maxlen);
+
+/*-- assuan-buffer.c --*/
+AssuanError assuan_read_line (ASSUAN_CONTEXT ctx,
+ char **line, size_t *linelen);
+int assuan_pending_line (ASSUAN_CONTEXT ctx);
+AssuanError assuan_write_line (ASSUAN_CONTEXT ctx, const char *line );
+AssuanError assuan_send_data (ASSUAN_CONTEXT ctx,
+ const void *buffer, size_t length);
+
+/* The file descriptor must be pending before assuan_receivefd is
+ call. This means that assuan_sendfd should be called *before* the
+ trigger is sent (normally via assuan_send_data ("I sent you a
+ descriptor")). */
+AssuanError assuan_sendfd (ASSUAN_CONTEXT ctx, int fd);
+AssuanError assuan_receivefd (ASSUAN_CONTEXT ctx, int *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_log_stream (ASSUAN_CONTEXT ctx, FILE *fp);
+int assuan_set_error (ASSUAN_CONTEXT ctx, int err, const char *text);
+void assuan_set_pointer (ASSUAN_CONTEXT ctx, void *pointer);
+void *assuan_get_pointer (ASSUAN_CONTEXT ctx);
+
+void assuan_begin_confidential (ASSUAN_CONTEXT ctx);
+void assuan_end_confidential (ASSUAN_CONTEXT ctx);
+
+/*-- assuan-errors.c (built) --*/
+const char *assuan_strerror (AssuanError err);
+
+/*-- assuan-logging.c --*/
+
+/* Set the stream to which assuan should log. By default, this is
+ stderr. */
+extern void assuan_set_assuan_log_stream (FILE *fp);
+
+/* Return the stream which is currently being using for logging. */
+extern FILE *assuan_get_assuan_log_stream (void);
+
+/* User defined call back. Return a prefix to be used at the start of
+ a line emitted by assuan on the log stream. The default
+ implementation returns the empty string, i.e. "" */
+extern const char *assuan_get_assuan_log_prefix (void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* ASSUAN_H */
diff --git a/branches/gpgme-1-0-branch/assuan/mkerrors b/branches/gpgme-1-0-branch/assuan/mkerrors
new file mode 100755
index 00000000..11129419
--- /dev/null
+++ b/branches/gpgme-1-0-branch/assuan/mkerrors
@@ -0,0 +1,82 @@
+#!/bin/sh
+# mkerrors - Extract error strings from assuan.h
+# and create C source for assuan_strerror
+# Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+#
+# This file is part of Assuan.
+#
+# Assuan is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+#
+# Assuan is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+
+cat <<EOF
+/* Generated automatically by mkerrors */
+/* Do not edit! */
+
+#include <stdio.h>
+#include "assuan.h"
+
+/**
+ * assuan_strerror:
+ * @err: Error code
+ *
+ * This function returns a textual representaion of the given
+ * errorcode. If this is an unknown value, a string with the value
+ * is returned (Beware: it is hold in a static buffer).
+ *
+ * Return value: String with the error description.
+ **/
+const char *
+assuan_strerror (AssuanError err)
+{
+ const char *s;
+ static char buf[50];
+
+ switch (err)
+ {
+EOF
+
+awk '
+/ASSUAN_No_Error/ { okay=1 }
+!okay {next}
+/}/ { exit 0 }
+/ASSUAN_[A-Za-z_]*/ { print_code($1) }
+
+
+function print_code( s )
+{
+printf " case %s: s=\"", s ;
+gsub(/_/, " ", s );
+printf "%s\"; break;\n", tolower(substr(s,8));
+}
+'
+
+cat <<EOF
+ default:
+ {
+ unsigned int source, code;
+
+ source = ((err >> 24) & 0xff);
+ code = (err & 0x00ffffff);
+ if (source) /* Assume this is an libgpg-error. */
+ sprintf (buf, "ec=%u.%u", source, code );
+ else
+ sprintf (buf, "ec=%d", err );
+ s=buf; break;
+ }
+ }
+
+ return s;
+}
+
+EOF \ No newline at end of file