[Pkg-gnupg-commit] [libassuan] 304/437: Refactored platform system code.

Eric Dorland eric at moszumanska.debian.org
Fri May 22 05:33:56 UTC 2015


This is an automated email from the git hooks/post-receive script.

eric pushed a commit to branch master
in repository libassuan.

commit 4266559927264f0cce31b07a207dbd23d578e147
Author: Werner Koch <wk at gnupg.org>
Date:   Tue Mar 16 13:04:42 2010 +0000

    Refactored platform system code.
---
 src/ChangeLog      |   6 +
 src/Makefile.am    |  11 +
 src/system-posix.c | 339 +++++++++++++++++++++++++++
 src/system-w32.c   | 466 +++++++++++++++++++++++++++++++++++++
 src/system-w32ce.c | 464 +++++++++++++++++++++++++++++++++++++
 src/system.c       | 660 +----------------------------------------------------
 6 files changed, 1296 insertions(+), 650 deletions(-)

diff --git a/src/ChangeLog b/src/ChangeLog
index dd71683..1d5ff2e 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,9 @@
+2010-03-16  Werner Koch  <wk at g10code.com>
+
+	* system.c: For better readability move platform dependend code to ..
+	* system-posix.c, system-w32.c, system-w32ce.c: .. New.
+	* Makefile.am (common_sources): Account for this change.
+
 2010-03-11  Werner Koch  <wk at g10code.com>
 
 	* assuan-defs.h [!HAVE_VASPRINTF]: Add macros vasprintf and asprintf.
diff --git a/src/Makefile.am b/src/Makefile.am
index 6403e79..c946f11 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -57,6 +57,17 @@ common_sources = \
 	assuan-socket.c
 
 if HAVE_W32_SYSTEM
+if HAVE_W32CE_SYSTEM
+common_sources += system-w32ce.c
+else
+common_sources += system-w32.c
+endif
+else
+common_sources += system-posix.c
+endif
+
+
+if HAVE_W32_SYSTEM
 
 LTRCCOMPILE = $(LIBTOOL) --mode=compile $(RC) \
      `echo $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) | \
diff --git a/src/system-posix.c b/src/system-posix.c
new file mode 100644
index 0000000..e36767a
--- /dev/null
+++ b/src/system-posix.c
@@ -0,0 +1,339 @@
+/* system-posix.c - System support functions.
+   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
+
+   This file is part of Assuan.
+
+   Assuan is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of
+   the License, or (at your option) any later version.
+
+   Assuan is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <errno.h>
+/* Solaris 8 needs sys/types.h before time.h.  */
+#include <sys/types.h>
+#include <time.h>
+#include <fcntl.h>
+#include <sys/wait.h>
+
+#include "assuan-defs.h"
+#include "debug.h"
+
+#ifdef _POSIX_OPEN_MAX
+#define MAX_OPEN_FDS _POSIX_OPEN_MAX
+#else
+#define MAX_OPEN_FDS 20
+#endif
+
+
+
+

+assuan_fd_t
+assuan_fdopen (int fd)
+{
+  return dup (fd);
+}
+
+
+

+/* Sleep for the given number of microseconds.  Default
+   implementation.  */
+void
+__assuan_usleep (assuan_context_t ctx, unsigned int usec)
+{
+  if (! usec)
+    return;
+
+#ifdef HAVE_NANOSLEEP
+  {
+    struct timespec req;
+    struct timespec rem;
+      
+    req.tv_sec = 0;
+    req.tv_nsec = usec * 1000;
+  
+    while (nanosleep (&req, &rem) < 0 && errno == EINTR)
+      req = rem;
+  }
+#else
+  {
+    struct timeval tv;
+  
+    tv.tv_sec  = usec / 1000000;
+    tv.tv_usec = usec % 1000000;
+    select (0, NULL, NULL, NULL, &tv);
+  }
+#endif
+}
+
+
+

+/* Create a pipe with one inheritable end.  Easy for Posix.  */
+int
+__assuan_pipe (assuan_context_t ctx, assuan_fd_t fd[2], int inherit_idx)
+{
+  return pipe (fd);
+}
+
+
+

+/* Close the given file descriptor, created with _assuan_pipe or one
+   of the socket functions.  Easy for Posix.  */
+int
+__assuan_close (assuan_context_t ctx, assuan_fd_t fd)
+{
+  return close (fd);
+}
+
+
+

+static ssize_t
+__assuan_read (assuan_context_t ctx, assuan_fd_t fd, void *buffer, size_t size)
+{
+  return read (fd, buffer, size);
+}
+
+
+

+static ssize_t
+__assuan_write (assuan_context_t ctx, assuan_fd_t fd, const void *buffer,
+		size_t size)
+{
+  return write (fd, buffer, size);
+}
+
+
+

+static int
+__assuan_recvmsg (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg,
+		  int flags)
+{
+  int ret;
+
+  do
+    ret = recvmsg (fd, msg, flags);
+  while (ret == -1 && errno == EINTR);
+
+  return ret;
+}
+
+
+

+static int
+__assuan_sendmsg (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg,
+		  int flags)
+{
+  int ret;
+
+  do
+    ret = sendmsg (fd, msg, flags);
+  while (ret == -1 && errno == EINTR);
+
+  return ret;
+}
+
+
+

+static int
+writen (int fd, const char *buffer, size_t length)
+{
+  while (length)
+    {
+      int nwritten = write (fd, buffer, length);
+      
+      if (nwritten < 0)
+        {
+          if (errno == EINTR)
+            continue;
+          return -1; /* write error */
+        }
+      length -= nwritten;
+      buffer += nwritten;
+    }
+  return 0;  /* okay */
+}
+
+
+int
+__assuan_spawn (assuan_context_t ctx, pid_t *r_pid, const char *name,
+		const char **argv,
+		assuan_fd_t fd_in, assuan_fd_t fd_out,
+		assuan_fd_t *fd_child_list,
+		void (*atfork) (void *opaque, int reserved),
+		void *atforkvalue, unsigned int flags)
+{
+  int pid;
+
+  pid = fork ();
+  if (pid < 0)
+    return -1;
+
+  if (pid == 0)
+    {
+      /* Child process (server side).  */
+      int i;
+      int n;
+      char errbuf[512];
+      int *fdp;
+      int fdnul;
+
+      if (atfork)
+	atfork (atforkvalue, 0);
+
+      fdnul = open ("/dev/null", O_WRONLY);
+      if (fdnul == -1)
+	{
+	  TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_spawn", ctx,
+		  "can't open `/dev/null': %s", strerror (errno));
+	  _exit (4);
+	}
+      
+      /* Dup handles to stdin/stdout. */
+      if (fd_out != STDOUT_FILENO)
+	{
+	  if (dup2 (fd_out == ASSUAN_INVALID_FD ? fdnul : fd_out,
+		    STDOUT_FILENO) == -1)
+	    {
+	      TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_spawn", ctx,
+		      "dup2 failed in child: %s", strerror (errno));
+	      _exit (4);
+	    }
+	}
+      
+      if (fd_in != STDIN_FILENO)
+	{
+	  if (dup2 (fd_in == ASSUAN_INVALID_FD ? fdnul : fd_in,
+		    STDIN_FILENO) == -1)
+	    {
+	      TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_spawn", ctx,
+		      "dup2 failed in child: %s", 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)
+	{
+	  if (dup2 (fdnul, STDERR_FILENO) == -1)
+	    {
+	      TRACE1 (ctx, ASSUAN_LOG_SYSIO, "pipe_connect_unix", ctx,
+		      "dup2(dev/null, 2) failed: %s", strerror (errno));
+	      _exit (4);
+	    }
+	}
+      close (fdnul);
+      
+      /* 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);
+	}
+      gpg_err_set_errno (0);
+      
+      if (! name)
+	{
+	  /* No name and no args given, thus we don't do an exec
+	     but continue the forked process.  */
+	  *argv = "server";
+	  
+	  /* FIXME: Cleanup.  */
+	  return 0;
+	}
+      
+      execv (name, (char *const *) argv); 
+      
+      /* oops - use the pipe to tell the parent about it */
+      snprintf (errbuf, sizeof(errbuf)-1,
+		"ERR %d can't exec `%s': %.50s\n",
+		_assuan_error (ctx, GPG_ERR_ASS_SERVER_START),
+		name, strerror (errno));
+      errbuf[sizeof(errbuf)-1] = 0;
+      writen (1, errbuf, strlen (errbuf));
+      _exit (4);
+    }
+
+  if (! name)
+    *argv = "client";
+  
+  *r_pid = pid;
+
+  return 0;
+}
+
+
+

