diff --git a/Source/kwsys/Process.h.in b/Source/kwsys/Process.h.in
index adca44bd21b5facf7eb6ebd03283ac96d61be7af..6119cd3da3b38352bf0a2de782957576fa6f13e0 100644
--- a/Source/kwsys/Process.h.in
+++ b/Source/kwsys/Process.h.in
@@ -33,6 +33,7 @@
 #define kwsysProcess_AddCommand          kwsys(Process_AddCommand)
 #define kwsysProcess_SetTimeout          kwsys(Process_SetTimeout)
 #define kwsysProcess_SetWorkingDirectory kwsys(Process_SetWorkingDirectory)
+#define kwsysProcess_SetPipeFile         kwsys(Process_SetPipeFile)
 #define kwsysProcess_Option_HideWindow   kwsys(Process_Option_HideWindow)
 #define kwsysProcess_GetOption           kwsys(Process_GetOption)
 #define kwsysProcess_SetOption           kwsys(Process_SetOption)
@@ -61,6 +62,7 @@
 #define kwsysProcess_WaitForData         kwsys(Process_WaitForData)
 #define kwsysProcess_Pipes_e             kwsys(Process_Pipes_e)
 #define kwsysProcess_Pipe_None           kwsys(Process_Pipe_None)
+#define kwsysProcess_Pipe_STDIN          kwsys(Process_Pipe_STDIN)
 #define kwsysProcess_Pipe_STDOUT         kwsys(Process_Pipe_STDOUT)
 #define kwsysProcess_Pipe_STDERR         kwsys(Process_Pipe_STDERR)
 #define kwsysProcess_Pipe_Timeout        kwsys(Process_Pipe_Timeout)
@@ -118,9 +120,17 @@ kwsysEXPORT void kwsysProcess_SetTimeout(kwsysProcess* cp, double timeout);
 /**
  * Set the working directory for the child process.  The working
  * directory can be absolute or relative to the current directory.
+ * Returns 1 for success and 0 for failure.
  */
-kwsysEXPORT void kwsysProcess_SetWorkingDirectory(kwsysProcess* cp,
-                                                  const char* dir);
+kwsysEXPORT int kwsysProcess_SetWorkingDirectory(kwsysProcess* cp,
+                                                 const char* dir);
+
+/**
+ * Set the name of a file to be attached to the given pipe.  Returns 1
+ * for success and 0 for failure.
+ */
+kwsysEXPORT int kwsysProcess_SetPipeFile(kwsysProcess* cp, int pipe,
+                                         const char* file);
 
 /**
  * Get/Set a platform-specific option.  Possible options are:
@@ -243,6 +253,7 @@ kwsysEXPORT int kwsysProcess_WaitForData(kwsysProcess* cp, char** data,
 enum kwsysProcess_Pipes_e
 {
   kwsysProcess_Pipe_None,
+  kwsysProcess_Pipe_STDIN,
   kwsysProcess_Pipe_STDOUT,
   kwsysProcess_Pipe_STDERR,
   kwsysProcess_Pipe_Timeout=255
@@ -292,6 +303,7 @@ kwsysEXPORT void kwsysProcess_Kill(kwsysProcess* cp);
 # undef kwsysProcess_AddCommand
 # undef kwsysProcess_SetTimeout
 # undef kwsysProcess_SetWorkingDirectory
+# undef kwsysProcess_SetPipeFile
 # undef kwsysProcess_Option_HideWindow
 # undef kwsysProcess_GetOption
 # undef kwsysProcess_SetOption
@@ -320,6 +332,7 @@ kwsysEXPORT void kwsysProcess_Kill(kwsysProcess* cp);
 # undef kwsysProcess_WaitForData
 # undef kwsysProcess_Pipes_e
 # undef kwsysProcess_Pipe_None
+# undef kwsysProcess_Pipe_STDIN
 # undef kwsysProcess_Pipe_STDOUT
 # undef kwsysProcess_Pipe_STDERR
 # undef kwsysProcess_Pipe_Timeout
diff --git a/Source/kwsys/ProcessUNIX.c b/Source/kwsys/ProcessUNIX.c
index 6888d598f7c19a0f8503127f66111b01f157eb29..42c9dadab8da08e36db20d04cb92cfc8eb96cc7c 100644
--- a/Source/kwsys/ProcessUNIX.c
+++ b/Source/kwsys/ProcessUNIX.c
@@ -86,6 +86,7 @@ static void kwsysProcessCleanup(kwsysProcess* cp, int error);
 static void kwsysProcessCleanupDescriptor(int* pfd);
 static int kwsysProcessCreate(kwsysProcess* cp, int index,
                               kwsysProcessCreateInformation* si, int* readEnd);
+static int kwsysProcessSetupOutputPipeFile(int* p, const char* name);
 static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout,
                                       kwsysProcessTime* timeoutTime);
 static int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime,
@@ -164,6 +165,15 @@ struct kwsysProcess_s
 
   /* The exit codes of each child process in the pipeline.  */
   int* CommandExitCodes;
