diff --git a/CMakeLists.txt b/CMakeLists.txt
index 83ebe227d39bad951623ce7514fe45f5cd2d11f3..68bd8c03deb106ec3b065073c11eb8a03d15ef27 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -29,9 +29,19 @@ SET(KWSYS_NO_ANSI_STRING_STREAM ${CMAKE_NO_ANSI_STRING_STREAM})
 SET(KWSYS_NO_ANSI_FOR_SCOPE ${CMAKE_NO_ANSI_FOR_SCOPE})
 
 SET(CLASSES Directory RegularExpression SystemTools)
-SET(HEADERS Configure)
+SET(H Process)
+SET(HXX Configure)
+
+IF(NOT UNIX)
+  ADD_EXECUTABLE(${KWSYS_NAMESPACE}ProcessFwd9x ProcessFwd9x.c)
+  ADD_EXECUTABLE(${KWSYS_NAMESPACE}EncodeExecutable EncodeExecutable.c)
+  SET(SRCS ProcessWin32.c ${CMAKE_CURRENT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c)
+  SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c
+                              PROPERTIES GENERATED 1)
+ELSE(NOT UNIX)
+  SET(SRCS ProcessUNIX.c)
+ENDIF(NOT UNIX)
 
-SET(SRCS)
 SET(KWSYS_INCLUDES)
 FOREACH(c ${CLASSES})
   SET(SRCS ${SRCS} ${c}.cxx)
@@ -42,7 +52,15 @@ FOREACH(c ${CLASSES})
       ${PROJECT_BINARY_DIR}/../${KWSYS_NAMESPACE}/${c}.hxx)
 ENDFOREACH(c)
 
-FOREACH(h ${HEADERS})
+FOREACH(h ${H})
+  CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/${h}.h.in
+                 ${PROJECT_BINARY_DIR}/../${KWSYS_NAMESPACE}/${h}.h
+                 @ONLY IMMEDIATE)
+  SET(KWSYS_INCLUDES ${KWSYS_INCLUDES}
+      ${PROJECT_BINARY_DIR}/../${KWSYS_NAMESPACE}/${h}.h)
+ENDFOREACH(h)
+
+FOREACH(h ${HXX})
   CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/${h}.hxx.in
                  ${PROJECT_BINARY_DIR}/../${KWSYS_NAMESPACE}/${h}.hxx
                  @ONLY IMMEDIATE)
@@ -93,3 +111,29 @@ IF(KWSYS_DEFAULTS)
   ADD_EXECUTABLE(test1 test1.cxx)
   TARGET_LINK_LIBRARIES(test1 ${KWSYS_NAMESPACE})
 ENDIF(KWSYS_DEFAULTS)