+/* FIXME: Add some sort of waitpid function that covers GPGME and
+   gpg-agent's use of assuan.  */
+static pid_t 
+__assuan_waitpid (assuan_context_t ctx, pid_t pid, int nowait,
+		  int *status, int options)
+{
+  /* We can't just release the PID, a waitpid is mandatory.  But
+     NOWAIT in POSIX systems just means the caller already did the
+     waitpid for this child.  */
+  if (! nowait)
+    return waitpid (pid, NULL, 0); 
+  return 0;
+}
+
+
+

+int
+__assuan_socketpair (assuan_context_t ctx, int namespace, int style,
+		     int protocol, assuan_fd_t filedes[2])
+{
+  return socketpair (namespace, style, protocol, filedes);
+}
+
+
+

+/* The default system hooks for assuan contexts.  */
+struct assuan_system_hooks _assuan_system_hooks =
+  {
+    ASSUAN_SYSTEM_HOOKS_VERSION,
+    __assuan_usleep,
+    __assuan_pipe,
+    __assuan_close,
+    __assuan_read,
+    __assuan_write,
+    __assuan_recvmsg,
+    __assuan_sendmsg,
+    __assuan_spawn,
+    __assuan_waitpid,
+    __assuan_socketpair    
+  };
diff --git a/src/system-w32.c b/src/system-w32.c
new file mode 100644
index 0000000..31da194
--- /dev/null
+++ b/src/system-w32.c
@@ -0,0 +1,466 @@
+/* system-w32.c - System support functions for Windows.
+   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
+
+   This file is part of Assuan.
+
+   Assuan is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of
+   the License, or (at your option) any later version.
+
+   Assuan is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <errno.h>
+#include <time.h>
+#include <fcntl.h>
+#include <windows.h>
+
+#include "assuan-defs.h"
+#include "debug.h"
+
+
+

+assuan_fd_t
+assuan_fdopen (int fd)
+{
+  assuan_fd_t ifd = (assuan_fd_t) _get_osfhandle (fd);
+  assuan_fd_t ofd;
+
+  if (! DuplicateHandle(GetCurrentProcess(), ifd, 
+			GetCurrentProcess(), &ofd, 0,
+			TRUE, DUPLICATE_SAME_ACCESS))
+    {
+      gpg_err_set_errno (EIO);
+      return ASSUAN_INVALID_FD;
+    }
+  return ofd;
+}
+
+
+

+/* Sleep for the given number of microseconds.  Default
+   implementation.  */
+void
+__assuan_usleep (assuan_context_t ctx, unsigned int usec)
+{
+  if (!usec)
+    return;
+
+  Sleep (usec / 1000);
+}
+
+
+

+/* Create a pipe with one inheritable end.  Default implementation.  */
+int
+__assuan_pipe (assuan_context_t ctx, assuan_fd_t fd[2], int inherit_idx)
+{
+  HANDLE rh;
+  HANDLE wh;
+  HANDLE th;
+  SECURITY_ATTRIBUTES sec_attr;
+
+  memset (&sec_attr, 0, sizeof (sec_attr));
+  sec_attr.nLength = sizeof (sec_attr);
+  sec_attr.bInheritHandle = FALSE;
+
+  if (!CreatePipe (&rh, &wh, &sec_attr, 0))
+    {
+      TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_pipe", ctx,
+	      "CreatePipe failed: %s", _assuan_w32_strerror (ctx, -1));
+      gpg_err_set_errno (EIO);
+      return -1;
+    }
+
+  if (! DuplicateHandle (GetCurrentProcess(), (inherit_idx == 0) ? rh : wh,
+			 GetCurrentProcess(), &th, 0,
+			 TRUE, DUPLICATE_SAME_ACCESS ))
+    {
+      TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_pipe", ctx,
+	      "DuplicateHandle failed: %s", _assuan_w32_strerror (ctx, -1));
+      CloseHandle (rh);
+      CloseHandle (wh);
+      gpg_err_set_errno (EIO);
+      return -1;
+    }
+  if (inherit_idx == 0)
+    {
+      CloseHandle (rh);
+      rh = th;
+    }
+  else
+    {
+      CloseHandle (wh);
+      wh = th;
+    }
+
+  fd[0] = rh;
+  fd[1] = wh;
+
+  return 0;
+}
+
+
+

+/* Close the given file descriptor, created with _assuan_pipe or one
+   of the socket functions.  Default implementation.  */
+int
+__assuan_close (assuan_context_t ctx, assuan_fd_t fd)
+{
+  int rc = closesocket (HANDLE2SOCKET(fd));
+  if (rc)
+    gpg_err_set_errno ( _assuan_sock_wsa2errno (WSAGetLastError ()) );
+  if (rc && WSAGetLastError () == WSAENOTSOCK)
+    {
+      rc = CloseHandle (fd);
+      if (rc)
+        /* FIXME. */
+        gpg_err_set_errno (EIO);
+    }
+  return rc;
+}
+
+
+