+
+  /* Name of files to which stdin and stdout pipes are attached.  */
+  char* PipeFileSTDIN;
+  char* PipeFileSTDOUT;
+  char* PipeFileSTDERR;
+
+  /* The real working directory of this process.  */
+  int RealWorkingDirectoryLength;
+  char* RealWorkingDirectory;
 };
 
 /*--------------------------------------------------------------------------*/
@@ -198,6 +208,9 @@ void kwsysProcess_Delete(kwsysProcess* cp)
   /* Free memory.  */
   kwsysProcess_SetCommand(cp, 0);
   kwsysProcess_SetWorkingDirectory(cp, 0);
+  kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDIN, 0);
+  kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDOUT, 0);
+  kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDERR, 0);
   if(cp->CommandExitCodes)
     {
     free(cp->CommandExitCodes);
@@ -322,19 +335,19 @@ void kwsysProcess_SetTimeout(kwsysProcess* cp, double timeout)
 }
 
 /*--------------------------------------------------------------------------*/
-void kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, const char* dir)
+int kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, const char* dir)
 {
   if(!cp)
     {
-    return;
+    return 0;
     }
   if(cp->WorkingDirectory == dir)
     {
-    return;
+    return 1;
     }
   if(cp->WorkingDirectory && dir && strcmp(cp->WorkingDirectory, dir) == 0)
     {
-    return;
+    return 1;
     }
   if(cp->WorkingDirectory)
     {
@@ -344,8 +357,45 @@ void kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, const char* dir)
   if(dir)
     {
     cp->WorkingDirectory = (char*)malloc(strlen(dir) + 1);
+    if(!cp->WorkingDirectory)
+      {
+      return 0;
+      }
     strcpy(cp->WorkingDirectory, dir);
     }
+  return 1;
+}
+
+/*--------------------------------------------------------------------------*/
+int kwsysProcess_SetPipeFile(kwsysProcess* cp, int pipe, const char* file)
+{
+  char** pfile;
+  if(!cp)
+    {
+    return 0;
+    }
+  switch(pipe)
+    {
+    case kwsysProcess_Pipe_STDIN: pfile = &cp->PipeFileSTDIN; break;
+    case kwsysProcess_Pipe_STDOUT: pfile = &cp->PipeFileSTDOUT; break;
+    case kwsysProcess_Pipe_STDERR: pfile = &cp->PipeFileSTDERR; break;
+    default: return 0;
+    }
+  if(*pfile)
+    {
+    free(*pfile);
+    *pfile = 0;
+    }
+  if(file)
+    {
+    *pfile = malloc(strlen(file)+1);
+    if(!*pfile)
+      {
+      return 0;
+      }
+    strcpy(*pfile, file);
+    }
+  return 1;
 }
 
 /*--------------------------------------------------------------------------*/
@@ -423,6 +473,27 @@ void kwsysProcess_Execute(kwsysProcess* cp)
     return;
     }
 
