Merged changes from upstream libassuan to allow building a W32 DLL.
authorWerner Koch <wk@gnupg.org>
Tue, 9 Aug 2005 13:19:24 +0000 (13:19 +0000)
committerWerner Koch <wk@gnupg.org>
Tue, 9 Aug 2005 13:19:24 +0000 (13:19 +0000)
24 files changed:
ChangeLog
assuan/ChangeLog
assuan/README.1st
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-util.c
assuan/assuan.h
assuan/mkerrors
configure.ac
gpgme/ChangeLog
gpgme/util.h

index a55f2ae..83209c4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2005-08-08  Werner Koch  <wk@g10code.com>
+
+       * configure.ac (stpcpy): Changed from replace to test.
+
 2005-03-24  Marcus Brinkmann  <marcus@g10code.de>
 
        * configure.ac (AH_BOTTOM): Removed.
index b73a5da..22c5189 100644 (file)
@@ -1,3 +1,50 @@
+2005-08-09  Werner Koch  <wk@g10code.com>
+
+       * README.1st: Adjusted to cope with changes done in upstream Assuan.
+
+       Merged changes for W32 support from libassuan.
+       
+       * assuan.h [_ASSUAN_EXT_SYM_PREFIX]: New.
+       * assuan-io.c [_ASSUAN_NO_PTH]: New.
+       * assuan-pipe-connect.c (fix_signals) [_ASSUAN_NO_FIXED_SIGNALS]: New.
+       (assuan_pipe_connect2) [_ASSUAN_USE_DOUBLE_FORK]: Use double fork.
+       (fix_signals) [_ASSUAN_USE_DOUBLE_FORK]: Do not wait..
+       * assuan-logging.c, assuan-io.c: Include config.h
+       Replaced all usages of _WIN32 by the new HAVE_W32_SYSTEM because
+       there is nothing winning in this API.
+       * assuan-pipe-connect.c (assuan_pipe_connect2) [_WIN32]: Return
+       error Not Imlemented.
+       * assuan-logging.c (_assuan_w32_strerror): New. 
+       * assuan-defs.h (w32_strerror): new.
+       * assuan-pipe-connect.c (assuan_pipe_connect2, fix_signals):
+       Factored signal code out to new function.
+       (build_w32_commandline, create_inheritable_pipe): New.  Taken
+       from gnupg 1.9.
+       (assuan_pipe_connect2) [W32]: Implemented for W32.
+       * assuan-pipe-server.c (assuan_init_pipe_server) [W32]: Map file
+       descriptors using _get_osfhandle.
+       * assuan-socket-connect.c (assuan_socket_connect) [W32]: Allow for
+       a drive letter in the path.
+       * assuan-client.c (assuan_transact): Handle empty and comment
+       commands correctly.
+       * assuan-util.c (_assuan_calloc): Avoid integer overflow.
+       * assuan-util.c (assuan_set_flag, assuan_get_flag): New.
+       * assuan-defs.h (struct assuan_context_s): New field flags.
+       * assuan.h (assuan_flag_t): New with one flag value
+       ASSUAN_NO_WAITPID for now.
+       * assuan-pipe-connect.c (do_finish): Take care of the no_waitpid
+       flag.
+       * mkerrors: Include config.h into assuan-errors.c.  This is
+       required so that assuan.h knows about the W32 macro.
+
+2005-08-09 Timo Schulz  <twoaday@g10code.com> (ported from libassuan by wk)
+       
+       * assuan-io.c (_assuan_simple_read, _assuan_simple_write): W32
+       support.
+       * assuan-socket.c (_assuan_close): New.
+       (_assuan_sock_new): New.
+       (_assuan_sock_bind): New.
+
 2005-03-22  Werner Koch  <wk@g10code.com>
 
        * assuan-defs.h (struct assuan_io): Renamed elements READ and
index 47bdefa..670efb5 100644 (file)
@@ -13,16 +13,15 @@ updating this directory, are:
    with ATH replacements.
 
 * assuan.h
-** Define _ASSUAN_IN_GPGME to enable GPGME specific code.
-** Put all exported Assuan functions in the _gpgme namespace.
-** Also wrap all system functions that are wrapped by GNU Pth to
-   _gpgme wrappers.
-
-* assuan-io.c
-** Don't try to support GNU Pth here.
-
-* assuan-pipe-connect.c
-** Do not install SIGPIPE signal handler here.
+** Preserve the block between "Begin/End GPGME specific modifications".
+   In particular make sure that
+     #define _ASSUAN_EXT_SYM_PREFIX _gpgme_
+     #define _ASSUAN_NO_PTH 
+     #define _ASSUAN_NO_FIXED_SIGNALS 
+     #define _ASSUAN_USE_DOUBLE_FORK
+   are defined.  This puts all exported Assuan functions in the _gpgme
+   namespace.  It also wraps all system functions that are wrapped by
+   GNU Pth to _gpgme wrappers.
 
 
  Copyright 2004 g10 Code GmbH