+static ssize_t
+__assuan_read (assuan_context_t ctx, assuan_fd_t fd, void *buffer, size_t size)
+{
+  /* Due to the peculiarities of the W32 API we can't use read for a
+     network socket and thus we try to use recv first and fallback to
+     read if recv detects that it is not a network socket.  */
+  int res;
+
+  res = recv (HANDLE2SOCKET (fd), buffer, size, 0);
+  if (res == -1)
+    {
+      switch (WSAGetLastError ())
+        {
+        case WSAENOTSOCK:
+          {
+            DWORD nread = 0;
+            
+            res = ReadFile (fd, buffer, size, &nread, NULL);
+            if (! res)
+              {
+                switch (GetLastError ())
+                  {
+                  case ERROR_BROKEN_PIPE:
+		    gpg_err_set_errno (EPIPE);
+		    break;
+
+                  default:
+		    gpg_err_set_errno (EIO); 
+                  }
+                res = -1;
+              }
+            else
+              res = (int) nread;
+          }
+          break;
+          
+        case WSAEWOULDBLOCK:
+	  gpg_err_set_errno (EAGAIN);
+	  break;
+
+        case ERROR_BROKEN_PIPE:
+	  gpg_err_set_errno (EPIPE);
+	  break;
+
+        default:
+	  gpg_err_set_errno (EIO);
+	  break;
+        }
+    }
+  return res;
+}
+
+
+

+static ssize_t
+__assuan_write (assuan_context_t ctx, assuan_fd_t fd, const void *buffer,
+		size_t size)
+{
+  /* Due to the peculiarities of the W32 API we can't use write for a
+     network socket and thus we try to use send first and fallback to
+     write if send detects that it is not a network socket.  */
+  int res;
+
+  res = send (HANDLE2SOCKET (fd), buffer, size, 0);
+  if (res == -1 && WSAGetLastError () == WSAENOTSOCK)
+    {
+      DWORD nwrite;
+
+      res = WriteFile (fd, buffer, size, &nwrite, NULL);
+      if (! res)
+        {
+          switch (GetLastError ())
+            {
+            case ERROR_BROKEN_PIPE: 
+            case ERROR_NO_DATA:
+	      gpg_err_set_errno (EPIPE);
+	      break;
+	      
+            default:
+	      gpg_err_set_errno (EIO);
+	      break;
+            }
+          res = -1;
+        }
+      else
+        res = (int) nwrite;
+    }
+  return res;
+}
+
+
+

+static int
+__assuan_recvmsg (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg,
+		  int flags)
+{
+  gpg_err_set_errno (ENOSYS);
+  return -1;
+}
+
+
+
+

+static int
+__assuan_sendmsg (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg,
+		  int flags)
+{
+  gpg_err_set_errno (ENOSYS);
+  return -1;
+}
+
+
+
+

+/* 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 (assuan_context_t ctx, const 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 = _assuan_malloc (ctx, 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;
+}
+
+
+int
+__assuan_spawn (assuan_context_t ctx, pid_t *r_pid, const char *name,
+		const char **argv,
+		assuan_fd_t fd_in, assuan_fd_t fd_out,
+		assuan_fd_t *fd_child_list,
+		void (*atfork) (void *opaque, int reserved),
+		void *atforkvalue, unsigned int flags)
+{
+  SECURITY_ATTRIBUTES sec_attr;
+  PROCESS_INFORMATION pi = 
+    {
+      NULL,      /* Returns process handle.  */
+      0,         /* Returns primary thread handle.  */
+      0,         /* Returns pid.  */
+      0          /* Returns tid.  */
+    };
+  STARTUPINFO si;
+  assuan_fd_t fd;
+  assuan_fd_t *fdp;
+  char *cmdline;
+  HANDLE nullfd = INVALID_HANDLE_VALUE;
+
+  /* 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.  */
+
+  /* Build the command line.  */
+  if (build_w32_commandline (ctx, argv, &cmdline))
+    return -1;
+
+  /* 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;
+  /* FIXME: Dup to nul if ASSUAN_INVALID_FD.  */
+  si.hStdInput  = fd_in;
+  si.hStdOutput = fd_out;
+
+  /* Dup stderr to /dev/null unless it is in the list of FDs to be
+     passed to the child. */
+  fd = assuan_fd_from_posix_fd (fileno (stderr));
+  fdp = fd_child_list;
+  if (fdp)
+    {
+      for (; *fdp != ASSUAN_INVALID_FD && *fdp != fd; fdp++)
+        ;
+    }
+  if (!fdp || *fdp == ASSUAN_INVALID_FD)
+    {
+      nullfd = CreateFileW (L"nul", GENERIC_WRITE,
+                           FILE_SHARE_READ | FILE_SHARE_WRITE,
+                           NULL, OPEN_EXISTING, 0, NULL);
+      if (nullfd == INVALID_HANDLE_VALUE)
+        {
+	  TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_spawn", ctx,
+		  "can't open `nul': %s", _assuan_w32_strerror (ctx, -1));
+          _assuan_free (ctx, cmdline);
+          gpg_err_set_errno (EIO);
+          return -1;
+        }
+      si.hStdError = nullfd;
+    }
+  else
+    si.hStdError = 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
+                       | ((flags & 128)? DETACHED_PROCESS : 0)
+                       | GetPriorityClass (GetCurrentProcess ())
+                       | CREATE_SUSPENDED), /* Creation flags.  */
+                      NULL,                 /* Environment.  */
+                      NULL,                 /* Use current drive/directory.  */
+                      &si,                  /* Startup information. */
+                      &pi                   /* Returns process information.  */
+                      ))
+    {
+      TRACE1 (ctx, ASSUAN_LOG_SYSIO, "pipe_connect_w32", ctx,
+	      "CreateProcess failed: %s", _assuan_w32_strerror (ctx, -1));
+      _assuan_free (ctx, cmdline);
+      if (nullfd != INVALID_HANDLE_VALUE)
+        CloseHandle (nullfd);
+
+      gpg_err_set_errno (EIO);
+      return -1;
+    }
+
+  _assuan_free (ctx, cmdline);
+  if (nullfd != INVALID_HANDLE_VALUE)
+    CloseHandle (nullfd);
+
+  ResumeThread (pi.hThread);
+  CloseHandle (pi.hThread); 
+
+  /*   _assuan_log_printf ("CreateProcess ready: hProcess=%p hThread=%p" */
+  /*                       " dwProcessID=%d dwThreadId=%d\n", */
+  /*                       pi.hProcess, pi.hThread, */
+  /*                       (int) pi.dwProcessId, (int) pi.dwThreadId); */
+
+  *r_pid = (pid_t) pi.hProcess;
+
+  /* No need to modify peer process, as we don't change the handle
+     names.  However this also means we are not safe, as we inherit
+     too many handles.  Should use approach similar to gpgme and glib
+     using a helper process.  */
+
+  return 0;
+}
+
+
+
+