+  /* Save the real working directory of this process and change to
+     the working directory for the child processes.  This is needed
+     to make pipe file paths evaluate correctly.  */
+  if(cp->WorkingDirectory)
+    {
+    int r;
+    if(!getcwd(cp->RealWorkingDirectory, cp->RealWorkingDirectoryLength))
+      {
+      kwsysProcessCleanup(cp, 1);
+      return;
+      }
+
+    /* Some platforms specify that the chdir call may be
+       interrupted.  Repeat the call until it finishes.  */
+    while(((r = chdir(cp->WorkingDirectory)) < 0) && (errno == EINTR));
+    if(r < 0)
+      {
+      kwsysProcessCleanup(cp, 1);
+      }
+    }
+
   /* We want no special handling of SIGCHLD.  Repeat call until it is
      not interrupted.  */
   memset(&newSigChldAction, 0, sizeof(struct sigaction));
@@ -463,6 +534,20 @@ void kwsysProcess_Execute(kwsysProcess* cp)
       }
     }
 
+  /* Replace the stderr pipe with a file if requested.  In this case
+     the select call will report that stderr is closed immediately.  */
+  if(cp->PipeFileSTDERR)
+    {
+    if(!kwsysProcessSetupOutputPipeFile(&si.StdErr, cp->PipeFileSTDERR))
+      {
+      kwsysProcessCleanup(cp, 1);
+      kwsysProcessCleanupDescriptor(&si.StdErr);
+      kwsysProcessCleanupDescriptor(&si.TermPipe);
+      return;
+      }
+    }
+
+
   /* The timeout period starts now.  */
   cp->StartTime = kwsysProcessTimeGetCurrent();
   cp->TimeoutTime.tv_sec = -1;
@@ -479,11 +564,11 @@ void kwsysProcess_Execute(kwsysProcess* cp)
 
       /* Release resources that may have been allocated for this
          process before an error occurred.  */
-      kwsysProcessCleanupDescriptor(&readEnd);
-      if(i > 0)
+      if(i > 0 || si.StdIn > 0)
         {
         kwsysProcessCleanupDescriptor(&si.StdIn);
         }
+      kwsysProcessCleanupDescriptor(&readEnd);
       kwsysProcessCleanupDescriptor(&si.StdOut);
       kwsysProcessCleanupDescriptor(&si.StdErr);
       kwsysProcessCleanupDescriptor(&si.TermPipe);
@@ -500,6 +585,16 @@ void kwsysProcess_Execute(kwsysProcess* cp)
   kwsysProcessCleanupDescriptor(&si.StdErr);
   kwsysProcessCleanupDescriptor(&si.TermPipe);
 
+  /* Restore the working directory. */
+  if(cp->RealWorkingDirectory)
+    {
+    /* Some platforms specify that the chdir call may be
+       interrupted.  Repeat the call until it finishes.  */
+    while((chdir(cp->RealWorkingDirectory) < 0) && (errno == EINTR));
+    free(cp->RealWorkingDirectory);
+    cp->RealWorkingDirectory = 0;
+    }
+
   /* All the pipes are now open.  */
   cp->PipesLeft = KWSYSPE_PIPE_COUNT;
 
@@ -895,6 +990,22 @@ static int kwsysProcessInitialize(kwsysProcess* cp)
     }
   memset(cp->CommandExitCodes, 0, sizeof(int)*cp->NumberOfCommands);
 
+  /* Allocate memory to save the real working directory.  */
+  {
+#if defined(MAXPATHLEN)
+  cp->RealWorkingDirectoryLength = MAXPATHLEN;
+#elif defined(PATH_MAX)
+  cp->RealWorkingDirectoryLength = PATH_MAX;
+#else
+  cp->RealWorkingDirectoryLength = 4096;
+#endif
+  cp->RealWorkingDirectory = malloc(cp->RealWorkingDirectoryLength);
+  if(!cp->RealWorkingDirectory)
+    {
+    return 0;
+    }
+  }
+
   return 1;
 }
 
@@ -928,6 +1039,12 @@ static void kwsysProcessCleanup(kwsysProcess* cp, int error)
           }
         }
       }
+
+    /* Restore the working directory.  */
+    if(cp->RealWorkingDirectory)
+      {
+      while((chdir(cp->RealWorkingDirectory) < 0) && (errno == EINTR));
+      }
     }
 
   /* Restore the SIGCHLD handler.  */