index d9163b7..99ea72e 100644 (file)
@@ -1,5 +1,5 @@
 /* assuan-buffer.c - read and send data
- *     Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+ *     Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
  *
  * This file is part of Assuan.
  *
@@ -25,6 +25,9 @@
 #include <errno.h>
 #include <unistd.h>
 #include <assert.h>
+#ifdef HAVE_W32_SYSTEM
+#include <process.h>
+#endif
 #include "assuan-defs.h"
 
 static int
@@ -49,12 +52,12 @@ writen (ASSUAN_CONTEXT ctx, const char *buffer, size_t length)
 /* Read an entire line.  */
 static int
 readline (ASSUAN_CONTEXT ctx, char *buf, size_t buflen,
-         int *r_nread, int *eof)
+         int *r_nread, int *r_eof)
 {
   size_t nleft = buflen;
   char *p;
 
-  *eof = 0;
+  *r_eof = 0;
   *r_nread = 0;
   while (nleft > 0)
     {
@@ -68,7 +71,7 @@ readline (ASSUAN_CONTEXT ctx, char *buf, size_t buflen,
         }
       else if (!n)
         {
-          *eof = 1;
+          *r_eof = 1;
           break; /* allow incomplete lines */
         }
       p = buf;
@@ -125,16 +128,18 @@ _assuan_read_line (ASSUAN_CONTEXT ctx)
   if (rc)
     {
       if (ctx->log_fp)
-       fprintf (ctx->log_fp, "%s[%p] <- [Error: %s]\n",
-                assuan_get_assuan_log_prefix (), ctx, strerror (errno));
+       fprintf (ctx->log_fp, "%s[%u.%p] DBG: <- [Error: %s]\n",
+                assuan_get_assuan_log_prefix (),
+                 (unsigned int)getpid (), ctx, strerror (errno));
       return ASSUAN_Read_Error;
     }
   if (!nread)
     {
       assert (ctx->inbound.eof);
       if (ctx->log_fp)
-       fprintf (ctx->log_fp, "%s[%p] <- [EOF]\n",
-                assuan_get_assuan_log_prefix (), ctx);
+       fprintf (ctx->log_fp, "%s[%u.%p] DBG: <- [EOF]\n",
+                assuan_get_assuan_log_prefix (),
+                 (unsigned int)getpid (), ctx);
       return -1;
     }
 
@@ -165,8 +170,9 @@ _assuan_read_line (ASSUAN_CONTEXT ctx)
       ctx->inbound.linelen = endp - line;
       if (ctx->log_fp)
        {
-         fprintf (ctx->log_fp, "%s[%p] <- ",
-                  assuan_get_assuan_log_prefix (), ctx);
+         fprintf (ctx->log_fp, "%s[%u.%p] DBG: <- ",
+                  assuan_get_assuan_log_prefix (),
+                   (unsigned int)getpid (), ctx);
          if (ctx->confidential)
            fputs ("[Confidential data not shown]", ctx->log_fp);
          else
@@ -180,8 +186,9 @@ _assuan_read_line (ASSUAN_CONTEXT ctx)
   else
     {
       if (ctx->log_fp)
-       fprintf (ctx->log_fp, "%s[%p] <- [Invalid line]\n",
-                assuan_get_assuan_log_prefix (), ctx);
+       fprintf (ctx->log_fp, "%s[%u.%p] DBG: <- [Invalid line]\n",
+                assuan_get_assuan_log_prefix (),
+                 (unsigned int)getpid (), ctx);
       *line = 0;
       ctx->inbound.linelen = 0;
       return ctx->inbound.eof ? ASSUAN_Line_Not_Terminated
@@ -199,10 +206,10 @@ _assuan_read_line (ASSUAN_CONTEXT ctx)
    Returns 0 on success or an assuan error code.
    See also: assuan_pending_line().
 */
-AssuanError
+assuan_error_t
 assuan_read_line (ASSUAN_CONTEXT ctx, char **line, size_t *linelen)
 {
-  AssuanError err;
+  assuan_error_t err;
 
   if (!ctx)
     return ASSUAN_Invalid_Value;
@@ -223,31 +230,33 @@ assuan_pending_line (ASSUAN_CONTEXT ctx)
 }
 
 
-AssuanError 
-assuan_write_line (ASSUAN_CONTEXT ctx, const char *line)
+assuan_error_t 
+_assuan_write_line (assuan_context_t ctx, const char *prefix,
+                    const char *line, size_t len)
 {
-  int rc;
-  size_t len;
-  const char *s;
+  int rc = 0;
+  size_t prefixlen = prefix? strlen (prefix):0;
 
-  if (!ctx)
-    return ASSUAN_Invalid_Value;
-
-  /* Make sure that we never take a LF from the user - this might
-     violate the protocol. */
-  s = strchr (line, '\n');
-  len = s? (s-line) : strlen (line);
-
-  if (len > LINELENGTH - 2)
-    return ASSUAN_Line_Too_Long;
+  /* 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: -> "
+                 "[supplied line too long -truncated]\n",
+                 assuan_get_assuan_log_prefix (),
+                 (unsigned int)getpid (), ctx);
+      if (prefixlen > 5)
+        prefixlen = 5;
+      if (len > ASSUAN_LINELENGTH - prefixlen - 2)
+        len = ASSUAN_LINELENGTH - prefixlen - 2 - 1;
+    }
 
-  /* fixme: we should do some kind of line buffering.  */
+  /* Fixme: we should do some kind of line buffering.  */
   if (ctx->log_fp)
     {
-      fprintf (ctx->log_fp, "%s[%p] -> ",
-              assuan_get_assuan_log_prefix (), ctx);
-      if (s)
-       fputs ("[supplied line contained a LF]", ctx->log_fp);
+      fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> ",
+              assuan_get_assuan_log_prefix (),
+               (unsigned int)getpid (), ctx);
       if (ctx->confidential)
        fputs ("[Confidential data not shown]", ctx->log_fp);
       else
@@ -255,27 +264,60 @@ assuan_write_line (ASSUAN_CONTEXT ctx, const char *line)
       putc ('\n', ctx->log_fp);
     }
 
-  rc = writen (ctx, line, len);
-  if (rc)
-    rc = ASSUAN_Write_Error;
+  if (prefixlen)
+    {
+      rc = writen (ctx, prefix, prefixlen);
+      if (rc)
+        rc = ASSUAN_Write_Error;
+    }
   if (!rc)
     {
-      rc = writen (ctx, "\n", 1);
+      rc = writen (ctx, line, len);
       if (rc)
         rc = ASSUAN_Write_Error;
+      if (!rc)
+        {
+          rc = writen (ctx, "\n", 1);
+          if (rc)
+            rc = ASSUAN_Write_Error;
+        }
     }
-
   return rc;
 }
 
 
+assuan_error_t 
+assuan_write_line (ASSUAN_CONTEXT ctx, const char *line)
+{
+  size_t len;
+  const char *s;
+
+  if (!ctx)
+    return ASSUAN_Invalid_Value;
+
+  /* Make sure that we never take a LF from the user - this might
+     violate the protocol. */
+  s = strchr (line, '\n');
+  len = s? (s-line) : strlen (line);
+
+  if (ctx->log_fp && s)
+    fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> "
+             "[supplied line contained a LF -truncated]\n",
+             assuan_get_assuan_log_prefix (),
+             (unsigned int)getpid (), ctx);
+
+  return _assuan_write_line (ctx, NULL, line, len);
+}
+
+
 \f
 /* Write out the data in buffer as datalines with line wrapping and
-   percent escaping.  This fucntion is used for GNU's custom streams */
+   percent escaping.  This function is used for GNU's custom streams */
 int
-_assuan_cookie_write_data (void *cookie, const char *buffer, size_t size)
+_assuan_cookie_write_data (void *cookie, const char *buffer, size_t orig_size)
 {
   ASSUAN_CONTEXT ctx = cookie;
+  size_t size = orig_size;
   char *line;
   size_t linelen;
 
@@ -317,8 +359,9 @@ _assuan_cookie_write_data (void *cookie, const char *buffer, size_t size)
         {
           if (ctx->log_fp)
             {
-             fprintf (ctx->log_fp, "%s[%p] -> ",
-                      assuan_get_assuan_log_prefix (), ctx);
+             fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> ",
+                      assuan_get_assuan_log_prefix (),
+                       (unsigned int)getpid (), ctx);
 
               if (ctx->confidential)
                 fputs ("[Confidential data not shown]", ctx->log_fp);
@@ -341,12 +384,12 @@ _assuan_cookie_write_data (void *cookie, const char *buffer, size_t size)
     }
 
   ctx->outbound.data.linelen = linelen;
-  return 0;
+  return (int)orig_size;
 }
 
 
 /* Write out any buffered data 
-   This fucntion is used for GNU's custom streams */
+   This function is used for GNU's custom streams */
 int
 _assuan_cookie_write_flush (void *cookie)
 {
@@ -364,8 +407,9 @@ _assuan_cookie_write_flush (void *cookie)
     {
       if (ctx->log_fp)
        {
-         fprintf (ctx->log_fp, "%s[%p] -> ",
-                  assuan_get_assuan_log_prefix (), ctx);
+         fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> ",
+                  assuan_get_assuan_log_prefix (),
+                   (unsigned int)getpid (), ctx);
          if (ctx->confidential)
            fputs ("[Confidential data not shown]", ctx->log_fp);
          else
@@ -404,7 +448,7 @@ _assuan_cookie_write_flush (void *cookie)
  * Return value: 0 on success or an error code
  **/
 \f
-AssuanError
+assuan_error_t
 assuan_send_data (ASSUAN_CONTEXT ctx, const void *buffer, size_t length)
 {
   if (!ctx)
@@ -430,7 +474,7 @@ assuan_send_data (ASSUAN_CONTEXT ctx, const void *buffer, size_t length)
   return 0;
 }
 
-AssuanError
+assuan_error_t
 assuan_sendfd (ASSUAN_CONTEXT ctx, int fd)
 {
   if (! ctx->io->sendfd)
@@ -440,7 +484,7 @@ assuan_sendfd (ASSUAN_CONTEXT ctx, int fd)
   return ctx->io->sendfd (ctx, fd);
 }
 
-AssuanError
+assuan_error_t
 assuan_receivefd (ASSUAN_CONTEXT ctx, int *fd)
 {
   if (! ctx->io->receivefd)
index d5c0ec8..a218994 100644 (file)
 #define xtoi_2(p)   ((xtoi_1(p) * 16) + xtoi_1((p)+1))
 
 
-AssuanError
+assuan_error_t
 _assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off)
 {
   char *line;
   int linelen;
-  AssuanError rc;
+  assuan_error_t rc;
 
   *okay = 0;
   *off = 0;
@@ -126,14 +126,14 @@ _assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off)
  * the one one returned by the server in error lines or from the
  * callback functions.
  **/
-AssuanError
+assuan_error_t
 assuan_transact (ASSUAN_CONTEXT ctx,
                  const char *command,
-                 AssuanError (*data_cb)(void *, const void *, size_t),
+                 assuan_error_t (*data_cb)(void *, const void *, size_t),
                  void *data_cb_arg,
-                 AssuanError (*inquire_cb)(void*, const char *),
+                 assuan_error_t (*inquire_cb)(void*, const char *),
                  void *inquire_cb_arg,
-                 AssuanError (*status_cb)(void*, const char *),
+                 assuan_error_t (*status_cb)(void*, const char *),
                  void *status_cb_arg)
 {
   int rc, okay, off;
@@ -144,6 +144,9 @@ assuan_transact (ASSUAN_CONTEXT ctx,
   if (rc)
     return rc;
 
+  if (*command == '#' || !*command)
+    return 0; /* Don't expect a response for a comment line.  */
+
  again:
   rc = _assuan_read_from_server (ctx, &okay, &off);
   if (rc)
index d260e92..ff1f6ff 100644 (file)
 #include <unistd.h>
 #include <errno.h>
 #include <sys/types.h>
+#ifndef HAVE_W32_SYSTEM
 #include <sys/wait.h>
+#endif
 
 #include "assuan-defs.h"
 
 /* Disconnect and release the context CTX. */
 void
-assuan_disconnect (ASSUAN_CONTEXT ctx)
+assuan_disconnect (assuan_context_t ctx)
 {
   if (ctx)
     {
-#if 0
-      /* This may not work if the pipe is full and the other end is
-        blocked.  */
       assuan_write_line (ctx, "BYE");
-#endif
       ctx->finish_handler (ctx);
       ctx->deinit_handler (ctx);
       ctx->deinit_handler = NULL;
@@ -51,8 +49,10 @@ assuan_disconnect (ASSUAN_CONTEXT ctx)
     }
 }
 
+/* Return the PID of the peer or -1 if not known. */
 pid_t
-assuan_get_pid (ASSUAN_CONTEXT ctx)
+assuan_get_pid (assuan_context_t ctx)
 {
-  return ctx ? ctx->pid : -1;
+  return (ctx && ctx->pid)? ctx->pid : -1;
 }
+
index 248dbf4..2917fe8 100644 (file)
@@ -1,5 +1,5 @@
 /* assuan-defs.c - Internal definitions to Assuan
- *     Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ *     Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc.
  *
  * This file is part of Assuan.
  *
 #define ASSUAN_DEFS_H
 
 #include <sys/types.h>
+#ifndef HAVE_W32_SYSTEM
 #include <sys/socket.h>
 #include <sys/un.h>
+#else
+#include <windows.h>
+#endif
 #include <unistd.h>
 
 #include "assuan.h"
 
+#ifndef HAVE_W32_SYSTEM
+#define DIRSEP_C '/'
+#else
+#define DIRSEP_C '\\'
+#endif
+
+#ifdef HAVE_W32_SYSTEM
+#define AF_LOCAL AF_UNIX
+/* We need to prefix the structure with a sockaddr_in header so we can
+   use it later for sendto and recvfrom. */
+struct sockaddr_un
+{
+  short          sun_family;
+  unsigned short sun_port;
+  struct         in_addr sun_addr;
+  char           sun_path[108-2-4]; /* Path name.  */
+};
+
+/* Not needed anymore because the current mingw32 defines this in
+   sys/types.h */
+/* typedef int ssize_t; */
+
+/* Missing W32 functions */
+int putc_unlocked (int c, FILE *stream);
+void * memrchr (const void *block, int c, size_t size);
+char * stpcpy (char *dest, const char *src);
+#endif
+
 #define LINELENGTH ASSUAN_LINELENGTH
 
 struct cmdtbl_s
@@ -43,24 +75,31 @@ struct assuan_io
   /* Routine to write to output_fd.  */
   ssize_t (*writefnc) (ASSUAN_CONTEXT, const void *, size_t);
   /* Send a file descriptor.  */
-  AssuanError (*sendfd) (ASSUAN_CONTEXT, int);
+  assuan_error_t (*sendfd) (ASSUAN_CONTEXT, int);
   /* Receive a file descriptor.  */
-  AssuanError (*receivefd) (ASSUAN_CONTEXT, int *);
+  assuan_error_t (*receivefd) (ASSUAN_CONTEXT, int *);
 };  
 
 struct assuan_context_s
 {
-  AssuanError err_no;
+  assuan_error_t err_no;
   const char *err_str;
-  int os_errno;  /* last system error number used with certain error codes*/
+  int os_errno;       /* Last system error number used with certain
+                         error codes. */
+
+  /* Context specific flags (cf. assuan_flag_t). */
+  struct 
+  {
+    unsigned int no_waitpid:1; /* See ASSUAN_NO_WAITPID. */
+  } flags; 
 
   int confidential;
-  int is_server;  /* set if this is context belongs to a server */
+  int is_server;      /* Set if this is context belongs to a server */
   int in_inquire;
   char *hello_line;
-  char *okay_line; /* see assan_set_okay_line() */
+  char *okay_line;    /* See assuan_set_okay_line() */
   
-  void *user_pointer;  /* for assuan_[gs]et_pointer () */
+  void *user_pointer;  /* For assuan_get_pointer and assuan-set_pointer (). */
 
   FILE *log_fp;
 
@@ -90,13 +129,10 @@ struct assuan_context_s
 
   int pipe_mode;  /* We are in pipe mode, i.e. we can handle just one
                      connection and must terminate then */
-  pid_t pid;     /* In pipe mode, the pid of the child server process.  
-                     In socket mode, the pid of the server */
+  pid_t pid;     /* The the pid of the peer. */
   int listen_fd;  /* The fd we are listening on (used by socket servers) */
   int connected_fd; /* helper */
 
-  pid_t client_pid; /* for a socket server the PID of the client or -1
-                       if not available */
 
   /* Used for Unix domain sockets.  */
   struct sockaddr_un myaddr;
@@ -145,7 +181,7 @@ void _assuan_release_context (ASSUAN_CONTEXT ctx);
 /* Make a connection to the Unix domain socket NAME and return a new
    Assuan context in CTX.  SERVER_PID is currently not used but may
    become handy in the future.  */
-AssuanError _assuan_domain_init (ASSUAN_CONTEXT *r_ctx,
+assuan_error_t _assuan_domain_init (ASSUAN_CONTEXT *r_ctx,
                                 int rendezvousfd,
                                 pid_t peer);
 
@@ -156,9 +192,11 @@ int _assuan_register_std_commands (ASSUAN_CONTEXT ctx);
 int _assuan_read_line (ASSUAN_CONTEXT ctx);
 int _assuan_cookie_write_data (void *cookie, const char *buffer, size_t size);
 int _assuan_cookie_write_flush (void *cookie);
+assuan_error_t _assuan_write_line (assuan_context_t ctx, const char *prefix,
+                                   const char *line, size_t len);
 
 /*-- assuan-client.c --*/
-AssuanError _assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off);
+assuan_error_t _assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off);
 
 
 /*-- assuan-util.c --*/
@@ -177,17 +215,40 @@ void  _assuan_free (void *p);
 void _assuan_log_print_buffer (FILE *fp, const void *buffer, size_t  length);
 void _assuan_log_sanitized_string (const char *string);
 
+#ifdef HAVE_W32_SYSTEM
+const char *_assuan_w32_strerror (int ec);
+#define w32_strerror(e) _assuan_w32_strerror ((e))
+#endif /*HAVE_W32_SYSTEM*/
+
+
+/*-- assuan-logging.c --*/
+void _assuan_set_default_log_stream (FILE *fp);
+
+void _assuan_log_printf (const char *format, ...)
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
+ __attribute__ ((format (printf,1,2)))
+#endif
+     ;
+
 /*-- assuan-io.c --*/
 ssize_t _assuan_simple_read (ASSUAN_CONTEXT ctx, void *buffer, size_t size);
 ssize_t _assuan_simple_write (ASSUAN_CONTEXT ctx, const void *buffer,
                              size_t size);
 
+/*-- assuan-socket.c --*/
+int _assuan_close (int fd);
+int _assuan_sock_new (int domain, int type, int proto);
+int _assuan_sock_bind (int sockfd, struct sockaddr *addr, int addrlen);
+int _assuan_sock_connect (int sockfd, struct sockaddr *addr, int addrlen);
+
 #ifdef HAVE_FOPENCOOKIE
 /* We have to implement funopen in terms of glibc's fopencookie. */
-FILE *funopen(const void *cookie, cookie_read_function_t *readfn,
-              cookie_write_function_t *writefn,
-              cookie_seek_function_t *seekfn,
-              cookie_close_function_t *closefn);
+FILE *_assuan_funopen(void *cookie,
+                      cookie_read_function_t *readfn,
+                      cookie_write_function_t *writefn,
+                      cookie_seek_function_t *seekfn,
+                      cookie_close_function_t *closefn);
+#define funopen(a,r,w,s,c) _assuan_funopen ((a), (r), (w), (s), (c))
 #endif /*HAVE_FOPENCOOKIE*/
 
 #endif /*ASSUAN_DEFS_H*/
index b92be3b..b55e9c3 100644 (file)
 #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 "assuan-defs.h"
 
-#define LOG(format, args...) \
-       fprintf (assuan_get_assuan_log_stream (), \
-                assuan_get_assuan_log_prefix (), \
-                "%s" format , ## args)
+#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 ctx)
+do_deinit (assuan_context_t ctx)
 {
   if (ctx->inbound.fd != -1)
-    close (ctx->inbound.fd);
+    _assuan_close (ctx->inbound.fd);
   ctx->inbound.fd = -1;
   ctx->outbound.fd = -1;
 
@@ -65,7 +75,7 @@ do_deinit (ASSUAN_CONTEXT ctx)
 
       assert (ctx->pendingfdscount > 0);
       for (i = 0; i < ctx->pendingfdscount; i ++)
-       close (ctx->pendingfds[i]);
+       _assuan_close (ctx->pendingfds[i]);
 
       free (ctx->pendingfds);
     }
@@ -76,10 +86,11 @@ do_deinit (ASSUAN_CONTEXT ctx)
 
 /* Read from the socket server.  */
 static ssize_t
-domain_reader (ASSUAN_CONTEXT ctx, void *buf, size_t buflen)
+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.  */
@@ -166,15 +177,15 @@ domain_reader (ASSUAN_CONTEXT ctx, void *buf, size_t buflen)
          /* XXX: Arg.  Not from whom we expected!  What do we want to
             do?  Should we just ignore it?  We shall do the latter
             for the moment.  */
-         LOG ("Not setup to receive messages from: `%s'.",
-              ((struct sockaddr_un *) msg.msg_name)->sun_path);
+         _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)
        {
-         LOG ("domain_reader: %s\n", strerror (errno));
+         _assuan_log_printf ("domain_reader: %s\n", strerror (errno));
          return -1;
        }
 
@@ -190,7 +201,7 @@ domain_reader (ASSUAN_CONTEXT ctx, void *buf, size_t buflen)
                         sizeof (int) * (ctx->pendingfdscount + 1));
          if (! tmp)
            {
-             LOG ("domain_reader: %s\n", strerror (errno));
+             _assuan_log_printf ("domain_reader: %s\n", strerror (errno));
              return -1;
            }
 
@@ -198,13 +209,16 @@ domain_reader (ASSUAN_CONTEXT ctx, void *buf, size_t buflen)
          ctx->pendingfds[ctx->pendingfdscount++]
            = *(int *) CMSG_DATA (&cmsg.hdr);
 
-         LOG ("Received file descriptor %d from peer.\n",
+         _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.  */
 
@@ -223,8 +237,9 @@ domain_reader (ASSUAN_CONTEXT ctx, void *buf, size_t buflen)
 
 /* Write to the domain server.  */
 static ssize_t
-domain_writer (ASSUAN_CONTEXT ctx, const void *buf, size_t buflen)
+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;
@@ -244,14 +259,21 @@ domain_writer (ASSUAN_CONTEXT ctx, const void *buf, size_t buflen)
 
   len = sendmsg (ctx->outbound.fd, &msg, 0);
   if (len < 0)
-    LOG ("domain_writer: %s\n", strerror (errno));
-
+    _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 AssuanError
-domain_sendfd (ASSUAN_CONTEXT ctx, int fd)
+static assuan_error_t
+domain_sendfd (assuan_context_t ctx, int fd)
 {
+#ifndef HAVE_W32_SYSTEM
   struct msghdr msg;
   struct
   {
@@ -282,19 +304,23 @@ domain_sendfd (ASSUAN_CONTEXT ctx, int fd)
   len = sendmsg (ctx->outbound.fd, &msg, 0);
   if (len < 0)
     {
-      LOG ("domain_sendfd: %s\n", strerror (errno));
+      _assuan_log_printf ("domain_sendfd: %s\n", strerror (errno));
       return ASSUAN_General_Error;
     }
   else
     return 0;
+#else
+  return 0;
+#endif
 }
 
-static AssuanError
-domain_receivefd (ASSUAN_CONTEXT ctx, int *fd)
+static assuan_error_t
+domain_receivefd (assuan_context_t ctx, int *fd)
 {
+#ifndef HAVE_W32_SYSTEM
   if (ctx->pendingfds == 0)
     {
-      LOG ("No pending file descriptors!\n");
+      _assuan_log_printf ("no pending file descriptors!\n");
       return ASSUAN_General_Error;
     }
 
@@ -312,7 +338,7 @@ domain_receivefd (ASSUAN_CONTEXT ctx, int *fd)
       ctx->pendingfds = realloc (ctx->pendingfds,
                                 ctx->pendingfdscount * sizeof (int));
     }
-
+#endif
   return 0;
 }
 
@@ -321,14 +347,14 @@ domain_receivefd (ASSUAN_CONTEXT ctx, int *fd)
 /* Make a connection to the Unix domain socket NAME and return a new
    Assuan context in CTX.  SERVER_PID is currently not used but may
    become handy in the future.  */
-AssuanError
-_assuan_domain_init (ASSUAN_CONTEXT *r_ctx, int rendezvousfd, pid_t peer)
+assuan_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 };
 
-  AssuanError err;
-  ASSUAN_CONTEXT ctx;
+  assuan_error_t err;
+  assuan_context_t ctx;
   int fd;
   size_t len;
   int tries;
@@ -349,17 +375,17 @@ _assuan_domain_init (ASSUAN_CONTEXT *r_ctx, int rendezvousfd, pid_t peer)
 
   /* Setup the socket.  */
 
-  fd = socket (PF_LOCAL, SOCK_DGRAM, 0);
+  fd = _assuan_sock_new (PF_LOCAL, SOCK_DGRAM, 0);
   if (fd == -1)
     {
-      LOG ("can't create socket: %s\n", strerror (errno));
+      _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;
@@ -380,13 +406,14 @@ _assuan_domain_init (ASSUAN_CONTEXT *r_ctx, int rendezvousfd, pid_t peer)
       /* 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)
        {
-         LOG ("cannot determine an appropriate temporary file "
-              "name.  DOS in progress?\n");
+         _assuan_log_printf ("cannot determine an appropriate temporary file "
+            "name.  DoS in progress?\n");
          _assuan_release_context (ctx);
-         close (fd);
+         _assuan_close (fd);
          return ASSUAN_General_Error;
        }
 
@@ -396,17 +423,17 @@ _assuan_domain_init (ASSUAN_CONTEXT *r_ctx, int rendezvousfd, pid_t peer)
       memcpy (ctx->myaddr.sun_path, buf, len);
       len += offsetof (struct sockaddr_un, sun_path);
 
-      err = bind (fd, (struct sockaddr *) &ctx->myaddr, len);
+      err = _assuan_sock_bind (fd, (struct sockaddr *) &ctx->myaddr, len);
       if (! err)
        break;
     }
 
   if (err)
     {
-      LOG ("can't bind to `%s': %s\n", ctx->myaddr.sun_path,
-          strerror (errno));
+      _assuan_log_printf ("can't bind to `%s': %s\n", ctx->myaddr.sun_path,
+           strerror (errno));
       _assuan_release_context (ctx);
-      close (fd);
+      _assuan_close (fd);
       return ASSUAN_Connect_Failed;
     }
 
@@ -418,7 +445,7 @@ _assuan_domain_init (ASSUAN_CONTEXT *r_ctx, int rendezvousfd, pid_t peer)
     fp = fdopen (rendezvousfd, "w+");
     if (! fp)
       {
-       LOG ("can't open rendezvous port: %s\n", strerror (errno));
+       _assuan_log_printf ("can't open rendezvous port: %s\n", strerror (errno));
        return ASSUAN_Connect_Failed;
       }
 
@@ -447,10 +474,10 @@ _assuan_domain_init (ASSUAN_CONTEXT *r_ctx, int rendezvousfd, pid_t peer)
   return 0;
 }
 
-AssuanError
-assuan_domain_connect (ASSUAN_CONTEXT * r_ctx, int rendezvousfd, pid_t peer)
+assuan_error_t
+assuan_domain_connect (assuan_context_t * r_ctx, int rendezvousfd, pid_t peer)
 {
-  AssuanError aerr;
+  assuan_error_t aerr;
   int okay, off;
 
   aerr = _assuan_domain_init (r_ctx, rendezvousfd, peer);
@@ -460,10 +487,11 @@ assuan_domain_connect (ASSUAN_CONTEXT * r_ctx, int rendezvousfd, pid_t peer)
   /* Initial handshake.  */
   aerr = _assuan_read_from_server (*r_ctx, &okay, &off);
   if (aerr)
-    LOG ("can't connect to server: %s\n", assuan_strerror (aerr));
+    _assuan_log_printf ("can't connect to server: %s\n",
+                        assuan_strerror (aerr));
   else if (okay != 1)
     {
-      LOG ("can't connect to server: `");
+      _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;
index b62b140..45d53c2 100644 (file)
 #include "assuan-defs.h"
 
 /* Initialize a server.  */
-AssuanError
+assuan_error_t
 assuan_init_domain_server (ASSUAN_CONTEXT *r_ctx,
                           int rendezvousfd,
                           pid_t peer)
 {
-  AssuanError err;
+  assuan_error_t err;
 
   err = _assuan_domain_init (r_ctx, rendezvousfd, peer);
   if (err)
index 7a774cb..21501a3 100644 (file)
@@ -135,7 +135,7 @@ std_handler_end (ASSUAN_CONTEXT ctx, char *line)
   return set_error (ctx, Not_Implemented, NULL); 
 }
 
-AssuanError
+assuan_error_t
 assuan_command_parse_fd (ASSUAN_CONTEXT ctx, char *line, int *rfd)
 {
   char *endp;
@@ -391,7 +391,7 @@ my_strcasecmp (const char *a, const char *b)
 }
 
 /* Parse the line, break out the command, find it in the command
-   table, remove leading and white spaces from the arguments, all the
+   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)
@@ -484,7 +484,7 @@ process_request (ASSUAN_CONTEXT ctx)
     }
   else 
     {
-      char errline[256];
+      char errline[300];
 
       if (rc < 100)
         sprintf (errline, "ERR %d server fault (%.50s)",
@@ -493,8 +493,40 @@ process_request (ASSUAN_CONTEXT ctx)
         {
           const char *text = ctx->err_no == rc? ctx->err_str:NULL;
 
-          sprintf (errline, "ERR %d %.50s%s%.100s",
-                   rc, assuan_strerror (rc), text? " - ":"", text?text:"");
+#if defined(__GNUC__) && defined(__ELF__)
+          /* If we have weak symbol support we try to use the error
+             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
+             weak symbol support is available in case GNU ld is not
+             used. */
+          unsigned int source, code;
+
+          int gpg_strerror_r (unsigned int err, char *buf, size_t buflen)
+            __attribute__ ((weak));
+
+          const char *gpg_strsource (unsigned int err)
+            __attribute__ ((weak));
+
+          source = ((rc >> 24) & 0xff);
+          code = (rc & 0x00ffffff);
+          if (source && gpg_strsource && gpg_strerror_r)
+            {
+              /* Assume this is an libgpg-error. */
+              char ebuf[50];
+
+              gpg_strerror_r (rc, ebuf, sizeof ebuf );
+              sprintf (errline, "ERR %d %.50s <%.30s>%s%.100s",
+                       rc,
+                       ebuf,
+                       gpg_strsource (rc),
+                       text? " - ":"", text?text:"");
+            }
+          else
+#endif /* __GNUC__  && __ELF__ */
+            sprintf (errline, "ERR %d %.50s%s%.100s",
+                     rc, assuan_strerror (rc), text? " - ":"", text?text:"");
         }
       rc = assuan_write_line (ctx, errline);
     }
@@ -512,7 +544,7 @@ process_request (ASSUAN_CONTEXT ctx)
  * assuan_process:
  * @ctx: assuan context
  * 
- * This fucntion is used to handle the assuan protocol after a
+ * This function is used to handle the assuan protocol after a
  * connection has been established using assuan_accept().  This is the
  * main protocol handler.
  * 
@@ -625,7 +657,7 @@ 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. */
-AssuanError
+assuan_error_t
 assuan_set_okay_line (ASSUAN_CONTEXT ctx, const char *line)
 {
   if (!ctx)
@@ -652,15 +684,16 @@ assuan_set_okay_line (ASSUAN_CONTEXT ctx, const char *line)
 
 
 
-void
+assuan_error_t
 assuan_write_status (ASSUAN_CONTEXT ctx, const char *keyword, const char *text)
 {
   char buffer[256];
   char *helpbuf;
   size_t n;
+  assuan_error_t ae;
 
   if ( !ctx || !keyword)
-    return;
+    return ASSUAN_Invalid_Value;
   if (!text)
     text = "";
 
@@ -674,7 +707,7 @@ assuan_write_status (ASSUAN_CONTEXT ctx, const char *keyword, const char *text)
           strcat (buffer, " ");
           strcat (buffer, text);
         }
-      assuan_write_line (ctx, buffer);
+      ae = assuan_write_line (ctx, buffer);
     }
   else if ( (helpbuf = xtrymalloc (n)) )
     {
@@ -685,7 +718,10 @@ assuan_write_status (ASSUAN_CONTEXT ctx, const char *keyword, const char *text)
           strcat (helpbuf, " ");
           strcat (helpbuf, text);
         }
-      assuan_write_line (ctx, helpbuf);
+      ae = assuan_write_line (ctx, helpbuf);
       xfree (helpbuf);
     }
+  else
+    ae = 0;
+  return ae;
 }
index ec9d8e6..8d034ca 100644 (file)
@@ -134,11 +134,11 @@ free_membuf (struct membuf *mb)
  * 
  * Return value: 0 on success or an ASSUAN error code
  **/
-AssuanError
-assuan_inquire (ASSUAN_CONTEXT ctx, const char *keyword,
-                char **r_buffer, size_t *r_length, size_t maxlen)
+assuan_error_t
+assuan_inquire (assuan_context_t ctx, const char *keyword,
+                unsigned char **r_buffer, size_t *r_length, size_t maxlen)
 {
-  AssuanError rc;
+  assuan_error_t rc;
   struct membuf mb;
   char cmdbuf[LINELENGTH-10]; /* (10 = strlen ("INQUIRE ")+CR,LF) */
   unsigned char *line, *p;
index 5dca009..321f2ba 100644 (file)
@@ -1,5 +1,5 @@
 /* assuan-io.c - Wraps the read and write functions.
- *     Copyright (C) 2002 Free Software Foundation, Inc.
+ *     Copyright (C) 2002, 2004 Free Software Foundation, Inc.
  *
  * This file is part of Assuan.
  *
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 
  */
 
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
 #include "assuan-defs.h"
 #include <sys/types.h>
 #include <unistd.h>
+#ifdef HAVE_W32_SYSTEM
+#include <windows.h>
+#endif
 
-#ifdef _ASSUAN_IN_GPGME
-ssize_t
-_assuan_simple_read (ASSUAN_CONTEXT ctx, void *buffer, size_t size)
-{
-  return read (ctx->inbound.fd, buffer, size);
-}
-
-ssize_t
-_assuan_simple_write (ASSUAN_CONTEXT ctx, const void *buffer, size_t size)
-{
-  return write (ctx->outbound.fd, buffer, size);
-}
-
-#else
-
+#ifndef _ASSUAN_NO_PTH
 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);
 
+#ifndef HAVE_W32_SYSTEM
 #pragma weak pth_read
 #pragma weak pth_write
+#endif
+#endif /*!_ASSUAN_NO_PTH*/
 
 ssize_t
-_assuan_simple_read (ASSUAN_CONTEXT ctx, void *buffer, size_t size)
+_assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size)
 {
+#ifdef _ASSUAN_NO_PTH
+  return read (ctx->inbound.fd, buffer, size);
+#else
+# ifndef HAVE_W32_SYSTEM
   return (pth_read ? pth_read : read) (ctx->inbound.fd, buffer, size);
+# else
+  return pth_read ? pth_read (ctx->inbound.fd, buffer, size)
+                  : recv (ctx->inbound.fd, buffer, size, 0);
+# endif
+# endif
 }
 
 ssize_t
-_assuan_simple_write (ASSUAN_CONTEXT ctx, const void *buffer, size_t size)
+_assuan_simple_write (assuan_context_t ctx, const void *buffer, size_t size)
 {
+#ifdef _ASSUAN_NO_PTH
+  return write (ctx->outbound.fd, buffer, size);
+#else
+# ifndef HAVE_W32_SYSTEM
   return (pth_write ? pth_write : write) (ctx->outbound.fd, buffer, size);
-}
-
+# else
+  return pth_write ? pth_write (ctx->outbound.fd, buffer, size)
+                   : send (ctx->outbound.fd, buffer, size, 0);
+# endif
 #endif
+}
index aae3f7b..04f138e 100644 (file)
@@ -1,5 +1,5 @@
 /* assuan-listen.c - Wait for a connection (server) 
- *     Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ *     Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc.
  *
  * This file is part of Assuan.
  *
@@ -26,8 +26,8 @@
 
 #include "assuan-defs.h"
 
-AssuanError
-assuan_set_hello_line (ASSUAN_CONTEXT ctx, const char *line)
+assuan_error_t
+assuan_set_hello_line (assuan_context_t ctx, const char *line)
 {
   if (!ctx)
     return ASSUAN_Invalid_Value;
@@ -41,8 +41,13 @@ assuan_set_hello_line (ASSUAN_CONTEXT ctx, const char *line)
       char *buf = xtrymalloc (3+strlen(line)+1);
       if (!buf)
         return ASSUAN_Out_Of_Core;
-      strcpy (buf, "OK ");
-      strcpy (buf+3, line);
+      if (strchr (line, '\n'))
+        strcpy (buf, line);
+      else
+        {
+          strcpy (buf, "OK ");
+          strcpy (buf+3, line);
+        }
       xfree (ctx->hello_line);
       ctx->hello_line = buf;
     }
@@ -61,10 +66,11 @@ assuan_set_hello_line (ASSUAN_CONTEXT ctx, const char *line)
  * Return value: 0 on success or an error if the connection could for
  * some reason not be established.
  **/