+/* FIXME: Add some sort of waitpid function that covers GPGME and
+   gpg-agent's use of assuan.  */
+static pid_t 
+__assuan_waitpid (assuan_context_t ctx, pid_t pid, int nowait,
+		  int *status, int options)
+{
+  CloseHandle ((HANDLE) pid);
+  return 0;
+}
+
+
+

+int
+__assuan_socketpair (assuan_context_t ctx, int namespace, int style,
+		     int protocol, assuan_fd_t filedes[2])
+{
+  gpg_err_set_errno (ENOSYS);
+  return -1;
+}
+
+

+/* The default system hooks for assuan contexts.  */
+struct assuan_system_hooks _assuan_system_hooks =
+  {
+    ASSUAN_SYSTEM_HOOKS_VERSION,
+    __assuan_usleep,
+    __assuan_pipe,
+    __assuan_close,
+    __assuan_read,
+    __assuan_write,
+    __assuan_recvmsg,
+    __assuan_sendmsg,
+    __assuan_spawn,
+    __assuan_waitpid,
+    __assuan_socketpair    
+  };
diff --git a/src/system-w32ce.c b/src/system-w32ce.c
new file mode 100644
index 0000000..ce0796c
--- /dev/null
+++ b/src/system-w32ce.c
@@ -0,0 +1,464 @@
+/* system-w32ce.c - System support functions for WindowsCE.
+   Copyright (C) 2010 Free Software Foundation, Inc.
+
+   This file is part of Assuan.
+
+   Assuan is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of
+   the License, or (at your option) any later version.
+
+   Assuan is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <errno.h>
+#include <time.h>
+#include <fcntl.h>
+#include <windows.h>
+
+#include "assuan-defs.h"
+#include "debug.h"
+
+
+

+assuan_fd_t
+assuan_fdopen (int fd)
+{
+  assuan_fd_t ifd = (assuan_fd_t)fd;
+  assuan_fd_t ofd;
+
+  if (! DuplicateHandle(GetCurrentProcess(), ifd, 
+			GetCurrentProcess(), &ofd, 0,
+			TRUE, DUPLICATE_SAME_ACCESS))
+    {
+      gpg_err_set_errno (EIO);
+      return ASSUAN_INVALID_FD;
+    }
+  return ofd;
+}
+
+
+

+/* Sleep for the given number of microseconds.  Default
+   implementation.  */
+void
+__assuan_usleep (assuan_context_t ctx, unsigned int usec)
+{
+  if (!usec)
+    return;
+
+  Sleep (usec / 1000);
+}
+
+
+

+/* Create a pipe with one inheritable end.  Default implementation.  */
+int
+__assuan_pipe (assuan_context_t ctx, assuan_fd_t fd[2], int inherit_idx)
+{
+  HANDLE rh;
+  HANDLE wh;
+  HANDLE th;
+  SECURITY_ATTRIBUTES sec_attr;
+
+  memset (&sec_attr, 0, sizeof (sec_attr));
+  sec_attr.nLength = sizeof (sec_attr);
+  sec_attr.bInheritHandle = FALSE;
+
+  if (!CreatePipe (&rh, &wh, &sec_attr, 0))
+    {
+      TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_pipe", ctx,
+	      "CreatePipe failed: %s", _assuan_w32_strerror (ctx, -1));
+      gpg_err_set_errno (EIO);
+      return -1;
+    }
+
+  if (! DuplicateHandle (GetCurrentProcess(), (inherit_idx == 0) ? rh : wh,
+			 GetCurrentProcess(), &th, 0,
+			 TRUE, DUPLICATE_SAME_ACCESS ))
+    {
+      TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_pipe", ctx,
+	      "DuplicateHandle failed: %s", _assuan_w32_strerror (ctx, -1));
+      CloseHandle (rh);
+      CloseHandle (wh);
+      gpg_err_set_errno (EIO);
+      return -1;
+    }
+  if (inherit_idx == 0)
+    {
+      CloseHandle (rh);
+      rh = th;
+    }
+  else
+    {
+      CloseHandle (wh);
+      wh = th;
+    }
+
+  fd[0] = rh;
+  fd[1] = wh;
+
+  return 0;
+}
+
+
+

+/* Close the given file descriptor, created with _assuan_pipe or one
+   of the socket functions.  Default implementation.  */
+int
+__assuan_close (assuan_context_t ctx, assuan_fd_t fd)
+{
+  int rc = closesocket (HANDLE2SOCKET(fd));
+  if (rc)
+    gpg_err_set_errno ( _assuan_sock_wsa2errno (WSAGetLastError ()) );
+  if (rc && WSAGetLastError () == WSAENOTSOCK)
+    {
+      rc = CloseHandle (fd);
+      if (rc)
+        /* FIXME. */
+        gpg_err_set_errno (EIO);
+    }
+  return rc;
+}
+
+
+

+static ssize_t
+__assuan_read (assuan_context_t ctx, assuan_fd_t fd, void *buffer, size_t size)
+{
+  /* Due to the peculiarities of the W32 API we can't use read for a
+     network socket and thus we try to use recv first and fallback to
+     read if recv detects that it is not a network socket.  */
+  int res;
+
+  res = recv (HANDLE2SOCKET (fd), buffer, size, 0);
+  if (res == -1)
+    {
+      switch (WSAGetLastError ())
+        {
+        case WSAENOTSOCK:
+          {
+            DWORD nread = 0;
+            
+            res = ReadFile (fd, buffer, size, &nread, NULL);
+            if (! res)
+              {
+                switch (GetLastError ())
+                  {
+                  case ERROR_BROKEN_PIPE:
+		    gpg_err_set_errno (EPIPE);
+		    break;
+
+                  default:
+		    gpg_err_set_errno (EIO); 
+                  }
+                res = -1;
+              }
+            else
+              res = (int) nread;
+          }
+          break;
+          
+        case WSAEWOULDBLOCK:
+	  gpg_err_set_errno (EAGAIN);
+	  break;
+
+        case ERROR_BROKEN_PIPE:
+	  gpg_err_set_errno (EPIPE);
+	  break;
+
+        default:
+	  gpg_err_set_errno (EIO);
+	  break;
+        }
+    }
+  return res;
+}
+
+
+