@@ -940,6 +1057,11 @@ static void kwsysProcessCleanup(kwsysProcess* cp, int error)
     free(cp->ForkPIDs);
     cp->ForkPIDs = 0;
     }
+  if(cp->RealWorkingDirectory)
+    {
+    free(cp->RealWorkingDirectory);
+    cp->RealWorkingDirectory = 0;
+    }
 
   /* Close pipe handles.  */
   for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)
@@ -971,6 +1093,21 @@ static int kwsysProcessCreate(kwsysProcess* cp, int index,
     si->StdIn = *readEnd;
     *readEnd = 0;
     }
+  else if(cp->PipeFileSTDIN)
+    {
+    /* Open a file for the child's stdin to read.  */
+    si->StdIn = open(cp->PipeFileSTDIN, O_RDONLY);
+    if(si->StdIn < 0)
+      {
+      return 0;
+      }
+
+    /* Set close-on-exec flag on the pipe's end.  */
+    if(fcntl(si->StdIn, F_SETFD, FD_CLOEXEC) < 0)
+      {
+      return 0;
+      }
+    }
   else
     {
     si->StdIn = 0;
@@ -995,6 +1132,16 @@ static int kwsysProcessCreate(kwsysProcess* cp, int index,
     }
   }
 
+  /* Replace the stdout pipe with a file if requested.  In this case
+     the select call will report that stdout is closed immediately.  */
+  if(index == cp->NumberOfCommands-1 && cp->PipeFileSTDOUT)
+    {
+    if(!kwsysProcessSetupOutputPipeFile(&si->StdOut, cp->PipeFileSTDOUT))
+      {
+      return 0;
+      }
+    }
+
   /* Create the error reporting pipe.  */
   if(pipe(si->ErrorPipe) < 0)
     {
@@ -1020,7 +1167,7 @@ static int kwsysProcessCreate(kwsysProcess* cp, int index,
     close(si->ErrorPipe[0]);
 
     /* Setup the stdin, stdout, and stderr pipes.  */
-    if(index > 0)
+    if(index > 0 || si->StdIn > 0)
       {
       dup2(si->StdIn, 0);
       }
@@ -1038,20 +1185,6 @@ static int kwsysProcessCreate(kwsysProcess* cp, int index,
     /* Restore all default signal handlers. */
     kwsysProcessRestoreDefaultSignalHandlers();
 
-    /* Change to the working directory specified, if any.  */
-    if(cp->WorkingDirectory)
-      {
-      /* Some platforms specify that the chdir call may be
-         interrupted.  Repeat the call until it finishes.  */
-      int r;
-      while(((r = chdir(cp->WorkingDirectory)) < 0) && (errno == EINTR));
-      if(r < 0)
-        {
-        /* Failure.  Report error to parent and terminate.  */
-        kwsysProcessChildErrorExit(si->ErrorPipe[1]);
-        }
-      }
-
     /* Execute the real process.  If successful, this does not return.  */
     execvp(cp->Commands[index][0], cp->Commands[index]);
 
@@ -1091,7 +1224,7 @@ static int kwsysProcessCreate(kwsysProcess* cp, int index,
   }
 
   /* Successfully created this child process.  */
-  if(index > 0)
+  if(index > 0 || si->StdIn > 0)
     {
     /* The parent process does not need the input pipe read end.  */
     kwsysProcessCleanupDescriptor(&si->StdIn);
@@ -1103,6 +1236,36 @@ static int kwsysProcessCreate(kwsysProcess* cp, int index,
   return 1;
 }
 
+/*--------------------------------------------------------------------------*/
+static int kwsysProcessSetupOutputPipeFile(int* p, const char* name)
+{
+  int fout;
+  if(!name)
+    {
+    return 1;
+    }
+
+  /* Close the existing descriptor.  */
+  kwsysProcessCleanupDescriptor(p);
+
+  /* Open a file for the pipe to write (permissions 644).  */
+  if((fout = open(name, O_WRONLY | O_CREAT | O_TRUNC,
+                  S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0)
+    {
+    return 0;
+    }
+
+  /* Set close-on-exec flag on the pipe's end.  */
+  if(fcntl(fout, F_SETFD, FD_CLOEXEC) < 0)
+    {
+    return 0;
+    }
+
+  /* Assign the replacement descriptor.  */
+  *p = fout;
+  return 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.  */
diff --git a/Source/kwsys/ProcessWin32.c b/Source/kwsys/ProcessWin32.c
index 6563fc92f9e35714b1c79095782347f1301a0484..90f54b60e796806a50ebb79dd1fd4e625e98d6d9 100644
--- a/Source/kwsys/ProcessWin32.c
+++ b/Source/kwsys/ProcessWin32.c
@@ -80,6 +80,7 @@ static int kwsysProcessCreate(kwsysProcess* cp, int index,
                               kwsysProcessCreateInformation* si,
                               PHANDLE readEnd);
 static void kwsysProcessDestroy(kwsysProcess* cp, int event);
+static int kwsysProcessSetupOutputPipeFile(PHANDLE handle, const char* name);
 static void kwsysProcessCleanupHandle(PHANDLE h);
 static void kwsysProcessCleanup(kwsysProcess* cp, int error);
 static void kwsysProcessCleanErrorMessage(kwsysProcess* cp);
@@ -181,6 +182,11 @@ struct kwsysProcess_s
   /* Data specific to each pipe and its thread.  */
   kwsysProcessPipeData Pipe[KWSYSPE_PIPE_COUNT];
 
+  /* Name of files to which stdin and stdout pipes are attached.  */
+  char* PipeFileSTDIN;
+  char* PipeFileSTDOUT;
+  char* PipeFileSTDERR;
+
   /* ------------- Data managed per call to Execute ------------- */
 
   /* The exceptional behavior that terminated the process, if any.  */
@@ -229,6 +235,10 @@ struct kwsysProcess_s
   /* Data and process termination events for which to wait.  */
   PHANDLE ProcessEvents;
   int ProcessEventsLength;
+
+  /* Real working directory of our own process.  */
+  DWORD RealWorkingDirectoryLength;
+  char* RealWorkingDirectory;
 };
 
 /*--------------------------------------------------------------------------*/
@@ -456,6 +466,9 @@ void kwsysProcess_Delete(kwsysProcess* cp)
   /* Free memory.  */
   kwsysProcess_SetCommand(cp, 0);
   kwsysProcess_SetWorkingDirectory(cp, 0);
+  kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDIN, 0);
+  kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDOUT, 0);
+  kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDERR, 0);
   if(cp->CommandExitCodes)
     {
     free(cp->CommandExitCodes);
@@ -715,11 +728,11 @@ void kwsysProcess_SetTimeout(kwsysProcess* cp, double timeout)
 }
 
 /*--------------------------------------------------------------------------*/
-void kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, const char* dir)
+int kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, const char* dir)
 {
   if(!cp)
     {
-    return;
+    return 0;
     }
   if(cp->WorkingDirectory)
     {
@@ -733,13 +746,51 @@ void kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, const char* dir)
     if(length > 0)
       {
       cp->WorkingDirectory = (char*)malloc(length);
+      if(!cp->WorkingDirectory)
+        {
+        return 0;
+        }
       if(!GetFullPathName(dir, length, cp->WorkingDirectory, 0))
         {
         free(cp->WorkingDirectory);
         cp->WorkingDirectory = 0;
+        return 0;
         }
       }
     }
+  return 1;
+}
+
+/*--------------------------------------------------------------------------*/
+int kwsysProcess_SetPipeFile(kwsysProcess* cp, int pipe, const char* file)
+{
+  char** pfile;
+  if(!cp)
+    {
+    return 0;
+    }
+  switch(pipe)
+    {
+    case kwsysProcess_Pipe_STDIN: pfile = &cp->PipeFileSTDIN; break;
+    case kwsysProcess_Pipe_STDOUT: pfile = &cp->PipeFileSTDOUT; break;
+    case kwsysProcess_Pipe_STDERR: pfile = &cp->PipeFileSTDERR; break;
+    default: return 0;
+    }
+  if(*pfile)
+    {
+    free(*pfile);
+    *pfile = 0;
+    }
+  if(file)
+    {
+    *pfile = malloc(strlen(file)+1);
+    if(!*pfile)
+      {
+      return 0;
+      }
+    strcpy(*pfile, file);
+    }
+  return 1;
 }
 
 /*--------------------------------------------------------------------------*/