-AssuanError
-assuan_accept (ASSUAN_CONTEXT ctx)
+assuan_error_t
+assuan_accept (assuan_context_t ctx)
 {
   int rc;
+  const char *p, *pend;
 
   if (!ctx)
     return ASSUAN_Invalid_Value;
@@ -77,9 +83,26 @@ assuan_accept (ASSUAN_CONTEXT ctx)
   if (rc)
     return rc;
 
-  /* send the hello */
-  rc = assuan_write_line (ctx, ctx->hello_line? ctx->hello_line
-                                              : "OK Your orders please");
+  /* Send the hello. */
+  p = ctx->hello_line;
+  if (p && (pend = strchr (p, '\n')))
+    { /* This is a multi line hello.  Send all but the last line as
+         comments. */
+      do
+        {
+          rc = _assuan_write_line (ctx, "# ", p, pend - p);
+          if (rc)
+            return rc;
+          p = pend + 1;
+          pend = strchr (p, '\n');
+        }
+      while (pend);
+      rc = _assuan_write_line (ctx, "OK ", p, strlen (p));
+    }
+  else if (p)
+    rc = assuan_write_line (ctx, p);
+  else
+    rc = assuan_write_line (ctx, "OK Pleased to meet you");
   if (rc)
     return rc;
   
@@ -92,14 +115,14 @@ assuan_accept (ASSUAN_CONTEXT ctx)
 
 
 int
-assuan_get_input_fd (ASSUAN_CONTEXT ctx)
+assuan_get_input_fd (assuan_context_t ctx)
 {
   return ctx? ctx->input_fd : -1;
 }
 
 
 int
-assuan_get_output_fd (ASSUAN_CONTEXT ctx)
+assuan_get_output_fd (assuan_context_t ctx)
 {
   return ctx? ctx->output_fd : -1;
 }
@@ -107,25 +130,25 @@ assuan_get_output_fd (ASSUAN_CONTEXT ctx)
 
 /* Close the fd descriptor set by the command INPUT FD=n.  We handle
    this fd inside assuan so that we can do some initial checks */
-AssuanError
-assuan_close_input_fd (ASSUAN_CONTEXT ctx)
+assuan_error_t
+assuan_close_input_fd (assuan_context_t ctx)
 {
   if (!ctx || ctx->input_fd == -1)
     return ASSUAN_Invalid_Value;
-  close (ctx->input_fd);
+  _assuan_close (ctx->input_fd);
   ctx->input_fd = -1;
   return 0;
 }
 
 /* Close the fd descriptor set by the command OUTPUT FD=n.  We handle
    this fd inside assuan so that we can do some initial checks */
-AssuanError
-assuan_close_output_fd (ASSUAN_CONTEXT ctx)
+assuan_error_t
+assuan_close_output_fd (assuan_context_t ctx)
 {
   if (!ctx || ctx->output_fd == -1)
     return ASSUAN_Invalid_Value;
 
-  close (ctx->output_fd);
+  _assuan_close (ctx->output_fd);
   ctx->output_fd = -1;
   return 0;
 }
index 340ce72..7c65d57 100644 (file)
@@ -1,5 +1,5 @@
 /* assuan-logging.c - Default logging function.
- *     Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ *     Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
  *
  * This file is part of Assuan.
  *
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 
  */
 
-#include "assuan-defs.h"
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
 #include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#ifdef HAVE_W32_SYSTEM
+#include <windows.h>
+#endif /*HAVE_W32_SYSTEM*/
+
+#include "assuan-defs.h"
 
+static char prefix_buffer[80];
 static FILE *_assuan_log;
 
 void
+_assuan_set_default_log_stream (FILE *fp)
+{
+  if (!_assuan_log)
+    _assuan_log = fp;
+}
+
+void
 assuan_set_assuan_log_stream (FILE *fp)
 {
   _assuan_log = fp;
@@ -35,8 +52,61 @@ assuan_get_assuan_log_stream (void)
   return _assuan_log ? _assuan_log : stderr;
 }
 
+
+/* Set the prefix to be used for logging to TEXT or
+   resets it to the default if TEXT is NULL. */
+void
+assuan_set_assuan_log_prefix (const char *text)
+{
+  if (text)
+    {
+      strncpy (prefix_buffer, text, sizeof (prefix_buffer)-1);
+      prefix_buffer[sizeof (prefix_buffer)-1] = 0;
+    }
+  else
+    *prefix_buffer = 0;
+}
+
 const char *
 assuan_get_assuan_log_prefix (void)
 {
-  return "";
+  return prefix_buffer;
+}
+
+
+void
+_assuan_log_printf (const char *format, ...)
+{
+  va_list arg_ptr;
+  FILE *fp;
+  const char *prf;
+
+  fp = assuan_get_assuan_log_stream ();
+  prf = assuan_get_assuan_log_prefix ();
+  if (*prf)
+    {
+      fputs (prf, fp);
+      fputs (": ", fp);
+    }
+
+  va_start (arg_ptr, format);
+  vfprintf (fp, format, arg_ptr );
+  va_end (arg_ptr);
+}
+
+
+
+#ifdef HAVE_W32_SYSTEM
+const char *
+_assuan_w32_strerror (int ec)
+{
+  static char strerr[256];
+  
+  if (ec == -1)
+    ec = (int)GetLastError ();
+  FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, ec,
+                 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
+                 strerr, sizeof (strerr)-1, NULL);
+  return strerr;    
 }