+static ssize_t
+__assuan_write (assuan_context_t ctx, assuan_fd_t fd, const void *buffer,
+		size_t size)
+{
+  /* Due to the peculiarities of the W32 API we can't use write for a
+     network socket and thus we try to use send first and fallback to
+     write if send detects that it is not a network socket.  */
+  int res;
+
+  res = send (HANDLE2SOCKET (fd), buffer, size, 0);
+  if (res == -1 && WSAGetLastError () == WSAENOTSOCK)
+    {
+      DWORD nwrite;
+
+      res = WriteFile (fd, buffer, size, &nwrite, NULL);
+      if (! res)
+        {
+          switch (GetLastError ())
+            {
+            case ERROR_BROKEN_PIPE: 
+            case ERROR_NO_DATA:
+	      gpg_err_set_errno (EPIPE);
+	      break;
+	      
+            default:
+	      gpg_err_set_errno (EIO);
+	      break;
+            }
+          res = -1;
+        }
+      else
+        res = (int) nwrite;
+    }
+  return res;
+}
+
+
+

+static int
+__assuan_recvmsg (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg,
+		  int flags)
+{
+  gpg_err_set_errno (ENOSYS);
+  return -1;
+}
+
+
+
+

+static int
+__assuan_sendmsg (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg,
+		  int flags)
+{
+  gpg_err_set_errno (ENOSYS);
+  return -1;
+}
+
+
+
+

+/* 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 (assuan_context_t ctx, const 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 = _assuan_malloc (ctx, 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;
+}
+
+
+int
+__assuan_spawn (assuan_context_t ctx, pid_t *r_pid, const char *name,
+		const char **argv,
+		assuan_fd_t fd_in, assuan_fd_t fd_out,
+		assuan_fd_t *fd_child_list,
+		void (*atfork) (void *opaque, int reserved),
+		void *atforkvalue, unsigned int flags)
+{
+  SECURITY_ATTRIBUTES sec_attr;
+  PROCESS_INFORMATION pi = 
+    {
+      NULL,      /* Returns process handle.  */
+      0,         /* Returns primary thread handle.  */
+      0,         /* Returns pid.  */
+      0          /* Returns tid.  */
+    };
+  STARTUPINFO si;
+  assuan_fd_t fd;
+  assuan_fd_t *fdp;
+  char *cmdline;
+  HANDLE nullfd = INVALID_HANDLE_VALUE;
+
+  /* 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.  */
+
+  /* Build the command line.  */
+  if (build_w32_commandline (ctx, argv, &cmdline))
+    return -1;
+
+  /* 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;
+  /* FIXME: Dup to nul if ASSUAN_INVALID_FD.  */
+  si.hStdInput  = fd_in;
+  si.hStdOutput = fd_out;
+
+  /* Dup stderr to /dev/null unless it is in the list of FDs to be
+     passed to the child. */
+  fd = assuan_fd_from_posix_fd (fileno (stderr));
+  fdp = fd_child_list;
+  if (fdp)
+    {
+      for (; *fdp != ASSUAN_INVALID_FD && *fdp != fd; fdp++)
+        ;
+    }
+  if (!fdp || *fdp == ASSUAN_INVALID_FD)
+    {
+      nullfd = CreateFileW (L"nul", GENERIC_WRITE,
+                           FILE_SHARE_READ | FILE_SHARE_WRITE,
+                           NULL, OPEN_EXISTING, 0, NULL);
+      if (nullfd == INVALID_HANDLE_VALUE)
+        {
+	  TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_spawn", ctx,
+		  "can't open `nul': %s", _assuan_w32_strerror (ctx, -1));
+          _assuan_free (ctx, cmdline);
+          gpg_err_set_errno (EIO);
+          return -1;
+        }
+      si.hStdError = nullfd;
+    }
+  else
+    si.hStdError = 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
+                       | CREATE_SUSPENDED), /* Creation flags.  */
+                      NULL,                 /* Environment.  */
+                      NULL,                 /* Use current drive/directory.  */
+                      &si,                  /* Startup information. */
+                      &pi                   /* Returns process information.  */
+                      ))
+    {
+      TRACE1 (ctx, ASSUAN_LOG_SYSIO, "pipe_connect_w32", ctx,
+	      "CreateProcess failed: %s", _assuan_w32_strerror (ctx, -1));
+      _assuan_free (ctx, cmdline);
+      if (nullfd != INVALID_HANDLE_VALUE)
+        CloseHandle (nullfd);
+
+      gpg_err_set_errno (EIO);
+      return -1;
+    }
+
+  _assuan_free (ctx, cmdline);
+  if (nullfd != INVALID_HANDLE_VALUE)
+    CloseHandle (nullfd);
+
+  ResumeThread (pi.hThread);
+  CloseHandle (pi.hThread); 
+
+  /*   _assuan_log_printf ("CreateProcess ready: hProcess=%p hThread=%p" */
+  /*                       " dwProcessID=%d dwThreadId=%d\n", */
+  /*                       pi.hProcess, pi.hThread, */
+  /*                       (int) pi.dwProcessId, (int) pi.dwThreadId); */
+
+  *r_pid = (pid_t) pi.hProcess;
+
+  /* No need to modify peer process, as we don't change the handle
+     names.  However this also means we are not safe, as we inherit
+     too many handles.  Should use approach similar to gpgme and glib
+     using a helper process.  */
+
+  return 0;
+}
+
+
+
+

+/* FIXME: Add some sort of waitpid function that covers GPGME and
+   gpg-agent's use of assuan.  */
+static pid_t 
+__assuan_waitpid (assuan_context_t ctx, pid_t pid, int nowait,
+		  int *status, int options)
+{
+  CloseHandle ((HANDLE) pid);
+  return 0;
+}
+
+
+

+int
+__assuan_socketpair (assuan_context_t ctx, int namespace, int style,
+		     int protocol, assuan_fd_t filedes[2])
+{
+  gpg_err_set_errno (ENOSYS);
+  return -1;
+}
+
+

+/* The default system hooks for assuan contexts.  */
+struct assuan_system_hooks _assuan_system_hooks =
+  {
+    ASSUAN_SYSTEM_HOOKS_VERSION,
+    __assuan_usleep,
+    __assuan_pipe,
+    __assuan_close,
+    __assuan_read,
+    __assuan_write,
+    __assuan_recvmsg,
+    __assuan_sendmsg,
+    __assuan_spawn,
+    __assuan_waitpid,
+    __assuan_socketpair    
+  };
diff --git a/src/system.c b/src/system.c
index fa942f7..22d7a0b 100644
--- a/src/system.c
+++ b/src/system.c
@@ -28,11 +28,6 @@
 #include <sys/types.h>
 #include <time.h>
 #include <fcntl.h>
-#ifdef HAVE_W32_SYSTEM
-# include <windows.h>
-#else
-# include <sys/wait.h>
-#endif
 
 #include "assuan-defs.h"
 #include "debug.h"
@@ -45,30 +40,7 @@
 
 #define DEBUG_SYSIO 0
 
-

