assuan/
authorMarcus Brinkmann <mb@g10code.com>
Tue, 19 Sep 2006 14:01:54 +0000 (14:01 +0000)
committerMarcus Brinkmann <mb@g10code.com>
Tue, 19 Sep 2006 14:01:54 +0000 (14:01 +0000)
Update to current version.

2006-09-19  Marcus Brinkmann  <marcus@g10code.de>

* configure.ac: Turn stpcpy into a replacement function.
Check for unistd.h and add setenv as replacement function.

gpgme/
2006-09-19  Marcus Brinkmann  <marcus@g10code.de>

* setenv.c: New file.

27 files changed:
ChangeLog
assuan/ChangeLog
assuan/Makefile.am
assuan/assuan-buffer.c
assuan/assuan-client.c
assuan/assuan-connect.c
assuan/assuan-defs.h
assuan/assuan-domain-connect.c
assuan/assuan-domain-server.c
assuan/assuan-handler.c
assuan/assuan-inquire.c
assuan/assuan-io.c
assuan/assuan-listen.c
assuan/assuan-logging.c
assuan/assuan-pipe-connect.c
assuan/assuan-pipe-server.c
assuan/assuan-socket-connect.c
assuan/assuan-socket-server.c
assuan/assuan-socket.c
assuan/assuan-uds.c [new file with mode: 0644]
assuan/assuan-util.c
assuan/assuan.h
assuan/funopen.c
assuan/mkerrors
configure.ac
gpgme/gpgme.h
gpgme/setenv.c [new file with mode: 0644]

index 1e9c68b..a91322d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2006-09-19  Marcus Brinkmann  <marcus@g10code.de>
+
+       * configure.ac: Turn stpcpy into a replacement function.
+       Check for unistd.h and add setenv as replacement function.
+
 2006-07-29  Marcus Brinkmann  <marcus@g10code.de>
 
        * configure.ac: Check for network libraries and set NETLIBS.
index 3aef839..d9519c1 100644 (file)
@@ -1,3 +1,171 @@
+2006-09-19  Marcus Brinkmann  <marcus@g10code.de>
+
+       * assuan.h (assuan_init_socket_server_ext)
+       [_ASSUAN_EXT_SYM_PREFIX]: Fix typo in macro.
+
+2006-09-19  Werner Koch  <wk@g10code.com>
+
+       * assuan-defs.h (putc_unlocked): Add prototype.
+
+       * assuan-socket-server.c (accept_connection): Made LEN a socklen_t.
+
+       * assuan.h: Replaced assuan error code enum by simple defines and
+       made assuan_error_t an int.
+       * mkerrors: Changed parser accordingly.
+
+2006-09-19  Marcus Brinkmann  <marcus@g10code.de>
+
+       * assuan-pipe-connect.c: Add hacks for Slowaris.
+       * assuan-socket.c: Likewise here.
+
+       * assuan.h (enum): Avoid trailing comma in enumerator list.  Ugh.
+
+       * mkerrors (_assuan_error): Change return type to assuan_error_t.
+       * assuan-buffer.c (_assuan_read_line): Change return type to
+       assuan_error_t.  Map returned value of -1.
+       (_assuan_write_line): Change type of RC to assuan_error_t.
+       * assuan-defs.h (_assuan_read_line, _assuan_error): Likewise for
+       prototypes.
+
+       * assuan-defs.h (unsetenv): Define correctly.
+
+2006-09-14  Werner Koch  <wk@g10code.com>
+
+       * assuan-io.c (_assuan_waitpid): New.  Changed all waitpid calls
+       to this.
+
+       * assuan.h (_ASSUAN_DEPRECATED): New internal macro.
+       (assuan_pipe_connect2): Declare deprecated.
+       (assuan_init_connected_socket_server): Declare deprecated.
+
+       * assuan-connect.c (assuan_get_peercred): New.
+       * assuan-socket-server.c (accept_connection_bottom): Save uid and gid.
+
+2006-09-13  Werner Koch  <wk@g10code.com>
+
+       * assuan-client.c (assuan_transact): Need to map the error code.
+       * mkerrors: Need to map ASSUAN_No_Secret_Key.
+
+       * assuan-pipe-server.c (is_valid_socket): New.
+       (assuan_init_pipe_server): Use UDS with the environmet variable is
+       set and a valid descriptor is given.  Ignore FILEDES in this case.
+
+       * assuan-socket-server.c (assuan_init_socket_server_ext): New.
+       Changed other init fucntions to make use of it.
+
+       * assuan-handler.c (assuan_command_parse_fd): Allow for lowercase
+       "fd".
+       (std_handler_reset): Close pending fds.
+       * assuan-uds.c (uds_receivefd): Fixed.
+       (_assuan_uds_close_fds): New.
+
+       * assuan-socket-connect.c (assuan_socket_connect_ext): New. Takes
+       all code of assuan_socket_connect plus an option to use sendmsg.
+       * assuan-pipe-connect.c (assuan_pipe_connect_ext): New arg FLAGS.
+
+2006-09-12  Werner Koch  <wk@g10code.com>
+
+       * assuan-buffer.c (_assuan_write_line): Also log the prefix.
+
+       * assuan-defs.h (DIM, DIMof): New.
+
+       * assuan-domain-server.c: Removed.
+       * assuan-domain-connect.c: Renamed to ..
+       * assuan-uds.c: this.
+       (domain_reader, domain_writer, domain_sendfd, domain_receivefd) 
+       (assuan_domain_connect, _assuan_domain_init): Removed. 
+       (uds_reader, uds_writer, uds_sendfd, uds_receivefd) 
+       (_assuan_init_uds_io): New.
+       (_assuan_uds_deinit): New.
+
+       * assuan-io.c (_assuan_simple_sendmsg, _assuan_simple_recvmsg): New.
+       (my_pth_fdmode, my_pth_select): New.
+
+2006-09-11  Werner Koch  <wk@g10code.com>
+
+       * assuan-pipe-server.c (assuan_init_pipe_server): Allow for
+       FILEDES to be NULL and try to start as a socketpair server in this
+       case.
+
+       * assuan-pipe-connect.c (assuan_pipe_connect2): Split up into two
+       functions (unix and w32) for clarity.
+       (pipe_connect_unix): This is the new fucntion.  Add USE_CMSG flag.
+       (pipe_connect_w32): Ditto.
+       (initial_handshake): Factored out code.
+       (socketpair_connect): New.
+       (assuan_pipe_connect_ext): New.
+       (do_finish): Handle case if outbound and inbound fd are the same.
+       This is to support socketpairs.
+
+2006-09-10  Werner Koch  <wk@g10code.com>
+
+       * assuan-util.c (_assuan_log_print_buffer)
+       (_assuan_log_sanitized_string,assuan_set_log_stream): Moved to ..
+       * assuan-logging.c: .. here.
+       (_assuan_log_print_buffer): Only print the leading bytes in hex
+       log mode unless the new env variable ASSUAN_FULL_LOGGING has been
+       set.
+       (_assuan_set_default_log_stream): Test this env variable.
+
+2006-09-06  Werner Koch  <wk@g10code.com>
+
+       * assuan.h (_ASSUAN_ONLY_GPG_ERRORS): New.
+
+       * assuan-handler.c (dispatch_command): Use Syntax_Error instead of
+       Invalid_Command.
+
+       * assuan-domain-connect.c: Changed alloc malloc/free/realloc to
+       xtrymalloc et al.
+       (read_int, write_int): Make args void pointers.
+       (domain_receivefd): Take care of realloc shrinking failure.
+
+       * assuan-buffer.c (_assuan_read_line, _assuan_write_line)
+       (assuan_write_line, _assuan_cookie_write_data)
+       (_assuan_cookie_write_flush): Print the inbound fd instead of the
+       address of the context when logging I/0.  This makes it more
+       readable.
+
+2006-09-05  Werner Koch  <wk@g10code.com>
+
+       * assuan-defs.h (err_code, err_is_eof): New.
+
+       * mkerrors (_assuan_error): New.  Wrapped all error code
+       assignments in a call to this.
+       (assuan_strerror): Map gpg-style error codes back. Also print a
+       string for the old EOF code.
+       (assuan_set_assuan_err_source): New.
+
+       * assuan-logging.c (_assuan_log_printf): Do not change ERRNO and
+       print the pid.
+
+       * assuan-domain-connect.c (domain_reader): Replaced plain printf
+       by assuan_log function.
+
+2005-10-24  Werner Koch  <wk@g10code.com>
+
+       * putc_unlocked.c, memrchr.c, isascii.c, funopen.c: Changed
+       distribution terms to LGPL.  This are small and trivial files so
+       there are no obstacles of doing so.
+       * assuan-socket.c: Likewise, the stated GPL was not intended.
+
+2005-10-08  Marcus Brinkmann  <marcus@g10code.de>
+
+       * assuan-defs.h (setenv, unsetenv, clearenv) [!HAVE_SETENV]:
+       Define to _assuan_*.
+       * setenv.c: Include "assuan-defs.h".
+       (__add_to_environ): Make static.
+
+2005-10-07  Marcus Brinkmann  <marcus@g10code.de>
+
+       * assuan-defs.h (memrchr) [!HAVE_MEMRCHR]: New prototype.
+       (stpcpy) [!HAVE_STPCPY]: Likewise.
+       * stpcpy.c: New LGPL'ed file from the GNU C Library.
+       * setenv.c: New file.
+       * assuan-domain-connect.c (read_int): New function.
+       (write_int): New function.
+       (domain_reader): Use read_int.
+       (domain_sendfd): Use write_int.
+
 2005-10-01  Marcus Brinkmann  <marcus@g10code.de>
 
        * assuan.h (assuan_pipe_connect, assuan_pipe_connect2): Make type
index b88b7dc..e19a356 100644 (file)
@@ -15,7 +15,7 @@
 #
 # 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 
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 
 
 ## Process this file with automake to produce Makefile.in
 
@@ -44,12 +44,11 @@ libassuan_la_SOURCES = \
        assuan-socket-server.c \
        assuan-pipe-connect.c \
        assuan-socket-connect.c  \
-       assuan-socket.c \
+       assuan-uds.c \
        funopen.c \
        assuan-io.c \
-       assuan-domain-connect.c \
-       assuan-domain-server.c \
-       assuan-logging.c
+       assuan-logging.c \
+       assuan-socket.c
 
-assuan-errors.c : assuan.h
+assuan-errors.c : assuan.h mkerrors
        $(srcdir)/mkerrors < $(srcdir)/assuan.h > assuan-errors.c
index 99ea72e..5580392 100644 (file)
@@ -15,7 +15,8 @@
  *
  * 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 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA. 
  */
 
 #include <config.h>
 #endif
 #include "assuan-defs.h"
 
+
+/* Extended version of write(2) to guarantee that all bytes are
+   written.  Returns 0 on success or -1 and ERRNO on failure. */
 static int
-writen (ASSUAN_CONTEXT ctx, const char *buffer, size_t length)
+writen (assuan_context_t ctx, const char *buffer, size_t length)
 {
   while (length)
     {
@@ -49,9 +53,11 @@ writen (ASSUAN_CONTEXT ctx, const char *buffer, size_t length)
   return 0;  /* okay */
 }
 
-/* Read an entire line.  */
+/* Read an entire line. Returns 0 on success or -1 and ERRNo on
+   failure.  EOF is indictated by setting the integer at address
+   R_EOF.  */
 static int
-readline (ASSUAN_CONTEXT ctx, char *buf, size_t buflen,
+readline (assuan_context_t ctx, char *buf, size_t buflen,
          int *r_nread, int *r_eof)
 {
   size_t nleft = buflen;
@@ -88,8 +94,9 @@ readline (ASSUAN_CONTEXT ctx, char *buf, size_t buflen,
 }
 
 
-int
-_assuan_read_line (ASSUAN_CONTEXT ctx)
+/* Function returns an Assuan error. */
+assuan_error_t
+_assuan_read_line (assuan_context_t ctx)
 {
   char *line = ctx->inbound.line;
   int nread, atticlen;
@@ -97,7 +104,7 @@ _assuan_read_line (ASSUAN_CONTEXT ctx)
   char *endp = 0;
 
   if (ctx->inbound.eof)
-    return -1;
+    return _assuan_error (-1);
 
   atticlen = ctx->inbound.attic.linelen;
   if (atticlen)
@@ -128,19 +135,20 @@ _assuan_read_line (ASSUAN_CONTEXT ctx)
   if (rc)
     {
       if (ctx->log_fp)
-       fprintf (ctx->log_fp, "%s[%u.%p] DBG: <- [Error: %s]\n",
+       fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- [Error: %s]\n",
                 assuan_get_assuan_log_prefix (),
-                 (unsigned int)getpid (), ctx, strerror (errno));
-      return ASSUAN_Read_Error;
+                 (unsigned int)getpid (), ctx->inbound.fd,
+                 strerror (errno));
+      return _assuan_error (ASSUAN_Read_Error);
     }
   if (!nread)
     {
       assert (ctx->inbound.eof);
       if (ctx->log_fp)
-       fprintf (ctx->log_fp, "%s[%u.%p] DBG: <- [EOF]\n",
+       fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- [EOF]\n",
                 assuan_get_assuan_log_prefix (),
-                 (unsigned int)getpid (), ctx);
-      return -1;
+                 (unsigned int)getpid (), ctx->inbound.fd);
+      return _assuan_error (-1);
     }
 
   ctx->inbound.attic.pending = 0;
@@ -170,9 +178,9 @@ _assuan_read_line (ASSUAN_CONTEXT ctx)
       ctx->inbound.linelen = endp - line;
       if (ctx->log_fp)
        {
-         fprintf (ctx->log_fp, "%s[%u.%p] DBG: <- ",
+         fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- ",
                   assuan_get_assuan_log_prefix (),
-                   (unsigned int)getpid (), ctx);
+                   (unsigned int)getpid (), ctx->inbound.fd);
          if (ctx->confidential)
            fputs ("[Confidential data not shown]", ctx->log_fp);
          else
@@ -186,13 +194,14 @@ _assuan_read_line (ASSUAN_CONTEXT ctx)
   else
     {
       if (ctx->log_fp)
-       fprintf (ctx->log_fp, "%s[%u.%p] DBG: <- [Invalid line]\n",
+       fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- [Invalid line]\n",
                 assuan_get_assuan_log_prefix (),
-                 (unsigned int)getpid (), ctx);
+                 (unsigned int)getpid (), ctx->inbound.fd);
       *line = 0;
       ctx->inbound.linelen = 0;
-      return ctx->inbound.eof ? ASSUAN_Line_Not_Terminated
-       : ASSUAN_Line_Too_Long;
+      return _assuan_error (ctx->inbound.eof 
+                            ? ASSUAN_Line_Not_Terminated
+                            : ASSUAN_Line_Too_Long);
     }
 }
 
@@ -207,12 +216,12 @@ _assuan_read_line (ASSUAN_CONTEXT ctx)
    See also: assuan_pending_line().
 */
 assuan_error_t
-assuan_read_line (ASSUAN_CONTEXT ctx, char **line, size_t *linelen)
+assuan_read_line (assuan_context_t ctx, char **line, size_t *linelen)
 {
   assuan_error_t err;
 
   if (!ctx)
-    return ASSUAN_Invalid_Value;
+    return _assuan_error (ASSUAN_Invalid_Value);
 
   err = _assuan_read_line (ctx);
   *line = ctx->inbound.line;
@@ -224,7 +233,7 @@ assuan_read_line (ASSUAN_CONTEXT ctx, char **line, size_t *linelen)
 /* 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)
+assuan_pending_line (assuan_context_t ctx)
 {
   return ctx && ctx->inbound.attic.pending;
 }
@@ -234,17 +243,17 @@ assuan_error_t
 _assuan_write_line (assuan_context_t ctx, const char *prefix,
                     const char *line, size_t len)
 {
-  int rc = 0;
+  assuan_error_t rc = 0;
   size_t prefixlen = prefix? strlen (prefix):0;
 
   /* Make sure that the line is short enough. */
   if (len + prefixlen + 2 > ASSUAN_LINELENGTH)
     {
       if (ctx->log_fp)
-        fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> "
+        fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> "
                  "[supplied line too long -truncated]\n",
                  assuan_get_assuan_log_prefix (),
-                 (unsigned int)getpid (), ctx);
+                 (unsigned int)getpid (), ctx->inbound.fd);
       if (prefixlen > 5)
         prefixlen = 5;
       if (len > ASSUAN_LINELENGTH - prefixlen - 2)
@@ -254,13 +263,17 @@ _assuan_write_line (assuan_context_t ctx, const char *prefix,
   /* Fixme: we should do some kind of line buffering.  */
   if (ctx->log_fp)
     {
-      fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> ",
+      fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> ",
               assuan_get_assuan_log_prefix (),
-               (unsigned int)getpid (), ctx);
+               (unsigned int)getpid (), ctx->inbound.fd);
       if (ctx->confidential)
        fputs ("[Confidential data not shown]", ctx->log_fp);
       else
-       _assuan_log_print_buffer (ctx->log_fp, line, len);
+        {
+          if (prefixlen)
+            _assuan_log_print_buffer (ctx->log_fp, prefix, prefixlen);
+          _assuan_log_print_buffer (ctx->log_fp, line, len);
+        }
       putc ('\n', ctx->log_fp);
     }
 
@@ -268,18 +281,18 @@ _assuan_write_line (assuan_context_t ctx, const char *prefix,
     {
       rc = writen (ctx, prefix, prefixlen);
       if (rc)
-        rc = ASSUAN_Write_Error;
+        rc = _assuan_error (ASSUAN_Write_Error);
     }
   if (!rc)
     {
       rc = writen (ctx, line, len);
       if (rc)
-        rc = ASSUAN_Write_Error;
+        rc = _assuan_error (ASSUAN_Write_Error);
       if (!rc)
         {
           rc = writen (ctx, "\n", 1);
           if (rc)
-            rc = ASSUAN_Write_Error;
+            rc = _assuan_error (ASSUAN_Write_Error);
         }
     }
   return rc;
@@ -287,13 +300,13 @@ _assuan_write_line (assuan_context_t ctx, const char *prefix,
 
 
 assuan_error_t 
-assuan_write_line (ASSUAN_CONTEXT ctx, const char *line)
+assuan_write_line (assuan_context_t ctx, const char *line)
 {
   size_t len;
   const char *s;
 
   if (!ctx)
-    return ASSUAN_Invalid_Value;
+    return _assuan_error (ASSUAN_Invalid_Value);
 
   /* Make sure that we never take a LF from the user - this might
      violate the protocol. */
@@ -301,10 +314,10 @@ assuan_write_line (ASSUAN_CONTEXT ctx, const char *line)
   len = s? (s-line) : strlen (line);
 
   if (ctx->log_fp && s)
-    fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> "
-             "[supplied line contained a LF -truncated]\n",
+    fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> "
+             "[supplied line contained a LF - truncated]\n",
              assuan_get_assuan_log_prefix (),
-             (unsigned int)getpid (), ctx);
+             (unsigned int)getpid (), ctx->inbound.fd);
 
   return _assuan_write_line (ctx, NULL, line, len);
 }