+#endif /*HAVE_W32_SYSTEM*/
index f79884c..4ce3862 100644 (file)
 #include <errno.h>
 #include <fcntl.h>
 #include <sys/types.h>
+#ifndef HAVE_W32_SYSTEM
 #include <sys/wait.h>
+#else
+#include <windows.h>
+#endif
 
 #include "assuan-defs.h"
 
 #define MAX_OPEN_FDS 20
 #endif
 
-#define LOG(format, args...) \
-       fprintf (assuan_get_assuan_log_stream (), \
-                assuan_get_assuan_log_prefix (), \
-                "%s" format , ## args)
+#ifdef HAVE_W32_SYSTEM
+/* We assume that a HANDLE can be represented by an int which should
+   be true for all i386 systems (HANDLE is defined as void *) and
+   these are the only systems for which Windows is available.  Further
+   we assume that -1 denotes an invalid handle.  */
+#define fd_to_handle(a)  ((HANDLE)(a))
+#define handle_to_fd(a)  ((int)(a))
+#define pid_to_handle(a) ((HANDLE)(a))
+#define handle_to_pid(a) ((int)(a))
+#endif /*HAVE_W32_SYSTEM*/
+
+
+/* This should be called to make sure that SIGPIPE gets ignored.  */
+static void
+fix_signals (void)
+{
+#ifndef _ASSUAN_NO_FIXED_SIGNALS
+#ifndef HAVE_DOSISH_SYSTEM  /* No SIGPIPE for these systems.  */
+  static int fixed_signals;
+
+  if (!fixed_signals)
+    { 
+      struct sigaction act;
+        
+      sigaction (SIGPIPE, NULL, &act);
+      if (act.sa_handler == SIG_DFL)
+       {
+         act.sa_handler = SIG_IGN;
+         sigemptyset (&act.sa_mask);
+         act.sa_flags = 0;
+         sigaction (SIGPIPE, &act, NULL);
+        }
+      fixed_signals = 1;
+      /* FIXME: This is not MT safe */
+    }
+#endif /*HAVE_DOSISH_SYSTEM*/
+#endif /*!_ASSUAN_NO_FIXED_SIGNALS*/
+}
+
 
+#ifndef HAVE_W32_SYSTEM
 static int
 writen (int fd, const char *buffer, size_t length)
 {
@@ -63,75 +103,328 @@ writen (int fd, const char *buffer, size_t length)
     }
   return 0;  /* okay */
 }
-
+#endif
 
 static int