-assuan_fd_t
-assuan_fdopen (int fd)
-{
-#ifdef HAVE_W32_SYSTEM
-#ifdef HAVE_W32CE_SYSTEM
-  assuan_fd_t ifd = (assuan_fd_t)fd;
-#else
-  assuan_fd_t ifd = (assuan_fd_t) _get_osfhandle (fd);
-#endif
-  assuan_fd_t ofd;
 
-  if (! DuplicateHandle(GetCurrentProcess(), ifd, 
-			GetCurrentProcess(), &ofd, 0,
-			TRUE, DUPLICATE_SAME_ACCESS))
-    {
-      gpg_err_set_errno (EIO);
-      return ASSUAN_INVALID_FD;
-    }
-  return ofd;
-#else
-  return dup (fd);
-#endif
-}
 
 

 /* Manage memory specific to a context.  */
@@ -154,40 +126,8 @@ _assuan_system_hooks_copy (assuan_system_hooks_t dst,
     ;
 }
 
-

-/* Sleep for the given number of microseconds.  Default
-   implementation.  */
-void
-__assuan_usleep (assuan_context_t ctx, unsigned int usec)
-{
-  if (! usec)
-    return;
-
-#ifdef HAVE_NANOSLEEP
-  {
-    struct timespec req;
-    struct timespec rem;
-      
-    req.tv_sec = 0;
-    req.tv_nsec = usec * 1000;
-  
-    while (nanosleep (&req, &rem) < 0 && errno == EINTR)
-      req = rem;
-  }
-#elif defined(HAVE_W32_SYSTEM)
-  Sleep (usec / 1000);
-#else
-  {
-    struct timeval tv;
-  
-    tv.tv_sec  = usec / 1000000;
-    tv.tv_usec = usec % 1000000;
-    select (0, NULL, NULL, NULL, &tv);
-  }
-#endif
-}
-
 
+

 /* Sleep for the given number of microseconds.  */
 void
 _assuan_usleep (assuan_context_t ctx, unsigned int usec)
@@ -198,61 +138,8 @@ _assuan_usleep (assuan_context_t ctx, unsigned int usec)
   (ctx->system.usleep) (ctx, usec);
 }
 
-

-/* Create a pipe with one inheritable end.  Default implementation.  */
-int
-__assuan_pipe (assuan_context_t ctx, assuan_fd_t fd[2], int inherit_idx)
-{
-#ifdef HAVE_W32_SYSTEM
-  HANDLE rh;
-  HANDLE wh;
-  HANDLE th;
-  SECURITY_ATTRIBUTES sec_attr;
-
-  memset (&sec_attr, 0, sizeof (sec_attr));
-  sec_attr.nLength = sizeof (sec_attr);
-  sec_attr.bInheritHandle = FALSE;
-
-  if (!CreatePipe (&rh, &wh, &sec_attr, 0))
-    {
-      TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_pipe", ctx,
-	      "CreatePipe failed: %s", _assuan_w32_strerror (ctx, -1));
-      gpg_err_set_errno (EIO);
-      return -1;
-    }
-
-  if (! DuplicateHandle (GetCurrentProcess(), (inherit_idx == 0) ? rh : wh,
-			 GetCurrentProcess(), &th, 0,
-			 TRUE, DUPLICATE_SAME_ACCESS ))
-    {
-      TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_pipe", ctx,
-	      "DuplicateHandle failed: %s", _assuan_w32_strerror (ctx, -1));
-      CloseHandle (rh);
-      CloseHandle (wh);
-      gpg_err_set_errno (EIO);
-      return -1;
-    }
-  if (inherit_idx == 0)
-    {
-      CloseHandle (rh);
-      rh = th;
-    }
-  else
-    {
-      CloseHandle (wh);
-      wh = th;
-    }
-
-  fd[0] = rh;
-  fd[1] = wh;
-
-  return 0;
-#else
-  return pipe (fd);
-#endif
-}
-
 
+

 /* Create a pipe with one inheritable end.  */
 int
 _assuan_pipe (assuan_context_t ctx, assuan_fd_t fd[2], int inherit_idx)
@@ -269,30 +156,8 @@ _assuan_pipe (assuan_context_t ctx, assuan_fd_t fd[2], int inherit_idx)
   return TRACE_SUC2 ("read=0x%x, write=0x%x", fd[0], fd[1]); 
 }
 
-

-/* Close the given file descriptor, created with _assuan_pipe or one
-   of the socket functions.  Default implementation.  */
-int
-__assuan_close (assuan_context_t ctx, assuan_fd_t fd)
-{
-#ifdef HAVE_W32_SYSTEM
-  int rc = closesocket (HANDLE2SOCKET(fd));
-  if (rc)
-    gpg_err_set_errno ( _assuan_sock_wsa2errno (WSAGetLastError ()) );
-  if (rc && WSAGetLastError () == WSAENOTSOCK)
-    {
-      rc = CloseHandle (fd);
-      if (rc)
-        /* FIXME. */
-        gpg_err_set_errno (EIO);
-    }
-  return rc;
-#else
-  return close (fd);
-#endif
-}
-
 
+

 /* Close the given file descriptor, created with _assuan_pipe or one
    of the socket functions.  */
 int
@@ -304,64 +169,8 @@ _assuan_close (assuan_context_t ctx, assuan_fd_t fd)
   return (ctx->system.close) (ctx, fd);
 }
 
-

-static ssize_t
-__assuan_read (assuan_context_t ctx, assuan_fd_t fd, void *buffer, size_t size)
-{
-#ifdef HAVE_W32_SYSTEM
-  /* Due to the peculiarities of the W32 API we can't use read for a
-     network socket and thus we try to use recv first and fallback to
-     read if recv detects that it is not a network socket.  */
-  int res;
-
-  res = recv (HANDLE2SOCKET (fd), buffer, size, 0);
-  if (res == -1)
-    {
-      switch (WSAGetLastError ())
-        {
-        case WSAENOTSOCK:
-          {
-            DWORD nread = 0;
-            
-            res = ReadFile (fd, buffer, size, &nread, NULL);
-            if (! res)
-              {
-                switch (GetLastError ())
-                  {
-                  case ERROR_BROKEN_PIPE:
-		    gpg_err_set_errno (EPIPE);
-		    break;
-
-                  default:
-		    gpg_err_set_errno (EIO); 
-                  }
-                res = -1;
-              }
-            else
-              res = (int) nread;
-          }
-          break;
-          
-        case WSAEWOULDBLOCK:
-	  gpg_err_set_errno (EAGAIN);
-	  break;
-
-        case ERROR_BROKEN_PIPE:
-	  gpg_err_set_errno (EPIPE);
-	  break;
-
-        default:
-	  gpg_err_set_errno (EIO);
-	  break;
-        }
-    }
-  return res;
-#else	/*!HAVE_W32_SYSTEM*/
-  return read (fd, buffer, size);
-#endif	/*!HAVE_W32_SYSTEM*/
-}
-
 