+
+IF(NOT UNIX)
+  SET(BIN_DIR ${CMAKE_CURRENT_BINARY_DIR})
+  IF(EXECUTABLE_OUTPUT_PATH)
+    SET(BIN_DIR ${EXECUTABLE_OUTPUT_PATH})
+  ENDIF(EXECUTABLE_OUTPUT_PATH)
+
+  SET(MAKE_SYSTEM)
+  SET(CFG_INTDIR "/${CMAKE_CFG_INTDIR}")
+  IF(CMAKE_BUILD_TOOL MATCHES "make")
+    SET(CFG_INTDIR "")
+  ENDIF(CMAKE_BUILD_TOOL MATCHES "make")
+
+  SET(CMD ${BIN_DIR}${CFG_INTDIR}/${KWSYS_NAMESPACE}EncodeExecutable.exe)
+  SET(FWD ${BIN_DIR}${CFG_INTDIR}/${KWSYS_NAMESPACE}ProcessFwd9x.exe)
+  ADD_CUSTOM_COMMAND(
+    TARGET ${KWSYS_NAMESPACE}
+    SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/ProcessFwd9x.c
+    COMMAND ${CMD}
+    ARGS ${FWD} ${CMAKE_CURRENT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c
+         ${KWSYS_NAMESPACE} ProcessFwd9x
+    OUTPUTS ${CMAKE_CURRENT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c
+    DEPENDS ${CMD} ${FWD})
+  ADD_DEPENDENCIES(${KWSYS_NAMESPACE} ${KWSYS_NAMESPACE}ProcessFwd9x
+                   ${KWSYS_NAMESPACE}EncodeExecutable)
+ENDIF(NOT UNIX)
diff --git a/EncodeExecutable.c b/EncodeExecutable.c
new file mode 100644
index 0000000000000000000000000000000000000000..34c444e0747dbbb48bf20d7624c951b5aee20a3a
--- /dev/null
+++ b/EncodeExecutable.c
@@ -0,0 +1,99 @@
+/*=========================================================================
+
+Program:   KWSys - Kitware System Library
+Module:    EncodeExecutable.c
+Language:  C++
+Date:      $Date$
+Version:   $Revision$
+
+Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
+See http://www.cmake.org/HTML/Copyright.html for details.
+
+This software is distributed WITHOUT ANY WARRANTY; without even 
+the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#include <stdio.h>
+
+int main(int argc, char* argv[])
+{
+  FILE* ifp;
+  FILE* ofp;
+  int i;
+  int n;
+  int count = 0;
+  unsigned char buffer[1024];
+  
+  /* Check arguments.  */
+  if(argc != 5)
+    {
+    fprintf(stderr, "Usage: %s <input> <output> <kwsys-name> <array>\n",
+            argv[0]);
+    return 1;
+    }
+  
+  /* Open the input file.  */
+  ifp = fopen(argv[1], "rb");
+  if(!ifp)
+    {
+    fprintf(stderr, "Cannot open input file: \"%s\"\n", argv[1]);
+    return 2;
+    }
+  ofp = fopen(argv[2], "w");
+  if(!ofp)
+    {
+    fprintf(stderr, "Cannot open output file: \"%s\"\n", argv[2]);
+    return 2;
+    }
+  
+  /* Prepend header comment.  */
+  fprintf(ofp, "/*\n * DO NOT EDIT\n * This file is generated by:\n");
+  fprintf(ofp, " * %s\n */\n\n", argv[0]);
+  fprintf(ofp, "#include <stdio.h>\n\n");
+  
+  /* Split file up in 1024-byte chunks.  */
+  while((n = fread(buffer, 1, 1024, ifp)) > 0)
+    {
+    fprintf(ofp, "static unsigned char kwsysEncodedArray%s_%d[%d] = {\n", 
+            argv[4], count++, n);
+    for(i=0; i < n-1; ++i)
+      {
+      fprintf(ofp, "0x%02X", buffer[i]);
+      if(i%10 == 9)
+        {
+        fprintf(ofp, ",\n");
+        }
+      else
+        {
+        fprintf(ofp, ", ");
+        }
+      }
+    fprintf(ofp, "0x%02X};\n\n", buffer[n-1]);
+    }
+  fclose(ifp);
+  
+  /* Provide a function to write the data to a file.  */
+  fprintf(ofp, "extern int %sEncodedWriteArray%s(const char* fname)\n",
+          argv[3], argv[4]);
+  fprintf(ofp, "{\n");
+  fprintf(ofp, "  FILE* ofp = fopen(fname, \"wb\");\n");
+  fprintf(ofp, "  if(!ofp) { return 0; }\n");
+  for(i=0; i < count; ++i)
+    {
+    fprintf(ofp, "  if(fwrite(kwsysEncodedArray%s_%d, 1,\n"
+                 "            sizeof(kwsysEncodedArray%s_%d), ofp) !=\n"
+                 "       sizeof(kwsysEncodedArray%s_%d))\n",
+            argv[4], i, argv[4], i, argv[4], i);
+    fprintf(ofp, "    {\n");
+    fprintf(ofp, "    fclose(ofp);\n");
+    fprintf(ofp, "    _unlink(fname);\n");
+    fprintf(ofp, "    return 0;\n");
+    fprintf(ofp, "    }\n");
+    }
+  fprintf(ofp, "  fclose(ofp);\n");
+  fprintf(ofp, "  return 1;\n");
+  fprintf(ofp, "}\n");
+  fclose(ofp);
+  return 0;
+}
diff --git a/Process.h.in b/Process.h.in
new file mode 100644
index 0000000000000000000000000000000000000000..076bd175d56d3f847fc7e7424409269f88d03a85
--- /dev/null
+++ b/Process.h.in
@@ -0,0 +1,172 @@
+/*=========================================================================
+
+  Program:   KWSys - Kitware System Library
+  Module:    Process.h.in
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
+  See http://www.cmake.org/HTML/Copyright.html for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even 
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef @KWSYS_NAMESPACE@_Process_h
+#define @KWSYS_NAMESPACE@_Process_h
+
+#define kwsys(x) @KWSYS_NAMESPACE@##x
+#define kwsysProcess_STDOUT kwsys(Process_STDOUT)
+#define kwsysProcess_STDERR kwsys(Process_STDERR)
+#define kwsysProcess_Timeout kwsys(Process_Timeout)
+#define kwsysProcess_Starting kwsys(Process_Starting)
+#define kwsysProcess_Executing kwsys(Process_Executing)
+#define kwsysProcess_Expired kwsys(Process_Expired)
+#define kwsysProcess_Exited kwsys(Process_Exited)
+#define kwsysProcess_Killed kwsys(Process_Killed)
+#define kwsysProcess_Signalled kwsys(Process_Signalled)
+#define kwsysProcess_Error kwsys(Process_Error)
+#define kwsysProcess_State kwsys(Process_State)
+#define kwsysProcess_Pipes_e kwsys(Process_Pipes_e)
+#define kwsysProcess_State_e kwsys(Process_State_e)
+#define kwsysProcess_s kwsys(Process_s)
+#define kwsysProcess kwsys(Process)
+#define kwsysProcess_New kwsys(Process_New)
+#define kwsysProcess_Delete kwsys(Process_Delete)
+#define kwsysProcess_SetCommand kwsys(Process_SetCommand)
+#define kwsysProcess_SetTimeout kwsys(Process_SetTimeout)
+#define kwsysProcess_GetState kwsys(Process_GetState)
+#define kwsysProcess_GetExitCode kwsys(Process_GetExitCode)
+#define kwsysProcess_GetErrorString kwsys(Process_GetErrorString)
+#define kwsysProcess_Execute kwsys(Process_Execute)
+#define kwsysProcess_WaitForData kwsys(Process_WaitForData)
+#define kwsysProcess_WaitForExit kwsys(Process_WaitForExit)
+#define kwsysProcess_Kill kwsys(Process_Kill)
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+typedef enum kwsysProcess_Pipes_e
+{
+  kwsysProcess_STDOUT=1,
+  kwsysProcess_STDERR=2,
+  kwsysProcess_Timeout=255
+} kwsysProcess_Pipes;
+
+typedef enum kwsysProcess_State_e
+{
+  kwsysProcess_Starting,  /* Between New and Execute; No process run yet */
+  kwsysProcess_Executing, /* Process is running */
+  kwsysProcess_Expired,   /* Process timeout expired and was killed */
+  kwsysProcess_Exited,    /* Process exited */
+  kwsysProcess_Killed,    /* Process was killed by Kill */
+  kwsysProcess_Signalled, /* Process was terminated by a signal (crash / ctrl-C) */
+  kwsysProcess_Error      /* Internal error of Process */
+} kwsysProcess_State;
+
+typedef struct kwsysProcess_s kwsysProcess;
+
+kwsysProcess* kwsysProcess_New();
+
+void kwsysProcess_Delete(kwsysProcess* cp);
+
+void kwsysProcess_SetCommand(kwsysProcess* cp, char const* const* command);
+
+void kwsysProcess_SetTimeout(kwsysProcess* cp, double timeout);
+
+/*
+ * Get the current internal state of the kwsysProcess instance
+ */
+int kwsysProcess_GetState(kwsysProcess* cp);
+
+/*
+ * Get process return code or when signalled, get the signal code 
+ */
+int kwsysProcess_GetExitCode(kwsysProcess* cp);
+
+/*
+ * On kwsysProcess_Error get the error message
+ */
+const char* kwsysProcess_GetErrorString(kwsysProcess* cp);
+
+void kwsysProcess_Execute(kwsysProcess* cp);
+
+/*
+ * Block until data available on requested pipe or one of the timeouts expired,
+ * or the process exits. If the pipe is not specified, data on that pipe are
+ * ignored.
+ *
+ * pipes - a list of interested pipes - kwsysProcess_STDOUT | kwsysProcess_STDERR
+ * data - returns pointer to data if read, NULL otherwise
+ * length - length of the returned data
+ * userTimeout - timeout for the current kwsysProcess_WaitForData call
+ *     the userTimeout will contain the remaining time
+ *
+ * Returns:
+ *    0 - Process exited or killed or process timeout expired with no data
+ *        available, or no process running.
+ *    PIPE id otherwise:
+ *       kwsysProcess_STDOUT - if stdout is returned
+ *       kwsysProcess_STDERR - if stderr is returned
+ *       kwsysProcess_Timeout - if user timeout expired
+ */ 
+int kwsysProcess_WaitForData(kwsysProcess* cp, int pipes, char** data, int* length,
+                          double* userTimeout);
+
+/*
+ * Block until the process exits or the timeout expires. If no process is
+ * running, return immediatly.
+ *
+ * Returns:
+ *    0 - When user timeout expires
+ *    1 - Otherwise
+ */
+int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout);
+
+/* 
+ * Kills the process.  kwsysProcess_WaitForExit should still be called
+ * after kwsysProcess_Kill.
+ */
+void kwsysProcess_Kill(kwsysProcess* cp);
+
+#if defined(__cplusplus)
+} /* extern "C" */
+#endif
+
+
+/* If we are building a kwsysProcess .c file, let it use these macros.  */
+#if !defined(KWSYS_IN_PROCESS_C)
+# undef kwsys
+# undef kwsysProcess_STDOUT
+# undef kwsysProcess_STDERR
+# undef kwsysProcess_Timeout
+# undef kwsysProcess_Starting
+# undef kwsysProcess_Executing
+# undef kwsysProcess_Expired
+# undef kwsysProcess_Exited
+# undef kwsysProcess_Killed
+# undef kwsysProcess_Signalled
+# undef kwsysProcess_Error
+# undef kwsysProcess_State
+# undef kwsysProcess_Pipes_e
+# undef kwsysProcess_State_e
+# undef kwsysProcess_s
+# undef kwsysProcess
+# undef kwsysProcess_New
+# undef kwsysProcess_Delete
+# undef kwsysProcess_SetCommand
+# undef kwsysProcess_SetTimeout
+# undef kwsysProcess_GetState
+# undef kwsysProcess_GetExitCode
+# undef kwsysProcess_GetErrorString
+# undef kwsysProcess_Execute
+# undef kwsysProcess_WaitForData
+# undef kwsysProcess_WaitForExit
+# undef kwsysProcess_Kill
+#endif
+
+#endif
diff --git a/ProcessFwd9x.c b/ProcessFwd9x.c
new file mode 100644
index 0000000000000000000000000000000000000000..27d66a9edd3d2d1c6bcf331e89e4d3cf578dace1
--- /dev/null
+++ b/ProcessFwd9x.c
@@ -0,0 +1,145 @@
+/*=========================================================================
+
+Program:   KWSys - Kitware System Library
+Module:    ProcessFwd9x.c
+Language:  C++
+Date:      $Date$
+Version:   $Revision$
+
+Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
+See http://www.cmake.org/HTML/Copyright.html for details.
+
+This software is distributed WITHOUT ANY WARRANTY; without even 
+the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+
+/*
+  On Windows9x platforms, this executable is spawned between a parent
+  process and the child it is invoking to work around a bug.  See the
+  Win32 implementation file for details.
+*/
+
+#include <windows.h>
+#include <stdio.h>
+
+int main()
+{
+  /* Process startup information for the real child.  */
+  STARTUPINFO si;
+  PROCESS_INFORMATION pi;
+  
+  /* The result of waiting for the child to exit.  */
+  DWORD waitResult;
+  
+  /* The child's process return code.  */
+  DWORD retVal;
+
+  /* The command line used to invoke this process.  */
+  LPSTR commandLine = GetCommandLine();
+
+  /* Pointer that will be advanced to the beginning of the command
+     line of the real child process.  */
+  LPSTR cmdLine = commandLine;
+  
+  /* Handle to the error reporting pipe provided by the parent.  This
+     is parsed off the command line.  */
+  HANDLE errorPipe = 0;
+
+  /* Handle to the event the parent uses to tell us to kill the child.
+     This is parsed off the command line.  */
+  HANDLE killEvent = 0;
+  
+  /* An array of the handles on which we wait when the child is
+     running.  */
+  HANDLE waitHandles[2] = {0, 0};
+  
+  /* Move the pointer past the name of this executable.  */
+  if(*cmdLine == '"')
+    {
+    ++cmdLine;
+    while(*cmdLine && *cmdLine != '"') { ++cmdLine; }
+    if(*cmdLine) { ++cmdLine; }
+    }
+  else
+    {
+    while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
+    }
+
+  /* Parse the error pipe handle.  */
+  while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
+  sscanf(cmdLine, "%d", &errorPipe);
+
+  /* Parse the kill event handle.  */
+  while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
+  while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
+  sscanf(cmdLine, "%d", &killEvent);
+  
+  /* Skip to the beginning of the command line of the real child.  */
+  while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
+  while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
+
+  /* Create the subprocess.  */
+  ZeroMemory(&si, sizeof(si));
+  ZeroMemory(&pi, sizeof(pi));
+  si.cb = sizeof(si);
+  si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
+  si.wShowWindow = SW_SHOWDEFAULT;
+  si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
+  si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
+  si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
+  if(!CreateProcess(0, cmdLine, 0, 0, TRUE, 0, 0, 0, &si, &pi))
+    {
+    /* Error creating the process.  Report the error to the parent
+       process through the special error reporting pipe.  */
+    LPVOID lpMsgBuf;
+    DWORD n;
+    FormatMessage( 
+      FORMAT_MESSAGE_ALLOCATE_BUFFER | 
+      FORMAT_MESSAGE_FROM_SYSTEM | 
+      FORMAT_MESSAGE_IGNORE_INSERTS,
+      NULL,
+      GetLastError(),
+      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+      (LPTSTR) &lpMsgBuf,
+      0,
+      NULL 
+      );
+    WriteFile(errorPipe, lpMsgBuf, strlen(lpMsgBuf)+1, &n, 0);
+    LocalFree( lpMsgBuf );
+    return 1;
+    }
+  CloseHandle(pi.hThread);  
+
+  /* Wait for subprocess to exit or for kill event from parent.  */
+  waitHandles[0] = killEvent;
+  waitHandles[1] = pi.hProcess;
+  waitResult = WaitForMultipleObjects(2, waitHandles, 0, INFINITE);
+
+  /* Check what happened.  */
+  if(waitResult == WAIT_OBJECT_0)
+    {
+    /* We were asked to kill the child.  */
+    TerminateProcess(pi.hProcess, -1);
+    WaitForSingleObject(pi.hProcess, INFINITE);
+    CloseHandle(pi.hProcess);
+    return 1;
+    }
+  else if(GetExitCodeProcess(pi.hProcess, &retVal))
+    {
+    /* The child exited and we could get the return code.  */
+    CloseHandle(pi.hProcess);
+    return retVal;
+    }
+  else
+    {
+    /* The child exited and we could not get the return code.  Report
+       the problem to the parent process.  */
+    DWORD n;
+    const char* msg = "Failed to get process return code.";
+    WriteFile(errorPipe, msg, strlen(msg)+1, &n, 0);
+    CloseHandle(pi.hProcess);
+    return -1;
+    }
+}
diff --git a/ProcessUNIX.c b/ProcessUNIX.c
new file mode 100644
index 0000000000000000000000000000000000000000..af936a0e7efca639ad1e65a8a4238b25e8cb07b4
--- /dev/null
+++ b/ProcessUNIX.c
@@ -0,0 +1,924 @@
+/*=========================================================================
+
+Program:   KWSys - Kitware System Library
+Module:    ProcessUNIX.c
+Language:  C++
+Date:      $Date$
+Version:   $Revision$
+
+Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
+See http://www.cmake.org/HTML/Copyright.html for details.
+
+This software is distributed WITHOUT ANY WARRANTY; without even 
+the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#define KWSYS_IN_PROCESS_C
+#include <Process.h>
+
+/*
+
+Implementation for UNIX
+  
+On UNIX, a child process is forked to exec the program.  Three
+output pipes from the child are read by the parent process using a
+select call to block until data are ready.  Two of the pipes are
+stdout and stderr for the child.  The third is a special error pipe
+that has two purposes.  First, if the child cannot exec the program,
+the error is reported through the error pipe.  Second, the error
+pipe is left open until the child exits.  This is used in
+conjunction with the timeout on the select call to implement a
+timeout for program even when it closes stdout and stderr.
+*/
+
+#include <stdio.h>     /* snprintf */
+#include <stdlib.h>    /* malloc, free */
+#include <string.h>    /* strdup, strerror, memset */
+#include <sys/time.h>  /* struct timeval */
+#include <sys/types.h> /* pid_t, fd_set */
+#include <sys/wait.h>  /* waitpid */
+#include <unistd.h>    /* pipe, close, fork, execvp, select, _exit */
+#include <fcntl.h>     /* fcntl */
+#include <errno.h>     /* errno */
+#include <time.h>      /* gettimeofday */
+#include <signal.h>    /* sigaction */
+
+/* The number of pipes for the child's output.  The standard stdout
+   and stderr pipes are the first two.  One more pipe is used for the
+   child to report errors to the parent before the real process is
+   invoked.  */
+#define KWSYSPE_PIPE_COUNT 3
+#define KWSYSPE_PIPE_STDOUT 0
+#define KWSYSPE_PIPE_STDERR 1
+#define KWSYSPE_PIPE_ERROR 2
+
+/* The maximum amount to read from a pipe at a time.  */
+#define KWSYSPE_PIPE_BUFFER_SIZE 1024
+
+typedef struct timeval kwsysProcessTime;
+
+/*--------------------------------------------------------------------------*/
+static void kwsysProcessInitialize(kwsysProcess* cp);
+static void kwsysProcessCleanup(kwsysProcess* cp, int error);
+static void kwsysProcessCleanupDescriptor(int* pfd);
+static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout,
+                                      kwsysProcessTime* timeoutTime);
+static int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime,
+                                      kwsysProcessTime* timeoutLength);
+static kwsysProcessTime kwsysProcessTimeGetCurrent();
+static double kwsysProcessTimeToDouble(kwsysProcessTime t);
+static kwsysProcessTime kwsysProcessTimeFromDouble(double d);
+static int kwsysProcessTimeLess(kwsysProcessTime in1, kwsysProcessTime in2);
+static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1, kwsysProcessTime in2);
+static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProcessTime in2);
+static void kwsysProcessChildErrorExit(kwsysProcess* cp);
+static void kwsysProcessRestoreDefaultSignalHandlers();
+
+/*--------------------------------------------------------------------------*/
+/* Structure containing data used to implement the child's execution.  */
+struct kwsysProcess_s
+{
+  /* The command line to execute. */
+  char** Command;
+
+  /* Descriptors for the read ends of the child's output pipes. */
+  int PipeReadEnds[KWSYSPE_PIPE_COUNT];
+  
+  /* Descriptors for the write ends of the child's output pipes. */
+  int PipeWriteEnds[KWSYSPE_PIPE_COUNT];
+  
+  /* Buffer for pipe data.  */
+  char PipeBuffer[KWSYSPE_PIPE_BUFFER_SIZE];
+
+  /* Process ID returned by the fork.  */
+  pid_t ForkPID;
+  
+  /* Flag for whether the child reported an error.  */
+  int ChildError;
+  
+  /* The timeout length.  */
+  float Timeout;
+  
+  /* Time at which the child started.  Negative for no timeout.  */
+  kwsysProcessTime StartTime;
+  
+  /* Time at which the child will timeout.  Negative for no timeout.  */
+  kwsysProcessTime TimeoutTime;
+  
+  /* Flag for whether the timeout expired.  */
+  int TimeoutExpired;
+  
+  /* The old SIGCHLD handler.  */
+  struct sigaction OldSigChldAction;
+  
+  /* The number of pipes left open during execution.  */
+  int PipesLeft;
+  
+  /* File descriptor set for call to select.  */
+  fd_set PipeSet;
+
+  /* The current status of the child process. */
+  int State;
+
+  /* The exit code of the child process, if any.  */
+  int ExitCode;
+  
+  /* Whether the process was killed.  */
+  int Killed;
+  
+  /* Buffer for error message in case of failure.  */
+  char ErrorMessage[KWSYSPE_PIPE_BUFFER_SIZE+1];
+  int ErrorMessageLength;
+};
+
+/*--------------------------------------------------------------------------*/
+kwsysProcess* kwsysProcess_New()
+{
+  /* Allocate a process control structure.  */
+  kwsysProcess* cp = (kwsysProcess*)malloc(sizeof(kwsysProcess));
+  if(!cp)
+    {
+    return 0;
+    }
+  memset(cp, 0, sizeof(kwsysProcess));
+  cp->State = kwsysProcess_Starting;
+  return cp;
+}
+
+/*--------------------------------------------------------------------------*/
+void kwsysProcess_Delete(kwsysProcess* cp)
+{
+  /* If the process is executing, wait for it to finish.  */
+  if(cp->State == kwsysProcess_Executing)
+    {
+    kwsysProcess_WaitForExit(cp, 0);
+    }
+  
+  /* Free memory.  */
+  kwsysProcess_SetCommand(cp, 0);
+  free(cp);
+}
+
+/*--------------------------------------------------------------------------*/
+void kwsysProcess_SetCommand(kwsysProcess* cp, char const* const* command)
+{
+  if(cp->Command)
+    {
+    char** c = cp->Command;
+    while(*c)
+      {
+      free(*c++);
+      }
+    free(cp->Command);
+    cp->Command = 0;
+    }
+  if(command)
+    {
+    char const* const* c = command;
+    int n = 0;
+    int i = 0;
+    while(*c++);
+    n = c - command - 1;
+    cp->Command = (char**)malloc((n+1)*sizeof(char*));
+    for(i=0; i < n; ++i)
+      {
+      cp->Command[i] = strdup(command[i]);
+      }
+    cp->Command[n] = 0;
+    }  
+}
+
+/*--------------------------------------------------------------------------*/
+void kwsysProcess_SetTimeout(kwsysProcess* cp, double timeout)
+{
+  cp->Timeout = timeout;
+  if(cp->Timeout < 0)
+    {
+    cp->Timeout = 0;
+    }
+}
+
+/*--------------------------------------------------------------------------*/
+int kwsysProcess_GetState(kwsysProcess* cp)
+{
+  return cp->State;
+}
+
+/*--------------------------------------------------------------------------*/
+int kwsysProcess_GetExitCode(kwsysProcess* cp)
+{
+  return cp->ExitCode;
+}
+
+/*--------------------------------------------------------------------------*/
+const char* kwsysProcess_GetErrorString(kwsysProcess* cp)
+{
+  if(cp->State == kwsysProcess_Error)
+    {
+    return cp->PipeBuffer;
+    }
+  return "";
+}
+
+/*--------------------------------------------------------------------------*/
+void kwsysProcess_Execute(kwsysProcess* cp)
+{
+  int i;
+  struct sigaction newSigChldAction;
+  
+  /* Do not execute a second copy simultaneously.  */
+  if(cp->State == kwsysProcess_Executing)
+    {
+    return;
+    }
+  
+  /* Initialize the control structure for a new process.  */
+  kwsysProcessInitialize(cp);
+  
+  /* We want no special handling of SIGCHLD.  Repeat call until it is
+     not interrupted.  */
+  newSigChldAction.sa_handler = SIG_DFL;
+  while((sigaction(SIGCHLD, &newSigChldAction, &cp->OldSigChldAction) < 0) &&
+        (errno == EINTR));
+  
+  /* Create pipes for subprocess output.  */
+  for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)
+    {
+    int p[2];
+    
+    /* Create the pipe.  */
+    if(pipe(p) < 0)
+      {
+      kwsysProcessCleanup(cp, 1);
+      return;
+      }
+    
+    /* Set close-on-exec flag on the pipe's ends.  */
+    if((fcntl(p[0], F_SETFD, FD_CLOEXEC) < 0) ||
+       (fcntl(p[1], F_SETFD, FD_CLOEXEC) < 0))
+      {
+      kwsysProcessCleanup(cp, 1);
+      return;
+      }
+    
+    /* Store the pipe.  */
+    cp->PipeReadEnds[i] = p[0];
+    cp->PipeWriteEnds[i] = p[1];
+    }
+  
+  /* The timeout period starts now.  */
+  cp->StartTime = kwsysProcessTimeGetCurrent();
+  cp->TimeoutTime.tv_sec = -1;
+  cp->TimeoutTime.tv_usec = -1;
+  
+  /* Fork off a child process.  */
+  cp->ForkPID = fork();
+  if(cp->ForkPID < 0)
+    {
+    kwsysProcessCleanup(cp, 1);
+    return;
+    }
+  
+  /* If this is the child process, run the real process.  */  
+  if(cp->ForkPID == 0)
+    {
+    /* Close stdin.  */
+    close(0);
+    
+    /* Setup the stdout/stderr pipes.  */
+    dup2(cp->PipeWriteEnds[KWSYSPE_PIPE_STDOUT], 1);
+    dup2(cp->PipeWriteEnds[KWSYSPE_PIPE_STDERR], 2);
+    
+    /* Clear the close-on-exec flag for stdout, stderr, and the child
+       error report pipe.  All other pipe handles will be closed when
+       exec succeeds.  */
+    fcntl(1, F_SETFD, 0);
+    fcntl(2, F_SETFD, 0);
+    fcntl(cp->PipeWriteEnds[KWSYSPE_PIPE_ERROR], F_SETFD, 0);
+    
+    /* Restore all default signal handlers. */
+    kwsysProcessRestoreDefaultSignalHandlers();
+    
+    /* Execute the real process.  If successful, this does not return.  */
+    execvp(cp->Command[0], cp->Command);
+    
+    /* Failure.  Report error to parent and terminate.  */
+    kwsysProcessChildErrorExit(cp);
+    }
+  
+  /* The parent process does not need the pipe write ends.  */
+  for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)
+    {
+    kwsysProcessCleanupDescriptor(&cp->PipeWriteEnds[i]);
+    }
+  
+  /* All the pipes are now open.  */
+  cp->PipesLeft = KWSYSPE_PIPE_COUNT;
+  
+  /* The process has now started.  */
+  cp->State = kwsysProcess_Executing;
+}
+
+/*--------------------------------------------------------------------------*/
+int kwsysProcess_WaitForData(kwsysProcess* cp, int pipes, char** data, int* length,
+                          double* userTimeout)
+{
+  int i;
+  int max = -1;
+  kwsysProcessTime* timeout = 0;
+  kwsysProcessTime timeoutLength;
+  kwsysProcessTime timeoutTime;
+  kwsysProcessTime userStartTime;
+  int user = 0;
+  int expired = 0;
+  int pipeId = 0;
+  int numReady = 0;
+  
+  /* Record the time at which user timeout period starts.  */
+  if(userTimeout)
+    {
+    userStartTime = kwsysProcessTimeGetCurrent();
+    }
+  
+  /* Calculate the time at which a timeout will expire, and whether it
+     is the user or process timeout.  */
+  user = kwsysProcessGetTimeoutTime(cp, userTimeout, &timeoutTime);
+  
+  /* Data can only be available when pipes are open.  If the process
+     is not running, cp->PipesLeft will be 0.  */
+  while(cp->PipesLeft > 0)
+    {
+    /* Check for any open pipes with data reported ready by the last
+       call to select.  */
+    for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)
+      {
+      if(cp->PipeReadEnds[i] >= 0 &&
+         FD_ISSET(cp->PipeReadEnds[i], &cp->PipeSet))
+        {
+        int n;
+        
+        /* We are handling this pipe now.  Remove it from the set.  */
+        FD_CLR(cp->PipeReadEnds[i], &cp->PipeSet);
+        
+        /* The pipe is ready to read without blocking.  Keep trying to
+           read until the operation is not interrupted.  */
+        while(((n = read(cp->PipeReadEnds[i], cp->PipeBuffer,
+                         KWSYSPE_PIPE_BUFFER_SIZE)) < 0) && (errno == EINTR));
+        if(n > 0)
+          {
+          /* We have data on this pipe.  */
+          if(i == KWSYSPE_PIPE_ERROR)
+            {
+            /* This is data on the special error reporting pipe.  The
+               child process failed to execute the program.  */
+            cp->ChildError = 1;
+            if(n > KWSYSPE_PIPE_BUFFER_SIZE - cp->ErrorMessageLength)
+              {
+              n = KWSYSPE_PIPE_BUFFER_SIZE - cp->ErrorMessageLength;
+              }
+            if(n > 0)
+              {
+              memcpy(cp->ErrorMessage+cp->ErrorMessageLength,
+                     cp->PipeBuffer, n);
+              cp->ErrorMessageLength += n;
+              cp->ErrorMessage[cp->ErrorMessageLength] = 0;
+              }
+            }
+          else if(pipes & (1 << i))
+            {
+            /* Caller wants this data.  Report it.  */
+            *data = cp->PipeBuffer;
+            *length = n;
+            pipeId = (1 << i);
+            break;
+            }
+          }
+        else
+          {
+          /* We are done reading from this pipe.  */
+          kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]);
+          --cp->PipesLeft;
+          }
+        }
+      }
+    
+    /* If we have data, break early.  */
+    if(pipeId)
+      {
+      break;
+      }
+    
+    /* Make sure the set is empty (it should always be empty here
+       anyway).  */
+    FD_ZERO(&cp->PipeSet);
+    
+    /* Add the pipe reading ends that are still open.  */
+    max = -1;
+    for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)
+      {
+      if(cp->PipeReadEnds[i] >= 0)
+        {
+        FD_SET(cp->PipeReadEnds[i], &cp->PipeSet);
+        if(cp->PipeReadEnds[i] > max)
+          {
+          max = cp->PipeReadEnds[i];
+          }
+        }
+      }
+  
+    /* Make sure we have a non-empty set.  */
+    if(max < 0)
+      {
+      /* All pipes have closed.  Child has terminated.  */
+      break;
+      }
+    
+    /* Setup a timeout if required.  */
+    if(timeoutTime.tv_sec < 0)
+      {
+      timeout = 0;
+      }
+    else
+      {
+      timeout = &timeoutLength;
+      }
+    if(kwsysProcessGetTimeoutLeft(&timeoutTime, &timeoutLength))
+      {
+      /* Timeout has already expired.  */
+      expired = 1;
+      break;
+      }
+    
+    /* Run select to block until data are available.  Repeat call
+       until it is not interrupted.  */
+    while(((numReady = select(max+1, &cp->PipeSet, 0, 0, timeout)) < 0) &&
+          (errno == EINTR));
+    
+    /* Check result of select.  */
+    if(numReady == 0)
+      {
+      /* Select's timeout expired.  */
+      expired = 1;
+      break;
+      }
+    else if(numReady < 0)
+      {
+      /* Select returned an error.  Leave the error description in the
+         pipe buffer.  */
+      snprintf(cp->ErrorMessage, KWSYSPE_PIPE_BUFFER_SIZE,
+               "%s", strerror(errno));
+      
+      /* Kill the child now.  */
+      kwsysProcess_Kill(cp);
+      cp->Killed = 0;
+      cp->ChildError = 1;
+      cp->PipesLeft = 0;
+      }
+    }
+  
+  /* Update the user timeout.  */
+  if(userTimeout)
+    {
+    kwsysProcessTime userEndTime = kwsysProcessTimeGetCurrent();
+    kwsysProcessTime difference = kwsysProcessTimeSubtract(userEndTime,
+                                                     userStartTime);
+    double d = kwsysProcessTimeToDouble(difference);
+    *userTimeout -= d;
+    if(*userTimeout < 0)
+      {
+      *userTimeout = 0;
+      }
+    }
+  
+  /* Check what happened.  */
+  if(pipeId)
+    {
+    /* Data are ready on a pipe.  */
+    return pipeId;
+    }
+  else if(expired)
+    {
+    /* A timeout has expired.  */
+    if(user)
+      {
+      /* The user timeout has expired.  It has no time left.  */
+      return kwsysProcess_Timeout;
+      }
+    else
+      {
+      /* The process timeout has expired.  Kill the child now.  */
+      kwsysProcess_Kill(cp);
+      cp->Killed = 0;
+      cp->TimeoutExpired = 1;
+      cp->PipesLeft = 0;
+      return 0;
+      }
+    }
+  else
+    {
+    /* No pipes are left open.  */
+    return 0;
+    }
+}
+
+/*--------------------------------------------------------------------------*/
+int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout)
+{
+  int result = 0;
+  int status = 0;
+  int pipe = 0;
+  
+  /* Make sure we are executing a process.  */
+  if(cp->State != kwsysProcess_Executing)
+    {
+    return 1;
+    }
+  
+  /* Wait for all the pipes to close.  Ignore all data.  */
+  while((pipe = kwsysProcess_WaitForData(cp, 0, 0, 0, userTimeout)) > 0)
+    {
+    if(pipe == kwsysProcess_Timeout)
+      {
+      return 0;
+      }
+    }
+
+  /* Wait for the child to terminate.  The process should have already
+     exited because KWSYSPE_PIPE_ERROR has been closed by this point.
+     Repeat the call until it is not interrupted.  */
+  while(((result = waitpid(cp->ForkPID, &status, 0)) < 0) && (errno == EINTR));
+  if(result <= 0)
+    {
+    /* Unexpected error.  */
+    kwsysProcessCleanup(cp, 1);
+    return 1;
+    }
+  
+  /* Check whether the child reported an error invoking the process.  */
+  if(cp->ChildError)
+    {
+    /* The error message is already in its buffer.  Tell
+       kwsysProcessCleanup to not create it.  */
+    kwsysProcessCleanup(cp, 0);
+    cp->State = kwsysProcess_Error;
+    return 1;
+    }
+  
+  /* Determine the outcome.  */
+  if(cp->Killed)
+    {
+    /* We killed the child.  */
+    cp->State = kwsysProcess_Killed;
+    }
+  else if(cp->TimeoutExpired)
+    {
+    /* The timeout expired.  */
+    cp->State = kwsysProcess_Expired;
+    }
+  else if(WIFEXITED(status))
+    {
+    /* The child exited.  */
+    cp->State = kwsysProcess_Exited;
+    cp->ExitCode = (int)WEXITSTATUS(status);
+    }
+  else if(WIFSIGNALED(status))
+    {
+    /* The child received an unhandled signal.  */
+    cp->State = kwsysProcess_Signalled;
+    cp->ExitCode = (int)WTERMSIG(status);
+    }
+  else
+    {
+    /* Error getting the child return code.  */
+    strcpy(cp->ErrorMessage, "Error getting child return code.");
+    cp->State = kwsysProcess_Error;
+    }
+  
+  /* Normal cleanup.  */
+  kwsysProcessCleanup(cp, 0);
+  return 1;
+}
+
+/*--------------------------------------------------------------------------*/
+void kwsysProcess_Kill(kwsysProcess* cp)
+{  
+  /* Make sure we are executing a process.  */
+  if(cp->State != kwsysProcess_Executing)
+    {
+    return;
+    }
+  
+  /* Kill the child.  */
+  cp->Killed = 1;
+  kill(cp->ForkPID, SIGKILL);
+}
+
+/*--------------------------------------------------------------------------*/
+/* Initialize a process control structure for kwsysProcess_Execute.  */
+void kwsysProcessInitialize(kwsysProcess* cp)
+{
+  int i;
+  for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)
+    {
+    cp->PipeReadEnds[i] = -1;
+    cp->PipeWriteEnds[i] = -1;
+    }
+  cp->ForkPID = -1;
+  cp->ChildError = 0;
+  cp->StartTime.tv_sec = -1;
+  cp->StartTime.tv_usec = -1;
+  cp->TimeoutTime.tv_sec = -1;
+  cp->TimeoutTime.tv_usec = -1;
+  cp->TimeoutExpired = 0;
+  cp->PipesLeft = 0;
+  FD_ZERO(&cp->PipeSet);
+  cp->State = kwsysProcess_Starting;
+  cp->Killed = 0;
+  cp->ExitCode = 0;
+  cp->ErrorMessage[0] = 0;
+  cp->ErrorMessageLength = 0;
+}
+
+/*--------------------------------------------------------------------------*/
+/* Free all resources used by the given kwsysProcess instance that were
+   allocated by kwsysProcess_Execute.  */
+void kwsysProcessCleanup(kwsysProcess* cp, int error)
+{
+  int i;
+  
+  /* If cleaning up due to an error, report the error message.  */
+  if(error)
+    {
+    snprintf(cp->ErrorMessage, KWSYSPE_PIPE_BUFFER_SIZE, "%s", strerror(errno));
+    cp->State = kwsysProcess_Error;
+    }
+  
+  /* Restore the SIGCHLD handler.  */
+  while((sigaction(SIGCHLD, &cp->OldSigChldAction, 0) < 0) &&
+        (errno == EINTR));
+  
+  /* Close pipe handles.  */
+  for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)
+    {
+    kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]);
+    kwsysProcessCleanupDescriptor(&cp->PipeWriteEnds[i]);
+    }
+}
+
+/*--------------------------------------------------------------------------*/
+/* Close the given file descriptor if it is open.  Reset its value to -1.  */
+void kwsysProcessCleanupDescriptor(int* pfd)
+{
+  if(pfd && *pfd >= 0)
+    {
+    /* Keep trying to close until it is not interrupted by a
+     * signal.  */
+    while((close(*pfd) < 0) && (errno == EINTR));
+    *pfd = -1;
+    }
+}
+
+/*--------------------------------------------------------------------------*/
+/* Get the time at which either the process or user timeout will
+   expire.  Returns 1 if the user timeout is first, and 0 otherwise.  */
+int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout,
+                               kwsysProcessTime* timeoutTime)
+{
+  /* The first time this is called, we need to calculate the time at
+     which the child will timeout.  */
+  if(cp->Timeout && cp->TimeoutTime.tv_sec < 0)
+    {
+    kwsysProcessTime length = kwsysProcessTimeFromDouble(cp->Timeout);
+    cp->TimeoutTime = kwsysProcessTimeAdd(cp->StartTime, length);
+    }
+  
+  /* Start with process timeout.  */
+  *timeoutTime = cp->TimeoutTime;
+  
+  /* Check if the user timeout is earlier.  */
+  if(userTimeout)
+    {
+    kwsysProcessTime currentTime = kwsysProcessTimeGetCurrent();
+    kwsysProcessTime userTimeoutLength = kwsysProcessTimeFromDouble(*userTimeout);
+    kwsysProcessTime userTimeoutTime = kwsysProcessTimeAdd(currentTime,
+                                                     userTimeoutLength);
+    if(kwsysProcessTimeLess(userTimeoutTime, *timeoutTime))
+      {
+      *timeoutTime = userTimeoutTime;
+      return 1;
+      }
+    }
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+/* Get the length of time before the given timeout time arrives.
+   Returns 1 if the time has already arrived, and 0 otherwise.  */
+int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime,
+                               kwsysProcessTime* timeoutLength)
+{
+  if(timeoutTime->tv_sec < 0)
+    {
+    /* No timeout time has been requested.  */
+    return 0;
+    }
+  else
+    {
+    /* Calculate the remaining time.  */
+    kwsysProcessTime currentTime = kwsysProcessTimeGetCurrent();
+    *timeoutLength = kwsysProcessTimeSubtract(*timeoutTime, currentTime);
+    if(timeoutLength->tv_sec < 0)
+      {
+      /* Timeout has already expired.  */
+      return 1;
+      }
+    else
+      {
+      /* There is some time left.  */
+      return 0;
+      }
+    }
+}
+
+/*--------------------------------------------------------------------------*/
+kwsysProcessTime kwsysProcessTimeGetCurrent()
+{
+  kwsysProcessTime current;
+  gettimeofday(&current, 0);
+  return current;
+}
+
+/*--------------------------------------------------------------------------*/
+double kwsysProcessTimeToDouble(kwsysProcessTime t)
+{
+  return (double)t.tv_sec + t.tv_usec*0.000001;  
+}
+
+/*--------------------------------------------------------------------------*/
+kwsysProcessTime kwsysProcessTimeFromDouble(double d)
+{
+  kwsysProcessTime t;
+  t.tv_sec = (long)d;
+  t.tv_usec = (long)((d-t.tv_sec)*1000000);
+  return t;
+}
+
+/*--------------------------------------------------------------------------*/
+int kwsysProcessTimeLess(kwsysProcessTime in1, kwsysProcessTime in2)
+{
+  return ((in1.tv_sec < in2.tv_sec) ||
+          ((in1.tv_sec == in2.tv_sec) && (in1.tv_usec < in2.tv_usec)));
+}
+
+/*--------------------------------------------------------------------------*/
+kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1, kwsysProcessTime in2)
+{
+  kwsysProcessTime out;
+  out.tv_sec = in1.tv_sec + in2.tv_sec;
+  out.tv_usec = in1.tv_usec + in2.tv_usec;
+  if(out.tv_usec > 1000000)
+    {
+    out.tv_usec -= 1000000;
+    out.tv_sec += 1;
+    }
+  return out;
+}
+
+/*--------------------------------------------------------------------------*/
+kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProcessTime in2)
+{
+  kwsysProcessTime out;
+  out.tv_sec = in1.tv_sec - in2.tv_sec;
+  out.tv_usec = in1.tv_usec - in2.tv_usec;
+  if(out.tv_usec < 0)
+    {
+    out.tv_usec += 1000000;
+    out.tv_sec -= 1;
+    }
+  return out;
+}
+
+/*--------------------------------------------------------------------------*/
+/* When the child process encounters an error before its program is
+   invoked, this is called to report the error to the parent and
+   exit.  */
+void kwsysProcessChildErrorExit(kwsysProcess* cp)
+{
+  /* Construct the error message.  */
+  char buffer[KWSYSPE_PIPE_BUFFER_SIZE];
+  snprintf(buffer, KWSYSPE_PIPE_BUFFER_SIZE, "%s", strerror(errno));
+  
+  /* Report the error to the parent through the special pipe.  */
+  write(cp->PipeWriteEnds[KWSYSPE_PIPE_ERROR], buffer, strlen(buffer));
+  
+  /* Terminate without cleanup.  */
+  _exit(1);
+}
+
+/*--------------------------------------------------------------------------*/
+/* Restores all signal handlers to their default values.  */
+void kwsysProcessRestoreDefaultSignalHandlers()
+{
+  struct sigaction act;
+  act.sa_handler = SIG_DFL;
+#ifdef SIGHUP
+  sigaction(SIGHUP, &act, 0);
+#endif
+#ifdef SIGINT
+  sigaction(SIGINT, &act, 0);
+#endif
+#ifdef SIGQUIT
+  sigaction(SIGQUIT, &act, 0);
+#endif
+#ifdef SIGILL
+  sigaction(SIGILL, &act, 0);
+#endif
+#ifdef SIGTRAP
+  sigaction(SIGTRAP, &act, 0);
+#endif
+#ifdef SIGABRT
+  sigaction(SIGABRT, &act, 0);
+#endif
+#ifdef SIGIOT
+  sigaction(SIGIOT, &act, 0);
+#endif
+#ifdef SIGBUS
+  sigaction(SIGBUS, &act, 0);
+#endif
+#ifdef SIGFPE
+  sigaction(SIGFPE, &act, 0);
+#endif
+#ifdef SIGUSR1
+  sigaction(SIGUSR1, &act, 0);
+#endif
+#ifdef SIGSEGV
+  sigaction(SIGSEGV, &act, 0);
+#endif
+#ifdef SIGUSR2
+  sigaction(SIGUSR2, &act, 0);
+#endif
+#ifdef SIGPIPE
+  sigaction(SIGPIPE, &act, 0);
+#endif
+#ifdef SIGALRM
+  sigaction(SIGALRM, &act, 0);
+#endif
+#ifdef SIGTERM
+  sigaction(SIGTERM, &act, 0);
+#endif
+#ifdef SIGSTKFLT
+  sigaction(SIGSTKFLT, &act, 0);
+#endif
+#ifdef SIGCLD
+  sigaction(SIGCLD, &act, 0);
+#endif
+#ifdef SIGCHLD
+  sigaction(SIGCHLD, &act, 0);
+#endif
+#ifdef SIGCONT
+  sigaction(SIGCONT, &act, 0);
+#endif
+#ifdef SIGTSTP
+  sigaction(SIGTSTP, &act, 0);
+#endif
+#ifdef SIGTTIN
+  sigaction(SIGTTIN, &act, 0);
+#endif
+#ifdef SIGTTOU
+  sigaction(SIGTTOU, &act, 0);
+#endif
+#ifdef SIGURG
+  sigaction(SIGURG, &act, 0);
+#endif
+#ifdef SIGXCPU
+  sigaction(SIGXCPU, &act, 0);
+#endif
+#ifdef SIGXFSZ
+  sigaction(SIGXFSZ, &act, 0);
+#endif
+#ifdef SIGVTALRM
+  sigaction(SIGVTALRM, &act, 0);
+#endif
+#ifdef SIGPROF
+  sigaction(SIGPROF, &act, 0);
+#endif
+#ifdef SIGWINCH
+  sigaction(SIGWINCH, &act, 0);
+#endif
+#ifdef SIGPOLL
+  sigaction(SIGPOLL, &act, 0);
+#endif
+#ifdef SIGIO
+  sigaction(SIGIO, &act, 0);
+#endif
+#ifdef SIGPWR
+  sigaction(SIGPWR, &act, 0);
+#endif
+#ifdef SIGSYS
+  sigaction(SIGSYS, &act, 0);
+#endif
+#ifdef SIGUNUSED
+  sigaction(SIGUNUSED, &act, 0);
+#endif
+}
diff --git a/ProcessWin32.c b/ProcessWin32.c
new file mode 100644
index 0000000000000000000000000000000000000000..5f321a93ec76b3eee3929574e6db72825e047a8a
--- /dev/null
+++ b/ProcessWin32.c
@@ -0,0 +1,1234 @@
+/*=========================================================================
+
+Program:   KWSys - Kitware System Library
+Module:    ProcessWin32.c
+Language:  C++
+Date:      $Date$
+Version:   $Revision$
+
+Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
+See http://www.cmake.org/HTML/Copyright.html for details.
+
+This software is distributed WITHOUT ANY WARRANTY; without even 
+the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#define KWSYS_IN_PROCESS_C
+#include <Process.h>
+
+/*
+
+Implementation for Windows
+  
+On windows, a thread is created to wait for data on each pipe.  The
+threads are synchronized with the main thread to simulate the use of
+a UNIX-style select system call.
+  
+On Windows9x platforms, a small WIN32 console application is spawned
+in-between the calling process and the actual child to be executed.
+This is to work-around a problem with connecting pipes from WIN16
+console applications to WIN32 applications.
+  
+For more information, please check Microsoft Knowledge Base Articles
+Q190351 and Q150956.
+
+*/
+
+#include <windows.h> /* Windows API */
+#include <string.h>  /* strlen, strdup */
+#include <stdio.h>   /* sprintf */
+#include <process.h> /* _getpid */
+#include <io.h>      /* _unlink */
+
+/* The number of pipes for the child's output.  The standard stdout
+   and stderr pipes are the first two.  One more pipe is used on Win9x
+   for the forwarding executable to use in reporting problems.  */
+#define CMPE_PIPE_COUNT 3
+#define CMPE_PIPE_STDOUT 0
+#define CMPE_PIPE_STDERR 1
+#define CMPE_PIPE_ERROR 2
+
+/* The maximum amount to read from a pipe at a time.  */
+#define CMPE_PIPE_BUFFER_SIZE 1024
+
+#define kwsysEncodedWriteArrayProcessFwd kwsys(EncodedWriteArrayProcessFwd)
+
+typedef LARGE_INTEGER kwsysProcessTime;
+
+/*--------------------------------------------------------------------------*/
+typedef struct kwsysProcessPipeData_s kwsysProcessPipeData;
+static DWORD WINAPI kwsysProcessPipeThread(LPVOID ptd);
+static void kwsysProcessPipeThreadReadPipe(kwsysProcess* cp, kwsysProcessPipeData* td);
+static void kwsysProcessCleanupHandle(PHANDLE h);
+static void kwsysProcessCleanup(kwsysProcess* cp, int error);
+static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout,
+                                      kwsysProcessTime* timeoutTime);
+static int kwsysProcessGetTimeoutLeft(kwsysProcess* cp, kwsysProcessTime* timeoutTime,
+                                      kwsysProcessTime* timeoutLength);
+static kwsysProcessTime kwsysProcessTimeGetCurrent();
+static DWORD kwsysProcessTimeToDWORD(kwsysProcessTime t);
+static double kwsysProcessTimeToDouble(kwsysProcessTime t);
+static kwsysProcessTime kwsysProcessTimeFromDouble(double d);
+static int kwsysProcessTimeLess(kwsysProcessTime in1, kwsysProcessTime in2);
+static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1, kwsysProcessTime in2);
+static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProcessTime in2);
+extern int kwsysEncodedWriteArrayProcessFwd9x(const char* fname);
+
+/*--------------------------------------------------------------------------*/
+/* A structure containing data for each pipe's thread.  */
+struct kwsysProcessPipeData_s
+{
+  /* ------------- Data managed per instance of kwsysProcess ------------- */
+  
+  /* Handle for the thread for this pipe.  */
+  HANDLE Thread;
+    
+  /* Semaphore indicating a process and pipe are available.  */
+  HANDLE Ready;
+    
+  /* Semaphore indicating when this thread's buffer is empty.  */
+  HANDLE Empty;
+    
+  /* Semaphore indicating a pipe thread has reset for another process.  */
+  HANDLE Reset;
+    
+  /* Index of this pipe.  */
+  int Index;
+
+  /* The kwsysProcess instance owning this pipe.  */
+  kwsysProcess* Process;
+  
+  /* ------------- Data managed per call to Execute ------------- */
+  
+  /* Buffer for data read in this pipe's thread.  */
+  char DataBuffer[CMPE_PIPE_BUFFER_SIZE];
+    
+  /* The length of the data stored in the buffer.  */
+  DWORD DataLength;
+    
+  /* Whether the pipe has been closed.  */
+  int Closed;
+    
+  /* Handle for the read end of this pipe. */
+  HANDLE Read;
+  
+  /* Handle for the write end of this pipe. */
+  HANDLE Write;
+};  
+
+/*--------------------------------------------------------------------------*/
+/* Structure containing data used to implement the child's execution.  */
+struct kwsysProcess_s
+{
+  /* ------------- Data managed per instance of kwsysProcess ------------- */
+  
+  /* The status of the process.  */
+  int State;
+  
+  /* The command line to execute. */
+  char* Command;
+  
+  /* On Win9x platforms, the path to the forwarding executable.  */
+  char* Win9x;
+  
+  /* On Win9x platforms, the kill event for the forwarding executable.  */
+  HANDLE Win9xKillEvent;
+  
+  /* Mutex to protect the shared index used by threads to report data.  */
+  HANDLE SharedIndexMutex;
+  
+  /* Semaphore used by threads to signal data ready.  */
+  HANDLE Full;
+  
+  /* The number of pipes needed to implement the child's execution.
+     This is 3 on Win9x and 2 otherwise.  */
+  int PipeCount;
+  
+  /* Whether we are currently deleting this kwsysProcess instance.  */
+  int Deleting;
+  
+  /* Data specific to each pipe and its thread.  */
+  kwsysProcessPipeData Pipe[CMPE_PIPE_COUNT];  
+  
+  /* ------------- Data managed per call to Execute ------------- */
+  
+  /* The process exit code, if any.  */
+  int ExitCode;
+  
+  /* Index of last pipe to report data, if any.  */
+  int CurrentIndex;
+  
+  /* Index shared by threads to report data.  */  
+  int SharedIndex;
+  
+  /* The timeout length.  */
+  double Timeout;
+  
+  /* Time at which the child started.  */
+  kwsysProcessTime StartTime;
+  
+  /* Time at which the child will timeout.  Negative for no timeout.  */
+  kwsysProcessTime TimeoutTime;
+  
+  /* Flag for whether the process was killed.  */
+  int Killed;
+  
+  /* Flag for whether the timeout expired.  */
+  int TimeoutExpired;
+  
+  /* Flag for whether the process has terminated.  */
+  int Terminated;
+  
+  /* The number of pipes still open during execution and while waiting
+     for pipes to close after process termination.  */
+  int PipesLeft;
+  
+  /* Buffer for error messages (possibly from Win9x child).  */
+  char ErrorMessage[CMPE_PIPE_BUFFER_SIZE+1];
+  int ErrorMessageLength;
+  
+  /* The actual command line that will be used to create the process.  */
+  char* RealCommand;
+
+  /* Windows process information data.  */
+  PROCESS_INFORMATION ProcessInformation;
+};
+
+/*--------------------------------------------------------------------------*/
+kwsysProcess* kwsysProcess_New()
+{
+  int i;
+
+  /* Process control structure.  */
+  kwsysProcess* cp;
+
+  /* Path to Win9x forwarding executable.  */
+  char* win9x = 0;
+
+  /* Windows version number data.  */
+  OSVERSIONINFO osv;
+  
+  /* Allocate a process control structure.  */
+  cp = (kwsysProcess*)malloc(sizeof(kwsysProcess));
+  ZeroMemory(cp, sizeof(*cp));
+  
+  /* Set initial status.  */
+  cp->State = kwsysProcess_Starting;
+  
+  /* Choose a method of running the child based on version of
+     windows.  */
+  ZeroMemory(&osv, sizeof(osv));
+  osv.dwOSVersionInfoSize = sizeof(osv);
+  GetVersionEx(&osv);
+  if(osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
+    {
+    /* This is Win9x.  We need the console forwarding executable to
+       work-around a Windows 9x bug.  */
+    char fwdName[_MAX_FNAME+1] = "";
+    char tempDir[_MAX_PATH+1] = "";
+    
+    /* We will try putting the executable in the system temp
+       directory.  */
+    DWORD length = GetEnvironmentVariable("TEMP", tempDir, _MAX_PATH);
+    
+    /* Construct the executable name from the process id and kwsysProcess
+       instance.  This should be unique.  */
+    sprintf(fwdName, "cmw9xfwd_%u_%p.exe", _getpid(), cp);
+    
+    /* If the environment variable "TEMP" gave us a directory, use it.  */
+    if(length > 0 && length <= _MAX_PATH)
+      {
+      /* Make sure there is no trailing slash.  */
+      size_t tdlen = strlen(tempDir);
+      if(tempDir[tdlen-1] == '/' || tempDir[tdlen-1] == '\\')
+        {
+        tempDir[tdlen-1] = 0;
+        --tdlen;
+        }
+      
+      /* Allocate a buffer to hold the forwarding executable path.  */
+      win9x = (char*)malloc(tdlen + strlen(fwdName) + 2);
+      if(!win9x)
+        {
+        kwsysProcess_Delete(cp);
+        return 0;
+        }
+      
+      /* Construct the full path to the forwarding executable.  */
+      sprintf(win9x, "%s/%s", tempDir, fwdName);
+      }
+    
+    /* If we found a place to put the forwarding executable, try to
+       write it. */
+    if(win9x)
+      {
+      if(!kwsysEncodedWriteArrayProcessFwd9x(win9x))
+        {
+        /* Failed to create forwarding executable.  Give up.  */
+        free(win9x);
+        kwsysProcess_Delete(cp);
+        return 0;
+        }
+      }
+    else
+      {
+      /* Failed to find a place to put forwarding executable.  */
+      kwsysProcess_Delete(cp);
+      return 0;
+      }
+    }
+  
+  /* We need the extra error pipe on Win9x.  */
+  cp->Win9x = win9x;
+  cp->PipeCount = cp->Win9x? 3:2;
+  
+  /* Initially no thread owns the mutex.  Initialize semaphore to 1.  */
+  if(!(cp->SharedIndexMutex = CreateSemaphore(0, 1, 1, 0)))
+    {
+    kwsysProcess_Delete(cp);
+    return 0;
+    }
+  
+  /* Initially no data are available.  Initialize semaphore to 0.  */
+  if(!(cp->Full = CreateSemaphore(0, 0, 1, 0)))
+    {
+    kwsysProcess_Delete(cp);
+    return 0;
+    }
+
+  if(cp->Win9x)
+    {
+    /* Create an event to tell the forwarding executable to kill the
+       child.  */
+    SECURITY_ATTRIBUTES sa;
+    ZeroMemory(&sa, sizeof(sa));
+    sa.nLength = sizeof(sa);
+    sa.bInheritHandle = TRUE;
+    if(!(cp->Win9xKillEvent = CreateEvent(&sa, TRUE, 0, 0)))
+      {
+      kwsysProcess_Delete(cp);
+      return 0;
+      }
+    }
+    
+  /* Create the thread to read each pipe.  */
+  for(i=0; i < cp->PipeCount; ++i)
+    {
+    DWORD dummy=0;
+    
+    /* Assign the thread its index.  */
+    cp->Pipe[i].Index = i;
+    
+    /* Give the thread a pointer back to the kwsysProcess instance.  */
+    cp->Pipe[i].Process = cp;
+    
+    /* The pipe is not yet ready to read.  Initialize semaphore to 0.  */
+    if(!(cp->Pipe[i].Ready = CreateSemaphore(0, 0, 1, 0)))
+      {
+      kwsysProcess_Delete(cp);
+      return 0;
+      }
+    
+    /* The pipe is not yet reset.  Initialize semaphore to 0.  */
+    if(!(cp->Pipe[i].Reset = CreateSemaphore(0, 0, 1, 0)))
+      {
+      kwsysProcess_Delete(cp);
+      return 0;
+      }
+    
+    /* The thread's buffer is initially empty.  Initialize semaphore to 1.  */
+    if(!(cp->Pipe[i].Empty = CreateSemaphore(0, 1, 1, 0)))
+      {
+      kwsysProcess_Delete(cp);
+      return 0;
+      }
+    
+    /* Create the thread.  It will block immediately.  */
+    if(!(cp->Pipe[i].Thread = CreateThread(0, 0, kwsysProcessPipeThread,
+                                           &cp->Pipe[i], 0, &dummy)))
+      {
+      kwsysProcess_Delete(cp);
+      return 0;
+      }
+    }
+  
+  return cp;
+}
+
+/*--------------------------------------------------------------------------*/
+void kwsysProcess_Delete(kwsysProcess* cp)
+{
+  int i;
+
+  /* If the process is executing, wait for it to finish.  */
+  if(cp->State == kwsysProcess_Executing)
+    {
+    kwsysProcess_WaitForExit(cp, 0);
+    }
+  
+  /* We are deleting the kwsysProcess instance.  */
+  cp->Deleting = 1;
+  
+  /* Terminate each of the threads.  */
+  for(i=0; i < cp->PipeCount; ++i)
+    {
+    if(cp->Pipe[i].Thread)
+      {
+      /* Signal the thread we are ready for it.  It will terminate
+         immediately since Deleting is set.  */
+      ReleaseSemaphore(cp->Pipe[i].Ready, 1, 0);
+      
+      /* Wait for the thread to exit.  */
+      WaitForSingleObject(cp->Pipe[i].Thread, INFINITE);
+      
+      /* Close the handle to the thread. */
+      kwsysProcessCleanupHandle(&cp->Pipe[i].Thread);
+      }
+    
+    /* Cleanup the pipe's semaphores.  */
+    kwsysProcessCleanupHandle(&cp->Pipe[i].Ready);
+    kwsysProcessCleanupHandle(&cp->Pipe[i].Empty);
+    }  
+  
+  /* Close the shared semaphores.  */
+  kwsysProcessCleanupHandle(&cp->SharedIndexMutex);
+  kwsysProcessCleanupHandle(&cp->Full);
+  
+  /* Close the Win9x kill event handle.  */
+  if(cp->Win9x)
+    {
+    kwsysProcessCleanupHandle(&cp->Win9xKillEvent);
+    }
+  
+  /* Free memory.  */
+  kwsysProcess_SetCommand(cp, 0);
+  if(cp->Win9x)
+    {
+    _unlink(cp->Win9x);
+    free(cp->Win9x);
+    }
+  free(cp);
+}
+
+/*--------------------------------------------------------------------------*/
+void kwsysProcess_SetCommand(kwsysProcess* cp, char const* const* command)
+{
+  if(cp->Command)
+    {
+    free(cp->Command);
+    cp->Command = 0;
+    }
+  if(command)
+    {
+    /* We need to construct a single string representing the command
+       and its arguments.  We will surround each argument with
+       double-quotes so it can contain spaces.  We need to escape
+       double-quotes and all backslashes before them.  We also need to
+       escape backslashes at the end of an argument because they come
+       before the closing double-quote for the argument.  */
+    char* cmd;
+    char const* const* arg;
+    int length = 0;
+    /* First determine the length of the final string.  */
+    for(arg = command; *arg; ++arg)
+      {
+      /* Keep track of how many backslashes have been encountered in a
+         row in this argument.  */
+      int backslashes = 0;
+      const char* c;
+
+      /* Add the length of the argument, plus 3 for the double quotes
+         and space separating the arguments.  */
+      length += strlen(*arg) + 3;
+      
+      /* Scan the string to find characters that need escaping.  */
+      for(c=*arg; *c; ++c)
+        {
+        if(*c == '\\')
+          {
+          /* Found a backslash.  It may need to be escaped later.  */
+          ++backslashes;
+          }
+        else if(*c == '"')
+          {
+          /* Found a double-quote.  We need to escape it and all
+             immediately preceding backslashes.  */
+          length += backslashes + 1;
+          backslashes = 0;
+          }
+        else
+          {
+          /* Found another character.  This eliminates the possibility
+             that any immediately preceding backslashes will be
+             escaped.  */
+          backslashes = 0;
+          }
+        }
+      
+      /* We need to escape all ending backslashes. */
+      length += backslashes;
+      }
+    
+    /* Allocate enough space for the command.  We do not need an extra
+       byte for the terminating null because we allocated a space for
+       the first argument that we will not use.  */
+    cp->Command = (char*)malloc(length);
+    
+    /* Construct the command line in the allocated buffer.  */
+    cmd = cp->Command;
+    for(arg = command; *arg; ++arg)
+      {
+      /* Keep track of how many backslashes have been encountered in a
+         row in an argument.  */
+      int backslashes = 0;
+      const char* c;
+      
+      /* Add the separating space if this is not the first argument.  */
+      if(arg != command)
+        {
+        *cmd++ = ' ';
+        }
+
+      /* Add the opening double-quote for this argument.  */
+      *cmd++ = '"';
+
+      /* Add the characters of the argument, possibly escaping them.  */
+      for(c=*arg; *c; ++c)
+        {
+        if(*c == '\\')
+          {
+          /* Found a backslash.  It may need to be escaped later.  */
+          ++backslashes;
+          *cmd++ = '\\';
+          }
+        else if(*c == '"')
+          {
+          /* Add enough backslashes to escape any that preceded the
+             double-quote.  */
+          while(backslashes > 0)
+            {
+            --backslashes;
+            *cmd++ = '\\';
+            }
+          
+          /* Add the backslash to escape the double-quote.  */
+          *cmd++ = '\\';
+          
+          /* Add the double-quote itself.  */
+          *cmd++ = '"';
+          }
+        else
+          {
+          /* We encountered a normal character.  This eliminates any
+             escaping needed for preceding backslashes.  Add the
+             character.  */
+          backslashes = 0;
+          *cmd++ = *c;
+          }
+        }
+      
+      /* Add enough backslashes to escape any trailing ones.  */
+      while(backslashes > 0)
+        {
+        --backslashes;
+        *cmd++ = '\\';
+        }
+
+      /* Add the opening double-quote for this argument.  */
+      *cmd++ = '"';
+      }
+    
+    /* Add the terminating null character to the command line.  */
+    *cmd++ = 0;
+    }
+}
+
+/*--------------------------------------------------------------------------*/
+void kwsysProcess_SetTimeout(kwsysProcess* cp, double timeout)
+{
+  cp->Timeout = timeout;
+}
+
+/*--------------------------------------------------------------------------*/
+int kwsysProcess_GetState(kwsysProcess* cp)
+{
+  return cp->State;
+}
+
+/*--------------------------------------------------------------------------*/
+int kwsysProcess_GetExitCode(kwsysProcess* cp)
+{
+  return cp->ExitCode;
+}
+
+/*--------------------------------------------------------------------------*/
+const char* kwsysProcess_GetErrorString(kwsysProcess* cp)
+{
+  return cp->ErrorMessage;
+}
+
+/*--------------------------------------------------------------------------*/
+void kwsysProcess_Execute(kwsysProcess* cp)
+{
+  int i=0;
+
+  /* Windows child startup control data.  */
+  STARTUPINFO si;
+  
+  /* Do not execute a second time.  */
+  if(cp->State == kwsysProcess_Executing)
+    {
+    return;
+    }
+  
+  /* Initialize startup info data.  */
+  ZeroMemory(&si, sizeof(si));
+  si.cb = sizeof(si);
+  
+  /* Reset internal status flags.  */
+  cp->TimeoutExpired = 0;
+  cp->Terminated = 0;
+  cp->Killed = 0;
+  
+  /* Reset error data.  */
+  cp->ErrorMessage[0] = 0;
+  cp->ErrorMessageLength = 0;
+  
+  /* Reset the Win9x kill event.  */
+  if(cp->Win9x)
+    {
+    if(!ResetEvent(cp->Win9xKillEvent))
+      {
+      kwsysProcessCleanup(cp, 1);
+      return;
+      }
+    }
+  
+  /* Create a pipe for each child output.  */
+  for(i=0; i < cp->PipeCount; ++i)
+    {
+    HANDLE writeEnd;
+    DWORD dummy=0;
+    
+    /* The pipe is not closed.  */
+    cp->Pipe[i].Closed = 0;
+    
+    /* Create the pipe.  Neither end is directly inherited.  */
+    if(!CreatePipe(&cp->Pipe[i].Read, &writeEnd, 0, 0))
+      {
+      kwsysProcessCleanup(cp, 1);
+      return;
+      }
+    
+    /* Create an inherited duplicate of the write end.  This also closes
+       the non-inherited version. */
+    if(!DuplicateHandle(GetCurrentProcess(), writeEnd,
+                        GetCurrentProcess(), &cp->Pipe[i].Write,
+                        0, TRUE, (DUPLICATE_CLOSE_SOURCE |
+                                  DUPLICATE_SAME_ACCESS)))
+      {
+      kwsysProcessCleanup(cp, 1);
+      CloseHandle(writeEnd);
+      return;
+      }
+    }
+  
+  /* Construct the real command line.  */
+  if(cp->Win9x)
+    {
+    /* Windows 9x */
+    
+    /* The forwarding executable is given a handle to the error pipe
+       and a handle to the kill event.  */
+    cp->RealCommand = malloc(strlen(cp->Win9x)+strlen(cp->Command)+100);
+    sprintf(cp->RealCommand, "%s %d %d %s", cp->Win9x,
+            cp->Pipe[CMPE_PIPE_ERROR].Write,
+            cp->Win9xKillEvent, cp->Command);
+    }
+  else
+    {
+    /* Not Windows 9x */    
+    cp->RealCommand = strdup(cp->Command);
+    }
+
+  /* Connect the child's output pipes to the threads.  */
+  si.dwFlags = STARTF_USESTDHANDLES;
+  si.hStdOutput = cp->Pipe[CMPE_PIPE_STDOUT].Write;
+  si.hStdError = cp->Pipe[CMPE_PIPE_STDERR].Write;
+  
+  /* Hide the forwarding executable console on Windows 9x.  */
+  si.dwFlags |= STARTF_USESHOWWINDOW;  
+  if(cp->Win9x)
+    {
+    si.wShowWindow = SW_HIDE;
+    }
+  else
+    {
+    si.wShowWindow = SW_SHOWDEFAULT;
+    }
+  
+  /* The timeout period starts now.  */
+  cp->StartTime = kwsysProcessTimeGetCurrent();
+  cp->TimeoutTime = kwsysProcessTimeFromDouble(-1);
+  
+  /* CREATE THE CHILD PROCESS */
+  if(!CreateProcess(0, cp->RealCommand, 0, 0, TRUE, CREATE_NEW_CONSOLE, 0,
+                    0, &si, &cp->ProcessInformation))
+    {
+    kwsysProcessCleanup(cp, 1);
+    return;
+    }
+  
+  /* ---- It is no longer safe to call kwsysProcessCleanup. ----- */
+  /* Tell the pipe threads that a process has started.  */
+  for(i=0; i < cp->PipeCount; ++i)
+    {
+    ReleaseSemaphore(cp->Pipe[i].Ready, 1, 0);
+    }
+  
+  /* We don't care about the child's main thread.  */
+  kwsysProcessCleanupHandle(&cp->ProcessInformation.hThread);
+  
+  /* No pipe has reported data.  */
+  cp->CurrentIndex = CMPE_PIPE_COUNT;
+  cp->PipesLeft = cp->PipeCount;
+  
+  /* The process has now started.  */
+  cp->State = kwsysProcess_Executing;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int kwsysProcess_WaitForData(kwsysProcess* cp, int pipes, char** data, int* length,
+                             double* userTimeout)
+{
+  kwsysProcessTime userStartTime;
+  kwsysProcessTime timeoutLength;
+  kwsysProcessTime timeoutTime;
+  DWORD timeout;
+  int user;
+  int done = 0;
+  int expired = 0;
+  int pipeId = 0;
+  DWORD w;
+  HANDLE events[2];
+  
+  /* Make sure we are executing a process.  */
+  if(cp->State != kwsysProcess_Executing || cp->Killed || cp->TimeoutExpired)
+    {
+    return 0;
+    }
+  
+  /* We will wait for data until the process termiantes or data are
+     available. */
+  events[0] = cp->Full;
+  events[1] = cp->ProcessInformation.hProcess;
+  
+  /* Record the time at which user timeout period starts.  */
+  if(userTimeout)
+    {
+    userStartTime = kwsysProcessTimeGetCurrent();
+    }
+  
+  /* Calculate the time at which a timeout will expire, and whether it
+     is the user or process timeout.  */
+  user = kwsysProcessGetTimeoutTime(cp, userTimeout, &timeoutTime);
+  
+  /* Loop until we have a reason to return.  */
+  while(!done && cp->PipesLeft > 0)
+    {
+    /* If we previously got data from a thread, let it know we are
+       done with the data.  */
+    if(cp->CurrentIndex < CMPE_PIPE_COUNT)
+      {
+      ReleaseSemaphore(cp->Pipe[cp->CurrentIndex].Empty, 1, 0);
+      cp->CurrentIndex = CMPE_PIPE_COUNT;
+      }
+    
+    /* Setup a timeout if required.  */
+    if(kwsysProcessGetTimeoutLeft(cp, &timeoutTime, &timeoutLength))
+      {
+      /* Timeout has already expired.  */
+      expired = 1;
+      done = 1;
+      break;
+      }
+    if(timeoutTime.QuadPart < 0)
+      {
+      timeout = INFINITE;
+      }
+    else
+      {
+      timeout = kwsysProcessTimeToDWORD(timeoutLength);
+      }
+    
+    /* Wait for a pipe's thread to signal or the application to
+       terminate.  */
+    w = WaitForMultipleObjects(cp->Terminated?1:2, events, 0, timeout);
+    if(w == WAIT_TIMEOUT)
+      {
+      /* Timeout has expired.  */
+      expired = 1;
+      done = 1;
+      }
+    else if(w == WAIT_OBJECT_0)
+      {
+      /* Save the index of the reporting thread and release the mutex.
+         The thread will block until we signal its Empty mutex.  */
+      cp->CurrentIndex = cp->SharedIndex;
+      ReleaseSemaphore(cp->SharedIndexMutex, 1, 0);
+      
+      /* Data are available or a pipe closed.  */
+      if(cp->Pipe[cp->CurrentIndex].Closed)
+        {
+        /* The pipe closed.  */
+        --cp->PipesLeft;
+        }
+      else if(cp->CurrentIndex == CMPE_PIPE_ERROR)
+        {
+        /* This is data on the special error reporting pipe for Win9x.
+           Append it to the error buffer.  */
+        int length = cp->Pipe[cp->CurrentIndex].DataLength;
+        if(length > CMPE_PIPE_BUFFER_SIZE - cp->ErrorMessageLength)
+          {
+          length = CMPE_PIPE_BUFFER_SIZE - cp->ErrorMessageLength;
+          }
+        if(length > 0)
+          {
+          memcpy(cp->ErrorMessage+cp->ErrorMessageLength,
+                 cp->Pipe[cp->CurrentIndex].DataBuffer, length);
+          cp->ErrorMessageLength += length;
+          }
+        else
+          {
+          cp->ErrorMessage[cp->ErrorMessageLength] = 0;
+          }
+        }
+      else if(pipes & (1 << cp->CurrentIndex))
+        {
+        /* Caller wants this data.  Report it.  */
+        *data = cp->Pipe[cp->CurrentIndex].DataBuffer;
+        *length = cp->Pipe[cp->CurrentIndex].DataLength;
+        pipeId = (1 << cp->CurrentIndex);
+        done = 1;
+        }
+      else
+        {
+        /* Caller does not care about this pipe.  Ignore the data.  */
+        }
+      }
+    else
+      {
+      int i;
+
+      /* Process has terminated.  */
+      cp->Terminated = 1;
+      
+      /* Close our copies of the pipe write handles so the pipe
+         threads can detect end-of-data.  */
+      for(i=0; i < cp->PipeCount; ++i)
+        {
+        kwsysProcessCleanupHandle(&cp->Pipe[i].Write);
+        }
+      }
+    }
+  
+  /* Update the user timeout.  */
+  if(userTimeout)
+    {
+    kwsysProcessTime userEndTime = kwsysProcessTimeGetCurrent();
+    kwsysProcessTime difference = kwsysProcessTimeSubtract(userEndTime,
+                                                           userStartTime);
+    double d = kwsysProcessTimeToDouble(difference);
+    *userTimeout -= d;
+    if(*userTimeout < 0)
+      {
+      *userTimeout = 0;
+      }
+    }
+  
+  /* Check what happened.  */
+  if(pipeId)
+    {
+    /* Data are ready on a pipe.  */
+    return pipeId;
+    }
+  else if(expired)
+    {
+    /* A timeout has expired.  */
+    if(user)
+      {
+      /* The user timeout has expired.  It has no time left.  */
+      return kwsysProcess_Timeout;
+      }
+    else
+      {
+      /* The process timeout has expired.  Kill the child now.  */
+      kwsysProcess_Kill(cp);
+      cp->TimeoutExpired = 1;
+      cp->Killed = 0;
+      return 0;
+      }
+    }
+  else
+    {
+    /* The process has terminated and no more data are available.  */
+    return 0;
+    }
+}
+
+/*--------------------------------------------------------------------------*/
+int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout)
+{
+  int i;
+  int pipe = 0;
+  int pipesLeft = cp->PipeCount;
+  
+  /* Buffer for child's return value.  */
+  int childReturnValue = 0;
+  
+  /* Make sure we are executing a process.  */
+  if(cp->State != kwsysProcess_Executing)
+    {
+    return 1;
+    }
+  
+  /* Wait for the process to terminate.  Ignore all data.  */
+  while((pipe = kwsysProcess_WaitForData(cp, 0, 0, 0, userTimeout)) > 0)
+    {
+    if(pipe == kwsysProcess_Timeout)
+      {
+      /* The user timeout has expired.  */
+      return 0;
+      }
+    }
+
+  /* When the last pipe closes in WaitForData, the loop terminates
+     without releaseing the pipe's thread.  Release it now.  */
+  if(cp->CurrentIndex < CMPE_PIPE_COUNT)
+    {
+    ReleaseSemaphore(cp->Pipe[cp->CurrentIndex].Empty, 1, 0);
+    cp->CurrentIndex = CMPE_PIPE_COUNT;
+    }
+
+  /* Wait for all pipe threads to reset.  */
+  for(i=0; i < cp->PipeCount; ++i)
+    {
+    WaitForSingleObject(cp->Pipe[i].Reset, INFINITE);
+    }
+  
+  /* ---- It is now safe again to call kwsysProcessCleanup. ----- */
+  /* Close all the pipes.  */
+  kwsysProcessCleanup(cp, 0);
+  
+  /* We are done reading all data.  Wait for the child to terminate.
+     This will only block if we killed the child and are waiting for
+     it to cleanup.  */
+  WaitForSingleObject(cp->ProcessInformation.hProcess, INFINITE);
+  
+  /* Determine the outcome.  */
+  if(cp->Killed)
+    {
+    /* We killed the child.  */
+    cp->State = kwsysProcess_Killed;
+    }
+  else if(cp->ErrorMessageLength)
+    {
+    /* Failed to run the process.  */
+    cp->State = kwsysProcess_Error;
+    }
+  else if(cp->TimeoutExpired)
+    {
+    /* The timeout expired.  */
+    cp->State = kwsysProcess_Expired;
+    }
+  else if(GetExitCodeProcess(cp->ProcessInformation.hProcess,
+                             &childReturnValue))
+    {
+    /* The child exited.  */
+    cp->State = kwsysProcess_Exited;
+    cp->ExitCode = childReturnValue;
+    }
+  else
+    {
+    /* Error getting the child return code.  */
+    strcpy(cp->ErrorMessage, "Error getting child return code.");
+    cp->State = kwsysProcess_Error;
+    }
+  
+  /* The child process is terminated.  */
+  CloseHandle(cp->ProcessInformation.hProcess);  
+  
+  return 1;
+}
+
+/*--------------------------------------------------------------------------*/
+void kwsysProcess_Kill(kwsysProcess* cp)
+{
+  int i;
+  
+  /* Make sure we are executing a process.  */
+  if(cp->State != kwsysProcess_Executing || cp->TimeoutExpired || cp->Killed ||
+     cp->Terminated)
+    {
+    return;
+    }
+  
+  /* If we are killing a process that just reported data, release
+     the pipe's thread.  */
+  if(cp->CurrentIndex < CMPE_PIPE_COUNT)
+    {
+    ReleaseSemaphore(cp->Pipe[cp->CurrentIndex].Empty, 1, 0);
+    cp->CurrentIndex = CMPE_PIPE_COUNT;
+    }
+  
+  /* Wake up all the pipe threads with dummy data.  */
+  for(i=0; i < cp->PipeCount; ++i)
+    {
+    DWORD dummy;
+    WriteFile(cp->Pipe[i].Write, "", 1, &dummy, 0);
+    }
+  
+  /* Tell pipe threads to reset until we run another process.  */
+  while(cp->PipesLeft > 0)
+    {
+    WaitForSingleObject(cp->Full, INFINITE);
+    cp->CurrentIndex = cp->SharedIndex;
+    ReleaseSemaphore(cp->SharedIndexMutex, 1, 0);
+    cp->Pipe[cp->CurrentIndex].Closed = 1;
+    ReleaseSemaphore(cp->Pipe[cp->CurrentIndex].Empty, 1, 0);
+    --cp->PipesLeft;
+    }
+  
+  /* Kill the child.  */
+  cp->Killed = 1;
+  if(cp->Win9x)
+    {
+    /* Windows 9x.  Tell the forwarding executable to kill the child.  */
+    SetEvent(cp->Win9xKillEvent);
+    }
+  else
+    {
+    /* Not Windows 9x.  Just terminate the child.  */
+    TerminateProcess(cp->ProcessInformation.hProcess, -1);
+    }
+}
+
+/*--------------------------------------------------------------------------*/
+
+/*
+  Function executed for each pipe's thread.  Argument is a pointer to
+  the kwsysProcessPipeData instance for this thread.
+*/
+DWORD WINAPI kwsysProcessPipeThread(LPVOID ptd)
+{
+  kwsysProcessPipeData* td = (kwsysProcessPipeData*)ptd;
+  kwsysProcess* cp = td->Process;
+  
+  /* Wait for a process to be ready.  */
+  while((WaitForSingleObject(td->Ready, INFINITE), !cp->Deleting))
+    {
+    /* Read output from the process for this thread's pipe.  */
+    kwsysProcessPipeThreadReadPipe(cp, td);
+    
+    /* We were signalled to exit with our buffer empty.  Reset the
+       mutex for a new process.  */
+    ReleaseSemaphore(td->Empty, 1, 0);
+    
+    /* Signal the main thread we have reset for a new process.  */
+    ReleaseSemaphore(td->Reset, 1, 0);
+    }
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+/*
+  Function called in each pipe's thread to handle data for one
+  execution of a subprocess.
+*/
+void kwsysProcessPipeThreadReadPipe(kwsysProcess* cp, kwsysProcessPipeData* td)
+{
+  /* Wait for space in the thread's buffer. */
+  while((WaitForSingleObject(td->Empty, INFINITE), !td->Closed))
+    {
+    /* Read data from the pipe.  This may block until data are available.  */
+    if(!ReadFile(td->Read, td->DataBuffer, CMPE_PIPE_BUFFER_SIZE,
+                 &td->DataLength, 0))
+      {
+      if(GetLastError() != ERROR_BROKEN_PIPE)
+        {
+        /* UNEXPECTED failure to read the pipe.  */
+        }
+      
+      /* The pipe closed.  There are no more data to read.  */
+      td->Closed = 1;
+      }
+    
+    /* Wait for our turn to be handled by the main thread.  */
+    WaitForSingleObject(cp->SharedIndexMutex, INFINITE);
+    
+    /* Tell the main thread we have something to report.  */
+    cp->SharedIndex = td->Index;
+    ReleaseSemaphore(cp->Full, 1, 0);
+    }
+}
+
+/*--------------------------------------------------------------------------*/
+
+/* Close the given handle if it is open.  Reset its value to 0.  */
+void kwsysProcessCleanupHandle(PHANDLE h)
+{
+  if(h && *h)
+    {
+    CloseHandle(*h);
+    *h = 0;
+    }
+}
+
+/*--------------------------------------------------------------------------*/
+
+/* Close all handles created by kwsysProcess_Execute.  */
+void kwsysProcessCleanup(kwsysProcess* cp, int error)
+{
+  int i;
+  
+  /* If this is an error case, report the error.  */
+  if(error)
+    {
+    FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+                  0, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                  cp->ErrorMessage, CMPE_PIPE_BUFFER_SIZE, 0); 
+    cp->State = kwsysProcess_Error;
+    }
+  
+  /* Free memory.  */
+  if(cp->RealCommand)
+    {
+    free(cp->RealCommand);
+    cp->RealCommand = 0;
+    }
+
+  /* Close each pipe.  */
+  for(i=0; i < cp->PipeCount; ++i)
+    {
+    kwsysProcessCleanupHandle(&cp->Pipe[i].Write);
+    kwsysProcessCleanupHandle(&cp->Pipe[i].Read);
+    }  
+}
+
+/*--------------------------------------------------------------------------*/
+/* Get the time at which either the process or user timeout will
+   expire.  Returns 1 if the user timeout is first, and 0 otherwise.  */
+int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout,
+                               kwsysProcessTime* timeoutTime)
+{
+  /* The first time this is called, we need to calculate the time at
+     which the child will timeout.  */
+  if(cp->Timeout && cp->TimeoutTime.QuadPart < 0)
+    {
+    kwsysProcessTime length = kwsysProcessTimeFromDouble(cp->Timeout);
+    cp->TimeoutTime = kwsysProcessTimeAdd(cp->StartTime, length);
+    }  
+  
+  /* Start with process timeout.  */
+  *timeoutTime = cp->TimeoutTime;
+  
+  /* Check if the user timeout is earlier.  */
+  if(userTimeout)
+    {
+    kwsysProcessTime currentTime = kwsysProcessTimeGetCurrent();
+    kwsysProcessTime userTimeoutLength = kwsysProcessTimeFromDouble(*userTimeout);
+    kwsysProcessTime userTimeoutTime = kwsysProcessTimeAdd(currentTime,
+                                                           userTimeoutLength);
+    if(kwsysProcessTimeLess(userTimeoutTime, *timeoutTime))
+      {
+      *timeoutTime = userTimeoutTime;
+      return 1;
+      }
+    }
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+/* Get the length of time before the given timeout time arrives.
+   Returns 1 if the time has already arrived, and 0 otherwise.  */
+int kwsysProcessGetTimeoutLeft(kwsysProcess* cp, kwsysProcessTime* timeoutTime,
+                               kwsysProcessTime* timeoutLength)
+{
+  if(timeoutTime->QuadPart < 0)
+    {
+    /* No timeout time has been requested.  */
+    return 0;
+    }
+  else
+    {
+    /* Calculate the remaining time.  */
+    kwsysProcessTime currentTime = kwsysProcessTimeGetCurrent();
+    *timeoutLength = kwsysProcessTimeSubtract(*timeoutTime, currentTime);
+    if(timeoutLength->QuadPart < 0)
+      {
+      /* Timeout has already expired.  */
+      return 1;
+      }
+    else
+      {
+      /* There is some time left.  */
+      return 0;
+      }
+    }
+}
+
+/*--------------------------------------------------------------------------*/
+kwsysProcessTime kwsysProcessTimeGetCurrent()
+{
+  kwsysProcessTime current;
+  FILETIME ft;
+  GetSystemTimeAsFileTime(&ft);
+  current.LowPart = ft.dwLowDateTime;
+  current.HighPart = ft.dwHighDateTime;
+  return current;
+}
+
+/*--------------------------------------------------------------------------*/
+DWORD kwsysProcessTimeToDWORD(kwsysProcessTime t)
+{
+  return (DWORD)(t.QuadPart * 0.0001);
+}
+
+/*--------------------------------------------------------------------------*/
+double kwsysProcessTimeToDouble(kwsysProcessTime t)
+{
+  return t.QuadPart * 0.0000001;
+}
+
+/*--------------------------------------------------------------------------*/
+kwsysProcessTime kwsysProcessTimeFromDouble(double d)
+{
+  kwsysProcessTime t;
+  t.QuadPart = (LONGLONG)(d*10000000);
+  return t;
+}
+
+/*--------------------------------------------------------------------------*/
+int kwsysProcessTimeLess(kwsysProcessTime in1, kwsysProcessTime in2)
+{
+  return in1.QuadPart < in2.QuadPart;
+}
+
+/*--------------------------------------------------------------------------*/
+kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1, kwsysProcessTime in2)
+{
+  kwsysProcessTime out;
+  out.QuadPart = in1.QuadPart + in2.QuadPart;
+  return out;
+}
+
+/*--------------------------------------------------------------------------*/
+kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProcessTime in2)
+{
+  kwsysProcessTime out;
+  out.QuadPart = in1.QuadPart - in2.QuadPart;
+  return out;
+}