-do_finish (ASSUAN_CONTEXT ctx)
+do_finish (assuan_context_t ctx)
 {
   if (ctx->inbound.fd != -1)
     {
-      close (ctx->inbound.fd);
+      _assuan_close (ctx->inbound.fd);
       ctx->inbound.fd = -1;
     }
   if (ctx->outbound.fd != -1)
     {
-      close (ctx->outbound.fd);
+      _assuan_close (ctx->outbound.fd);
       ctx->outbound.fd = -1;
     }
-  if (ctx->pid != -1)
+  if (ctx->pid != -1 && ctx->pid)
     {
-#if 0
-      /* This is already done by the double fork.  */
-      waitpid (ctx->pid, NULL, 0);  /* FIXME Check return value.  */
+#ifndef HAVE_W32_SYSTEM
+#ifndef _ASSUAN_USE_DOUBLE_FORK
+      if (!ctx->flags.no_waitpid)
+        waitpid (ctx->pid, NULL, 0); 
       ctx->pid = -1;
 #endif
+#endif /*!HAVE_W32_SYSTEM*/
     }
   return 0;
 }
 
 static void
-do_deinit (ASSUAN_CONTEXT ctx)
+do_deinit (assuan_context_t ctx)
 {
   do_finish (ctx);
 }
 
 
+#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.  */
+static int
+build_w32_commandline (char * const *argv, char **cmdline)
+{
+  int i, n;
+  const char *s;
+  char *buf, *p;
+
+  *cmdline = NULL;
+  n = 0;
+  for (i=0; (s=argv[i]); i++)
+    {
+      n += strlen (s) + 1 + 2;  /* (1 space, 2 quoting */
+      for (; *s; s++)
+        if (*s == '\"')
+          n++;  /* Need to double inner quotes.  */
+    }
+  n++;
+
+  buf = p = xtrymalloc (n);
+  if (!buf)
+    return -1;
+
+  for (i=0; argv[i]; i++) 
+    {
+      if (i)
+        p = stpcpy (p, " ");
+      if (!*argv[i]) /* Empty string. */
+        p = stpcpy (p, "\"\"");
+      else if (strpbrk (argv[i], " \t\n\v\f\""))
+        {
+          p = stpcpy (p, "\"");
+          for (s=argv[i]; *s; s++)
+            {
+              *p++ = *s;
+              if (*s == '\"')
+                *p++ = *s;
+            }
+          *p++ = '\"';
+          *p = 0;
+        }
+      else
+        p = stpcpy (p, argv[i]);
+    }
+
+  *cmdline= buf;
+  return 0;
+}
+#endif /*HAVE_W32_SYSTEM*/
+
+
+#ifdef HAVE_W32_SYSTEM
+/* Create pipe where one end end is inheritable.  */
+static int
+create_inheritable_pipe (int filedes[2], int for_write)
+{
+  HANDLE r, w, h;
+  SECURITY_ATTRIBUTES sec_attr;
+
+  memset (&sec_attr, 0, sizeof sec_attr );
+  sec_attr.nLength = sizeof sec_attr;
+  sec_attr.bInheritHandle = FALSE;
+    
+  if (!CreatePipe (&r, &w, &sec_attr, 0))
+    {
+      _assuan_log_printf ("CreatePipe failed: %s\n", w32_strerror (-1));
+      return -1;
+    }
+
+  if (!DuplicateHandle (GetCurrentProcess(), for_write? r : w,
+                        GetCurrentProcess(), &h, 0,
+                        TRUE, DUPLICATE_SAME_ACCESS ))
+    {
+      _assuan_log_printf ("DuplicateHandle failed: %s\n", w32_strerror (-1));
+      CloseHandle (r);
+      CloseHandle (w);
+      return -1;
+    }
+  if (for_write)
+    {
+      CloseHandle (r);
+      r = h;
+    }
+  else
+    {
+      CloseHandle (w);
+      w = h;
+    }
+
+  filedes[0] = handle_to_fd (r);
+  filedes[1] = handle_to_fd (w);
+  return 0;
+}
+#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.  */
-AssuanError
-assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, char *const argv[],
-                    int *fd_child_list)
+   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, char *const argv[],
+                      int *fd_child_list,
+                      void (*atfork) (void *opaque, int reserved),
+                      void *atforkvalue)
 {
-#ifndef _ASSUAN_IN_GPGME
-  static int fixed_signals = 0;
-#endif
-  AssuanError err;
+#ifdef HAVE_W32_SYSTEM
+  assuan_error_t err;
   int rp[2];
   int wp[2];
+  char mypidstr[50];
+  char *cmdline;
+  SECURITY_ATTRIBUTES sec_attr;
+  PROCESS_INFORMATION pi = 
+    {
+      NULL,      /* Returns process handle.  */
+      0,         /* Returns primary thread handle.  */
+      0,         /* Returns pid.  */
+      0          /* Returns tid.  */
+    };
+  STARTUPINFO si;
+  int fd, *fdp;
+  HANDLE nullfd = INVALID_HANDLE_VALUE;
 
   if (!ctx || !name || !argv || !argv[0])
     return ASSUAN_Invalid_Value;
 
-#ifndef _ASSUAN_IN_GPGME
-  if (!fixed_signals)
-    { 
-      struct sigaction act;
-        
-      sigaction (SIGPIPE, NULL, &act);
-      if (act.sa_handler == SIG_DFL)
-       {
-         act.sa_handler = SIG_IGN;
-         sigemptyset (&act.sa_mask);
-         act.sa_flags = 0;
-         sigaction (SIGPIPE, &act, NULL);
+  fix_signals ();
+
+  sprintf (mypidstr, "%lu", (unsigned long)getpid ());
+
+  /* Build the command line.  */
+  if (build_w32_commandline (argv, &cmdline))
+    return ASSUAN_Out_Of_Core;
+
+  /* Create thew two pipes. */
+  if (create_inheritable_pipe (rp, 0))
+    {
+      xfree (cmdline);
+      return ASSUAN_General_Error;
+    }
+  
+  if (create_inheritable_pipe (wp, 1))
+    {
+      CloseHandle (fd_to_handle (rp[0]));
+      CloseHandle (fd_to_handle (rp[1]));
+      xfree (cmdline);
+      return ASSUAN_General_Error;
+    }
+
+  
+  err = _assuan_new_context (ctx);
+  if (err)
+    {
+      CloseHandle (fd_to_handle (rp[0]));
+      CloseHandle (fd_to_handle (rp[1]));
+      CloseHandle (fd_to_handle (wp[0]));
+      CloseHandle (fd_to_handle (wp[1]));
+      xfree (cmdline);
+      return ASSUAN_General_Error;
+    }
+
+  (*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: Actually we should set the "_assuan_pipe_connect_pid" env
+     variable.  However this requires us to write a full environment
+     handler, because the strings are expected in sorted order.  The
+     suggestion given in the MS Reference Library, to save the old
+     value, changeit, create proces and restore it, is not thread
+     safe.  */
+
+  /* Start the process.  */
+  memset (&sec_attr, 0, sizeof sec_attr );
+  sec_attr.nLength = sizeof sec_attr;
+  sec_attr.bInheritHandle = FALSE;
+  
+  memset (&si, 0, sizeof si);
+  si.cb = sizeof (si);
+  si.dwFlags = STARTF_USESTDHANDLES;
+  si.hStdInput  = fd_to_handle (wp[0]);
+  si.hStdOutput = fd_to_handle (rp[1]);
+
+  /* Dup stderr to /dev/null unless it is in the list of FDs to be
+     passed to the child. */
+  fd = fileno (stderr);
+  fdp = fd_child_list;
+  if (fdp)
+    {
+      for (; *fdp != -1 && *fdp != fd; fdp++)
+        ;
+    }
+  if (!fdp || *fdp == -1)
+    {
+      nullfd = CreateFile ("nul", GENERIC_WRITE,
+                           FILE_SHARE_READ | FILE_SHARE_WRITE,
+                           NULL, OPEN_EXISTING, 0, NULL);
+      if (nullfd == INVALID_HANDLE_VALUE)
+        {
+          _assuan_log_printf ("can't open `nul': %s\n", w32_strerror (-1));
+          CloseHandle (fd_to_handle (rp[0]));
+          CloseHandle (fd_to_handle (rp[1]));
+          CloseHandle (fd_to_handle (wp[0]));
+          CloseHandle (fd_to_handle (wp[1]));
+          xfree (cmdline);
+          _assuan_release_context (*ctx); 
+          return -1;
         }
-      fixed_signals = 1;
-      /* FIXME: This is not MT safe */
+      si.hStdError = nullfd;
     }
-#endif
+  else
+    si.hStdError = fd_to_handle (_get_osfhandle (fd));
+
+
+  /* Note: We inherit all handles flagged as inheritable.  This seems
+     to be a security flaw but there seems to be no way of selecting
+     handles to inherit. */
+  /*   _assuan_log_printf ("CreateProcess, path=`%s' cmdline=`%s'\n", */
+  /*                       name, cmdline); */
+  if (!CreateProcess (name,                 /* Program to start.  */
+                      cmdline,              /* Command line arguments.  */
+                      &sec_attr,            /* Process security attributes.  */
+                      &sec_attr,            /* Thread security attributes.  */
+                      TRUE,                 /* Inherit handles.  */
+                      (CREATE_DEFAULT_ERROR_MODE
+                       | GetPriorityClass (GetCurrentProcess ())
+                       | CREATE_SUSPENDED), /* Creation flags.  */
+                      NULL,                 /* Environment.  */
+                      NULL,                 /* Use current drive/directory.  */
+                      &si,                  /* Startup information. */
+                      &pi                   /* Returns process information.  */
+                      ))
+    {
+      _assuan_log_printf ("CreateProcess failed: %s\n", w32_strerror (-1));
+      CloseHandle (fd_to_handle (rp[0]));
+      CloseHandle (fd_to_handle (rp[1]));
+      CloseHandle (fd_to_handle (wp[0]));
+      CloseHandle (fd_to_handle (wp[1]));
+      if (nullfd != INVALID_HANDLE_VALUE)
+        CloseHandle (nullfd);
+      xfree (cmdline);
+      _assuan_release_context (*ctx); 
+      return ASSUAN_General_Error;
+    }
+  xfree (cmdline);
+  cmdline = NULL;
+  if (nullfd != INVALID_HANDLE_VALUE)
+    {
+      CloseHandle (nullfd);
+      nullfd = INVALID_HANDLE_VALUE;
+    }
+
+  CloseHandle (fd_to_handle (rp[1]));
+  CloseHandle (fd_to_handle (wp[0]));
+
+  /*   _assuan_log_printf ("CreateProcess ready: hProcess=%p hThread=%p" */
+  /*                       " dwProcessID=%d dwThreadId=%d\n", */
+  /*                       pi.hProcess, pi.hThread, */
+  /*                       (int) pi.dwProcessId, (int) pi.dwThreadId); */
+
+  ResumeThread (pi.hThread);
+  CloseHandle (pi.hThread); 
+  (*ctx)->pid = 0;  /* We don't use the PID. */
+  CloseHandle (pi.hProcess); /* We don't need to wait for the process. */
+
+#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;
@@ -158,8 +451,8 @@ assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, char *const argv[],
   (*ctx)->deinit_handler = do_deinit;
   (*ctx)->finish_handler = do_finish;
 
-  /* FIXME: Use _gpgme_io_spawn.  The PID stored here is actually
-     soon useless.  */
+  /* 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)
     {
@@ -173,111 +466,131 @@ assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, char *const argv[],
 
   if ((*ctx)->pid == 0)
     {
-      /* Intermediate child to prevent zombie processes.  */
-      pid_t pid;
-
+#ifdef _ASSUAN_USE_DOUBLE_FORK      
       if ((pid = fork ()) == 0)
+#endif
        {
-         /* Child.  */
-
-         int i, n;
-         char errbuf[512];
-         int *fdp;
-
-         /* Dup handles to stdin/stdout. */
-         if (rp[1] != STDOUT_FILENO)
-           {
-             if (dup2 (rp[1], STDOUT_FILENO) == -1)
-               {
-                 LOG ("dup2 failed in child: %s\n", strerror (errno));
-                 _exit (4);
-               }
-           }
-         if (wp[0] != STDIN_FILENO)
-           {
-             if (dup2 (wp[0], STDIN_FILENO) == -1)
-               {
-                 LOG ("dup2 failed in child: %s\n", strerror (errno));
-                 _exit (4);
-               }
-           }
-         
-         /* Dup stderr to /dev/null unless it is in the list of FDs to be
-            passed to the child. */
-         fdp = fd_child_list;
-         if (fdp)
-           {
-             for (; *fdp != -1 && *fdp != STDERR_FILENO; fdp++)
-               ;
-           }
-         if (!fdp || *fdp == -1)
-           {
-             int fd = open ("/dev/null", O_WRONLY);
-             if (fd == -1)
-               {
-                 LOG ("can't open `/dev/null': %s\n", strerror (errno));
-                 _exit (4);
-               }
-             if (dup2 (fd, STDERR_FILENO) == -1)
-               {
-                 LOG ("dup2(dev/null, 2) failed: %s\n", strerror (errno));
-                 _exit (4);
-               }
-           }
-
-
-         /* Close all files which will not be duped and are not in the
-            fd_child_list. */
-         n = sysconf (_SC_OPEN_MAX);
-         if (n < 0)
-           n = MAX_OPEN_FDS;
-         for (i=0; i < n; i++)
-           {
-             if ( i == STDIN_FILENO || i == STDOUT_FILENO || i == STDERR_FILENO)
-               continue;
-             fdp = fd_child_list;
-             if (fdp)
-               {
-                 while (*fdp != -1 && *fdp != i)
-                   fdp++;
-               }
-             
-             if (!(fdp && *fdp != -1))
-               close(i);
-           }
-
-         errno = 0;
-
-         execv (name, argv); 
-         /* oops - use the pipe to tell the parent about it */
-         snprintf (errbuf, sizeof(errbuf)-1, "ERR %d can't exec `%s': %.50s\n",
-                   ASSUAN_Problem_Starting_Server, name, strerror (errno));
-         errbuf[sizeof(errbuf)-1] = 0;
-         writen (1, errbuf, strlen (errbuf));
-         _exit (4);
-       } /* End child.  */
+          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, 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)
-      LOG ("can't connect server: %s\n", assuan_strerror (err));
+      _assuan_log_printf ("can't connect server: %s\n",
+                          assuan_strerror (err));
     else if (okay != 1)
       {
-       LOG ("can't connect server: `%s'\n", (*ctx)->inbound.line);
+       _assuan_log_printf ("can't connect server: `%s'\n",
+                            (*ctx)->inbound.line);
        err = ASSUAN_Connect_Failed;
       }
   }
@@ -292,15 +605,13 @@ assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, char *const argv[],
 }
 
 
-
-
-
-
-
-
-
-
-
-
-
-
+/* 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.  */
+assuan_error_t
+assuan_pipe_connect (assuan_context_t *ctx, const char *name, char *const argv[],
+                    int *fd_child_list)
+{
+  return assuan_pipe_connect2 (ctx, name, argv, fd_child_list, NULL, NULL);
+}
index ba269b0..beff9a3 100644 (file)
 #include <stdlib.h>
 #include <stdio.h>
 #include <unistd.h>
+#ifdef HAVE_W32_SYSTEM
+#include <windows.h>
+#include <fcntl.h>
+#endif
 
 #include "assuan-defs.h"
 
+
 static void
 deinit_pipe_server (ASSUAN_CONTEXT ctx)
 {
@@ -69,7 +74,6 @@ _assuan_new_context (ASSUAN_CONTEXT *r_ctx)
   ctx->io = &io;
 
   ctx->listen_fd = -1;
-  ctx->client_pid = (pid_t)-1;
   /* Use the pipe server handler as a default.  */
   ctx->deinit_handler = deinit_pipe_server;
   ctx->accept_handler = accept_connection;
@@ -84,7 +88,6 @@ _assuan_new_context (ASSUAN_CONTEXT *r_ctx)
 }
 
 
-
 int
 assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2])
 {
@@ -94,11 +97,30 @@ assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2])
   if (!rc)
     {
       ASSUAN_CONTEXT ctx = *r_ctx;
+      const char *s;
+      unsigned long ul;
 
       ctx->is_server = 1;
-      ctx->inbound.fd = filedes[0];
+#ifdef HAVE_W32_SYSTEM
+      /* MS Windows has so many different types of handle that one
+         needs to tranlsate them at many place forth and back.  Also
+         make sure that the fiel descriptos are in binary mode.  */
+      setmode (filedes[0], O_BINARY);
+      setmode (filedes[1], O_BINARY);
+      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];
+#endif
       ctx->pipe_mode = 1;