@@ -832,6 +883,20 @@ void kwsysProcess_Execute(kwsysProcess* cp)
     return;
     }
 
+  /* Save the real working directory of this process and change to
+     the working directory for the child processes.  This is needed
+     to make pipe file paths evaluate correctly.  */
+  if(cp->WorkingDirectory)
+    {
+    if(!GetCurrentDirectory(cp->RealWorkingDirectoryLength,
+                            cp->RealWorkingDirectory))
+      {
+      kwsysProcessCleanup(cp, 1);
+      return;
+      }
+    SetCurrentDirectory(cp->WorkingDirectory);
+    }
+
   /* Reset the Win9x resume and kill events.  */
   if(cp->Win9x)
     {
@@ -880,6 +945,19 @@ void kwsysProcess_Execute(kwsysProcess* cp)
     return;
     }
 
+  /* Replace the stderr pipe with a file if requested.  In this case
+     the pipe thread will still run but never report data.  */
+  if(cp->PipeFileSTDERR)
+    {
+    if(!kwsysProcessSetupOutputPipeFile(&si.StartupInfo.hStdError,
+                                        cp->PipeFileSTDERR))
+      {
+      kwsysProcessCleanup(cp, 1);
+      kwsysProcessCleanupHandle(&si.StartupInfo.hStdError);
+      return;
+      }
+    }
+
   /* Create the pipeline of processes.  */
   {
   HANDLE readEnd = 0;
@@ -916,6 +994,14 @@ void kwsysProcess_Execute(kwsysProcess* cp)
      processes in the pipeline.  */
   kwsysProcessCleanupHandle(&si.StartupInfo.hStdError);
 
+  /* Restore the working directory.  */
+  if(cp->RealWorkingDirectory)
+    {
+    SetCurrentDirectory(cp->RealWorkingDirectory);
+    free(cp->RealWorkingDirectory);
+    cp->RealWorkingDirectory = 0;
+    }
+
   /* The timeout period starts now.  */
   cp->StartTime = kwsysProcessTimeGetCurrent();
   cp->TimeoutTime = kwsysProcessTimeFromDouble(-1);
@@ -1372,6 +1458,20 @@ int kwsysProcessInitialize(kwsysProcess* cp)
   cp->ProcessEvents[0] = cp->Full;
   cp->ProcessEventsLength = cp->NumberOfCommands+1;
 
+  /* Allocate space to save the real working directory of this process.  */
+  if(cp->WorkingDirectory)
+    {
+    cp->RealWorkingDirectoryLength = GetCurrentDirectory(0, 0);
+    if(cp->RealWorkingDirectoryLength > 0)
+      {
+      cp->RealWorkingDirectory = malloc(cp->RealWorkingDirectoryLength);
+      if(!cp->RealWorkingDirectory)
+        {
+        return 0;
+        }
+      }
+    }
+
   return 1;
 }
 