+

 ssize_t
 _assuan_read (assuan_context_t ctx, assuan_fd_t fd, void *buffer, size_t size)
 {
@@ -376,48 +185,8 @@ _assuan_read (assuan_context_t ctx, assuan_fd_t fd, void *buffer, size_t size)
 #endif
 }
 
-

-static ssize_t
-__assuan_write (assuan_context_t ctx, assuan_fd_t fd, const void *buffer,
-		size_t size)
-{
-#ifdef HAVE_W32_SYSTEM
-  /* Due to the peculiarities of the W32 API we can't use write for a
-     network socket and thus we try to use send first and fallback to
-     write if send detects that it is not a network socket.  */
-  int res;
-
-  res = send (HANDLE2SOCKET (fd), buffer, size, 0);
-  if (res == -1 && WSAGetLastError () == WSAENOTSOCK)
-    {
-      DWORD nwrite;
-
-      res = WriteFile (fd, buffer, size, &nwrite, NULL);
-      if (! res)
-        {
-          switch (GetLastError ())
-            {
-            case ERROR_BROKEN_PIPE: 
-            case ERROR_NO_DATA:
-	      gpg_err_set_errno (EPIPE);
-	      break;
-	      
-            default:
-	      gpg_err_set_errno (EIO);
-	      break;
-            }
-          res = -1;
-        }
-      else
-        res = (int) nwrite;
-    }
-  return res;
-#else	/*!HAVE_W32_SYSTEM*/
-  return write (fd, buffer, size);
-#endif	/*!HAVE_W32_SYSTEM*/
-}
-
 
+

 ssize_t
 _assuan_write (assuan_context_t ctx, assuan_fd_t fd, const void *buffer,
 	       size_t size)
@@ -433,25 +202,8 @@ _assuan_write (assuan_context_t ctx, assuan_fd_t fd, const void *buffer,
 #endif
 }
 
-

-static int
-__assuan_recvmsg (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg,
-		  int flags)
-{
-#ifdef HAVE_W32_SYSTEM
-  gpg_err_set_errno (ENOSYS);
-  return -1;
-#else
-  int ret;
-  do
-    ret = recvmsg (fd, msg, flags);
-  while (ret == -1 && errno == EINTR);
-
-  return ret;
-#endif
-}
-
 
+

 int
 _assuan_recvmsg (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg,
 		 int flags)
@@ -485,25 +237,8 @@ _assuan_recvmsg (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg,
 #endif
 }
 
-

-static int
-__assuan_sendmsg (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg,
-		  int flags)
-{
-#ifdef HAVE_W32_SYSTEM
-  gpg_err_set_errno (ENOSYS);
-  return -1;
-#else
-  int ret;
-  do
-    ret = sendmsg (fd, msg, flags);
-  while (ret == -1 && errno == EINTR);
-
-  return ret;
-#endif
-}
-
 
+

 int
 _assuan_sendmsg (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg,
 		 int flags)
@@ -536,340 +271,8 @@ _assuan_sendmsg (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg,
 #endif
 }
 
-