@@ -316,7 +329,7 @@ assuan_write_line (ASSUAN_CONTEXT ctx, const char *line)
 int
 _assuan_cookie_write_data (void *cookie, const char *buffer, size_t orig_size)
 {
-  ASSUAN_CONTEXT ctx = cookie;
+  assuan_context_t ctx = cookie;
   size_t size = orig_size;
   char *line;
   size_t linelen;
@@ -359,9 +372,9 @@ _assuan_cookie_write_data (void *cookie, const char *buffer, size_t orig_size)
         {
           if (ctx->log_fp)
             {
-             fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> ",
+             fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> ",
                       assuan_get_assuan_log_prefix (),
-                       (unsigned int)getpid (), ctx);
+                       (unsigned int)getpid (), ctx->inbound.fd);
 
               if (ctx->confidential)
                 fputs ("[Confidential data not shown]", ctx->log_fp);
@@ -375,7 +388,7 @@ _assuan_cookie_write_data (void *cookie, const char *buffer, size_t orig_size)
           linelen++;
           if (writen (ctx, ctx->outbound.data.line, linelen))
             {
-              ctx->outbound.data.error = ASSUAN_Write_Error;
+              ctx->outbound.data.error = _assuan_error (ASSUAN_Write_Error);
               return 0;
             }
           line = ctx->outbound.data.line;
@@ -393,7 +406,7 @@ _assuan_cookie_write_data (void *cookie, const char *buffer, size_t orig_size)
 int
 _assuan_cookie_write_flush (void *cookie)
 {
-  ASSUAN_CONTEXT ctx = cookie;
+  assuan_context_t ctx = cookie;
   char *line;
   size_t linelen;
 
@@ -407,9 +420,9 @@ _assuan_cookie_write_flush (void *cookie)
     {
       if (ctx->log_fp)
        {
-         fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> ",
+         fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> ",
                   assuan_get_assuan_log_prefix (),
-                   (unsigned int)getpid (), ctx);
+                   (unsigned int)getpid (), ctx->inbound.fd);
          if (ctx->confidential)
            fputs ("[Confidential data not shown]", ctx->log_fp);
          else
@@ -421,7 +434,7 @@ _assuan_cookie_write_flush (void *cookie)
       linelen++;
       if (writen (ctx, ctx->outbound.data.line, linelen))
         {
-          ctx->outbound.data.error = ASSUAN_Write_Error;
+          ctx->outbound.data.error = _assuan_error (ASSUAN_Write_Error);
           return 0;
         }
       ctx->outbound.data.linelen = 0;
@@ -449,12 +462,12 @@ _assuan_cookie_write_flush (void *cookie)
  **/
 \f
 assuan_error_t
-assuan_send_data (ASSUAN_CONTEXT ctx, const void *buffer, size_t length)
+assuan_send_data (assuan_context_t ctx, const void *buffer, size_t length)
 {
   if (!ctx)
-    return ASSUAN_Invalid_Value;
+    return _assuan_error (ASSUAN_Invalid_Value);
   if (!buffer && length)
-    return ASSUAN_Invalid_Value;
+    return _assuan_error (ASSUAN_Invalid_Value);
 
   if (!buffer)
     { /* flush what we have */
@@ -475,7 +488,7 @@ assuan_send_data (ASSUAN_CONTEXT ctx, const void *buffer, size_t length)
 }
 
 assuan_error_t
-assuan_sendfd (ASSUAN_CONTEXT ctx, int fd)
+assuan_sendfd (assuan_context_t ctx, int fd)
 {
   if (! ctx->io->sendfd)
     return set_error (ctx, Not_Implemented,
@@ -485,7 +498,7 @@ assuan_sendfd (ASSUAN_CONTEXT ctx, int fd)
 }
 
 assuan_error_t
-assuan_receivefd (ASSUAN_CONTEXT ctx, int *fd)
+assuan_receivefd (assuan_context_t ctx, int *fd)
 {
   if (! ctx->io->receivefd)
     return set_error (ctx, Not_Implemented,
index 2f78d0c..06e3966 100644 (file)
@@ -15,7 +15,8 @@
  *
  * 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 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA. 
  */
 
 #include <config.h>
@@ -33,7 +34,7 @@
 
 
 assuan_error_t
-_assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off)
+_assuan_read_from_server (assuan_context_t ctx, int *okay, int *off)
 {
   char *line;
   int linelen;
@@ -103,7 +104,7 @@ _assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off)
       *off = 3;
     }
   else
-    rc = ASSUAN_Invalid_Response;
+    rc = _assuan_error (ASSUAN_Invalid_Response);
   return rc;
 }
 
@@ -112,7 +113,7 @@ _assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off)
 /**
  * assuan_transact:
  * @ctx: The Assuan context
- * @command: Coimmand line to be send to server
+ * @command: Command line to be send to the 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
@@ -124,19 +125,22 @@ _assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off)
  * 
  * 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.
+ * callback functions.  Take care: When a callback returns an error
+ * this function returns immediately with an error and thus the caller
+ * will altter return an Assuan error (write erro in most cases).
  **/
 assuan_error_t
-assuan_transact (ASSUAN_CONTEXT ctx,
+assuan_transact (assuan_context_t ctx,
                  const char *command,
-                 assuan_error_t (*data_cb)(void *, const void *, size_t),
+                 int (*data_cb)(void *, const void *, size_t),
                  void *data_cb_arg,
-                 assuan_error_t (*inquire_cb)(void*, const char *),
+                 int (*inquire_cb)(void*, const char *),
                  void *inquire_cb_arg,
-                 assuan_error_t (*status_cb)(void*, const char *),
+                 int (*status_cb)(void*, const char *),
                  void *status_cb_arg)
 {
-  int rc, okay, off;
+  assuan_error_t rc;
+  int okay, off;
   char *line;
   int linelen;
 
@@ -157,14 +161,14 @@ assuan_transact (ASSUAN_CONTEXT ctx,
 
   if (!okay)
     {
-      rc = atoi (line);
+      rc = _assuan_error (atoi (line));
       if (rc < 100)
         rc = ASSUAN_Server_Fault;
     }
   else if (okay == 2)
     {
       if (!data_cb)
-        rc = ASSUAN_No_Data_Callback;
+        rc = _assuan_error (ASSUAN_No_Data_Callback);
       else 
         {
           char *s, *d;
@@ -193,7 +197,7 @@ assuan_transact (ASSUAN_CONTEXT ctx,
         {
           assuan_write_line (ctx, "END"); /* get out of inquire mode */
           _assuan_read_from_server (ctx, &okay, &off); /* dummy read */
-          rc = ASSUAN_No_Inquire_Callback;
+          rc = _assuan_error (ASSUAN_No_Inquire_Callback);
         }
       else
         {
@@ -214,7 +218,7 @@ assuan_transact (ASSUAN_CONTEXT ctx,
   else if (okay == 5)
     {
       if (!data_cb)
-        rc = ASSUAN_No_Data_Callback;
+        rc = _assuan_error (ASSUAN_No_Data_Callback);
       else 
         {
           rc = data_cb (data_cb_arg, NULL, 0);
index ff1f6ff..92995d8 100644 (file)
@@ -15,7 +15,8 @@
  *
  * 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 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA. 
  */
 
 #ifdef HAVE_CONFIG_H
@@ -49,10 +50,30 @@ assuan_disconnect (assuan_context_t ctx)
     }
 }
 
-/* Return the PID of the peer or -1 if not known. */
+/* Return the PID of the peer or -1 if not known. This function works
+   in some situations where assuan_get_ucred fails. */
 pid_t
 assuan_get_pid (assuan_context_t ctx)
 {
   return (ctx && ctx->pid)? ctx->pid : -1;
 }
 
+
+/* Return user credentials. PID, UID and GID amy be gived as NULL if
+   you are not interested in this value.  For getting the pid of the
+   peer the assuan_get_pid is usually better suited. */
+assuan_error_t
+assuan_get_peercred (assuan_context_t ctx, pid_t *pid, uid_t *uid, gid_t *gid)
+{
+  if (!ctx)
+    return _assuan_error (ASSUAN_Invalid_Value);
+  if (!ctx->peercred.valid)
+    return _assuan_error (ASSUAN_General_Error);
+  if (pid)
+    *pid = ctx->peercred.pid;
+  if (uid)
+    *uid = ctx->peercred.uid;
+  if (gid)
+    *gid = ctx->peercred.gid;
+  return 0;
+}
index 2917fe8..7a96c0f 100644 (file)
@@ -1,5 +1,5 @@
 /* assuan-defs.c - Internal definitions to Assuan
- *     Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc.
+ *     Copyright (C) 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
  *
  * This file is part of Assuan.
  *
@@ -15,7 +15,8 @@
  *
  * 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 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
  */
 
 #ifndef ASSUAN_DEFS_H
@@ -62,24 +63,30 @@ char * stpcpy (char *dest, const char *src);
 
 #define LINELENGTH ASSUAN_LINELENGTH
 
+
 struct cmdtbl_s
 {
   const char *name;
-  int (*handler)(ASSUAN_CONTEXT, char *line);
+  int (*handler)(assuan_context_t, char *line);
 };
 
+
+/* A structure to dispatch I/O functions.  All these functions need to
+   return 0 on success and set ERRNO on failure.  */
 struct assuan_io
 {
   /* Routine to read from input_fd.  */
-  ssize_t (*readfnc) (ASSUAN_CONTEXT, void *, size_t);
+  ssize_t (*readfnc) (assuan_context_t, void *, size_t);
   /* Routine to write to output_fd.  */
-  ssize_t (*writefnc) (ASSUAN_CONTEXT, const void *, size_t);
+  ssize_t (*writefnc) (assuan_context_t, const void *, size_t);
   /* Send a file descriptor.  */
-  assuan_error_t (*sendfd) (ASSUAN_CONTEXT, int);
+  assuan_error_t (*sendfd) (assuan_context_t, int);
   /* Receive a file descriptor.  */
-  assuan_error_t (*receivefd) (ASSUAN_CONTEXT, int *);
-};  
+  assuan_error_t (*receivefd) (assuan_context_t, int *);
+};
+
 
+/* The context we use with most functions. */
 struct assuan_context_s
 {
   assuan_error_t err_no;
@@ -88,18 +95,18 @@ struct assuan_context_s
                          error codes. */
 
   /* Context specific flags (cf. assuan_flag_t). */
-  struct 
+  struct
   {
     unsigned int no_waitpid:1; /* See ASSUAN_NO_WAITPID. */
-  } flags; 
+  } flags;
 
   int confidential;
   int is_server;      /* Set if this is context belongs to a server */
   int in_inquire;
   char *hello_line;
   char *okay_line;    /* See assuan_set_okay_line() */
-  
-  void *user_pointer;  /* For assuan_get_pointer and assuan-set_pointer (). */
+
+  void *user_pointer;  /* For assuan_get_pointer and assuan_set_pointer (). */
 
   FILE *log_fp;
 
@@ -109,7 +116,7 @@ struct assuan_context_s
     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 */
+                     is always written at this pos. */
     struct {
       char line[LINELENGTH];
       int linelen ;
@@ -122,49 +129,55 @@ struct assuan_context_s
     struct {
       FILE *fp;
       char line[LINELENGTH];
-      int linelen; 
+      int linelen;
       int error;
-    } data; 
+    } 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;     /* The the pid of the peer. */
+                     connection and must terminate then. */
+  pid_t pid;     /* The pid of the peer. */
   int listen_fd;  /* The fd we are listening on (used by socket servers) */
   int connected_fd; /* helper */
 
+  struct {
+    int   valid;   /* Whether this structure has valid information. */
+    pid_t pid;     /* The pid of the peer. */
+    uid_t uid;     /* The uid of the peer. */
+    gid_t gid;     /* The gid of the peer. */
+  } peercred;
 
   /* 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);
+
+  /* Structure used for unix domain socket buffering.  FIXME: We don't
+     use datagrams anymore thus we could get away with a simpler
+     buffering approach. */
+  struct {
+    void *buffer;         /* Malloced buffer. */
+    int bufferallocated;  /* Memory allocated.  */
+    int bufferoffset;     /* Offset of start of buffer.  */
+    int buffersize;       /* Bytes buffered.  */
+    
+    int pendingfds[5];    /* Array to save received descriptors.  */
+    int pendingfdscount;  /* Number of received descriptors. */
+  } uds;
+
+  void (*deinit_handler)(assuan_context_t);
+  int (*accept_handler)(assuan_context_t);
+  int (*finish_handler)(assuan_context_t);
 
   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 *);
+  void (*bye_notify_fnc)(assuan_context_t);
+  void (*reset_notify_fnc)(assuan_context_t);
+  void (*cancel_notify_fnc)(assuan_context_t);
+  int  (*option_handler_fnc)(assuan_context_t,const char*, const char*);
+  void (*input_notify_fnc)(assuan_context_t, const char *);
+  void (*output_notify_fnc)(assuan_context_t, const char *);
 
   int input_fd;   /* set by INPUT command */
   int output_fd;  /* set by OUTPUT command */
@@ -174,29 +187,45 @@ struct assuan_context_s
 };
 
 /*-- assuan-pipe-server.c --*/
-int _assuan_new_context (ASSUAN_CONTEXT *r_ctx);
-void _assuan_release_context (ASSUAN_CONTEXT ctx);
+int _assuan_new_context (assuan_context_t *r_ctx);
+void _assuan_release_context (assuan_context_t ctx);
+
+/*-- assuan-uds.c --*/
+void _assuan_uds_close_fds (assuan_context_t ctx);
+void _assuan_uds_deinit (assuan_context_t ctx);
+void _assuan_init_uds_io (assuan_context_t 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.  */
-assuan_error_t _assuan_domain_init (ASSUAN_CONTEXT *r_ctx,
-                                int rendezvousfd,
-                                pid_t peer);
 
 /*-- assuan-handler.c --*/
-int _assuan_register_std_commands (ASSUAN_CONTEXT ctx);
+int _assuan_register_std_commands (assuan_context_t ctx);
 
 /*-- assuan-buffer.c --*/
-int _assuan_read_line (ASSUAN_CONTEXT ctx);
+assuan_error_t _assuan_read_line (assuan_context_t ctx);
 int _assuan_cookie_write_data (void *cookie, const char *buffer, size_t size);
 int _assuan_cookie_write_flush (void *cookie);
 assuan_error_t _assuan_write_line (assuan_context_t ctx, const char *prefix,
                                    const char *line, size_t len);
 
 /*-- assuan-client.c --*/
-assuan_error_t _assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off);
+assuan_error_t _assuan_read_from_server (assuan_context_t ctx,
+                                         int *okay, int *off);
+
+/*-- assuan-error.c --*/
+
+
+/* Map error codes as used in this implementaion to the libgpg-error
+   codes. */
+assuan_error_t _assuan_error (int oldcode);
+
+/* Extrac the erro code from A.  This works for both the old and the
+   new style error codes. This needs to be whenever an error code is
+   compared. */
+#define err_code(a) ((a) & 0x00ffffff)
+
+/* Check whether A is the erro code for EOF.  We allow forold and new
+   style EOF error codes here.  */
+#define err_is_eof(a) ((a) == (-1) || err_code (a) == 16383)
+
 
 
 /*-- assuan-util.c --*/
@@ -210,10 +239,8 @@ void  _assuan_free (void *p);
 #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);
+#define set_error(c,e,t) \
+        assuan_set_error ((c), _assuan_error (ASSUAN_ ## e), (t))
 
 #ifdef HAVE_W32_SYSTEM
 const char *_assuan_w32_strerror (int ec);
@@ -229,11 +256,18 @@ void _assuan_log_printf (const char *format, ...)
  __attribute__ ((format (printf,1,2)))
 #endif
      ;
+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,
+pid_t _assuan_waitpid (pid_t pid, int *status, int options);
+
+ssize_t _assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size);
+ssize_t _assuan_simple_write (assuan_context_t ctx, const void *buffer,
                              size_t size);
+ssize_t _assuan_simple_sendmsg (assuan_context_t ctx, struct msghdr *msg);
+ssize_t _assuan_simple_recvmsg (assuan_context_t ctx, struct msghdr *msg);
 
 /*-- assuan-socket.c --*/
 int _assuan_close (int fd);
@@ -251,5 +285,25 @@ FILE *_assuan_funopen(void *cookie,
 #define funopen(a,r,w,s,c) _assuan_funopen ((a), (r), (w), (s), (c))
 #endif /*HAVE_FOPENCOOKIE*/
 
-#endif /*ASSUAN_DEFS_H*/
+/* Prototypes for replacement functions.  */
+#ifndef HAVE_MEMRCHR
+void *memrchr (const void *block, int c, size_t size);
+#endif
+#ifndef HAVE_STPCPY
+char *stpcpy (char *dest, const char *src);
+#endif
+#ifndef HAVE_SETENV
+#define setenv _assuan_setenv
+#define unsetenv _assuan_unsetenv
+#define clearenv _assuan_clearenv
+int setenv (const char *name, const char *value, int replace);
+#endif
+#ifndef HAVE_PUTC_UNLOCKED
+int putc_unlocked (int c, FILE *stream)
+#endif
 
+#define DIM(v)              (sizeof(v)/sizeof((v)[0]))
+#define DIMof(type,member)   DIM(((type *)0)->member)
+
+
+#endif /*ASSUAN_DEFS_H*/
index b55e9c3..e69de29 100644 (file)
@@ -1,504 +0,0 @@
-/* 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>
-#ifndef HAVE_W32_SYSTEM
-#include <sys/socket.h>
-#include <sys/un.h>
-#else
-#include <windows.h>
-#endif
-#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"
-
-#ifndef PF_LOCAL
-# ifdef PF_UNIX
-#  define PF_LOCAL PF_UNIX
-# else
-#  define PF_LOCAL AF_UNIX
-# endif
-# ifndef AF_LOCAL
-#  define AF_LOCAL AF_UNIX
-# endif
-#endif
-
-
-static void
-do_deinit (assuan_context_t ctx)
-{
-  if (ctx->inbound.fd != -1)
-    _assuan_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 ++)
-       _assuan_close (ctx->pendingfds[i]);
-
-      free (ctx->pendingfds);
-    }
-
-  unlink (ctx->myaddr.sun_path);
-}
-
-
-/* Read from the socket server.  */
-static ssize_t
-domain_reader (assuan_context_t ctx, void *buf, size_t buflen)
-{
-  int len = ctx->domainbuffersize;
-
-#ifndef HAVE_W32_SYSTEM
- 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.  */
-         _assuan_log_printf ("not setup to receive messages from `%s'\n",
-                              ((struct sockaddr_un *) msg.msg_name)->sun_path);
-         goto start;
-       }
-
-      len = recvmsg (ctx->inbound.fd, &msg, 0);
-      if (len < 0)
-       {
-         _assuan_log_printf ("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)
-           {
-             _assuan_log_printf ("domain_reader: %s\n", strerror (errno));
-             return -1;
-           }
-
-         ctx->pendingfds = tmp;
-         ctx->pendingfds[ctx->pendingfdscount++]
-           = *(int *) CMSG_DATA (&cmsg.hdr);
-
-         _assuan_log_printf ("received file descriptor %d from peer\n",
-              ctx->pendingfds[ctx->pendingfdscount - 1]);
-       }
-
-      if (len == 0)
-       goto start;
-    }
-#else
-  len = recvfrom (ctx->inbound.fd, buf, buflen, 0, NULL, NULL);
-#endif
-
-  /* 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_t ctx, const void *buf, size_t buflen)
-{
-#ifndef HAVE_W32_SYSTEM
-  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)
-    _assuan_log_printf ("domain_writer: %s\n", strerror (errno));
-#else
-  int len;
-  
-  len = sendto (ctx->outbound.fd, buf, buflen, 0,
-                (struct sockaddr *)&ctx->serveraddr,
-                sizeof (struct sockaddr_in));
-#endif  
-  return len;
-}
-
-static assuan_error_t
-domain_sendfd (assuan_context_t ctx, int fd)
-{
-#ifndef HAVE_W32_SYSTEM
-  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)
-    {
-      _assuan_log_printf ("domain_sendfd: %s\n", strerror (errno));
-      return ASSUAN_General_Error;
-    }
-  else
-    return 0;
-#else
-  return 0;
-#endif
-}
-
-static assuan_error_t
-domain_receivefd (assuan_context_t ctx, int *fd)
-{
-#ifndef HAVE_W32_SYSTEM
-  if (ctx->pendingfds == 0)
-    {
-      _assuan_log_printf ("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));
-    }
-#endif
-  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.  */
-assuan_error_t
-_assuan_domain_init (assuan_context_t *r_ctx, int rendezvousfd, pid_t peer)
-{
-  static struct assuan_io io = { domain_reader, domain_writer,
-                                domain_sendfd, domain_receivefd };
-
-  assuan_error_t err;
-  assuan_context_t 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 = _assuan_sock_new (PF_LOCAL, SOCK_DGRAM, 0);
-  if (fd == -1)
-    {
-      _assuan_log_printf ("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));
-
-      /* XXX: W32 tmpnam is broken */
-      p = tmpnam (buf);
-      if (! p)
-       {
-         _assuan_log_printf ("cannot determine an appropriate temporary file "
-            "name.  DoS in progress?\n");
-         _assuan_release_context (ctx);
-         _assuan_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 = _assuan_sock_bind (fd, (struct sockaddr *) &ctx->myaddr, len);
-      if (! err)
-       break;
-    }
-
-  if (err)
-    {
-      _assuan_log_printf ("can't bind to `%s': %s\n", ctx->myaddr.sun_path,
-           strerror (errno));
-      _assuan_release_context (ctx);
-      _assuan_close (fd);
-      return ASSUAN_Connect_Failed;
-    }
-
-  /* Rendezvous with our peer.  */
-  {
-    FILE *fp;
-    char *p;
-
-    fp = fdopen (rendezvousfd, "w+");
-    if (! fp)
-      {
-       _assuan_log_printf ("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;
-}
-
-assuan_error_t
-assuan_domain_connect (assuan_context_t * r_ctx, int rendezvousfd, pid_t peer)
-{
-  assuan_error_t 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)
-    _assuan_log_printf ("can't connect to server: %s\n",
-                        assuan_strerror (aerr));
-  else if (okay != 1)
-    {
-      _assuan_log_printf ("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;
-}
index 45d53c2..e69de29 100644 (file)
@@ -1,46 +0,0 @@
-/* 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.  */
-assuan_error_t
-assuan_init_domain_server (ASSUAN_CONTEXT *r_ctx,
-                          int rendezvousfd,
-                          pid_t peer)
-{
-  assuan_error_t 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;
-}
index 21501a3..bf00d1a 100644 (file)
@@ -15,7 +15,8 @@
  *
  * 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 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA. 
  */
 
 #include <config.h>
@@ -36,20 +37,20 @@ static int my_strcasecmp (const char *a, const char *b);
 
 
 static int
-dummy_handler (ASSUAN_CONTEXT ctx, char *line)
+dummy_handler (assuan_context_t ctx, char *line)
 {
   return set_error (ctx, Server_Fault, "no handler registered");
 }
 
 
 static int
-std_handler_nop (ASSUAN_CONTEXT ctx, char *line)
+std_handler_nop (assuan_context_t ctx, char *line)
 {
   return 0; /* okay */
 }
   
 static int
-std_handler_cancel (ASSUAN_CONTEXT ctx, char *line)
+std_handler_cancel (assuan_context_t ctx, char *line)
 {
   if (ctx->cancel_notify_fnc)
     ctx->cancel_notify_fnc (ctx);
@@ -57,7 +58,7 @@ std_handler_cancel (ASSUAN_CONTEXT ctx, char *line)
 }
 
 static int
-std_handler_option (ASSUAN_CONTEXT ctx, char *line)
+std_handler_option (assuan_context_t ctx, char *line)
 {
   char *key, *value, *p;
 
@@ -104,7 +105,7 @@ std_handler_option (ASSUAN_CONTEXT ctx, char *line)
 }
   
 static int
-std_handler_bye (ASSUAN_CONTEXT ctx, char *line)
+std_handler_bye (assuan_context_t ctx, char *line)
 {
   if (ctx->bye_notify_fnc)
     ctx->bye_notify_fnc (ctx);
@@ -114,33 +115,35 @@ std_handler_bye (ASSUAN_CONTEXT ctx, char *line)
 }
   
 static int
-std_handler_auth (ASSUAN_CONTEXT ctx, char *line)
+std_handler_auth (assuan_context_t ctx, char *line)
 {
   return set_error (ctx, Not_Implemented, NULL); 
 }
   
 static int
-std_handler_reset (ASSUAN_CONTEXT ctx, char *line)
+std_handler_reset (assuan_context_t ctx, char *line)
 {
   if (ctx->reset_notify_fnc)
     ctx->reset_notify_fnc (ctx);
   assuan_close_input_fd (ctx);
   assuan_close_output_fd (ctx);
+  _assuan_uds_close_fds (ctx);
   return 0;
 }
   
 static int
-std_handler_end (ASSUAN_CONTEXT ctx, char *line)
+std_handler_end (assuan_context_t ctx, char *line)
 {
   return set_error (ctx, Not_Implemented, NULL); 
 }
 
 assuan_error_t
-assuan_command_parse_fd (ASSUAN_CONTEXT ctx, char *line, int *rfd)
+assuan_command_parse_fd (assuan_context_t ctx, char *line, int *rfd)
 {
   char *endp;
 
-  if (strncmp (line, "FD", 2) != 0 || (line[2] != '=' && line[2] != '\0'))
+  if ( (strncmp (line, "FD", 2) && strncmp (line, "fd", 2))
+       || (line[2] != '=' && line[2] != '\0'))
     return set_error (ctx, Syntax_Error, "FD[=<n>] expected");
   line += 2;
   if (*line == '=')
@@ -149,7 +152,7 @@ assuan_command_parse_fd (ASSUAN_CONTEXT ctx, char *line, int *rfd)
       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 */
+      /* Remove that argument so that a notify handler won't see it. */
       memset (line, ' ', endp? (endp-line):strlen(line));
 
       if (*rfd == ctx->inbound.fd)
@@ -165,7 +168,7 @@ assuan_command_parse_fd (ASSUAN_CONTEXT ctx, char *line, int *rfd)
 
 /* Format is INPUT FD=<n> */
 static int
-std_handler_input (ASSUAN_CONTEXT ctx, char *line)
+std_handler_input (assuan_context_t ctx, char *line)
 {
   int rc, fd;
 
@@ -180,7 +183,7 @@ std_handler_input (ASSUAN_CONTEXT ctx, char *line)
 
 /* Format is OUTPUT FD=<n> */
 static int
-std_handler_output (ASSUAN_CONTEXT ctx, char *line)
+std_handler_output (assuan_context_t ctx, char *line)
 {
   int rc, fd;
 
@@ -202,7 +205,7 @@ std_handler_output (ASSUAN_CONTEXT ctx, char *line)
    with default handlers */
 static struct {
   const char *name;
-  int (*handler)(ASSUAN_CONTEXT, char *line);
+  int (*handler)(assuan_context_t, char *line);
   int always; /* always initialize this command */
 } std_cmd_table[] = {
   { "NOP",    std_handler_nop, 1 },
@@ -234,9 +237,9 @@ static struct {
  * Return value: 0 on success or an error code
  **/
 int
-assuan_register_command (ASSUAN_CONTEXT ctx,
+assuan_register_command (assuan_context_t ctx,
                          const char *cmd_name,
-                         int (*handler)(ASSUAN_CONTEXT, char *))
+                         int (*handler)(assuan_context_t, char *))
 {
   int i;
   const char *s;
@@ -245,7 +248,7 @@ assuan_register_command (ASSUAN_CONTEXT ctx,
     cmd_name = NULL;
 
   if (!cmd_name)
-    return ASSUAN_Invalid_Value;
+    return _assuan_error (ASSUAN_Invalid_Value);
 
   if (!handler)
     { /* find a default handler. */
@@ -268,7 +271,7 @@ assuan_register_command (ASSUAN_CONTEXT ctx,
       ctx->cmdtbl_size = 50;
       ctx->cmdtbl = xtrycalloc ( ctx->cmdtbl_size, sizeof *ctx->cmdtbl);
       if (!ctx->cmdtbl)
-        return ASSUAN_Out_Of_Core;
+        return _assuan_error (ASSUAN_Out_Of_Core);
       ctx->cmdtbl_used = 0;
     }
   else if (ctx->cmdtbl_used >= ctx->cmdtbl_size)
@@ -277,7 +280,7 @@ assuan_register_command (ASSUAN_CONTEXT ctx,
 
       x = xtryrealloc ( ctx->cmdtbl, (ctx->cmdtbl_size+10) * sizeof *x);
       if (!x)
-        return ASSUAN_Out_Of_Core;
+        return _assuan_error (ASSUAN_Out_Of_Core);
       ctx->cmdtbl = x;
       ctx->cmdtbl_size += 50;
     }
@@ -289,59 +292,62 @@ assuan_register_command (ASSUAN_CONTEXT ctx,
 }
 
 int
-assuan_register_bye_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT))
+assuan_register_bye_notify (assuan_context_t ctx,
+                            void (*fnc)(assuan_context_t))
 {
   if (!ctx)
-    return ASSUAN_Invalid_Value;
+    return _assuan_error (ASSUAN_Invalid_Value);
   ctx->bye_notify_fnc = fnc;
   return 0;
 }
 
 int
-assuan_register_reset_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT))
+assuan_register_reset_notify (assuan_context_t ctx,
+                              void (*fnc)(assuan_context_t))
 {
   if (!ctx)
-    return ASSUAN_Invalid_Value;
+    return _assuan_error (ASSUAN_Invalid_Value);
   ctx->reset_notify_fnc = fnc;
   return 0;
 }
 
 int
-assuan_register_cancel_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT))
+assuan_register_cancel_notify (assuan_context_t ctx,
+                               void (*fnc)(assuan_context_t))
 {
   if (!ctx)
-    return ASSUAN_Invalid_Value;
+    return _assuan_error (ASSUAN_Invalid_Value);
   ctx->cancel_notify_fnc = fnc;
   return 0;
 }
 
 int
-assuan_register_option_handler (ASSUAN_CONTEXT ctx,
-                               int (*fnc)(ASSUAN_CONTEXT,
+assuan_register_option_handler (assuan_context_t ctx,
+                               int (*fnc)(assuan_context_t,
                                           const char*, const char*))
 {
   if (!ctx)
-    return ASSUAN_Invalid_Value;
+    return _assuan_error (ASSUAN_Invalid_Value);
   ctx->option_handler_fnc = fnc;
   return 0;
 }
 
 int
-assuan_register_input_notify (ASSUAN_CONTEXT ctx,
-                              void (*fnc)(ASSUAN_CONTEXT, const char *))
+assuan_register_input_notify (assuan_context_t ctx,
+                              void (*fnc)(assuan_context_t, const char *))
 {
   if (!ctx)
-    return ASSUAN_Invalid_Value;
+    return _assuan_error (ASSUAN_Invalid_Value);
   ctx->input_notify_fnc = fnc;
   return 0;
 }
 
 int
-assuan_register_output_notify (ASSUAN_CONTEXT ctx,
-                              void (*fnc)(ASSUAN_CONTEXT, const char *))
+assuan_register_output_notify (assuan_context_t ctx,
+                              void (*fnc)(assuan_context_t, const char *))
 {
   if (!ctx)
-    return ASSUAN_Invalid_Value;
+    return _assuan_error (ASSUAN_Invalid_Value);
   ctx->output_notify_fnc = fnc;
   return 0;
 }
@@ -349,7 +355,7 @@ assuan_register_output_notify (ASSUAN_CONTEXT ctx,
 
 /* Helper to register the standards commands */
 int
-_assuan_register_std_commands (ASSUAN_CONTEXT ctx)
+_assuan_register_std_commands (assuan_context_t ctx)
 {
   int i, rc;
 
@@ -370,7 +376,7 @@ _assuan_register_std_commands (ASSUAN_CONTEXT ctx)
 /* 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)
+handle_data_line (assuan_context_t ctx, char *line, int linelen)
 {
   return set_error (ctx, Not_Implemented, NULL);
 }
@@ -394,7 +400,7 @@ my_strcasecmp (const char *a, const char *b)
    table, remove leading and white spaces from the arguments, call the
    handler with the argument line and return the error */
 static int 
-dispatch_command (ASSUAN_CONTEXT ctx, char *line, int linelen)
+dispatch_command (assuan_context_t ctx, char *line, int linelen)
 {
   char *p;
   const char *s;
@@ -406,7 +412,7 @@ dispatch_command (ASSUAN_CONTEXT ctx, char *line, int linelen)
   for (p=line; *p && *p != ' ' && *p != '\t'; p++)
     ;
   if (p==line)
-    return set_error (ctx, Invalid_Command, "leading white-space"); 
+    return set_error (ctx, Syntax_Error, "leading white-space"); 
   if (*p) 
     { /* Skip over leading WS after the keyword */
       *p++ = 0;
@@ -441,12 +447,12 @@ dispatch_command (ASSUAN_CONTEXT ctx, char *line, int linelen)
 
 \f
 static int
-process_request (ASSUAN_CONTEXT ctx)
+process_request (assuan_context_t ctx)
 {
   int rc;
 
   if (ctx->in_inquire)
-    return ASSUAN_Nested_Commands;
+    return _assuan_error (ASSUAN_Nested_Commands);
 
   rc = _assuan_read_line (ctx);
   if (rc)
@@ -477,8 +483,8 @@ process_request (ASSUAN_CONTEXT ctx)
     {
       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 */ 
+  else if (err_is_eof (rc))
+    { /* No error checking because the peer may have already disconnect. */ 
       assuan_write_line (ctx, "OK closing connection");
       ctx->finish_handler (ctx);
     }
@@ -488,7 +494,7 @@ process_request (ASSUAN_CONTEXT ctx)
 
       if (rc < 100)
         sprintf (errline, "ERR %d server fault (%.50s)",
-                 ASSUAN_Server_Fault, assuan_strerror (rc));
+                 _assuan_error (ASSUAN_Server_Fault), assuan_strerror (rc));
       else
         {
           const char *text = ctx->err_no == rc? ctx->err_str:NULL;
@@ -498,7 +504,7 @@ process_request (ASSUAN_CONTEXT ctx)
              strings from libgpg-error without creating a dependency.
              They are used for debugging purposes only, so there is no
              problem if they are not available.  We need to make sure
-             that we are using elf because only this guarantees that
+             that we are using ELF because only this guarantees that
              weak symbol support is available in case GNU ld is not
              used. */
           unsigned int source, code;
@@ -552,7 +558,7 @@ process_request (ASSUAN_CONTEXT ctx)
  * failed.  Note, that no error is returned for operational errors.
  **/
 int
-assuan_process (ASSUAN_CONTEXT ctx)
+assuan_process (assuan_context_t ctx)
 {
   int rc;
 
@@ -560,7 +566,7 @@ assuan_process (ASSUAN_CONTEXT ctx)
     rc = process_request (ctx);
   } while (!rc);
 
-  if (rc == -1)
+  if (err_is_eof (rc))
     rc = 0;
 
   return rc;
@@ -579,7 +585,7 @@ assuan_process (ASSUAN_CONTEXT ctx)
  * Return value: -1 for end of server, 0 on success or an error code
  **/
 int 
-assuan_process_next (ASSUAN_CONTEXT ctx)
+assuan_process_next (assuan_context_t ctx)
 {
   return process_request (ctx);
 }
@@ -603,7 +609,7 @@ assuan_process_next (ASSUAN_CONTEXT ctx)
  * error which is most likely a too small fdarray.
  **/
 int 
-assuan_get_active_fds (ASSUAN_CONTEXT ctx, int what,
+assuan_get_active_fds (assuan_context_t ctx, int what,
                        int *fdarray, int fdarraysize)
 {
   int n = 0;
@@ -636,7 +642,7 @@ assuan_get_active_fds (ASSUAN_CONTEXT ctx, int what,
    implementaion for systems w/o a glibc, a simple implementation
    could use a child process */
 FILE *
-assuan_get_data_fp (ASSUAN_CONTEXT ctx)
+assuan_get_data_fp (assuan_context_t ctx)
 {
 #if defined (HAVE_FOPENCOOKIE) || defined (HAVE_FUNOPEN)
   if (ctx->outbound.data.fp)
@@ -658,10 +664,10 @@ assuan_get_data_fp (ASSUAN_CONTEXT ctx)
 /* Set the text used for the next OK reponse.  This string is
    automatically reset to NULL after the next command. */
 assuan_error_t
-assuan_set_okay_line (ASSUAN_CONTEXT ctx, const char *line)
+assuan_set_okay_line (assuan_context_t ctx, const char *line)
 {
   if (!ctx)
-    return ASSUAN_Invalid_Value;
+    return _assuan_error (ASSUAN_Invalid_Value);
   if (!line)
     {
       xfree (ctx->okay_line);
@@ -673,7 +679,7 @@ assuan_set_okay_line (ASSUAN_CONTEXT ctx, const char *line)
          we should allocate the entire line in secure memory */
       char *buf = xtrymalloc (3+strlen(line)+1);
       if (!buf)
-        return ASSUAN_Out_Of_Core;
+        return _assuan_error (ASSUAN_Out_Of_Core);
       strcpy (buf, "OK ");
       strcpy (buf+3, line);
       xfree (ctx->okay_line);
@@ -685,7 +691,8 @@ assuan_set_okay_line (ASSUAN_CONTEXT ctx, const char *line)
 
 
 assuan_error_t
-assuan_write_status (ASSUAN_CONTEXT ctx, const char *keyword, const char *text)
+assuan_write_status (assuan_context_t ctx,
+                     const char *keyword, const char *text)
 {
   char buffer[256];
   char *helpbuf;
@@ -693,7 +700,7 @@ assuan_write_status (ASSUAN_CONTEXT ctx, const char *keyword, const char *text)
   assuan_error_t ae;
 
   if ( !ctx || !keyword)
-    return ASSUAN_Invalid_Value;
+    return _assuan_error (ASSUAN_Invalid_Value);
   if (!text)
     text = "";
 
index 0547aae..d8c52d0 100644 (file)
@@ -15,7 +15,8 @@
  *
  * 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 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA. 
  */
 
 #include <config.h>
@@ -146,14 +147,14 @@ assuan_inquire (assuan_context_t ctx, const char *keyword,
   int nodataexpected;
 
   if (!ctx || !keyword || (10 + strlen (keyword) >= sizeof (cmdbuf)))
-    return ASSUAN_Invalid_Value;
+    return _assuan_error (ASSUAN_Invalid_Value);
   nodataexpected = !r_buffer && !r_length && !maxlen;
   if (!nodataexpected && (!r_buffer || !r_length))
-    return ASSUAN_Invalid_Value;
+    return _assuan_error (ASSUAN_Invalid_Value);
   if (!ctx->is_server)
-    return ASSUAN_Not_A_Server;
+    return _assuan_error (ASSUAN_Not_A_Server);
   if (ctx->in_inquire)
-    return ASSUAN_Nested_Commands;
+    return _assuan_error (ASSUAN_Nested_Commands);
   
   ctx->in_inquire = 1;
   if (nodataexpected)
@@ -182,12 +183,12 @@ assuan_inquire (assuan_context_t ctx, const char *keyword,
         break; /* END command received*/
       if (line[0] == 'C' && line[1] == 'A' && line[2] == 'N')
         {
-          rc = ASSUAN_Canceled;
+          rc = _assuan_error (ASSUAN_Canceled);
           goto leave;
         }
       if (line[0] != 'D' || line[1] != ' ' || nodataexpected)
         {
-          rc = ASSUAN_Unexpected_Command;
+          rc = _assuan_error (ASSUAN_Unexpected_Command);
           goto leave;
         }
       if (linelen < 3)
@@ -214,7 +215,7 @@ assuan_inquire (assuan_context_t ctx, const char *keyword,
         }
       if (mb.too_large)
         {
-          rc = ASSUAN_Too_Much_Data;
+          rc = _assuan_error (ASSUAN_Too_Much_Data);
           goto leave;
         }
     }
@@ -223,7 +224,7 @@ assuan_inquire (assuan_context_t ctx, const char *keyword,
     {
       *r_buffer = get_membuf (&mb, r_length);
       if (!*r_buffer)
-        rc = ASSUAN_Out_Of_Core;
+        rc = _assuan_error (ASSUAN_Out_Of_Core);
     }
 
  leave:
index 321f2ba..0fe48b7 100644 (file)
@@ -1,5 +1,5 @@
 /* assuan-io.c - Wraps the read and write functions.
- *     Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+ *     Copyright (C) 2002, 2004, 2006 Free Software Foundation, Inc.
  *
  * This file is part of Assuan.
  *
  *
  * 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 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA. 
  */
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 
-#include "assuan-defs.h"
 #include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#if HAVE_SYS_UIO_H
+# include <sys/uio.h>
+#endif
 #include <unistd.h>
+#include <errno.h>
 #ifdef HAVE_W32_SYSTEM
-#include <windows.h>
+# include <windows.h>
+#else
+# include <sys/wait.h>
 #endif
 
+#include "assuan-defs.h"
+
+/* We can't include pth.h and we are not sure whether other headers
+   already included it.  This we define macros with the same
+   values. */
+#define MY_PTH_FDMODE_ERROR    (-1)
+#define MY_PTH_FDMODE_POLL     0
+#define MY_PTH_FDMODE_BLOCK    1
+#define MY_PTH_FDMODE_NONBLOCK 2
+
+
 #ifndef _ASSUAN_NO_PTH
+extern pid_t   pth_waitpid (pid_t pid, int *status, int options);
 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);
+extern int     pth_fdmode (int, int);
+extern int     pth_select(int, fd_set*, fd_set*, fd_set*, struct timeval*);
 
 #ifndef HAVE_W32_SYSTEM
+#pragma weak pth_waitpid
 #pragma weak pth_read
 #pragma weak pth_write
+#pragma weak pth_fdmode
+#pragma weak pth_select
 #endif
 #endif /*!_ASSUAN_NO_PTH*/
 
+#ifndef _ASSUAN_NO_PTH
+/* Wrapper around pth_fdmode. */
+static int
+my_pth_fdmode (int fd, int mode)
+{
+  if (pth_fdmode)
+    return pth_fdmode (fd, mode);
+  else
+    return MY_PTH_FDMODE_NONBLOCK; /* This is okay, given the way we use it. */
+}
+#endif /*_ASSUAN_NO_PTH*/
+
+#ifndef _ASSUAN_NO_PTH
+/* Wrapper around pth_select. */
+static int 
+my_pth_select (int nfd, fd_set *rfds, fd_set *wfds, fd_set *efds,
+               struct timeval *timeout)
+{
+  if (pth_select)
+    return pth_select (nfd, rfds, wfds, efds, timeout);
+  else
+    return 1; /* Fake one fd ready; this is okay, given the way we use it. */
+}
+#endif /*_ASSUAN_NO_PTH*/
+
+#ifndef HAVE_W32_SYSTEM
+pid_t 
+_assuan_waitpid (pid_t pid, int *status, int options)
+{
+#ifdef _ASSUAN_NO_PTH
+  return waitpid (pid, status, options);
+#else
+  return (pth_waitpid ? pth_waitpid : waitpid) (pid, status, options);
+#endif
+}
+#endif
+
+
 ssize_t
 _assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size)
 {
@@ -51,7 +114,7 @@ _assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size)
   return pth_read ? pth_read (ctx->inbound.fd, buffer, size)
                   : recv (ctx->inbound.fd, buffer, size, 0);
 # endif
-# endif
+#endif
 }
 
 ssize_t
@@ -68,3 +131,87 @@ _assuan_simple_write (assuan_context_t ctx, const void *buffer, size_t size)
 # endif
 #endif
 }
+
+
+ssize_t
+_assuan_simple_sendmsg (assuan_context_t ctx, struct msghdr *msg)
+{
+#if defined(HAVE_W32_SYSTEM)
+  return _assuan_error (ASSUAN_Not_Implemented);
+#elif defined(_ASSUAN_NO_PTH)
+  int ret;
+  while ( (ret = sendmsg (ctx->outbound.fd, msg, 0)) == -1 && errno == EINTR)
+    ;
+  return ret;
+#else
+  /* Pth does not provide a sendmsg function.  Thus we implement it here.  */
+  int ret;
+  int fd = ctx->outbound.fd;
+  int fdmode;
+
+  fdmode = my_pth_fdmode (fd, MY_PTH_FDMODE_POLL);
+  if (fdmode == MY_PTH_FDMODE_ERROR)
+    {
+      errno = EBADF;
+      return -1;
+    }
+  if (fdmode == MY_PTH_FDMODE_BLOCK)
+    {
+      fd_set fds;
+
+      FD_ZERO (&fds);
+      FD_SET (fd, &fds);
+      while ( (ret = my_pth_select (fd+1, NULL, &fds, NULL, NULL)) < 0
+              && errno == EINTR)
+        ;
+      if (ret < 0)
+        return -1;
+    }
+
+  while ((ret = sendmsg (fd, msg, 0)) == -1 && errno == EINTR)
+    ;
+  return ret;
+#endif
+}
+
+
+ssize_t
+_assuan_simple_recvmsg (assuan_context_t ctx, struct msghdr *msg)
+{
+#if defined(HAVE_W32_SYSTEM)
+  return _assuan_error (ASSUAN_Not_Implemented);
+#elif defined(_ASSUAN_NO_PTH)
+  int ret;
+  while ( (ret = recvmsg (ctx->inbound.fd, msg, 0)) == -1 && errno == EINTR)
+    ;
+  return ret;
+#else
+  /* Pth does not provide a recvmsg function.  Thus we implement it here.  */
+  int ret;
+  int fd = ctx->inbound.fd;
+  int fdmode;
+
+  fdmode = my_pth_fdmode (fd, MY_PTH_FDMODE_POLL);
+  if (fdmode == MY_PTH_FDMODE_ERROR)
+    {
+      errno = EBADF;
+      return -1;
+    }
+  if (fdmode == MY_PTH_FDMODE_BLOCK)
+    {
+      fd_set fds;
+
+      FD_ZERO (&fds);
+      FD_SET (fd, &fds);
+      while ( (ret = my_pth_select (fd+1, &fds, NULL, NULL, NULL)) < 0
+              && errno == EINTR)
+        ;
+      if (ret < 0)
+        return -1;
+    }
+
+  while ((ret = recvmsg (fd, msg, 0)) == -1 && errno == EINTR)
+    ;
+  return ret;
+#endif
+}
index 04f138e..04db68c 100644 (file)
@@ -15,7 +15,8 @@
  *
  * 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 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA. 
  */
 
 #include <config.h>
@@ -23,6 +24,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
+#include <errno.h>
 
 #include "assuan-defs.h"
 
@@ -30,7 +32,7 @@ assuan_error_t
 assuan_set_hello_line (assuan_context_t ctx, const char *line)
 {
   if (!ctx)
-    return ASSUAN_Invalid_Value;
+    return _assuan_error (ASSUAN_Invalid_Value);
   if (!line)
     {
       xfree (ctx->hello_line);
@@ -40,7 +42,7 @@ assuan_set_hello_line (assuan_context_t ctx, const char *line)
     {
       char *buf = xtrymalloc (3+strlen(line)+1);
       if (!buf)
-        return ASSUAN_Out_Of_Core;
+        return _assuan_error (ASSUAN_Out_Of_Core);
       if (strchr (line, '\n'))
         strcpy (buf, line);
       else
@@ -73,7 +75,7 @@ assuan_accept (assuan_context_t ctx)
   const char *p, *pend;
 
   if (!ctx)
-    return ASSUAN_Invalid_Value;
+    return _assuan_error (ASSUAN_Invalid_Value);
 
   if (ctx->pipe_mode > 1)
     return -1; /* second invocation for pipemode -> terminate */
@@ -134,7 +136,7 @@ assuan_error_t
 assuan_close_input_fd (assuan_context_t ctx)
 {
   if (!ctx || ctx->input_fd == -1)
-    return ASSUAN_Invalid_Value;
+    return _assuan_error (ASSUAN_Invalid_Value);
   _assuan_close (ctx->input_fd);
   ctx->input_fd = -1;
   return 0;
@@ -146,7 +148,7 @@ assuan_error_t
 assuan_close_output_fd (assuan_context_t ctx)
 {
   if (!ctx || ctx->output_fd == -1)
-    return ASSUAN_Invalid_Value;
+    return _assuan_error (ASSUAN_Invalid_Value);
 
   _assuan_close (ctx->output_fd);
   ctx->output_fd = -1;
index 7c65d57..cfc3d84 100644 (file)
  *
  * 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 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA. 
  */
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <stdarg.h>
 #ifdef HAVE_W32_SYSTEM
 #include <windows.h>
 #endif /*HAVE_W32_SYSTEM*/
+#include <errno.h>
+#include <ctype.h>
 
 #include "assuan-defs.h"
 
 static char prefix_buffer[80];
 static FILE *_assuan_log;
+static int full_logging;
 
 void
 _assuan_set_default_log_stream (FILE *fp)
 {
   if (!_assuan_log)
-    _assuan_log = fp;
+    {
+      _assuan_log = fp;
+      full_logging = !!getenv ("ASSUAN_FULL_LOGGING");
+    }
 }
 
 void
@@ -46,6 +54,22 @@ assuan_set_assuan_log_stream (FILE *fp)
   _assuan_log = fp;
 }
 
+
+/* Set the per context log stream.  Also enable the default log stream
+   if it has not been set.  */
+void
+assuan_set_log_stream (assuan_context_t ctx, FILE *fp)
+{
+  if (ctx)
+    {
+      if (ctx->log_fp)
+        fflush (ctx->log_fp);
+      ctx->log_fp = fp;
+      _assuan_set_default_log_stream (fp);
+    }
+}
+
+
 FILE *
 assuan_get_assuan_log_stream (void)
 {
@@ -80,18 +104,123 @@ _assuan_log_printf (const char *format, ...)
   va_list arg_ptr;
   FILE *fp;
   const char *prf;
-
+  int save_errno = errno;
+  
   fp = assuan_get_assuan_log_stream ();
   prf = assuan_get_assuan_log_prefix ();
   if (*prf)
-    {
-      fputs (prf, fp);
-      fputs (": ", fp);
-    }
+    fprintf (fp, "%s[%u]: ", prf, (unsigned int)getpid ());
 
   va_start (arg_ptr, format);
   vfprintf (fp, format, arg_ptr );
   va_end (arg_ptr);
+  errno = save_errno;
+}
+
+
+/* Dump a possibly binary string (used for debugging).  Distinguish
+   ascii text from binary and print it accordingly.  This function
+   takes FILE pointer arg becuase logging may be enabled on a per
+   context basis. */
+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)) && !(*s >= 0x80))
+      break;
+
+  s = buffer;
+  if (!n && *s != '[')
+    fwrite (buffer, length, 1, fp);
+  else
+    {
+#ifdef HAVE_FLOCKFILE
+      flockfile (fp);
+#endif
+      putc_unlocked ('[', fp);
+      if ( length > 16 && !full_logging)
+        {
+          for (n=0; n < 12; n++, s++)
+            fprintf (fp, " %02x", *s);
+          fprintf (fp, " ...(%d bytes skipped)", (int)length - 12);
+        }
+      else
+        {
+          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 = (const unsigned char *) 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)) || (*s >= 0x80))
+           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
 }
 
 
index ecedb16..8ee9c74 100644 (file)
@@ -1,5 +1,5 @@
 /* assuan-pipe-connect.c - Establish a pipe connection (client) 
- *     Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+ * Copyright (C) 2001, 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
  *
  * This file is part of Assuan.
  *
@@ -15,7 +15,8 @@
  *
  * 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 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA. 
  */
 
 #ifdef HAVE_CONFIG_H
 
 #include "assuan-defs.h"
 
+/* Hacks for Slowaris.  */
+#ifndef PF_LOCAL
+# ifdef PF_UNIX
+#  define PF_LOCAL PF_UNIX
+# else
+#  define PF_LOCAL AF_UNIX
+# endif
+#endif
+#ifndef AF_LOCAL
+# define AF_LOCAL AF_UNIX
+#endif
+
+
 #ifdef _POSIX_OPEN_MAX
 #define MAX_OPEN_FDS _POSIX_OPEN_MAX
 #else
@@ -111,6 +125,8 @@ do_finish (assuan_context_t ctx)
   if (ctx->inbound.fd != -1)
     {
       _assuan_close (ctx->inbound.fd);
+      if (ctx->inbound.fd == ctx->outbound.fd)
+        ctx->outbound.fd = -1;
       ctx->inbound.fd = -1;
     }
   if (ctx->outbound.fd != -1)
@@ -123,7 +139,7 @@ do_finish (assuan_context_t ctx)
 #ifndef HAVE_W32_SYSTEM
 #ifndef _ASSUAN_USE_DOUBLE_FORK
       if (!ctx->flags.no_waitpid)
-        waitpid (ctx->pid, NULL, 0); 
+        _assuan_waitpid (ctx->pid, NULL, 0); 
       ctx->pid = -1;
 #endif
 #endif /*!HAVE_W32_SYSTEM*/
@@ -138,6 +154,402 @@ do_deinit (assuan_context_t ctx)
 }
 
 
+/* Helper for pipe_connect. */
+static assuan_error_t
+initial_handshake (assuan_context_t *ctx)
+{
+  int okay, off;
+  assuan_error_t err;
+  
+  err = _assuan_read_from_server (*ctx, &okay, &off);
+  if (err)
+    _assuan_log_printf ("can't connect server: %s\n",
+                        assuan_strerror (err));
+  else if (okay != 1)
+    {
+      _assuan_log_printf ("can't connect server: `%s'\n",
+                          (*ctx)->inbound.line);
+      err = _assuan_error (ASSUAN_Connect_Failed);
+    }
+
+  if (err)
+    {
+      assuan_disconnect (*ctx);
+      *ctx = NULL;
+    }
+  return err;
+}
+
+
+#ifndef HAVE_W32_SYSTEM
+#define pipe_connect pipe_connect_unix
+/* Unix version of the pipe connection code.  We use an extra macro to
+   make ChangeLog entries easier. */
+static assuan_error_t
+pipe_connect_unix (assuan_context_t *ctx,
+                   const char *name, const char *const argv[],
+                   int *fd_child_list,
+                   void (*atfork) (void *opaque, int reserved),
+                   void *atforkvalue)
+{
+  assuan_error_t err;
+  int rp[2];
+  int wp[2];
+  char mypidstr[50];
+
+  if (!ctx || !name || !argv || !argv[0])
+    return _assuan_error (ASSUAN_Invalid_Value);
+
+  fix_signals ();
+
+  sprintf (mypidstr, "%lu", (unsigned long)getpid ());
+
+  if (pipe (rp) < 0)
+    return _assuan_error (ASSUAN_General_Error);
+  
+  if (pipe (wp) < 0)
+    {
+      close (rp[0]);
+      close (rp[1]);
+      return _assuan_error (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;
+
+  /* FIXME: For GPGME we should better use _gpgme_io_spawn.  The PID
+     stored here is actually soon useless.  */
+  (*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_error (ASSUAN_General_Error);
+    }
+
+  if ((*ctx)->pid == 0)
+    {
+#ifdef _ASSUAN_USE_DOUBLE_FORK      
+      pid_t pid;
+
+      if ((pid = fork ()) == 0)
+#endif
+       {
+          int i, n;
+          char errbuf[512];
+          int *fdp;
+          
+          if (atfork)
+            atfork (atforkvalue, 0);
+
+          /* Dup handles to stdin/stdout. */
+          if (rp[1] != STDOUT_FILENO)
+            {
+              if (dup2 (rp[1], STDOUT_FILENO) == -1)
+                {
+                  _assuan_log_printf ("dup2 failed in child: %s\n",
+                                      strerror (errno));
+                  _exit (4);
+                }
+            }
+          if (wp[0] != STDIN_FILENO)
+            {
+              if (dup2 (wp[0], STDIN_FILENO) == -1)
+                {
+                  _assuan_log_printf ("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)
+                {
+                  _assuan_log_printf ("can't open `/dev/null': %s\n",
+                                      strerror (errno));
+                  _exit (4);
+                }
+              if (dup2 (fd, STDERR_FILENO) == -1)
+                {
+                  _assuan_log_printf ("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;
+
+          /* We store our parents pid in the environment so that the
+             execed assuan server is able to read the actual pid of the
+             client.  The server can't use getppid because it might have
+             been double forked before the assuan server has been
+             initialized. */
+          setenv ("_assuan_pipe_connect_pid", mypidstr, 1);
+
+          /* Make sure that we never pass a connection fd variable
+             when using a simple pipe.  */
+          unsetenv ("_assuan_connection_fd");
+
+          execv (name, (char *const *) 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_error (ASSUAN_Problem_Starting_Server),
+                    name, strerror (errno));
+          errbuf[sizeof(errbuf)-1] = 0;
+          writen (1, errbuf, strlen (errbuf));
+          _exit (4);
+        }
+#ifdef _ASSUAN_USE_DOUBLE_FORK
+      if (pid == -1)
+       _exit (1);
+      else
+       _exit (0);
+#endif
+    }
+
+#ifdef _ASSUAN_USE_DOUBLE_FORK
+  _assuan_waitpid ((*ctx)->pid, NULL, 0);
+  (*ctx)->pid = -1;
+#endif
+
+  close (rp[1]);
+  close (wp[0]);
+
+  return initial_handshake (ctx);
+}
+#endif /*!HAVE_W32_SYSTEM*/
+
+
+#ifndef HAVE_W32_SYSTEM
+/* This function is similar to pipe_connect but uses a socketpair and
+   sets the I/O up to use sendmsg/recvmsg. */
+static assuan_error_t
+socketpair_connect (assuan_context_t *ctx,
+                    const char *name, const char *const argv[],
+                    int *fd_child_list,
+                    void (*atfork) (void *opaque, int reserved),
+                    void *atforkvalue)
+{
+  assuan_error_t err;
+  int fds[2];
+  char mypidstr[50];
+
+  if (!ctx
+      || (name && (!argv || !argv[0]))
+      || (!name && argv))
+    return _assuan_error (ASSUAN_Invalid_Value);
+
+  fix_signals ();
+
+  sprintf (mypidstr, "%lu", (unsigned long)getpid ());
+
+  if ( socketpair (AF_LOCAL, SOCK_STREAM, 0, fds) )
+    {
+      _assuan_log_printf ("socketpair failed: %s\n", strerror (errno));
+      return _assuan_error (ASSUAN_General_Error);
+    }
+  
+  err = _assuan_new_context (ctx);
+  if (err)
+    {
+      close (fds[0]);
+      close (fds[1]);
+      return err;
+    }
+  (*ctx)->pipe_mode = 1;
+  (*ctx)->inbound.fd  = fds[0]; 
+  (*ctx)->outbound.fd = fds[0]; 
+  _assuan_init_uds_io (*ctx);
+  (*ctx)->deinit_handler = _assuan_uds_deinit;
+  (*ctx)->finish_handler = do_finish;
+
+  (*ctx)->pid = fork ();
+  if ((*ctx)->pid < 0)
+    {
+      close (fds[0]);
+      close (fds[1]);
+      _assuan_release_context (*ctx); 
+      *ctx = NULL;
+      return _assuan_error (ASSUAN_General_Error);
+    }
+
+  if ((*ctx)->pid == 0)
+    {
+#ifdef _ASSUAN_USE_DOUBLE_FORK      
+      pid_t pid;
+
+      if ((pid = fork ()) == 0)
+#endif
+       {
+          int fd, i, n;
+          char errbuf[512];
+          int *fdp;
+          
+          if (atfork)
+            atfork (atforkvalue, 0);
+
+          /* Connect stdin and stdout to /dev/null. */
+          fd = open ("/dev/null", O_RDONLY);
+          if (fd == -1 || dup2 (fd, STDIN_FILENO) == -1)
+            {
+              _assuan_log_printf ("dup2(dev/null) failed: %s\n",
+                                  strerror (errno));
+              _exit (4);
+            }
+          fd = open ("/dev/null", O_WRONLY);
+          if (fd == -1 || dup2 (fd, STDOUT_FILENO) == -1)
+            {
+              _assuan_log_printf ("dup2(dev/null) failed: %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)
+            {
+              fd = open ("/dev/null", O_WRONLY);
+              if (fd == -1 || dup2 (fd, STDERR_FILENO) == -1)
+                {
+                  _assuan_log_printf ("dup2(dev/null) failed: %s\n",
+                                      strerror (errno));
+                  _exit (4);
+                }
+            }
+
+
+          /* Close all files which will not be duped, are not in the
+             fd_child_list and are not the connection fd. */
+          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 || i == fds[1])
+                continue;
+              fdp = fd_child_list;
+              if (fdp)
+                {
+                  while (*fdp != -1 && *fdp != i)
+                    fdp++;
+                }
+
+              if (!(fdp && *fdp != -1))
+                close(i);
+            }
+          errno = 0;
+
+          /* We store our parents pid in the environment so that the
+             execed assuan server is able to read the actual pid of the
+             client.  The server can't use getppid becuase it might have
+             been double forked before the assuan server has been
+             initialized. */
+          setenv ("_assuan_pipe_connect_pid", mypidstr, 1);
+
+          /* Now set the environment variable used to convey the
+             connection's file descriptor. */
+          sprintf (mypidstr, "%d", fds[1]);
+          if (setenv ("_assuan_connection_fd", mypidstr, 1))
+            {
+              _assuan_log_printf ("setenv failed: %s\n", strerror (errno));
+              _exit (4);
+            }
+
+          if (!name && !argv)
+            {
+              /* No name and no args given, thus we don't do an exec
+                 but continue the forked process.  */
+              _assuan_release_context (*ctx);
+              *ctx = NULL;
+              return 0;
+            }
+
+          execv (name, (char *const *) 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_error (ASSUAN_Problem_Starting_Server),
+                    name, strerror (errno));
+          errbuf[sizeof(errbuf)-1] = 0;
+          writen (fds[1], errbuf, strlen (errbuf));
+          _exit (4);
+        }
+#ifdef _ASSUAN_USE_DOUBLE_FORK
+      if (pid == -1)
+       _exit (1);
+      else
+       _exit (0);
+#endif
+    }
+
+
+#ifdef _ASSUAN_USE_DOUBLE_FORK
+  _assuan_waitpid ((*ctx)->pid, NULL, 0);
+  (*ctx)->pid = -1;
+#endif
+
+  close (fds[1]);
+  
+  return initial_handshake (ctx);
+}
+#endif /*!HAVE_W32_SYSTEM*/
+
+
+
 #ifdef HAVE_W32_SYSTEM
 /* Build a command line for use with W32's CreateProcess.  On success
    CMDLINE gets the address of a newly allocated string.  */
@@ -236,21 +648,16 @@ create_inheritable_pipe (int filedes[2], int for_write)
 #endif /*HAVE_W32_SYSTEM*/
 
 
-/* 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.  ATFORK is called in the
-   child right after the fork; ATFORKVALUE is passed as the first
-   argument and 0 is passed as the second argument. The ATFORK
-   function should only act if the second value is 0. */
-assuan_error_t
-assuan_pipe_connect2 (assuan_context_t *ctx,
-                      const char *name, const char *const argv[],
-                      int *fd_child_list,
-                      void (*atfork) (void *opaque, int reserved),
-                      void *atforkvalue)
-{
 #ifdef HAVE_W32_SYSTEM
+#define pipe_connect pipe_connect_w32
+/* W32 version of the pipe connection code. */
+static assuan_error_t
+pipe_connect_w32 (assuan_context_t *ctx,
+                  const char *name, const char *const argv[],
+                  int *fd_child_list,
+                  void (*atfork) (void *opaque, int reserved),
+                  void *atforkvalue)
+{
   assuan_error_t err;
   int rp[2];
   int wp[2];
@@ -269,7 +676,7 @@ assuan_pipe_connect2 (assuan_context_t *ctx,
   HANDLE nullfd = INVALID_HANDLE_VALUE;
 
   if (!ctx || !name || !argv || !argv[0])
-    return ASSUAN_Invalid_Value;
+    return _assuan_error (ASSUAN_Invalid_Value);
 
   fix_signals ();
 
@@ -277,13 +684,13 @@ assuan_pipe_connect2 (assuan_context_t *ctx,
 
   /* Build the command line.  */
   if (build_w32_commandline (argv, &cmdline))
-    return ASSUAN_Out_Of_Core;
+    return _assuan_error (ASSUAN_Out_Of_Core);
 
   /* Create thew two pipes. */
   if (create_inheritable_pipe (rp, 0))
     {
       xfree (cmdline);
-      return ASSUAN_General_Error;
+      return _assuan_error (ASSUAN_General_Error);
     }
   
   if (create_inheritable_pipe (wp, 1))
@@ -291,7 +698,7 @@ assuan_pipe_connect2 (assuan_context_t *ctx,
       CloseHandle (fd_to_handle (rp[0]));
       CloseHandle (fd_to_handle (rp[1]));
       xfree (cmdline);
-      return ASSUAN_General_Error;
+      return _assuan_error (ASSUAN_General_Error);
     }
 
   
@@ -303,7 +710,7 @@ assuan_pipe_connect2 (assuan_context_t *ctx,
       CloseHandle (fd_to_handle (wp[0]));
       CloseHandle (fd_to_handle (wp[1]));
       xfree (cmdline);
-      return ASSUAN_General_Error;
+      return _assuan_error (ASSUAN_General_Error);
     }
 
   (*ctx)->pipe_mode = 1;
@@ -390,7 +797,7 @@ assuan_pipe_connect2 (assuan_context_t *ctx,
         CloseHandle (nullfd);
       xfree (cmdline);
       _assuan_release_context (*ctx); 
-      return ASSUAN_General_Error;
+      return _assuan_error (ASSUAN_General_Error);
     }
   xfree (cmdline);
   cmdline = NULL;
@@ -413,200 +820,11 @@ assuan_pipe_connect2 (assuan_context_t *ctx,
   (*ctx)->pid = 0;  /* We don't use the PID. */
   CloseHandle (pi.hProcess); /* We don't need to wait for the process. */
 
-#else /*!HAVE_W32_SYSTEM*/
-  assuan_error_t err;
-  int rp[2];
-  int wp[2];
-  char mypidstr[50];
-
-  if (!ctx || !name || !argv || !argv[0])
-    return ASSUAN_Invalid_Value;
-
-  fix_signals ();
-
-  sprintf (mypidstr, "%lu", (unsigned long)getpid ());
-
-  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;
-
-  /* FIXME: For GPGME we should better use _gpgme_io_spawn.  The PID
-     stored here is actually soon useless.  */
-  (*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)
-    {
-#ifdef _ASSUAN_USE_DOUBLE_FORK      
-      pid_t pid;
-
-      if ((pid = fork ()) == 0)
-#endif
-       {
-          int i, n;
-          char errbuf[512];
-          int *fdp;
-          
-          if (atfork)
-            atfork (atforkvalue, 0);
-
-          /* Dup handles to stdin/stdout. */
-          if (rp[1] != STDOUT_FILENO)
-            {
-              if (dup2 (rp[1], STDOUT_FILENO) == -1)
-                {
-                  _assuan_log_printf ("dup2 failed in child: %s\n",
-                                      strerror (errno));
-                  _exit (4);
-                }
-            }
-          if (wp[0] != STDIN_FILENO)
-            {
-              if (dup2 (wp[0], STDIN_FILENO) == -1)
-                {
-                  _assuan_log_printf ("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)
-                {
-                  _assuan_log_printf ("can't open `/dev/null': %s\n",
-                                      strerror (errno));
-                  _exit (4);
-                }
-              if (dup2 (fd, STDERR_FILENO) == -1)
-                {
-                  _assuan_log_printf ("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;
-
-          /* We store our parents pid in the environment so that the
-             execed assuan server is able to read the actual pid of the
-             client.  The server can't use getppid becuase it might have
-             been double forked before the assuan server has been
-             initialized. */
-          setenv ("_assuan_pipe_connect_pid", mypidstr, 1);
-
-          execv (name, (char *const *) 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);
-        }
-#ifdef _ASSUAN_USE_DOUBLE_FORK
-      if (pid == -1)
-       _exit (1);
-      else
-       _exit (0);
-#endif
-    }
-
-#ifdef _ASSUAN_USE_DOUBLE_FORK
-  waitpid ((*ctx)->pid, NULL, 0);
-  (*ctx)->pid = -1;
-#endif
-
-  close (rp[1]);
-  close (wp[0]);
-
-#endif /*!HAVE_W32_SYSTEM*/
-
-  /* initial handshake */
-  {
-    int okay, off;
-
-    err = _assuan_read_from_server (*ctx, &okay, &off);
-    if (err)
-      _assuan_log_printf ("can't connect server: %s\n",
-                          assuan_strerror (err));
-    else if (okay != 1)
-      {
-       _assuan_log_printf ("can't connect server: `%s'\n",
-                            (*ctx)->inbound.line);
-       err = ASSUAN_Connect_Failed;
-      }
-  }
-
-  if (err)
-    {
-      assuan_disconnect (*ctx);
-      *ctx = NULL;
-    }
-
-  return err;
+  return initial_handshake (ctx);
 }
+#endif /*HAVE_W32_SYSTEM*/
 
-
+\f
 /* 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
@@ -615,5 +833,57 @@ assuan_error_t
 assuan_pipe_connect (assuan_context_t *ctx, const char *name,
                     const char *const argv[], int *fd_child_list)
 {
-  return assuan_pipe_connect2 (ctx, name, argv, fd_child_list, NULL, NULL);
+  return pipe_connect (ctx, name, argv, fd_child_list, NULL, NULL);
+}
+
+
+
+assuan_error_t
+assuan_pipe_connect2 (assuan_context_t *ctx,
+                      const char *name, const char *const argv[],
+                      int *fd_child_list,
+                      void (*atfork) (void *opaque, int reserved),
+                      void *atforkvalue)
+{
+  return pipe_connect (ctx, name, argv, fd_child_list, atfork, atforkvalue);
+}
+
+
+/* Connect to a server over a full-duplex socket (i.e. created by
+   socketpair), 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.  ATFORK is called in the child right after the
+   fork; ATFORKVALUE is passed as the first argument and 0 is passed
+   as the second argument. The ATFORK function should only act if the
+   second value is 0.
+
+   For now FLAGS may either take the value 0 to behave like
+   assuan_pipe_connect2 or 1 to enable the described full-duplex
+   socket behaviour.
+
+   If NAME as well as ARGV are NULL, no exec is done but the same
+   process is continued.  However all file descriptors are closed and
+   some special environment variables are set. To let the caller
+   detect whether the child or the parent continues, the child returns
+   a CTX of NULL. */
+assuan_error_t
+assuan_pipe_connect_ext (assuan_context_t *ctx,
+                         const char *name, const char *const argv[],
+                         int *fd_child_list,
+                         void (*atfork) (void *opaque, int reserved),
+                         void *atforkvalue, unsigned int flags)
+{
+  if ((flags & 1))
+    {
+#ifdef HAVE_W32_SYSTEM
+      return _assuan_error (ASSUAN_Not_Implemented);
+#else
+      return socketpair_connect (ctx, name, argv, fd_child_list,
+                                 atfork, atforkvalue);
+#endif
+    }
+  else
+    return pipe_connect (ctx, name, argv, fd_child_list, atfork, atforkvalue);
 }
+
index beff9a3..a19c88e 100644 (file)
  *
  * 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 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA. 
  */
 
 #include <config.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <unistd.h>
 #ifdef HAVE_W32_SYSTEM
 #include <windows.h>
 
 
 static void
-deinit_pipe_server (ASSUAN_CONTEXT ctx)
+deinit_pipe_server (assuan_context_t ctx)
 {
   /* nothing to do for this simple server */
 }
 
 static int
-accept_connection (ASSUAN_CONTEXT ctx)
+accept_connection (assuan_context_t ctx)
 {
   /* This is a NOP for a pipe server */
   return 0;
 }
 
 static int
-finish_connection (ASSUAN_CONTEXT ctx)
+finish_connection (assuan_context_t ctx)
 {
   /* This is a NOP for a pipe server */
   return 0;
@@ -53,19 +56,19 @@ finish_connection (ASSUAN_CONTEXT ctx)
 /* 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)
+_assuan_new_context (assuan_context_t *r_ctx)
 {
   static struct assuan_io io = { _assuan_simple_read,
                                 _assuan_simple_write,
                                 0, 0 };
 
-  ASSUAN_CONTEXT ctx;
+  assuan_context_t ctx;
   int rc;
 
   *r_ctx = NULL;
   ctx = xtrycalloc (1, sizeof *ctx);
   if (!ctx)
-    return ASSUAN_Out_Of_Core;
+    return _assuan_error (ASSUAN_Out_Of_Core);
   ctx->input_fd = -1;
   ctx->output_fd = -1;
 
@@ -88,15 +91,27 @@ _assuan_new_context (ASSUAN_CONTEXT *r_ctx)
 }
 
 
+/* Returns true if atoi(S) denotes a valid socket. */
+static int
+is_valid_socket (const char *s)
+{
+  struct stat buf;
+
+  if ( fstat (atoi (s), &buf ) )
+    return 0;
+  return S_ISSOCK (buf.st_mode);
+}
+
+
 int
-assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2])
+assuan_init_pipe_server (assuan_context_t *r_ctx, int filedes[2])
 {
   int rc;
 
   rc = _assuan_new_context (r_ctx);
   if (!rc)
     {
-      ASSUAN_CONTEXT ctx = *r_ctx;
+      assuan_context_t ctx = *r_ctx;
       const char *s;
       unsigned long ul;
 
@@ -110,8 +125,28 @@ assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2])
       ctx->inbound.fd  = _get_osfhandle (filedes[0]);
       ctx->outbound.fd = _get_osfhandle (filedes[1]);
 #else
-      ctx->inbound.fd  = filedes[0];
-      ctx->outbound.fd = filedes[1];
+      s = getenv ("_assuan_connection_fd");
+      if (s && *s && is_valid_socket (s) )
+        {
+          /* Well, we are called with an bi-directional file
+             descriptor.  Prepare for using sendmsg/recvmsg.  In this
+             case we ignore the passed file descriptors. */
+          ctx->inbound.fd  = ctx->outbound.fd = atoi (s);
+          _assuan_init_uds_io (ctx);
+          ctx->deinit_handler = _assuan_uds_deinit;
+        }
+      else if (filedes && filedes[0] != -1 && filedes[1] != -1 )
+        {
+          /* Standard pipe server. */
+          ctx->inbound.fd  = filedes[0];
+          ctx->outbound.fd = filedes[1];
+        }
+      else
+        {
+          _assuan_release_context (*r_ctx);
+          *r_ctx = NULL;
+          return ASSUAN_Problem_Starting_Server;
+        }
 #endif
       ctx->pipe_mode = 1;
 
@@ -127,7 +162,7 @@ assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2])
 
 
 void
-_assuan_release_context (ASSUAN_CONTEXT ctx)
+_assuan_release_context (assuan_context_t ctx)
 {
   if (ctx)
     {
@@ -138,7 +173,7 @@ _assuan_release_context (ASSUAN_CONTEXT ctx)
 }
 
 void
-assuan_deinit_server (ASSUAN_CONTEXT ctx)
+assuan_deinit_server (assuan_context_t ctx)
 {
   if (ctx)
     {
index 9937c7a..5953f1c 100644 (file)
@@ -15,7 +15,8 @@
  *
  * 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 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA. 
  */
 
 #include <config.h>
@@ -54,7 +55,7 @@
 
  
 static int
-do_finish (ASSUAN_CONTEXT ctx)
+do_finish (assuan_context_t ctx)
 {
   if (ctx->inbound.fd != -1)
     {
@@ -66,56 +67,70 @@ do_finish (ASSUAN_CONTEXT ctx)
 }
 
 static void
-do_deinit (ASSUAN_CONTEXT ctx)
+do_deinit (assuan_context_t 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.  */
 assuan_error_t
-assuan_socket_connect (ASSUAN_CONTEXT *r_ctx,
+assuan_socket_connect (assuan_context_t *r_ctx,
                        const char *name, pid_t server_pid)
 {
+  return assuan_socket_connect_ext (r_ctx, name, server_pid, 0);
+}
+
+
+/* Make a connection to the Unix domain socket NAME and return a new
+   Assuan context in CTX.  SERVER_PID is currently not used but may
+   become handy in the future.  With flags set to 1 sendmsg and
+   recvmesg are used. */
+assuan_error_t
+assuan_socket_connect_ext (assuan_context_t *r_ctx,
+                           const char *name, pid_t server_pid,
+                           unsigned int flags)
+{
   static struct assuan_io io = { _assuan_simple_read,
                                 _assuan_simple_write };
 
   assuan_error_t err;
-  ASSUAN_CONTEXT ctx;
+  assuan_context_t ctx;
   int fd;
   struct sockaddr_un srvr_addr;
   size_t len;
   const char *s;
 
   if (!r_ctx || !name)
-    return ASSUAN_Invalid_Value;
+    return _assuan_error (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.  To make things
-     easier we allow an optional dirver prefix.  */
+  /* We require that the name starts with a slash, so that we
+     eventually can reuse this function for other socket types.  To
+     make things easier we allow an optional dirver prefix.  */
   s = name;
   if (*s && s[1] == ':')
     s += 2;
   if (*s != DIRSEP_C && *s != '/')
-    return ASSUAN_Invalid_Value;
+    return _assuan_error (ASSUAN_Invalid_Value);
 
   if (strlen (name)+1 >= sizeof srvr_addr.sun_path)
-    return ASSUAN_Invalid_Value;
+    return _assuan_error (ASSUAN_Invalid_Value);
 
   err = _assuan_new_context (&ctx); 
   if (err)
       return err;
-  ctx->deinit_handler = do_deinit;
+  ctx->deinit_handler = ((flags&1))? _assuan_uds_deinit :  do_deinit;
   ctx->finish_handler = do_finish;
 
-
   fd = _assuan_sock_new (PF_LOCAL, SOCK_STREAM, 0);
   if (fd == -1)
     {
       _assuan_log_printf ("can't create socket: %s\n", strerror (errno));
       _assuan_release_context (ctx);
-      return ASSUAN_General_Error;
+      return _assuan_error (ASSUAN_General_Error);
     }
 
   memset (&srvr_addr, 0, sizeof srvr_addr);
@@ -131,13 +146,15 @@ assuan_socket_connect (ASSUAN_CONTEXT *r_ctx,
                           name, strerror (errno));
       _assuan_release_context (ctx);
       _assuan_close (fd);
-      return ASSUAN_Connect_Failed;
+      return _assuan_error (ASSUAN_Connect_Failed);
     }
 
   ctx->inbound.fd = fd;
   ctx->outbound.fd = fd;
   ctx->io = &io;
-
+  if ((flags&1))
+    _assuan_init_uds_io (ctx);
   /* initial handshake */
   {
     int okay, off;
@@ -151,7 +168,7 @@ assuan_socket_connect (ASSUAN_CONTEXT *r_ctx,
         /*LOG ("can't connect to server: `");*/
        _assuan_log_sanitized_string (ctx->inbound.line);
        fprintf (assuan_get_assuan_log_stream (), "'\n");
-       err = ASSUAN_Connect_Failed;
+       err = _assuan_error (ASSUAN_Connect_Failed);
       }
   }
 
@@ -163,3 +180,5 @@ assuan_socket_connect (ASSUAN_CONTEXT *r_ctx,
     *r_ctx = ctx;
   return 0;
 }
+
+
index 275af42..45c227d 100644 (file)
@@ -15,7 +15,8 @@
  *
  * 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 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA. 
  */
 
 #include <config.h>
 
 #include "assuan-defs.h"
 
+static struct assuan_io io = { _assuan_simple_read,
+                              _assuan_simple_write };
+
+
 static int
 accept_connection_bottom (assuan_context_t ctx)
 {
   int fd = ctx->connected_fd;
 
+  ctx->peercred.valid = 0;
 #ifdef HAVE_SO_PEERCRED
   {
-    /* This overrides any already set PID if the function returns a
-       valid one. */
     struct ucred cr; 
-    int cl = sizeof cr;
-
-    if ( !getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl)
-         && cr.pid != (pid_t)-1 && cr.pid ) 
-      ctx->pid = cr.pid;
+    socklen_t cl = sizeof cr;
+
+    if ( !getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl))
+      {
+         ctx->peercred.pid = cr.pid;
+         ctx->peercred.uid = cr.uid;
+         ctx->peercred.gid = cr.gid;
+         ctx->peercred.valid = 1;
+
+         /* This overrides any already set PID if the function returns
+            a valid one. */
+         if (cr.pid != (pid_t)-1 && cr.pid) 
+           ctx->pid = cr.pid;
+      }
   }
 #endif
 
@@ -72,13 +85,13 @@ accept_connection (assuan_context_t ctx)
 {
   int fd;
   struct sockaddr_un clnt_addr;
-  size_t len = sizeof clnt_addr;
+  socklen_t len = sizeof clnt_addr;
 
   fd = accept (ctx->listen_fd, (struct sockaddr*)&clnt_addr, &len );
   if (fd == -1)
     {
       ctx->os_errno = errno;
-      return ASSUAN_Accept_Failed;
+      return _assuan_error (ASSUAN_Accept_Failed);
     }
 
   ctx->connected_fd = fd;
@@ -104,71 +117,67 @@ deinit_socket_server (assuan_context_t 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_t *r_ctx, int listen_fd)
 {
-  assuan_context_t 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;
+  return assuan_init_socket_server_ext (r_ctx, listen_fd, 0);
 }
 
-/* Initialize a server using the already accepted socket FD. */
+/* Initialize a server using the already accepted socket FD.  This
+   fucntion is deprecated. */
 int
 assuan_init_connected_socket_server (assuan_context_t *r_ctx, int fd)
 {
+  return assuan_init_socket_server_ext (r_ctx, fd, 2);
+}
+
+
+/* 
+   Flag bits: 0 - use sendmsg/recvmsg to allow descriptor passing
+              1 - FD has already been accepted.
+*/
+int
+assuan_init_socket_server_ext (assuan_context_t *r_ctx, int fd,
+                               unsigned int flags)
+{
   assuan_context_t ctx;
   int rc;
 
   *r_ctx = NULL;
   ctx = xtrycalloc (1, sizeof *ctx);
   if (!ctx)
-    return ASSUAN_Out_Of_Core;
+    return _assuan_error (ASSUAN_Out_Of_Core);
   ctx->is_server = 1;
-  ctx->pipe_mode = 1; /* we want a second accept to indicate EOF */
+  if ((flags & 2))
+    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;
+  if ((flags & 2))
+    {
+      ctx->listen_fd = -1;
+      ctx->connected_fd = fd;
+    }
+  else
+    {
+      ctx->listen_fd = fd;
+      ctx->connected_fd = -1;
+    }
+  ctx->deinit_handler = (flags & 1)? _assuan_uds_deinit:deinit_socket_server;
+  ctx->accept_handler = ((flags & 2)
+                         ? accept_connection_bottom 
+                         : accept_connection);
   ctx->finish_handler = finish_connection;
 
+  ctx->io = &io;
+  if ((flags & 1))
+    _assuan_init_uds_io (ctx);
+
   rc = _assuan_register_std_commands (ctx);
   if (rc)
     xfree (ctx);
@@ -176,5 +185,3 @@ assuan_init_connected_socket_server (assuan_context_t *r_ctx, int fd)
     *r_ctx = ctx;
   return rc;
 }
-
-
index 005f730..6aa5708 100644 (file)
@@ -1,22 +1,24 @@
 /* assuan-socket.c
- * Copyright (C) 2004 Free Software Foundation, Inc.
+ * Copyright (C) 2004, 2005 Free Software Foundation, Inc.
  *
- * This file is part of GnuPG.
+ * This file is part of Assuan.
  *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * 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.
  *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+ * 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 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
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA. 
  */
+
 #include <config.h>
 #include <stdio.h>
 #ifdef HAVE_W32_SYSTEM
 #endif
 #include "assuan-defs.h"
 
+/* Hacks for Slowaris.  */
+#ifndef PF_LOCAL
+# ifdef PF_UNIX
+#  define PF_LOCAL PF_UNIX
+# else
+#  define PF_LOCAL AF_UNIX
+# endif
+#endif
+#ifndef AF_LOCAL
+# define AF_LOCAL AF_UNIX
+#endif
+
 int
 _assuan_close (int fd)
 {
diff --git a/assuan/assuan-uds.c b/assuan/assuan-uds.c
new file mode 100644 (file)
index 0000000..c725392
--- /dev/null
@@ -0,0 +1,285 @@
+/* assuan-uds.c - Assuan unix domain socket utilities
+ * Copyright (C) 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * 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>
+#ifndef HAVE_W32_SYSTEM
+#include <sys/socket.h>
+#include <sys/un.h>
+#else
+#include <windows.h>
+#endif
+#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"
+
+
+/* Read from a unix domain socket using sendmsg. 
+
+   FIXME: We don't need the buffering. It is a leftover from the time
+   when we used datagrams. */
+static ssize_t
+uds_reader (assuan_context_t ctx, void *buf, size_t buflen)
+{
+  int len = ctx->uds.buffersize;
+
+#ifndef HAVE_W32_SYSTEM
+
+  if (!ctx->uds.bufferallocated)
+    {
+      ctx->uds.buffer = xtrymalloc (2048);
+      if (!ctx->uds.buffer)
+        return _assuan_error (ASSUAN_Out_Of_Core);
+      ctx->uds.bufferallocated = 2048;
+    }
+
+  while (!len)  /* No data is buffered.  */
+    {
+      struct msghdr msg;
+      struct iovec iovec;
+      union {
+        struct cmsghdr cm;
+        char control[CMSG_SPACE(sizeof (int))];
+      } control_u;
+      struct cmsghdr *cmptr;
+
+      memset (&msg, 0, sizeof (msg));
+
+      msg.msg_name = NULL;
+      msg.msg_namelen = 0;
+      msg.msg_iov = &iovec;
+      msg.msg_iovlen = 1;
+      iovec.iov_base = ctx->uds.buffer;
+      iovec.iov_len = ctx->uds.bufferallocated;
+      msg.msg_control = control_u.control;
+      msg.msg_controllen = sizeof (control_u.control);
+
+      len = _assuan_simple_recvmsg (ctx, &msg);
+      if (len < 0)
+        return -1;
+
+      ctx->uds.buffersize = len;
+      ctx->uds.bufferoffset = 0;
+
+      cmptr = CMSG_FIRSTHDR (&msg);
+      if (cmptr && cmptr->cmsg_len == CMSG_LEN (sizeof(int)))
+        {
+          if (cmptr->cmsg_level != SOL_SOCKET
+              || cmptr->cmsg_type != SCM_RIGHTS)
+            _assuan_log_printf ("unexpected ancillary data received\n");
+          else
+            {
+              int fd = *((int*)CMSG_DATA (cmptr));
+
+              if (ctx->uds.pendingfdscount >= DIM (ctx->uds.pendingfds))
+                {
+                  _assuan_log_printf ("too many descriptors pending - "
+                                      "closing received descriptor %d\n", fd);
+                  _assuan_close (fd);
+                }
+              else
+                ctx->uds.pendingfds[ctx->uds.pendingfdscount++] = fd;
+            }
+       }
+    }
+#else /*HAVE_W32_SYSTEM*/
+  len = recvfrom (ctx->inbound.fd, buf, buflen, 0, NULL, NULL);
+#endif /*HAVE_W32_SYSTEM*/
+
+  /* Return some data to the user.  */
+
+  if (len > buflen) /* We have more than the user requested.  */
+    len = buflen;
+
+  memcpy (buf, ctx->uds.buffer + ctx->uds.bufferoffset, len);
+  ctx->uds.buffersize -= len;
+  assert (ctx->uds.buffersize >= 0);
+  ctx->uds.bufferoffset += len;
+  assert (ctx->uds.bufferoffset <= ctx->uds.bufferallocated);
+
+  return len;
+}
+
+
+/* Write to the domain server.  */
+static ssize_t
+uds_writer (assuan_context_t ctx, const void *buf, size_t buflen)
+{
+#ifndef HAVE_W32_SYSTEM
+  struct msghdr msg;
+  struct iovec iovec;
+  ssize_t len;
+
+  memset (&msg, 0, sizeof (msg));
+
+  msg.msg_name = NULL;
+  msg.msg_namelen = 0;
+  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 = _assuan_simple_sendmsg (ctx, &msg);
+#else /*HAVE_W32_SYSTEM*/
+  int len;
+  
+  len = sendto (ctx->outbound.fd, buf, buflen, 0,
+                (struct sockaddr *)&ctx->serveraddr,
+                sizeof (struct sockaddr_in));
+#endif /*HAVE_W32_SYSTEM*/
+  return len;
+}
+
+
+static assuan_error_t
+uds_sendfd (assuan_context_t ctx, int fd)
+{
+#ifndef HAVE_W32_SYSTEM
+  struct msghdr msg;
+  struct iovec iovec;
+  union {
+    struct cmsghdr cm;
+    char control[CMSG_SPACE(sizeof (int))];
+  } control_u;
+  struct cmsghdr *cmptr;
+  int len;
+  char buffer[80];
+
+  /* We need to send some real data so that a read won't return 0
+     which will be taken as an EOF.  It also helps with debugging. */ 
+  snprintf (buffer, sizeof(buffer)-1, "# descriptor %d is in flight\n", fd);
+  buffer[sizeof(buffer)-1] = 0;
+
+  memset (&msg, 0, sizeof (msg));
+
+  msg.msg_name = NULL;
+  msg.msg_namelen = 0;
+  msg.msg_iovlen = 1;
+  msg.msg_iov = &iovec;
+  iovec.iov_base = buffer;
+  iovec.iov_len = strlen (buffer);
+
+  msg.msg_control = control_u.control;
+  msg.msg_controllen = sizeof (control_u.control);
+  cmptr = CMSG_FIRSTHDR (&msg);
+  cmptr->cmsg_len = CMSG_LEN(sizeof(int));
+  cmptr->cmsg_level = SOL_SOCKET;
+  cmptr->cmsg_type = SCM_RIGHTS;
+  *((int*)CMSG_DATA (cmptr)) = fd;
+
+  len = _assuan_simple_sendmsg (ctx, &msg);
+  if (len < 0)
+    {
+      _assuan_log_printf ("uds_sendfd: %s\n", strerror (errno));
+      return _assuan_error (ASSUAN_Write_Error);
+    }
+  else
+    return 0;
+#else
+  return _assuan_error (ASSUAN_Not_Implemented);
+#endif
+}
+
+
+static assuan_error_t
+uds_receivefd (assuan_context_t ctx, int *fd)
+{
+#ifndef HAVE_W32_SYSTEM
+  int i;
+
+  if (!ctx->uds.pendingfdscount)
+    {
+      _assuan_log_printf ("no pending file descriptors!\n");
+      return _assuan_error (ASSUAN_General_Error);
+    }
+  assert (ctx->uds.pendingfdscount <= DIM(ctx->uds.pendingfds));
+
+  *fd = ctx->uds.pendingfds[0];
+  for (i=1; i < ctx->uds.pendingfdscount; i++)
+    ctx->uds.pendingfds[i-1] = ctx->uds.pendingfds[i];
+  ctx->uds.pendingfdscount--;
+
+  return 0;
+#else
+  return _assuan_error (ASSUAN_Not_Implemented);
+#endif
+}
+
+
+/* Close all pending fds. */
+void
+_assuan_uds_close_fds (assuan_context_t ctx)
+{
+  int i;
+
+  for (i = 0; i < ctx->uds.pendingfdscount; i++)
+    _assuan_close (ctx->uds.pendingfds[i]);
+  ctx->uds.pendingfdscount = 0;
+}
+
+/* Deinitialize the unix domain socket I/O functions.  */
+void
+_assuan_uds_deinit (assuan_context_t ctx)
+{
+  /* First call the finish_handler which should close descriptors etc. */
+  ctx->finish_handler (ctx);
+
+  if (ctx->uds.buffer)
+    {
+      assert (ctx->uds.bufferallocated);
+      ctx->uds.bufferallocated = 0;
+      xfree (ctx->uds.buffer);
+    }
+
+  _assuan_uds_close_fds (ctx);
+}
+
+
+/* Helper function to initialize a context for domain I/O. */
+void
+_assuan_init_uds_io (assuan_context_t ctx)
+{
+  static struct assuan_io io = { uds_reader, uds_writer,
+                                uds_sendfd, uds_receivefd };
+
+  ctx->io = &io;
+  ctx->uds.buffer = 0;
+  ctx->uds.bufferoffset = 0;
+  ctx->uds.buffersize = 0;
+  ctx->uds.bufferallocated = 0;
+  ctx->uds.pendingfdscount = 0;
+}
+
index 2c2f744..3e627fc 100644 (file)
@@ -15,7 +15,8 @@
  *
  * 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 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA. 
  */
 
 #include <config.h>
@@ -106,19 +107,6 @@ assuan_get_pointer (assuan_context_t ctx)
 
 
 void
-assuan_set_log_stream (assuan_context_t ctx, FILE *fp)
-{
-  if (ctx)
-    {
-      if (ctx->log_fp)
-        fflush (ctx->log_fp);
-      ctx->log_fp = fp;
-      _assuan_set_default_log_stream (fp);
-    }
-}
-
-
-void
 assuan_begin_confidential (assuan_context_t ctx)
 {
   if (ctx)
@@ -166,97 +154,3 @@ assuan_get_flag (assuan_context_t ctx, assuan_flag_t flag)
 }
 
 
-/* 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)) && !(*s >= 0x80))
-      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 = (const unsigned char *) 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)) || (*s >= 0x80))
-           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
-}
-
index b2641b2..0f36cdd 100644 (file)
@@ -15,7 +15,8 @@
  *
  * 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 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA. 
  */
 
 #ifndef ASSUAN_H
 #include <unistd.h>
 
 
-/* To use this file with libraries the following macros are often
-   useful:
+/* To use this file with libraries the following macros are useful:
 
-   #define _ASSUAN_EXT_SYM_PREFIX _foo_
+     #define _ASSUAN_EXT_SYM_PREFIX _foo_
    
      This prefixes all external symbols with "_foo_".
 
-   #define _ASSUAN_NO_PTH 
+     #define _ASSUAN_ONLY_GPG_ERRORS
 
-     This avoids inclusion of special GNU Pth hacks.
+     If this is defined all old-style Assuan error codes are made
+     inactive as well as other dereacted stuff.
 
-   #define _ASSUAN_NO_FIXED_SIGNALS 
+   The follwing macros are used internally in the implementation of
+   libassuan:
 
-     This disables changing of certain signal handler; i.e. SIGPIPE.
+     #define _ASSUAN_NO_PTH 
 
-   #define _ASSUAN_USE_DOUBLE_FORK
+       This avoids inclusion of special GNU Pth hacks.
 
-     Use a double fork approach when connecting to a server through a pipe.
+     #define _ASSUAN_NO_FIXED_SIGNALS 
+
+       This disables changing of certain signal handler; i.e. SIGPIPE.
+
+     #define _ASSUAN_USE_DOUBLE_FORK
+
+       Use a double fork approach when connecting to a server through
+       a pipe.
  */
 /**** Begin GPGME specific modifications. ******/
 #define _ASSUAN_EXT_SYM_PREFIX _gpgme_
@@ -115,12 +124,15 @@ int _gpgme_ath_recvmsg (int s, struct msghdr *msg, int flags);
 #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_init_socket_server_ext \
+  _ASSUAN_PREFIX(assuan_init_socket_server_ext)
 #define assuan_pipe_connect _ASSUAN_PREFIX(assuan_pipe_connect)
+#define assuan_pipe_connect_ext _ASSUAN_PREFIX(assuan_pipe_connect_ext)
 #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_socket_connect_ext _ASSUAN_PREFIX(assuan_socket_connect_ext)
 #define assuan_disconnect _ASSUAN_PREFIX(assuan_disconnect)
 #define assuan_get_pid _ASSUAN_PREFIX(assuan_get_pid)
+#define assuan_get_peercred _ASSUAN_PREFIX(assuan_get_peercred)
 #define assuan_transact _ASSUAN_PREFIX(assuan_transact)
 #define assuan_inquire _ASSUAN_PREFIX(assuan_inquire)
 #define assuan_read_line _ASSUAN_PREFIX(assuan_read_line)
@@ -137,6 +149,8 @@ int _gpgme_ath_recvmsg (int s, struct msghdr *msg, int flags);
 #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_err_source \
+  _ASSUAN_PREFIX(assuan_set_assuan_err_source)
 #define assuan_set_assuan_log_stream \
   _ASSUAN_PREFIX(assuan_set_assuan_log_stream)
 #define assuan_get_assuan_log_stream \
@@ -189,89 +203,121 @@ 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,
+/* Check for compiler features.  */
+#if __GNUC__
+#define _ASSUAN_GCC_VERSION (__GNUC__ * 10000 \
+                            + __GNUC_MINOR__ * 100 \
+                            + __GNUC_PATCHLEVEL__)
+
+#if _ASSUAN_GCC_VERSION > 30100
+#define _ASSUAN_DEPRECATED  __attribute__ ((__deprecated__))
+#endif
+#endif
+#ifndef _ASSUAN_DEPRECATED
+#define _ASSUAN_DEPRECATED
+#endif
+
+
+/* Assuan error codes.  These are only used by old applications or
+   those applications which won't make use of libgpg-error. */
+#ifndef _ASSUAN_ONLY_GPG_ERRORS
+#ifndef _ASSUAN_IN_LIBASSUAN
+#define  ASSUAN_No_Error 0
+#endif
+#define  ASSUAN_General_Error 1
+#define  ASSUAN_Out_Of_Core 2
+#define  ASSUAN_Invalid_Value 3
+#ifndef _ASSUAN_IN_LIBASSUAN
+#define  ASSUAN_Timeout 4
+#endif
+#define  ASSUAN_Read_Error 5
+#define  ASSUAN_Write_Error 6
+#define  ASSUAN_Problem_Starting_Server 7
+#define  ASSUAN_Not_A_Server 8
+#ifndef _ASSUAN_IN_LIBASSUAN
+#define  ASSUAN_Not_A_Client 9
+#endif
+#define  ASSUAN_Nested_Commands 10
+#define  ASSUAN_Invalid_Response 11
+#define  ASSUAN_No_Data_Callback 12
+#define  ASSUAN_No_Inquire_Callback 13
+#define  ASSUAN_Connect_Failed 14
+#define  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_Locale_Problem = 127,
-  ASSUAN_Not_Confirmed = 128,
-
-  /* Warning: Don't use the rror codes, below they are deprecated. */
-  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,
+#define  ASSUAN_Not_Implemented 100
+#define  ASSUAN_Server_Fault    101
+#ifndef _ASSUAN_IN_LIBASSUAN
+#define  ASSUAN_Invalid_Command 102
+#endif
+#define  ASSUAN_Unknown_Command 103
+#define  ASSUAN_Syntax_Error    104
+#ifndef _ASSUAN_IN_LIBASSUAN
+#define  ASSUAN_Parameter_Error 105
+#endif
+#define  ASSUAN_Parameter_Conflict 106
+#define  ASSUAN_Line_Too_Long 107
+#define  ASSUAN_Line_Not_Terminated 108
+#ifndef _ASSUAN_IN_LIBASSUAN
+#define  ASSUAN_No_Input 109
+#define  ASSUAN_No_Output 110
+#endif
+#define  ASSUAN_Canceled 111
+#ifndef _ASSUAN_IN_LIBASSUAN
+#define  ASSUAN_Unsupported_Algorithm 112
+#define  ASSUAN_Server_Resource_Problem 113
+#define  ASSUAN_Server_IO_Error 114
+#define  ASSUAN_Server_Bug 115
+#define  ASSUAN_No_Data_Available 116
+#define  ASSUAN_Invalid_Data 117
+#endif
+#define  ASSUAN_Unexpected_Command 118
+#define  ASSUAN_Too_Much_Data 119
+#ifndef _ASSUAN_IN_LIBASSUAN
+#define  ASSUAN_Inquire_Unknown 120
+#define  ASSUAN_Inquire_Error 121
+#define  ASSUAN_Invalid_Option 122
+#define  ASSUAN_Invalid_Index 123
+#define  ASSUAN_Unexpected_Status 124
+#define  ASSUAN_Unexpected_Data 125
+#define  ASSUAN_Invalid_Status 126
+#define  ASSUAN_Locale_Problem 127
+#define  ASSUAN_Not_Confirmed 128
+
+  /* Warning: Don't use the Error codes, below they are deprecated. */
+#define  ASSUAN_Bad_Certificate 201
+#define  ASSUAN_Bad_Certificate_Chain 202
+#define  ASSUAN_Missing_Certificate 203
+#define  ASSUAN_Bad_Signature 204
+#define  ASSUAN_No_Agent 205
+#define  ASSUAN_Agent_Error 206
+#define  ASSUAN_No_Public_Key 207
+#define  ASSUAN_No_Secret_Key 208
+#define  ASSUAN_Invalid_Name 209
+
+#define  ASSUAN_Cert_Revoked 301
+#define  ASSUAN_No_CRL_For_Cert 302
+#define  ASSUAN_CRL_Too_Old 303
+#define  ASSUAN_Not_Trusted 304
+
+#define  ASSUAN_Card_Error 401
+#define  ASSUAN_Invalid_Card 402
+#define  ASSUAN_No_PKCS15_App 403
+#define  ASSUAN_Card_Not_Present 404
+#define  ASSUAN_Invalid_Id 405
 
   /* Error codes in the range 1000 to 9999 may be used by applications
      at their own discretion. */
-  ASSUAN_USER_ERROR_FIRST = 1000,
-  ASSUAN_USER_ERROR_LAST = 9999
+#define  ASSUAN_USER_ERROR_FIRST 1000
+#define  ASSUAN_USER_ERROR_LAST 9999
+#endif
 
-} assuan_error_t;
+typedef int assuan_error_t;
 
-typedef assuan_error_t AssuanError; /* Deprecated. */
+typedef assuan_error_t AssuanError _ASSUAN_DEPRECATED; 
 
 /* This is a list of pre-registered ASSUAN commands */
-/* NOTE, these command IDs are now deprectated and solely exists for
+/* Note, these command IDs are now deprectated and solely exists for
    compatibility reasons. */
 typedef enum
 {
@@ -290,6 +336,13 @@ typedef enum
 } AssuanCommand;
 
 
+#else  /*!_ASSUAN_ONLY_GPG_ERRORS*/
+
+typedef int assuan_error_t;
+
+#endif /*!_ASSUAN_ONLY_GPG_ERRORS*/
+
+
 /* Definitions of flags for assuan_set_flag(). */
 typedef enum
   {
@@ -306,7 +359,9 @@ assuan_flag_t;
 
 struct assuan_context_s;
 typedef struct assuan_context_s *assuan_context_t;
-typedef struct assuan_context_s *ASSUAN_CONTEXT;
+#ifndef _ASSUAN_ONLY_GPG_ERRORS
+typedef struct assuan_context_s *ASSUAN_CONTEXT _ASSUAN_DEPRECATED;
+#endif /*_ASSUAN_ONLY_GPG_ERRORS*/
 
 /*-- assuan-handler.c --*/
 int assuan_register_command (assuan_context_t ctx,
@@ -343,7 +398,7 @@ assuan_error_t assuan_write_status (assuan_context_t ctx,
    file descriptor via CTX and stores it in *RDF (the CTX must be
    capable of passing file descriptors).  */
 assuan_error_t assuan_command_parse_fd (assuan_context_t ctx, char *line,
-                                    int *rfd);
+                                        int *rfd);
 
 /*-- assuan-listen.c --*/
 assuan_error_t assuan_set_hello_line (assuan_context_t ctx, const char *line);
@@ -360,55 +415,54 @@ void assuan_deinit_server (assuan_context_t ctx);
 
 /*-- assuan-socket-server.c --*/
 int assuan_init_socket_server (assuan_context_t *r_ctx, int listen_fd);
-int assuan_init_connected_socket_server (assuan_context_t *r_ctx, int fd);
-
+int assuan_init_connected_socket_server (assuan_context_t *r_ctx, 
+                                         int fd) _ASSUAN_DEPRECATED;
+int assuan_init_socket_server_ext (assuan_context_t *r_ctx, int fd,
+                                   unsigned int flags);
 
 /*-- assuan-pipe-connect.c --*/
-assuan_error_t assuan_pipe_connect (assuan_context_t *ctx, const char *name,
+assuan_error_t assuan_pipe_connect (assuan_context_t *ctx,
+                                    const char *name,
                                    const char *const argv[],
                                    int *fd_child_list);
-assuan_error_t assuan_pipe_connect2 (assuan_context_t *ctx, const char *name,
+assuan_error_t assuan_pipe_connect2 (assuan_context_t *ctx,
+                                     const char *name,
                                      const char *const argv[],
                                     int *fd_child_list,
                                      void (*atfork) (void*, int),
-                                     void *atforkvalue);
+                                     void *atforkvalue) _ASSUAN_DEPRECATED;
+assuan_error_t assuan_pipe_connect_ext (assuan_context_t *ctx, 
+                                        const char *name,
+                                        const char *const argv[],
+                                        int *fd_child_list,
+                                        void (*atfork) (void *, int),
+                                        void *atforkvalue,
+                                        unsigned int flags);
+
 /*-- assuan-socket-connect.c --*/
-assuan_error_t assuan_socket_connect (assuan_context_t *ctx, const char *name,
+assuan_error_t assuan_socket_connect (assuan_context_t *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.  */
-assuan_error_t assuan_domain_connect (assuan_context_t *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.  */
-assuan_error_t assuan_init_domain_server (assuan_context_t *r_ctx,
-                                      int rendezvousfd,
-                                      pid_t client);
-
+assuan_error_t assuan_socket_connect_ext (assuan_context_t *ctx,
+                                          const char *name,
+                                          pid_t server_pid,
+                                          unsigned int flags);
 
 /*-- assuan-connect.c --*/
 void assuan_disconnect (assuan_context_t ctx);
 pid_t assuan_get_pid (assuan_context_t ctx);
+assuan_error_t assuan_get_peercred (assuan_context_t ctx,
+                                    pid_t *pid, uid_t *uid, gid_t *gid);
 
 /*-- assuan-client.c --*/
 assuan_error_t 
 assuan_transact (assuan_context_t ctx,
                  const char *command,
-                 assuan_error_t (*data_cb)(void *, const void *, size_t),
+                 int (*data_cb)(void *, const void *, size_t),
                  void *data_cb_arg,
-                 assuan_error_t (*inquire_cb)(void*, const char *),
+                 int (*inquire_cb)(void*, const char *),
                  void *inquire_cb_arg,
-                 assuan_error_t (*status_cb)(void*, const char *),
+                 int (*status_cb)(void*, const char *),
                  void *status_cb_arg);
 
 
@@ -426,9 +480,8 @@ assuan_error_t assuan_send_data (assuan_context_t 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")).  */
+   called.  This means that assuan_sendfd should be called *before* the
+   trigger is sent (normally via assuan_write_line ("INPUT FD")).  */
 assuan_error_t assuan_sendfd (assuan_context_t ctx, int fd);
 assuan_error_t assuan_receivefd (assuan_context_t ctx, int *fd);
 
@@ -453,8 +506,20 @@ void assuan_set_flag (assuan_context_t ctx, assuan_flag_t flag, int value);
 int  assuan_get_flag (assuan_context_t ctx, assuan_flag_t flag);
 
 
-/*-- assuan-errors.c (built) --*/
+/*-- assuan-errors.c --*/
+
+#ifndef _ASSUAN_ONLY_GPG_ERRORS
+/* Return a string describing the assuan error.  The use of this
+   function is deprecated; it is better to call
+   assuan_set_assuan_err_source once and then make use libgpg-error. */
 const char *assuan_strerror (assuan_error_t err);
+#endif /*_ASSUAN_ONLY_GPG_ERRORS*/
+
+/* Enable gpg-error style error codes.  ERRSOURCE is one of gpg-error
+   sources.  Note, that this function is not thread-safe and should be
+   used right at startup. Switching back to the old style mode is not
+   supported. */
+void assuan_set_assuan_err_source (int errsource);
 
 /*-- assuan-logging.c --*/
 
index 47f3370..ac31007 100644 (file)
@@ -1,21 +1,22 @@
 /* funopen.c - Replacement for funopen.
- * Copyright (C) 2003 Free Software Foundation, Inc.
+ * Copyright (C) 2003, 2005 Free Software Foundation, Inc.
  *
- * This file is part of GnuPG.
+ * This file is part of Assuan.
  *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * 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.
  *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+ * 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 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
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA. 
  */
 
 #ifdef HAVE_CONFIG_H
@@ -54,7 +55,7 @@ _assuan_funopen(void *cookie,
   io.seek = seekfn;
   io.close = closefn;
 
-   return fopencookie (cookie,
+  return fopencookie (cookie,
                      readfn ? ( writefn ? "rw" : "r" )
                      : ( writefn ? "w" : ""), io);
 }
index e00011b..ded7ba3 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 # mkerrors - Extract error strings from assuan.h
 #            and create C source for assuan_strerror
-#      Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+#      Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
 #
 # This file is part of Assuan.
 #
 #
 # 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 
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 
 
 cat <<EOF
 /* Generated automatically by mkerrors */
-/* Do not edit! */
+/* Do not edit!  See mkerrors for copyright notice. */
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 
 #include <stdio.h>
+#include <assert.h>
+#include <errno.h>
+
+#undef _ASSUAN_IN_LIBASSUAN /* undef to get all error codes. */
 #include "assuan.h"
 
+/* If true the modern gpg-error style error codes are used in the
+   API. */
+static unsigned int err_source;
+
+/* Enable gpg-error style error codes.  ERRSOURCE is one of gpg-error
+   sources.  Note, that this function is not thread-safe and should be
+   used right at startup. Switching back to the old style mode is not
+   supported. */
+void
+assuan_set_assuan_err_source (int errsource)
+{
+  errsource &= 0xff;
+  err_source = errsource? errsource : 31 /*GPG_ERR_SOURCE_ANY*/;
+}
+
+
+/* Helper to map old style Assuan error codes to gpg-error codes.
+   This is used internally to keep an compatible ABI. */
+assuan_error_t
+_assuan_error (int oldcode)
+{
+  unsigned int n;
+
+  if (!err_source)
+    return (oldcode & 0x00ffffff); /* Make sure that the gpg-error
+                                      source part is cleared. */
+
+  switch (oldcode)
+    {
+    case ASSUAN_General_Error:           n = 257; break;
+    case ASSUAN_Accept_Failed:           n = 258; break;
+    case ASSUAN_Connect_Failed:          n = 259; break;
+    case ASSUAN_Invalid_Response:        n = 260; break;
+    case ASSUAN_Invalid_Value:           n = 261; break;
+    case ASSUAN_Line_Not_Terminated:     n = 262; break;
+    case ASSUAN_Line_Too_Long:           n = 263; break;
+    case ASSUAN_Nested_Commands:         n = 264; break;
+    case ASSUAN_No_Data_Callback:        n = 265; break;
+    case ASSUAN_No_Inquire_Callback:     n = 266; break;
+    case ASSUAN_Not_A_Server:            n = 267; break;
+    case ASSUAN_Not_Implemented:         n =  69; break;
+    case ASSUAN_Parameter_Conflict:      n = 280; break;
+    case ASSUAN_Problem_Starting_Server: n = 269; break;
+    case ASSUAN_Server_Fault:            n =  80; break;
+    case ASSUAN_Syntax_Error:            n = 276; break;
+    case ASSUAN_Too_Much_Data:           n = 273; break;
+    case ASSUAN_Unexpected_Command:      n = 274; break;
+    case ASSUAN_Unknown_Command:         n = 275; break;
+    case ASSUAN_Canceled:                n = 277; break;
+    case ASSUAN_No_Secret_Key:           n =  17; break;
+
+    case ASSUAN_Read_Error:
+      switch (errno)
+        {
+        case 0: n = 16381; /*GPG_ERR_MISSING_ERRNO*/  break;
+        default: n = 270;  /*GPG_ERR_ASS_READ_ERROR*/ break;
+        }
+      break;
+
+    case ASSUAN_Write_Error:
+      switch (errno)
+        {
+        case 0: n = 16381; /*GPG_ERR_MISSING_ERRNO*/  break;
+        default: n = 271;  /*GPG_ERR_ASS_WRITE_ERROR*/ break;
+        }
+      break;
+      
+    case ASSUAN_Out_Of_Core:
+      switch (errno)
+        {
+        case 0:  /* Should not happen but a user might have provided
+                    an incomplete implemented malloc function.  Give
+                    him a chance to correct this fault but make sure
+                    an error is indeed returned. */
+          n = 16381; /*GPG_ERR_MISSING_ERRNO*/
+          break;
+        case ENOMEM: n = (1 << 15) | 86; break;
+        default:  
+          n = 16382; /*GPG_ERR_UNKNOWN_ERRNO*/
+          break;
+        }
+      break;
+
+    case -1: n = 16383 /*GPG_ERR_EOF*/; break;
+
+    default:
+      n = 257; 
+      break;
+    }
+
+  return ((err_source << 24) | (n & 0x00ffffff));
+
+}
+
+
 /**
  * assuan_strerror:
  * @err:  Error code 
@@ -41,7 +140,7 @@ cat <<EOF
  * Return value: String with the error description.
  **/
 const char *
-assuan_strerror (AssuanError err)
+assuan_strerror (assuan_error_t err)
 {
   const char *s;
   static char buf[50];
@@ -51,10 +150,10 @@ assuan_strerror (AssuanError err)
 EOF
 
 awk '
-/ASSUAN_No_Error/    { okay=1 }
-!okay              {next}
-/}/                { exit 0 }
-/ASSUAN_[A-Za-z_]*/ { print_code($1) }
+/ASSUAN_No_Error/        { okay=1 }
+!okay                    {next}
+/^#define[ ]+ASSUAN_[A-Za-z_]*/ { print_code($2) }
+/ASSUAN_USER_ERROR_LAST/ { exit 0 }
 
 
 function print_code( s )
@@ -66,21 +165,62 @@ printf "%s\"; break;\n", tolower(substr(s,8));
 '
 
 cat <<EOF
+  case -1: s = "EOF (-1)"; break;
     default: 
       {
-        unsigned int source, code;
+        unsigned int source, code, n;
 
         source = ((err >> 24) & 0xff);
         code = (err & 0x00ffffff);
-        if (source) /* Assume this is an libgpg-error. */
-          sprintf (buf, "ec=%u.%u", source, code ); 
+        if (source) 
+          {
+            /* Assume this is an libgpg-error and try to map the codes
+               back. */
+            switch (code)
+              {
+              case 257: n = ASSUAN_General_Error          ; break;
+              case 258: n = ASSUAN_Accept_Failed          ; break;
+              case 259: n = ASSUAN_Connect_Failed         ; break;
+              case 260: n = ASSUAN_Invalid_Response       ; break;
+              case 261: n = ASSUAN_Invalid_Value          ; break;
+              case 262: n = ASSUAN_Line_Not_Terminated    ; break;
+              case 263: n = ASSUAN_Line_Too_Long          ; break;
+              case 264: n = ASSUAN_Nested_Commands        ; break;
+              case 265: n = ASSUAN_No_Data_Callback       ; break;
+              case 266: n = ASSUAN_No_Inquire_Callback    ; break;
+              case 267: n = ASSUAN_Not_A_Server           ; break;
+              case  69: n = ASSUAN_Not_Implemented        ; break;
+              case 280: n = ASSUAN_Parameter_Conflict     ; break;
+              case 269: n = ASSUAN_Problem_Starting_Server; break;
+              case 270: n = ASSUAN_Read_Error             ; break;
+              case 271: n = ASSUAN_Write_Error            ; break;
+              case  80: n = ASSUAN_Server_Fault           ; break;
+              case 276: n = ASSUAN_Syntax_Error           ; break;
+              case 273: n = ASSUAN_Too_Much_Data          ; break;
+              case 274: n = ASSUAN_Unexpected_Command     ; break;
+              case 275: n = ASSUAN_Unknown_Command        ; break;
+              case 277: n = ASSUAN_Canceled               ; break;
+              case ((1<<15)|86): n = ASSUAN_Out_Of_Core   ; break;
+              default:  n = 0; break;
+              }
+            if (n)
+              s = assuan_strerror (n);
+            else
+              {
+                sprintf (buf, "ec=%u.%u", source, code ); 
+                s=buf;
+              }
+          }
         else
-          sprintf (buf, "ec=%d", err ); 
-        s=buf; break;
+          {
+            sprintf (buf, "ec=%d", err ); 
+            s=buf;
+          }
       }
+      break;
     }
 
   return s;
 }
 
-EOF
\ No newline at end of file
+EOF
index d40fc32..45f295a 100644 (file)
@@ -202,8 +202,6 @@ AC_SUBST(NETLIBS)
 # Checks for library functions.
 AC_FUNC_FSEEKO
 
-AC_CHECK_FUNCS(stpcpy)
-
 AC_REPLACE_FUNCS(vasprintf)
 if test "$ac_cv_func_vasprintf" != yes; then
   GNUPG_CHECK_VA_COPY
@@ -462,6 +460,10 @@ fi
 AC_REPLACE_FUNCS(isascii)
 AC_REPLACE_FUNCS(putc_unlocked)
 AC_REPLACE_FUNCS(memrchr)
+AC_REPLACE_FUNCS(stpcpy)
+# Check for unistd.h for setenv replacement function.
+AC_CHECK_HEADERS(unistd.h)
+AC_REPLACE_FUNCS(setenv)
 
 # More assuan checks.
 AC_CHECK_HEADERS([sys/uio.h])
index f0fee7c..ac66242 100644 (file)
@@ -72,7 +72,7 @@ extern "C" {
    AM_PATH_GPGME macro) check that this header matches the installed
    library.  Warning: Do not edit the next line.  configure will do
    that for you!  */
-#define GPGME_VERSION "1.1.1-cvs1150"
+#define GPGME_VERSION "1.1.3-cvs1179"
 
 
 \f
diff --git a/gpgme/setenv.c b/gpgme/setenv.c
new file mode 100644 (file)
index 0000000..3c803b0
--- /dev/null
@@ -0,0 +1,352 @@
+/* Copyright (C) 1992,1995-2001,2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library 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.
+
+   The GNU C Library 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 the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02110-1301 USA.  */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "assuan-defs.h"
+
+#define __builtin_expect(cond,val) (cond)
+
+#include <errno.h>
+#if !_LIBC
+# if !defined errno && !defined HAVE_ERRNO_DECL
+extern int errno;
+# endif
+# define __set_errno(ev) ((errno) = (ev))
+#endif
+
+#if _LIBC || HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+#if _LIBC || HAVE_STRING_H
+# include <string.h>
+#endif
+#if _LIBC || HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#if !_LIBC
+# define __environ     environ
+# ifndef HAVE_ENVIRON_DECL
+extern char **environ;
+# endif
+#endif
+
+#if _LIBC
+/* This lock protects against simultaneous modifications of `environ'.  */
+# include <bits/libc-lock.h>
+__libc_lock_define_initialized (static, envlock)
+# define LOCK  __libc_lock_lock (envlock)
+# define UNLOCK        __libc_lock_unlock (envlock)
+#else
+# define LOCK
+# define UNLOCK
+#endif
+
+/* In the GNU C library we must keep the namespace clean.  */
+#ifdef _LIBC
+# define setenv __setenv
+# define unsetenv __unsetenv
+# define clearenv __clearenv
+# define tfind __tfind
+# define tsearch __tsearch
+#endif
+
+/* In the GNU C library implementation we try to be more clever and
+   allow arbitrarily many changes of the environment given that the used
+   values are from a small set.  Outside glibc this will eat up all
+   memory after a while.  */
+#if defined _LIBC || (defined HAVE_SEARCH_H && defined HAVE_TSEARCH \
+                     && defined __GNUC__)
+# define USE_TSEARCH   1
+# include <search.h>
+
+/* This is a pointer to the root of the search tree with the known
+   values.  */
+static void *known_values;
+
+# define KNOWN_VALUE(Str) \
+  ({                                                                         \
+    void *value = tfind (Str, &known_values, (__compar_fn_t) strcmp);        \
+    value != NULL ? *(char **) value : NULL;                                 \
+  })
+# define STORE_VALUE(Str) \
+  tsearch (Str, &known_values, (__compar_fn_t) strcmp)
+
+#else
+# undef USE_TSEARCH
+
+# define KNOWN_VALUE(Str) NULL
+# define STORE_VALUE(Str) do { } while (0)
+
+#endif
+
+
+/* If this variable is not a null pointer we allocated the current
+   environment.  */
+static char **last_environ;
+
+
+/* This function is used by `setenv' and `putenv'.  The difference between
+   the two functions is that for the former must create a new string which
+   is then placed in the environment, while the argument of `putenv'
+   must be used directly.  This is all complicated by the fact that we try
+   to reuse values once generated for a `setenv' call since we can never
+   free the strings.  */
+static int
+__add_to_environ (const char *name, const char *value, const char *combined,
+                 int replace)
+{
+  register char **ep;
+  register size_t size;
+  const size_t namelen = strlen (name);
+  const size_t vallen = value != NULL ? strlen (value) + 1 : 0;
+
+  LOCK;
+
+  /* We have to get the pointer now that we have the lock and not earlier
+     since another thread might have created a new environment.  */
+  ep = __environ;
+
+  size = 0;
+  if (ep != NULL)
+    {
+      for (; *ep != NULL; ++ep)
+       if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=')
+         break;
+       else
+         ++size;
+    }
+
+  if (ep == NULL || __builtin_expect (*ep == NULL, 1))
+    {
+      char **new_environ;
+
+      /* We allocated this space; we can extend it.  */
+      new_environ = (char **) realloc (last_environ,
+                                      (size + 2) * sizeof (char *));
+      if (new_environ == NULL)
+       {
+         UNLOCK;
+         return -1;
+       }
+
+      /* If the whole entry is given add it.  */
+      if (combined != NULL)
+       /* We must not add the string to the search tree since it belongs
+          to the user.  */
+       new_environ[size] = (char *) combined;
+      else
+       {
+         /* See whether the value is already known.  */
+#ifdef USE_TSEARCH
+# ifdef __GNUC__
+         char new_value[namelen + 1 + vallen];
+# else
+         char *new_value = (char *) alloca (namelen + 1 + vallen);
+# endif
+# ifdef _LIBC
+         __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1),
+                    value, vallen);
+# else
+         memcpy (new_value, name, namelen);
+         new_value[namelen] = '=';
+         memcpy (&new_value[namelen + 1], value, vallen);
+# endif
+
+         new_environ[size] = KNOWN_VALUE (new_value);
+         if (__builtin_expect (new_environ[size] == NULL, 1))
+#endif
+           {
+             new_environ[size] = (char *) malloc (namelen + 1 + vallen);
+             if (__builtin_expect (new_environ[size] == NULL, 0))
+               {
+                 __set_errno (ENOMEM);
+                 UNLOCK;
+                 return -1;
+               }
+
+#ifdef USE_TSEARCH
+             memcpy (new_environ[size], new_value, namelen + 1 + vallen);
+#else
+             memcpy (new_environ[size], name, namelen);
+             new_environ[size][namelen] = '=';
+             memcpy (&new_environ[size][namelen + 1], value, vallen);
+#endif
+             /* And save the value now.  We cannot do this when we remove
+                the string since then we cannot decide whether it is a
+                user string or not.  */
+             STORE_VALUE (new_environ[size]);
+           }
+       }
+
+      if (__environ != last_environ)
+       memcpy ((char *) new_environ, (char *) __environ,
+               size * sizeof (char *));
+
+      new_environ[size + 1] = NULL;
+
+      last_environ = __environ = new_environ;
+    }
+  else if (replace)
+    {
+      char *np;
+
+      /* Use the user string if given.  */
+      if (combined != NULL)
+       np = (char *) combined;
+      else
+       {
+#ifdef USE_TSEARCH
+# ifdef __GNUC__
+         char new_value[namelen + 1 + vallen];
+# else
+         char *new_value = (char *) alloca (namelen + 1 + vallen);
+# endif
+# ifdef _LIBC
+         __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1),
+                    value, vallen);
+# else
+         memcpy (new_value, name, namelen);
+         new_value[namelen] = '=';
+         memcpy (&new_value[namelen + 1], value, vallen);
+# endif
+
+         np = KNOWN_VALUE (new_value);
+         if (__builtin_expect (np == NULL, 1))
+#endif
+           {
+             np = malloc (namelen + 1 + vallen);
+             if (__builtin_expect (np == NULL, 0))
+               {
+                 UNLOCK;
+                 return -1;
+               }
+
+#ifdef USE_TSEARCH
+             memcpy (np, new_value, namelen + 1 + vallen);
+#else
+             memcpy (np, name, namelen);
+             np[namelen] = '=';
+             memcpy (&np[namelen + 1], value, vallen);
+#endif
+             /* And remember the value.  */
+             STORE_VALUE (np);
+           }
+       }
+
+      *ep = np;
+    }
+
+  UNLOCK;
+
+  return 0;
+}
+
+int
+setenv (const char *name, const char *value, int replace)
+{
+  if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  return __add_to_environ (name, value, NULL, replace);
+}
+
+int
+unsetenv (const char *name)
+{
+  size_t len;
+  char **ep;
+
+  if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  len = strlen (name);
+
+  LOCK;
+
+  ep = __environ;
+  while (*ep != NULL)
+    if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
+      {
+       /* Found it.  Remove this pointer by moving later ones back.  */
+       char **dp = ep;
+
+       do
+         dp[0] = dp[1];
+       while (*dp++);
+       /* Continue the loop in case NAME appears again.  */
+      }
+    else
+      ++ep;
+
+  UNLOCK;
+
+  return 0;
+}
+
+/* The `clearenv' was planned to be added to POSIX.1 but probably
+   never made it.  Nevertheless the POSIX.9 standard (POSIX bindings
+   for Fortran 77) requires this function.  */
+int
+clearenv (void)
+{
+  LOCK;
+
+  if (__environ == last_environ && __environ != NULL)
+    {
+      /* We allocated this environment so we can free it.  */
+      free (__environ);
+      last_environ = NULL;
+    }
+
+  /* Clear the environment pointer removes the whole environment.  */
+  __environ = NULL;
+
+  UNLOCK;
+
+  return 0;
+}
+#ifdef _LIBC
+libc_freeres_fn (free_mem)
+{
+  /* Remove all traces.  */
+  clearenv ();
+
+  /* Now remove the search tree.  */
+  __tdestroy (known_values, free);
+  known_values = NULL;
+}
+
+# undef setenv
+# undef unsetenv
+# undef clearenv
+weak_alias (__setenv, setenv)
+weak_alias (__unsetenv, unsetenv)
+weak_alias (__clearenv, clearenv)
+#endif
+
+