+
+      s = getenv ("_assuan_pipe_connect_pid");
+      if (s && (ul=strtoul (s, NULL, 10)) && ul)
+        ctx->pid = (pid_t)ul;
+      else
+        ctx->pid = (pid_t)-1;
+
     }
   return rc;
 }
index cd963ed..9937c7a 100644 (file)
@@ -1,5 +1,5 @@
 /* assuan-socket-connect.c - Assuan socket based client
- *     Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ *     Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
  *
  * This file is part of Assuan.
  *
 #include <stdlib.h>
 #include <stddef.h>
 #include <stdio.h>
+#include <string.h>
 #include <errno.h>
+#include <unistd.h>
 #include <sys/types.h>
+#ifndef HAVE_W32_SYSTEM
 #include <sys/socket.h>
 #include <sys/un.h>
-#include <unistd.h>
+#else
+#include <windows.h>
+#endif
 
 #include "assuan-defs.h"
 
-#define LOG(format, args...) \
-       fprintf (assuan_get_assuan_log_stream (), \
-                assuan_get_assuan_log_prefix (), \
-                "%s" format , ## args)
-
+/* 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
+
+#ifndef SUN_LEN
+# define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \
+                      + strlen ((ptr)->sun_path))
+#endif
+
 static int
 do_finish (ASSUAN_CONTEXT ctx)
 {
   if (ctx->inbound.fd != -1)
     {
-      close (ctx->inbound.fd);
+      _assuan_close (ctx->inbound.fd);
     }
   ctx->inbound.fd = -1;
   ctx->outbound.fd = -1;
@@ -55,56 +73,64 @@ do_deinit (ASSUAN_CONTEXT ctx)
 /* Make a connection to the Unix domain socket NAME and return a new
    Assuan context in CTX.  SERVER_PID is currently not used but may
    become handy in the future.  */