-#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 (assuan_context_t ctx, const 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 = _assuan_malloc (ctx, 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;
-}
-
-
-int
-__assuan_spawn (assuan_context_t ctx, pid_t *r_pid, const char *name,
-		const char **argv,
-		assuan_fd_t fd_in, assuan_fd_t fd_out,
-		assuan_fd_t *fd_child_list,
-		void (*atfork) (void *opaque, int reserved),
-		void *atforkvalue, unsigned int flags)
-{
-  SECURITY_ATTRIBUTES sec_attr;
-  PROCESS_INFORMATION pi = 
-    {
-      NULL,      /* Returns process handle.  */
-      0,         /* Returns primary thread handle.  */
-      0,         /* Returns pid.  */
-      0          /* Returns tid.  */
-    };
-  STARTUPINFO si;
-  assuan_fd_t fd;
-  assuan_fd_t *fdp;
-  char *cmdline;
-  HANDLE nullfd = INVALID_HANDLE_VALUE;
-
-  /* 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.  */
-
-  /* Build the command line.  */
-  if (build_w32_commandline (ctx, argv, &cmdline))
-    return -1;
-
-  /* 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;
-  /* FIXME: Dup to nul if ASSUAN_INVALID_FD.  */
-  si.hStdInput  = fd_in;
-  si.hStdOutput = fd_out;
-
-  /* Dup stderr to /dev/null unless it is in the list of FDs to be
-     passed to the child. */
-  fd = assuan_fd_from_posix_fd (fileno (stderr));
-  fdp = fd_child_list;
-  if (fdp)
-    {
-      for (; *fdp != ASSUAN_INVALID_FD && *fdp != fd; fdp++)
-        ;
-    }
-  if (!fdp || *fdp == ASSUAN_INVALID_FD)
-    {
-      nullfd = CreateFileW (L"nul", GENERIC_WRITE,
-                           FILE_SHARE_READ | FILE_SHARE_WRITE,
-                           NULL, OPEN_EXISTING, 0, NULL);
-      if (nullfd == INVALID_HANDLE_VALUE)
-        {
-	  TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_spawn", ctx,
-		  "can't open `nul': %s", _assuan_w32_strerror (ctx, -1));
-          _assuan_free (ctx, cmdline);
-          gpg_err_set_errno (EIO);
-          return -1;
-        }
-      si.hStdError = nullfd;
-    }
-  else
-    si.hStdError = fd;
-
-#ifdef HAVE_W32CE_SYSTEM
-# define DETACHED_PROCESS (0)
-#endif
-  /* 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
-                       | ((flags & 128)? DETACHED_PROCESS : 0)
-#ifndef HAVE_W32CE_SYSTEM
-                       | GetPriorityClass (GetCurrentProcess ())
-#endif
-                       | CREATE_SUSPENDED), /* Creation flags.  */
-                      NULL,                 /* Environment.  */
-                      NULL,                 /* Use current drive/directory.  */
-                      &si,                  /* Startup information. */
-                      &pi                   /* Returns process information.  */
-                      ))
-    {
-      TRACE1 (ctx, ASSUAN_LOG_SYSIO, "pipe_connect_w32", ctx,
-	      "CreateProcess failed: %s", _assuan_w32_strerror (ctx, -1));
-      _assuan_free (ctx, cmdline);
-      if (nullfd != INVALID_HANDLE_VALUE)
-        CloseHandle (nullfd);
-
-      gpg_err_set_errno (EIO);
-      return -1;
-    }
-
-  _assuan_free (ctx, cmdline);
-  if (nullfd != INVALID_HANDLE_VALUE)
-    CloseHandle (nullfd);
-
-  ResumeThread (pi.hThread);
-  CloseHandle (pi.hThread); 
-
-  /*   _assuan_log_printf ("CreateProcess ready: hProcess=%p hThread=%p" */
-  /*                       " dwProcessID=%d dwThreadId=%d\n", */
-  /*                       pi.hProcess, pi.hThread, */
-  /*                       (int) pi.dwProcessId, (int) pi.dwThreadId); */
-
-  *r_pid = (pid_t) pi.hProcess;
-
-  /* No need to modify peer process, as we don't change the handle
-     names.  However this also means we are not safe, as we inherit
-     too many handles.  Should use approach similar to gpgme and glib
-     using a helper process.  */
-
-  return 0;
-}
-
-#else
-
-static int
-writen (int fd, const char *buffer, size_t length)
-{
-  while (length)
-    {
-      int nwritten = write (fd, buffer, length);
-      
-      if (nwritten < 0)
-        {
-          if (errno == EINTR)
-            continue;
-          return -1; /* write error */
-        }
-      length -= nwritten;
-      buffer += nwritten;
-    }
-  return 0;  /* okay */
-}
-
-
-int
-__assuan_spawn (assuan_context_t ctx, pid_t *r_pid, const char *name,
-		const char **argv,
-		assuan_fd_t fd_in, assuan_fd_t fd_out,
-		assuan_fd_t *fd_child_list,
-		void (*atfork) (void *opaque, int reserved),
-		void *atforkvalue, unsigned int flags)
-{
-  int pid;
-
-  pid = fork ();
-  if (pid < 0)
-    return -1;
-
-  if (pid == 0)
-    {
-      /* Child process (server side).  */
-      int i;
-      int n;
-      char errbuf[512];
-      int *fdp;
-      int fdnul;
-
-      if (atfork)
-	atfork (atforkvalue, 0);
-
-      fdnul = open ("/dev/null", O_WRONLY);
-      if (fdnul == -1)
-	{
-	  TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_spawn", ctx,
-		  "can't open `/dev/null': %s", strerror (errno));
-	  _exit (4);
-	}
-      
-      /* Dup handles to stdin/stdout. */
-      if (fd_out != STDOUT_FILENO)
-	{
-	  if (dup2 (fd_out == ASSUAN_INVALID_FD ? fdnul : fd_out,
-		    STDOUT_FILENO) == -1)
-	    {
-	      TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_spawn", ctx,
-		      "dup2 failed in child: %s", strerror (errno));
-	      _exit (4);
-	    }
-	}
-      
-      if (fd_in != STDIN_FILENO)
-	{
-	  if (dup2 (fd_in == ASSUAN_INVALID_FD ? fdnul : fd_in,
-		    STDIN_FILENO) == -1)
-	    {
-	      TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_spawn", ctx,
-		      "dup2 failed in child: %s", 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)
-	{
-	  if (dup2 (fdnul, STDERR_FILENO) == -1)
-	    {
-	      TRACE1 (ctx, ASSUAN_LOG_SYSIO, "pipe_connect_unix", ctx,
-		      "dup2(dev/null, 2) failed: %s", strerror (errno));
-	      _exit (4);
-	    }
-	}
-      close (fdnul);
-      
-      /* 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);
-	}
-      gpg_err_set_errno (0);
-      
-      if (! name)
-	{
-	  /* No name and no args given, thus we don't do an exec
-	     but continue the forked process.  */
-	  *argv = "server";
-	  
-	  /* FIXME: Cleanup.  */
-	  return 0;
-	}
-      
-      execv (name, (char *const *) argv); 
-      
-      /* oops - use the pipe to tell the parent about it */
-      snprintf (errbuf, sizeof(errbuf)-1,
-		"ERR %d can't exec `%s': %.50s\n",
-		_assuan_error (ctx, GPG_ERR_ASS_SERVER_START),
-		name, strerror (errno));
-      errbuf[sizeof(errbuf)-1] = 0;
-      writen (1, errbuf, strlen (errbuf));
-      _exit (4);
-    }
-
-  if (! name)
-    *argv = "client";
-  
-  *r_pid = pid;
-
-  return 0;
-}
-#endif	/* ! HAVE_W32_SYSTEM */
-
 
+

 /* Create a new process from NAME and ARGV.  Provide FD_IN and FD_OUT
    as stdin and stdout.  Inherit the ASSUAN_INVALID_FD-terminated
    FD_CHILD_LIST as given (no remapping), which must be inheritable.
@@ -924,26 +327,10 @@ _assuan_spawn (assuan_context_t ctx, pid_t *r_pid, const char *name,
   return TRACE_SYSERR (res);
 }
 
+
 

 /* FIXME: Add some sort of waitpid function that covers GPGME and
    gpg-agent's use of assuan.  */
-static pid_t 
-__assuan_waitpid (assuan_context_t ctx, pid_t pid, int nowait,
-		  int *status, int options)
-{
-#ifndef HAVE_W32_SYSTEM
-  /* We can't just release the PID, a waitpid is mandatory.  But
-     NOWAIT in POSIX systems just means the caller already did the
-     waitpid for this child.  */
-  if (! nowait)
-    return waitpid (pid, NULL, 0); 
-#else	/* ! HAVE_W32_SYSTEM */
-  CloseHandle ((HANDLE) pid);
-#endif	/* HAVE_W32_SYSTEM */
-  return 0;
-}
-
-
 pid_t 
 _assuan_waitpid (assuan_context_t ctx, pid_t pid, int action,
 		 int *status, int options)
@@ -960,19 +347,8 @@ _assuan_waitpid (assuan_context_t ctx, pid_t pid, int action,
 #endif
 }
 
-

-int
-__assuan_socketpair (assuan_context_t ctx, int namespace, int style,
-		     int protocol, assuan_fd_t filedes[2])
-{
-#if HAVE_W32_SYSTEM
-  gpg_err_set_errno (ENOSYS);
-  return -1;
-#else
-  return socketpair (namespace, style, protocol, filedes);
-#endif
-}
 
+

 int
 _assuan_socketpair (assuan_context_t ctx, int namespace, int style,
 		    int protocol, assuan_fd_t filedes[2])
@@ -989,19 +365,3 @@ _assuan_socketpair (assuan_context_t ctx, int namespace, int style,
   return TRACE_SYSERR (res);
 }
 
-

-/* The default system hooks for assuan contexts.  */
-struct assuan_system_hooks _assuan_system_hooks =
-  {
-    ASSUAN_SYSTEM_HOOKS_VERSION,
-    __assuan_usleep,
-    __assuan_pipe,
-    __assuan_close,
-    __assuan_read,
-    __assuan_write,
-    __assuan_recvmsg,
-    __assuan_sendmsg,
-    __assuan_spawn,
-    __assuan_waitpid,
-    __assuan_socketpair    
-  };

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-gnupg/libassuan.git



More information about the Pkg-gnupg-commit mailing list