@@ -1398,6 +1498,26 @@ int kwsysProcessCreate(kwsysProcess* cp, int index,
     /* This function is done with this handle.  */
     *readEnd = 0;
     }
+  else if(cp->PipeFileSTDIN)
+    {
+    /* Create a handle to read a file for stdin.  */
+    HANDLE fin = CreateFile(cp->PipeFileSTDIN, GENERIC_READ,
+                            FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
+    if(fin == INVALID_HANDLE_VALUE)
+      {
+      return 0;
+      }
+    /* Create an inherited duplicate of the handle.  This also closes
+       the non-inherited version.  */
+    if(!DuplicateHandle(GetCurrentProcess(), fin,
+                        GetCurrentProcess(), &fin,
+                        0, TRUE, (DUPLICATE_CLOSE_SOURCE |
+                                  DUPLICATE_SAME_ACCESS)))
+      {
+      return 0;
+      }
+    si->StartupInfo.hStdInput = fin;
+    }
   else
     {
     si->StartupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
@@ -1424,13 +1544,25 @@ int kwsysProcessCreate(kwsysProcess* cp, int index,
     maybeClose = 0;
     }
   if(!DuplicateHandle(GetCurrentProcess(), writeEnd,
-                      GetCurrentProcess(), &si->StartupInfo.hStdOutput,
+                      GetCurrentProcess(), &writeEnd,
                       0, TRUE, (maybeClose | DUPLICATE_SAME_ACCESS)))
     {
     return 0;
     }
+  si->StartupInfo.hStdOutput = writeEnd;
   }
 
+  /* Replace the stdout pipe with a file if requested.  In this case
+     the pipe thread will still run but never report data.  */
+  if(index == cp->NumberOfCommands-1 && cp->PipeFileSTDOUT)
+    {
+    if(!kwsysProcessSetupOutputPipeFile(&si->StartupInfo.hStdOutput,
+                                        cp->PipeFileSTDOUT))
+      {
+      return 0;
+      }
+    }
+
   /* Create the child process.  */
   {
   BOOL r;
@@ -1473,9 +1605,8 @@ int kwsysProcessCreate(kwsysProcess* cp, int index,
   /* Create the child in a suspended state so we can wait until all
      children have been created before running any one.  */
   r = CreateProcess(0, realCommand, 0, 0, TRUE,
-                    cp->Win9x? 0 : CREATE_SUSPENDED, 0,
-                    cp->WorkingDirectory, &si->StartupInfo,
-                    &cp->ProcessInformation[index]);
+                    cp->Win9x? 0 : CREATE_SUSPENDED, 0, 0,
+                    &si->StartupInfo, &cp->ProcessInformation[index]);
 
   if(cp->Win9x)
     {
@@ -1581,6 +1712,41 @@ void kwsysProcessDestroy(kwsysProcess* cp, int event)
     }
 }
 
+/*--------------------------------------------------------------------------*/
+int kwsysProcessSetupOutputPipeFile(PHANDLE phandle, const char* name)
+{
+  HANDLE fout;
+  if(!name)
+    {
+    return 1;
+    }
+
+  /* Close the existing inherited handle.  */
+  kwsysProcessCleanupHandle(phandle);
+    
+  /* Create a handle to write a file for the pipe.  */
+  fout = CreateFile(name, GENERIC_WRITE, FILE_SHARE_READ, 0,
+                    CREATE_ALWAYS, 0, 0);
+  if(fout == INVALID_HANDLE_VALUE)
+    {
+    return 0;
+    }
+
+  /* Create an inherited duplicate of the handle.  This also closes
+     the non-inherited version.  */
+  if(!DuplicateHandle(GetCurrentProcess(), fout,
+                      GetCurrentProcess(), &fout,
+                      0, TRUE, (DUPLICATE_CLOSE_SOURCE |
+                                DUPLICATE_SAME_ACCESS)))
+    {
+    return 0;
+    }
+
+  /* Assign the replacement handle.  */
+  *phandle = fout;
+  return 1;
+}
+
 /*--------------------------------------------------------------------------*/
 
 /* Close the given handle if it is open.  Reset its value to 0.  */
@@ -1652,6 +1818,12 @@ void kwsysProcessCleanup(kwsysProcess* cp, int error)
         kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hProcess);
         }
       }
+
+    /* Restore the working directory.  */
+    if(cp->RealWorkingDirectory)
+      {
+      SetCurrentDirectory(cp->RealWorkingDirectory);
+      }
     }
 
   /* Free memory.  */
@@ -1665,6 +1837,11 @@ void kwsysProcessCleanup(kwsysProcess* cp, int error)
     free(cp->ProcessEvents);
     cp->ProcessEvents = 0;
     }
+  if(cp->RealWorkingDirectory)
+    {
+    free(cp->RealWorkingDirectory);
+    cp->RealWorkingDirectory = 0;
+    }
 
   /* Close each pipe.  */
   for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)