-AssuanError
+assuan_error_t
 assuan_socket_connect (ASSUAN_CONTEXT *r_ctx,
                        const char *name, pid_t server_pid)
 {
   static struct assuan_io io = { _assuan_simple_read,
                                 _assuan_simple_write };
 
-  AssuanError err;
+  assuan_error_t err;
   ASSUAN_CONTEXT ctx;
   int fd;
   struct sockaddr_un srvr_addr;
   size_t len;
+  const char *s;
 
   if (!r_ctx || !name)
     return ASSUAN_Invalid_Value;
   *r_ctx = NULL;
 
-  /* we require that the name starts with a slash, so that we can
-     alter reuse this function for other socket types */
-  if (*name != '/')
+  /* 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.  */
+  s = name;
+  if (*s && s[1] == ':')
+    s += 2;
+  if (*s != DIRSEP_C && *s != '/')
     return ASSUAN_Invalid_Value;
+
   if (strlen (name)+1 >= sizeof srvr_addr.sun_path)
     return ASSUAN_Invalid_Value;
 
   err = _assuan_new_context (&ctx); 
   if (err)
       return err;
-  ctx->pid = server_pid; /* save it in case we need it later */
   ctx->deinit_handler = do_deinit;
   ctx->finish_handler = do_finish;
 
-  fd = socket (PF_LOCAL, SOCK_STREAM, 0);
+
+  fd = _assuan_sock_new (PF_LOCAL, SOCK_STREAM, 0);
   if (fd == -1)
     {
-      LOG ("can't create socket: %s\n", strerror (errno));
+      _assuan_log_printf ("can't create socket: %s\n", strerror (errno));
       _assuan_release_context (ctx);
       return ASSUAN_General_Error;
     }
 
   memset (&srvr_addr, 0, sizeof srvr_addr);
   srvr_addr.sun_family = AF_LOCAL;
-  len = strlen (srvr_addr.sun_path) + 1;
-  memcpy (srvr_addr.sun_path, name, len);
-  len += (offsetof (struct sockaddr_un, sun_path));
+  strncpy (srvr_addr.sun_path, name, sizeof (srvr_addr.sun_path) - 1);
+  srvr_addr.sun_path[sizeof (srvr_addr.sun_path) - 1] = 0;
+  len = SUN_LEN (&srvr_addr);
+
 
-  if (connect (fd, (struct sockaddr *) &srvr_addr, len) == -1)
+  if (_assuan_sock_connect (fd, (struct sockaddr *) &srvr_addr, len) == -1)
     {
-      LOG ("can't connect to `%s': %s\n", name, strerror (errno));
+      _assuan_log_printf ("can't connect to `%s': %s\n",
+                          name, strerror (errno));
       _assuan_release_context (ctx);
-      close (fd);
+      _assuan_close (fd);
       return ASSUAN_Connect_Failed;
     }
 
@@ -118,10 +144,11 @@ assuan_socket_connect (ASSUAN_CONTEXT *r_ctx,
 
     err = _assuan_read_from_server (ctx, &okay, &off);
     if (err)
-      LOG ("can't connect to server: %s\n", assuan_strerror (err));
+      _assuan_log_printf ("can't connect to server: %s\n",
+                          assuan_strerror (err));
     else if (okay != 1)
       {
-       LOG ("can't connect to server: `");
+        /*LOG ("can't connect to server: `");*/
        _assuan_log_sanitized_string (ctx->inbound.line);
        fprintf (assuan_get_assuan_log_stream (), "'\n");
        err = ASSUAN_Connect_Failed;
index d92e6e4..275af42 100644 (file)
 #include <stdlib.h>
 #include <stdio.h>
 #include <errno.h>
+#include <unistd.h>
 #include <sys/types.h>
+#ifndef HAVE_W32_SYSTEM
 #include <sys/socket.h>
 #include <sys/un.h>
-#include <unistd.h>
+#else
+#include <windows.h>
+#endif
 
 #include "assuan-defs.h"
 
 static int
-accept_connection_bottom (ASSUAN_CONTEXT ctx)
+accept_connection_bottom (assuan_context_t ctx)
 {
   int fd = ctx->connected_fd;
 
-  ctx->client_pid = (pid_t)-1;
 #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) ) 
-      ctx->client_pid = cr.pid;
+    if ( !getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl)
+         && cr.pid != (pid_t)-1 && cr.pid ) 
+      ctx->pid = cr.pid;
   }
 #endif
 
@@ -62,13 +68,12 @@ accept_connection_bottom (ASSUAN_CONTEXT ctx)
 
 
 static int
-accept_connection (ASSUAN_CONTEXT ctx)
+accept_connection (assuan_context_t ctx)
 {
   int fd;
   struct sockaddr_un clnt_addr;
   size_t len = sizeof clnt_addr;
 
-  ctx->client_pid = (pid_t)-1;
   fd = accept (ctx->listen_fd, (struct sockaddr*)&clnt_addr, &len );
   if (fd == -1)
     {
@@ -81,11 +86,11 @@ accept_connection (ASSUAN_CONTEXT ctx)
 }
 
 static int
-finish_connection (ASSUAN_CONTEXT ctx)
+finish_connection (assuan_context_t ctx)
 {
   if (ctx->inbound.fd != -1)
     {
-      close (ctx->inbound.fd);
+      _assuan_close (ctx->inbound.fd);
     }
   ctx->inbound.fd = -1;
   ctx->outbound.fd = -1;
@@ -94,7 +99,7 @@ finish_connection (ASSUAN_CONTEXT ctx)
 
 
 static void
-deinit_socket_server (ASSUAN_CONTEXT ctx)
+deinit_socket_server (assuan_context_t ctx)
 {
   finish_connection (ctx);
 }
@@ -105,9 +110,9 @@ static struct assuan_io io = { _assuan_simple_read,
 /* Initialize a server for the socket LISTEN_FD which has already be
    put into listen mode */
 int
-assuan_init_socket_server (ASSUAN_CONTEXT *r_ctx, int listen_fd)
+assuan_init_socket_server (assuan_context_t *r_ctx, int listen_fd)
 {
-  ASSUAN_CONTEXT ctx;
+  assuan_context_t ctx;
   int rc;
 
   *r_ctx = NULL;
@@ -139,9 +144,9 @@ assuan_init_socket_server (ASSUAN_CONTEXT *r_ctx, int listen_fd)
 
 /* Initialize a server using the already accepted socket FD. */
 int
-assuan_init_connected_socket_server (ASSUAN_CONTEXT *r_ctx, int fd)
+assuan_init_connected_socket_server (assuan_context_t *r_ctx, int fd)
 {
-  ASSUAN_CONTEXT ctx;
+  assuan_context_t ctx;
   int rc;
 
   *r_ctx = NULL;
index fc0beed..7f442e9 100644 (file)
@@ -1,5 +1,5 @@
 /* assuan-util.c - Utility functions for Assuan 
- *     Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+ * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
  *
  * This file is part of Assuan.
  *
@@ -23,6 +23,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
+#include <errno.h>
 
 #include "assuan-defs.h"
 
@@ -55,9 +56,19 @@ _assuan_realloc (void *a, size_t n)
 void *
 _assuan_calloc (size_t n, size_t m)
 {
-  void *p = _assuan_malloc (n*m);
+  void *p;
+  size_t nbytes;
+    
+  nbytes = n * m;
+  if (m && nbytes / m != n) 
+    {
+      errno = ENOMEM;
+      return NULL;
+    }
+
+  p = _assuan_malloc (nbytes);
   if (p)
-    memset (p, 0, n* m);
+    memset (p, 0, nbytes);
   return p;
 }
 
@@ -73,7 +84,7 @@ _assuan_free (void *p)
   can take out a descriptive text.  Inside the assuan code, use the
   macro set_error instead of this function. */
 int
-assuan_set_error (ASSUAN_CONTEXT ctx, int err, const char *text)
+assuan_set_error (assuan_context_t ctx, int err, const char *text)
 {
   ctx->err_no = err;
   ctx->err_str = text;
@@ -81,33 +92,34 @@ assuan_set_error (ASSUAN_CONTEXT ctx, int err, const char *text)
 }
 
 void
-assuan_set_pointer (ASSUAN_CONTEXT ctx, void *pointer)
+assuan_set_pointer (assuan_context_t ctx, void *pointer)
 {
   if (ctx)
     ctx->user_pointer = pointer;
 }
 
 void *
-assuan_get_pointer (ASSUAN_CONTEXT ctx)
+assuan_get_pointer (assuan_context_t ctx)
 {
   return ctx? ctx->user_pointer : NULL;
 }
 
 
 void
-assuan_set_log_stream (ASSUAN_CONTEXT ctx, FILE *fp)
+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 ctx)
+assuan_begin_confidential (assuan_context_t ctx)
 {
   if (ctx)
     {
@@ -116,7 +128,7 @@ assuan_begin_confidential (ASSUAN_CONTEXT ctx)
 }
 
 void
-assuan_end_confidential (ASSUAN_CONTEXT ctx)
+assuan_end_confidential (assuan_context_t ctx)
 {
   if (ctx)
     {
@@ -124,6 +136,36 @@ assuan_end_confidential (ASSUAN_CONTEXT ctx)
     }
 }
 
+
+
+/* For context CTX, set the flag FLAG to VALUE.  Values for flags
+   are usually 1 or 0 but certain flags might allow for other values;
+   see the description of the type assuan_flag_t for details. */
+void
+assuan_set_flag (assuan_context_t ctx, assuan_flag_t flag, int value)
+{
+  if (!ctx)
+    return;
+  switch (flag)
+    {
+    case ASSUAN_NO_WAITPID: ctx->flags.no_waitpid = value; break;
+    }
+}
+
+/* Return the VALUE of FLAG in context CTX. */ 
+int
+assuan_get_flag (assuan_context_t ctx, assuan_flag_t flag)
+{
+  if (!ctx)
+    return 0;
+  switch (flag)
+    {
+    case ASSUAN_NO_WAITPID: return ctx->flags.no_waitpid;
+    }
+  return 0;
+}
+
+
 /* Dump a possibly binary string (used for debugging).  Distinguish
    ascii text from binary and print it accordingly.  */
 void
@@ -133,7 +175,7 @@ _assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length)
   int n;
 
   for (n=length,s=buffer; n; n--, s++)
-    if  (!isascii (*s) || iscntrl (*s) || !isprint (*s))
+    if  ((!isascii (*s) || iscntrl (*s) || !isprint (*s)) && !(*s >= 0x80))
       break;
 
   s = buffer;
@@ -197,7 +239,7 @@ _assuan_log_sanitized_string (const char *string)
          break;
 
        default:
-         if (isascii (*s) && isprint (*s))
+         if ((isascii (*s) && isprint (*s)) || (*s >= 0x80))
            putc_unlocked (*s, fp);
          else
            {
@@ -217,3 +259,4 @@ _assuan_log_sanitized_string (const char *string)
   funlockfile (fp);
 #endif
 }
+
index 05f0212..4740470 100644 (file)
@@ -1,5 +1,5 @@
-/* assuan.c - Definitions for the Assuan protocol
- *     Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+/* assuan.c - Definitions for the Assuan IPC library
+ * Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
  *
  * This file is part of Assuan.
  *
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <sys/socket.h>
 
-#define _ASSUAN_IN_GPGME
-#ifdef _ASSUAN_IN_GPGME
+/* To use this file with libraries the following macros are often
+   useful:
+
+   #define _ASSUAN_EXT_SYM_PREFIX _foo_
+   
+     This prefixes all external symbols with "_foo_".
+
+   #define _ASSUAN_NO_PTH 
+
+     This avoids inclusion of special GNU Pth hacks.
+
+   #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_
+#define _ASSUAN_NO_PTH 
+#define _ASSUAN_NO_FIXED_SIGNALS 
+#define _ASSUAN_USE_DOUBLE_FORK
 
 #ifdef _ASSUAN_IN_GPGME_BUILD_ASSUAN
 int _gpgme_io_read (int fd, void *buffer, size_t count);
 int _gpgme_io_write (int fd, const void *buffer, size_t count);
-ssize_t _gpgme_ath_select (int nfd, fd_set *rset, fd_set *wset, fd_set *eset,
-                          struct timeval *timeout);
 ssize_t _gpgme_ath_waitpid (pid_t pid, int *status, int options);
+#ifdef HAVE_W32_SYSTEM
+int _gpgme_ath_accept (int s, void *addr, int *length_ptr);
+#else /*!HAVE_W32_SYSTEM*/
+ssize_t _gpgme_ath_select (int nfd, fd_set *rset, fd_set *wset, fd_set *eset,
+                           struct timeval *timeout);
 int _gpgme_ath_accept (int s, struct sockaddr *addr, socklen_t *length_ptr);
 int _gpgme_ath_connect (int s, struct sockaddr *addr, socklen_t length);
 int _gpgme_ath_sendmsg (int s, const struct msghdr *msg, int flags);
 int _gpgme_ath_recvmsg (int s, struct msghdr *msg, int flags);
+#endif /*!HAVE_W32_SYSTEM*/
 
 #define read          _gpgme_io_read
 #define write         _gpgme_io_write
@@ -50,8 +74,9 @@ int _gpgme_ath_recvmsg (int s, struct msghdr *msg, int flags);
 #define connect       _gpgme_ath_connect
 #define sendmsg              _gpgme_ath_sendmsg
 #define recvmsg       _gpgme_ath_recvmsg
-#endif
-#endif
+#endif /*_ASSUAN_IN_GPGME_BUILD_ASSUAN*/
+/**** End GPGME specific modifications. ******/
+
 
 #ifdef _ASSUAN_EXT_SYM_PREFIX
 #define _ASSUAN_PREFIX1(x,y) x ## y
@@ -116,6 +141,8 @@ int _gpgme_ath_recvmsg (int s, struct msghdr *msg, int flags);
   _ASSUAN_PREFIX(assuan_get_assuan_log_stream)
 #define assuan_get_assuan_log_prefix \
   _ASSUAN_PREFIX(assuan_get_assuan_log_prefix)
+#define assuan_set_flag _ASSUAN_PREFIX(assuan_set_flag)
+#define assuan_get_flag _ASSUAN_PREFIX(assuan_get_flag)
 
 /* And now the internal functions, argh...  */
 #define _assuan_read_line _ASSUAN_PREFIX(_assuan_read_line)
@@ -138,14 +165,27 @@ int _gpgme_ath_recvmsg (int s, struct msghdr *msg, int flags);
 #define _assuan_log_print_buffer _ASSUAN_PREFIX(_assuan_log_print_buffer)
 #define _assuan_log_sanitized_string \
   _ASSUAN_PREFIX(_assuan_log_sanitized_string)
+#define _assuan_log_printf _ASSUAN_PREFIX(_assuan_log_printf)
+#define _assuan_set_default_log_stream \
+  _ASSUAN_PREFIX(_assuan_set_default_log_stream)
+#define _assuan_w32_strerror _ASSUAN_PREFIX(_assuan_w32_strerror)
+#define _assuan_write_line _ASSUAN_PREFIX(_assuan_write_line)
+#define _assuan_close _ASSUAN_PREFIX(_assuan_close)   
+#define _assuan_sock_new _ASSUAN_PREFIX(_assuan_sock_new)  
+#define _assuan_sock_bind _ASSUAN_PREFIX(_assuan_sock_bind)
+#define _assuan_sock_connect _ASSUAN_PREFIX(_assuan_sock_connect)
+
+#endif /*_ASSUAN_EXT_SYM_PREFIX*/
 
-#endif
 
 #ifdef __cplusplus
 extern "C"
 {
+#if 0
+}
 #endif
-  
+#endif
+
 
 typedef enum
 {
@@ -166,7 +206,7 @@ typedef enum
   ASSUAN_Connect_Failed = 14,
   ASSUAN_Accept_Failed = 15,
 
-  /* error codes above 99 are meant as status codes */
+  /* Error codes above 99 are meant as status codes */
   ASSUAN_Not_Implemented = 100,
   ASSUAN_Server_Fault    = 101,
   ASSUAN_Invalid_Command = 102,
@@ -194,9 +234,10 @@ typedef enum
   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,
@@ -216,11 +257,20 @@ typedef enum
   ASSUAN_Invalid_Card = 402,
   ASSUAN_No_PKCS15_App = 403,
   ASSUAN_Card_Not_Present = 404,
-  ASSUAN_Invalid_Id = 405
+  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
+
+} assuan_error_t;
 
-} AssuanError;
+typedef assuan_error_t AssuanError; /* Deprecated. */
 
 /* This is a list of pre-registered ASSUAN commands */
+/* NOTE, these command IDs are now deprectated and solely exists for
+   compatibility reasons. */
 typedef enum
 {
   ASSUAN_CMD_NOP = 0,
@@ -237,72 +287,90 @@ typedef enum
   ASSUAN_CMD_USER = 256  /* Other commands should be used with this offset*/
 } AssuanCommand;
 
+
+/* Definitions of flags for assuan_set_flag(). */
+typedef enum
+  {
+    /* When using a pipe server, by default Assuan will wait for the
+       forked process to die in assuan_disconnect.  In certain cases
+       this is not desirable.  By setting this flag, the waitpid will
+       be skipped and the caller is responsible to cleanup a forked
+       process. */
+    ASSUAN_NO_WAITPID = 1
+  } 
+assuan_flag_t;
+
 #define ASSUAN_LINELENGTH 1002 /* 1000 + [CR,]LF */
 
 struct assuan_context_s;
+typedef struct assuan_context_s *assuan_context_t;
 typedef struct assuan_context_s *ASSUAN_CONTEXT;
 
 /*-- assuan-handler.c --*/
-int assuan_register_command (ASSUAN_CONTEXT ctx,
+int assuan_register_command (assuan_context_t ctx,
                              const char *cmd_string,
-                             int (*handler)(ASSUAN_CONTEXT, char *));
-int assuan_register_bye_notify (ASSUAN_CONTEXT ctx,
-                                void (*fnc)(ASSUAN_CONTEXT));
-int assuan_register_reset_notify (ASSUAN_CONTEXT ctx,
-                                  void (*fnc)(ASSUAN_CONTEXT));
-int assuan_register_cancel_notify (ASSUAN_CONTEXT ctx,
-                                   void (*fnc)(ASSUAN_CONTEXT));
-int assuan_register_input_notify (ASSUAN_CONTEXT ctx,
-                                  void (*fnc)(ASSUAN_CONTEXT, const char *));
-int assuan_register_output_notify (ASSUAN_CONTEXT ctx,
-                                  void (*fnc)(ASSUAN_CONTEXT, const char *));
-
-int assuan_register_option_handler (ASSUAN_CONTEXT ctx,
-                                    int (*fnc)(ASSUAN_CONTEXT,
+                             int (*handler)(assuan_context_t, char *));
+int assuan_register_bye_notify (assuan_context_t ctx,
+                                void (*fnc)(assuan_context_t));
+int assuan_register_reset_notify (assuan_context_t ctx,
+                                  void (*fnc)(assuan_context_t));
+int assuan_register_cancel_notify (assuan_context_t ctx,
+                                   void (*fnc)(assuan_context_t));
+int assuan_register_input_notify (assuan_context_t ctx,
+                                  void (*fnc)(assuan_context_t, const char *));
+int assuan_register_output_notify (assuan_context_t ctx,
+                                  void (*fnc)(assuan_context_t, const char *));
+
+int assuan_register_option_handler (assuan_context_t ctx,
+                                    int (*fnc)(assuan_context_t,
                                                const char*, const char*));
 
-int assuan_process (ASSUAN_CONTEXT ctx);
-int assuan_process_next (ASSUAN_CONTEXT ctx);
-int assuan_get_active_fds (ASSUAN_CONTEXT ctx, int what,
+int assuan_process (assuan_context_t ctx);
+int assuan_process_next (assuan_context_t ctx);
+int assuan_get_active_fds (assuan_context_t ctx, int what,
                            int *fdarray, int fdarraysize);
 
 
-FILE *assuan_get_data_fp (ASSUAN_CONTEXT ctx);
-AssuanError assuan_set_okay_line (ASSUAN_CONTEXT ctx, const char *line);
-void assuan_write_status (ASSUAN_CONTEXT ctx,
-                          const char *keyword, const char *text);
+FILE *assuan_get_data_fp (assuan_context_t ctx);
+assuan_error_t assuan_set_okay_line (assuan_context_t ctx, const char *line);
+assuan_error_t assuan_write_status (assuan_context_t ctx,
+                                    const char *keyword, const char *text);
 
 /* Negotiate a file descriptor.  If LINE contains "FD=N", returns N
    assuming a local file descriptor.  If LINE contains "FD" reads a
    file descriptor via CTX and stores it in *RDF (the CTX must be
    capable of passing file descriptors).  */
-AssuanError assuan_command_parse_fd (ASSUAN_CONTEXT ctx, char *line,
+assuan_error_t assuan_command_parse_fd (assuan_context_t ctx, char *line,
                                     int *rfd);
 
 /*-- assuan-listen.c --*/
-AssuanError assuan_set_hello_line (ASSUAN_CONTEXT ctx, const char *line);
-AssuanError assuan_accept (ASSUAN_CONTEXT ctx);
-int assuan_get_input_fd (ASSUAN_CONTEXT ctx);
-int assuan_get_output_fd (ASSUAN_CONTEXT ctx);
-AssuanError assuan_close_input_fd (ASSUAN_CONTEXT ctx);
-AssuanError assuan_close_output_fd (ASSUAN_CONTEXT ctx);
+assuan_error_t assuan_set_hello_line (assuan_context_t ctx, const char *line);
+assuan_error_t assuan_accept (assuan_context_t ctx);
+int assuan_get_input_fd (assuan_context_t ctx);
+int assuan_get_output_fd (assuan_context_t ctx);
+assuan_error_t assuan_close_input_fd (assuan_context_t ctx);
+assuan_error_t assuan_close_output_fd (assuan_context_t ctx);
 
 
 /*-- assuan-pipe-server.c --*/
-int assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2]);
-void assuan_deinit_server (ASSUAN_CONTEXT ctx);
+int assuan_init_pipe_server (assuan_context_t *r_ctx, int filedes[2]);
+void assuan_deinit_server (assuan_context_t ctx);
 
 /*-- assuan-socket-server.c --*/
-int assuan_init_socket_server (ASSUAN_CONTEXT *r_ctx, int listen_fd);
-int assuan_init_connected_socket_server (ASSUAN_CONTEXT *r_ctx, int fd);
+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);
 
 
 /*-- assuan-pipe-connect.c --*/
-AssuanError assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name,
+assuan_error_t assuan_pipe_connect (assuan_context_t *ctx, const char *name,
                                  char *const argv[], int *fd_child_list);
+assuan_error_t assuan_pipe_connect2 (assuan_context_t *ctx, const char *name,
+                                     char *const argv[], int *fd_child_list,
+                                     void (*atfork) (void*, int),
+                                     void *atforkvalue);
 /*-- assuan-socket-connect.c --*/
-AssuanError assuan_socket_connect (ASSUAN_CONTEXT *ctx, const char *name,
-                                   pid_t server_pid);
+assuan_error_t assuan_socket_connect (assuan_context_t *ctx, const char *name,
+                                      pid_t server_pid);
 
 /*-- assuan-domain-connect.c --*/
 
@@ -310,7 +378,7 @@ AssuanError assuan_socket_connect (ASSUAN_CONTEXT *ctx, const char *name,
    bidirectional file descriptor (normally returned via socketpair)
    which the client can use to rendezvous with the server.  SERVER s
    the server's pid.  */
-AssuanError assuan_domain_connect (ASSUAN_CONTEXT *r_ctx,
+assuan_error_t assuan_domain_connect (assuan_context_t *r_ctx,
                                   int rendezvousfd,
                                   pid_t server);
 
@@ -319,74 +387,93 @@ AssuanError assuan_domain_connect (ASSUAN_CONTEXT *r_ctx,
 /* RENDEZVOUSFD is a bidirectional file descriptor (normally returned
    via socketpair) that the domain server can use to rendezvous with
    the client.  CLIENT is the client's pid.  */
-AssuanError assuan_init_domain_server (ASSUAN_CONTEXT *r_ctx,
+assuan_error_t assuan_init_domain_server (assuan_context_t *r_ctx,
                                       int rendezvousfd,
                                       pid_t client);
 
 
 /*-- assuan-connect.c --*/
-void assuan_disconnect (ASSUAN_CONTEXT ctx);
-pid_t assuan_get_pid (ASSUAN_CONTEXT ctx);
+void assuan_disconnect (assuan_context_t ctx);
+pid_t assuan_get_pid (assuan_context_t ctx);
 
 /*-- assuan-client.c --*/
-AssuanError 
-assuan_transact (ASSUAN_CONTEXT ctx,
+assuan_error_t 
+assuan_transact (assuan_context_t ctx,
                  const char *command,
-                 AssuanError (*data_cb)(void *, const void *, size_t),
+                 assuan_error_t (*data_cb)(void *, const void *, size_t),
                  void *data_cb_arg,
-                 AssuanError (*inquire_cb)(void*, const char *),
+                 assuan_error_t (*inquire_cb)(void*, const char *),
                  void *inquire_cb_arg,
-                 AssuanError (*status_cb)(void*, const char *),
+                 assuan_error_t (*status_cb)(void*, const char *),
                  void *status_cb_arg);
 
 
 /*-- assuan-inquire.c --*/
-AssuanError assuan_inquire (ASSUAN_CONTEXT ctx, const char *keyword,
-                            char **r_buffer, size_t *r_length, size_t maxlen);
+assuan_error_t assuan_inquire (assuan_context_t ctx, const char *keyword,
+                               unsigned char **r_buffer, size_t *r_length,
+                               size_t maxlen);
 
 /*-- assuan-buffer.c --*/
-AssuanError assuan_read_line (ASSUAN_CONTEXT ctx,
+assuan_error_t assuan_read_line (assuan_context_t ctx,
                               char **line, size_t *linelen);
-int assuan_pending_line (ASSUAN_CONTEXT ctx);
-AssuanError assuan_write_line (ASSUAN_CONTEXT ctx, const char *line );
-AssuanError assuan_send_data (ASSUAN_CONTEXT ctx,
+int assuan_pending_line (assuan_context_t ctx);
+assuan_error_t assuan_write_line (assuan_context_t ctx, const char *line );
+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")).  */
-AssuanError assuan_sendfd (ASSUAN_CONTEXT ctx, int fd);
-AssuanError assuan_receivefd (ASSUAN_CONTEXT ctx, int *fd);
+assuan_error_t assuan_sendfd (assuan_context_t ctx, int fd);
+assuan_error_t assuan_receivefd (assuan_context_t ctx, int *fd);
 
 /*-- assuan-util.c --*/
 void assuan_set_malloc_hooks ( void *(*new_alloc_func)(size_t n),
                                void *(*new_realloc_func)(void *p, size_t n),
                                void (*new_free_func)(void*) );
-void assuan_set_log_stream (ASSUAN_CONTEXT ctx, FILE *fp);
-int assuan_set_error (ASSUAN_CONTEXT ctx, int err, const char *text);
-void assuan_set_pointer (ASSUAN_CONTEXT ctx, void *pointer);
-void *assuan_get_pointer (ASSUAN_CONTEXT ctx);
+void assuan_set_log_stream (assuan_context_t ctx, FILE *fp);
+int assuan_set_error (assuan_context_t ctx, int err, const char *text);
+void assuan_set_pointer (assuan_context_t ctx, void *pointer);
+void *assuan_get_pointer (assuan_context_t ctx);
+
+void assuan_begin_confidential (assuan_context_t ctx);
+void assuan_end_confidential (assuan_context_t ctx);
+
+/* For context CTX, set the flag FLAG to VALUE.  Values for flags
+   are usually 1 or 0 but certain flags might allow for other values;
+   see the description of the type assuan_flag_t for details. */
+void assuan_set_flag (assuan_context_t ctx, assuan_flag_t flag, int value);
+
+/* Return the VALUE of FLAG in context CTX. */ 
+int  assuan_get_flag (assuan_context_t ctx, assuan_flag_t flag);
 
-void assuan_begin_confidential (ASSUAN_CONTEXT ctx);
-void assuan_end_confidential (ASSUAN_CONTEXT ctx);
 
 /*-- assuan-errors.c (built) --*/
-const char *assuan_strerror (AssuanError err);
+const char *assuan_strerror (assuan_error_t err);
 
 /*-- assuan-logging.c --*/
 
-/* Set the stream to which assuan should log.  By default, this is
-   stderr.  */
+/* Set the stream to which assuan should log message not associated
+   with a context.  By default, this is stderr.  The default value
+   will be changed when the first log stream is associated with a
+   context.  Note, that this function is not thread-safe and should
+   in general be used right at startup. */
 extern void assuan_set_assuan_log_stream (FILE *fp);
 
-/* Return the stream which is currently being using for logging.  */
+/* Return the stream which is currently being using for global logging.  */
 extern FILE *assuan_get_assuan_log_stream (void);
 
-/* User defined call back.  Return a prefix to be used at the start of
-   a line emitted by assuan on the log stream.  The default
-   implementation returns the empty string, i.e. ""  */
-extern const char *assuan_get_assuan_log_prefix (void);
+/* Set the prefix to be used at the start of a line emitted by assuan
+   on the log stream.  The default is the empty string.  Note, that
+   this function is not thread-safe and should in general be used
+   right at startup. */
+void assuan_set_assuan_log_prefix (const char *text);
+
+/* Return a prefix to be used at the start of a line emitted by assuan
+   on the log stream.  The default implementation returns the empty
+   string, i.e. ""  */
+const char *assuan_get_assuan_log_prefix (void);
 
 #ifdef __cplusplus
 }
index 1112941..e00011b 100755 (executable)
@@ -23,6 +23,10 @@ cat <<EOF
 /* Generated automatically by mkerrors */
 /* Do not edit! */
 
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
 #include <stdio.h>
 #include "assuan.h"
 
index 6a31bd5..2271357 100644 (file)
@@ -169,7 +169,7 @@ fi
 # Checks for library functions.
 AC_FUNC_FSEEKO
 
-AC_REPLACE_FUNCS(stpcpy)
+AC_CHECK_FUNCS(stpcpy)
 
 AC_REPLACE_FUNCS(vasprintf)
 if test "$ac_cv_func_vasprintf" != yes; then
index bd25f51..caa73ad 100644 (file)
@@ -1,3 +1,10 @@
+2005-08-08  Werner Koch  <wk@g10code.com>
+
+       * util.h (stpcpy): Renamed to ..
+       (_gpgme_stpcpy): .. this and made inline.  This avoids duplicate
+       definitions when linking statically.
+       * stpcpy.c: Removed.
+       
 2005-07-27  Marcus Brinkmann  <marcus@g10code.de>
 
        * gpgme.h (gpgme_status_code_t): Add GPGME_STATUS_PLAINTEXT.
index 0434208..6d54237 100644 (file)
@@ -1,6 +1,6 @@
 /* util.h 
    Copyright (C) 2000 Werner Koch (dd9jn)
-   Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH
+   Copyright (C) 2001, 2002, 2003, 2004, 2005 g10 Code GmbH
 
    This file is part of GPGME.
  
@@ -35,9 +35,18 @@ const char *_gpgme_get_gpgsm_path (void);
 \f
 /*-- replacement functions in <funcname>.c --*/
 #ifdef HAVE_CONFIG_H
+
 #ifndef HAVE_STPCPY
-char *stpcpy (char *a, const char *b);
-#endif
+static _GPGME_INLINE char *
+_gpgme_stpcpy (char *a, const char *b)
+{
+  while (*b)
+    *a++ = *b++;
+  *a = 0;
+  return a;
+}
+#define stpcpy(a,b) _gpgme_stpcpy ((a), (b))
+#endif /*!HAVE_STPCPY*/
 
 #if !HAVE_VASPRINTF
 #include <stdarg.h>