diff --git a/ProcessUNIX.c b/ProcessUNIX.c
index 1de81c7beebd426973f4cb0aee0434678b8786a1..8bcb671219d1444633c56d3db56ae55ea5f267db 100644
--- a/ProcessUNIX.c
+++ b/ProcessUNIX.c
@@ -165,7 +165,8 @@ static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1,
                                             kwsysProcessTime in2);
 static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1,
                                                  kwsysProcessTime in2);
-static void kwsysProcessSetExitException(kwsysProcess* cp, int sig);
+static void kwsysProcessSetExitExceptionByIndex(kwsysProcess* cp, int sig,
+                                                int idx);
 static void kwsysProcessChildErrorExit(int errorPipe);
 static void kwsysProcessRestoreDefaultSignalHandlers(void);
 static pid_t kwsysProcessFork(kwsysProcess* cp,
@@ -183,6 +184,26 @@ static void kwsysProcessesSignalHandler(int signum, siginfo_t* info,
 static void kwsysProcessesSignalHandler(int signum);
 #endif
 
+/* A structure containing results data for each process.  */
+typedef struct kwsysProcessResults_s kwsysProcessResults;
+struct kwsysProcessResults_s
+{
+  /* The status of the child process. */
+  int State;
+
+  /* The exceptional behavior that terminated the process, if any.  */
+  int ExitException;
+
+  /* The process exit code.  */
+  int ExitCode;
+
+  /* The process return code, if any.  */
+  int ExitValue;
+
+  /* Description for the ExitException.  */
+  char ExitExceptionString[KWSYSPE_PIPE_BUFFER_SIZE + 1];
+};
+
 /* Structure containing data used to implement the child's execution.  */
 struct kwsysProcess_s
 {
@@ -253,28 +274,18 @@ struct kwsysProcess_s
   /* The number of children still executing.  */
   int CommandsLeft;
 
-  /* The current status of the child process.  Must be atomic because
+  /* The status of the process structure.  Must be atomic because
      the signal handler checks this to avoid a race.  */
   volatile sig_atomic_t State;
 
-  /* The exceptional behavior that terminated the child process, if
-   * any.  */
-  int ExitException;
-
-  /* The exit code of the child process.  */
-  int ExitCode;
-
-  /* The exit value of the child process, if any.  */
-  int ExitValue;
-
   /* Whether the process was killed.  */
   volatile sig_atomic_t Killed;
 
   /* Buffer for error message in case of failure.  */
   char ErrorMessage[KWSYSPE_PIPE_BUFFER_SIZE + 1];
 
-  /* Description for the ExitException.  */
-  char ExitExceptionString[KWSYSPE_PIPE_BUFFER_SIZE + 1];
+  /* process results.  */
+  kwsysProcessResults* ProcessResults;
 
   /* The exit codes of each child process in the pipeline.  */
   int* CommandExitCodes;
@@ -350,6 +361,7 @@ void kwsysProcess_Delete(kwsysProcess* cp)
   if (cp->CommandExitCodes) {
     free(cp->CommandExitCodes);
   }
+  free(cp->ProcessResults);
   free(cp);
 }
 
@@ -652,17 +664,23 @@ int kwsysProcess_GetState(kwsysProcess* cp)
 
 int kwsysProcess_GetExitException(kwsysProcess* cp)
 {
-  return cp ? cp->ExitException : kwsysProcess_Exception_Other;
+  return (cp && cp->ProcessResults && (cp->NumberOfCommands > 0))
+    ? cp->ProcessResults[cp->NumberOfCommands - 1].ExitException
+    : kwsysProcess_Exception_Other;
 }
 
 int kwsysProcess_GetExitCode(kwsysProcess* cp)
 {
-  return cp ? cp->ExitCode : 0;
+  return (cp && cp->ProcessResults && (cp->NumberOfCommands > 0))
+    ? cp->ProcessResults[cp->NumberOfCommands - 1].ExitCode
+    : 0;
 }
 
 int kwsysProcess_GetExitValue(kwsysProcess* cp)
 {
-  return cp ? cp->ExitValue : -1;
+  return (cp && cp->ProcessResults && (cp->NumberOfCommands > 0))
+    ? cp->ProcessResults[cp->NumberOfCommands - 1].ExitValue
+    : -1;
 }
 
 const char* kwsysProcess_GetErrorString(kwsysProcess* cp)
@@ -677,10 +695,10 @@ const char* kwsysProcess_GetErrorString(kwsysProcess* cp)
 
 const char* kwsysProcess_GetExceptionString(kwsysProcess* cp)
 {
-  if (!cp) {
+  if (!(cp && cp->ProcessResults && (cp->NumberOfCommands > 0))) {
     return "GetExceptionString called with NULL process management structure";
   } else if (cp->State == kwsysProcess_State_Exception) {
-    return cp->ExitExceptionString;
+    return cp->ProcessResults[cp->NumberOfCommands - 1].ExitExceptionString;
   }
   return "No exception";
 }
@@ -1263,7 +1281,6 @@ static int kwsysProcessWaitForPipe(kwsysProcess* cp, char** data, int* length,
 
 int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout)
 {
-  int status = 0;
   int prPipe = 0;
 
   /* Make sure we are executing a process.  */
@@ -1294,10 +1311,6 @@ int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout)
     cp->State = kwsysProcess_State_Error;
     return 1;
   }
-
-  /* Use the status of the last process in the pipeline.  */
-  status = cp->CommandExitCodes[cp->NumberOfCommands - 1];
-
   /* Determine the outcome.  */
   if (cp->Killed) {
     /* We killed the child.  */
@@ -1305,23 +1318,31 @@ int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout)
   } else if (cp->TimeoutExpired) {
     /* The timeout expired.  */
     cp->State = kwsysProcess_State_Expired;
-  } else if (WIFEXITED(status)) {
-    /* The child exited normally.  */
-    cp->State = kwsysProcess_State_Exited;
-    cp->ExitException = kwsysProcess_Exception_None;
-    cp->ExitCode = status;
-    cp->ExitValue = (int)WEXITSTATUS(status);
-  } else if (WIFSIGNALED(status)) {
-    /* The child received an unhandled signal.  */
-    cp->State = kwsysProcess_State_Exception;
-    cp->ExitCode = status;
-    kwsysProcessSetExitException(cp, (int)WTERMSIG(status));
   } else {
-    /* Error getting the child return code.  */
-    strcpy(cp->ErrorMessage, "Error getting child return code.");
-    cp->State = kwsysProcess_State_Error;
+    /* The children exited.  Report the outcome of the child processes.  */
+    for (prPipe = 0; prPipe < cp->NumberOfCommands; ++prPipe) {
+      cp->ProcessResults[prPipe].ExitCode = cp->CommandExitCodes[prPipe];
+      if (WIFEXITED(cp->ProcessResults[prPipe].ExitCode)) {
+        /* The child exited normally.  */
+        cp->ProcessResults[prPipe].State = kwsysProcess_State_Exited;
+        cp->ProcessResults[prPipe].ExitException = kwsysProcess_Exception_None;
+        cp->ProcessResults[prPipe].ExitValue =
+          (int)WEXITSTATUS(cp->ProcessResults[prPipe].ExitCode);
+      } else if (WIFSIGNALED(cp->ProcessResults[prPipe].ExitCode)) {
+        /* The child received an unhandled signal.  */
+        cp->ProcessResults[prPipe].State = kwsysProcess_State_Exception;
+        kwsysProcessSetExitExceptionByIndex(
+          cp, (int)WTERMSIG(cp->ProcessResults[prPipe].ExitCode), prPipe);
+      } else {
+        /* Error getting the child return code.  */
+        strcpy(cp->ProcessResults[prPipe].ExitExceptionString,
+               "Error getting child return code.");
+        cp->ProcessResults[prPipe].State = kwsysProcess_State_Error;
+      }
+    }
+    /* support legacy state status value */
+    cp->State = cp->ProcessResults[cp->NumberOfCommands - 1].State;
   }
-
   /* Normal cleanup.  */
   kwsysProcessCleanup(cp, 0);
   return 1;
@@ -1445,11 +1466,7 @@ static int kwsysProcessInitialize(kwsysProcess* cp)
 #endif
   cp->State = kwsysProcess_State_Starting;
   cp->Killed = 0;
-  cp->ExitException = kwsysProcess_Exception_None;
-  cp->ExitCode = 1;
-  cp->ExitValue = 1;
   cp->ErrorMessage[0] = 0;
-  strcpy(cp->ExitExceptionString, "No exception");
 
   oldForkPIDs = cp->ForkPIDs;
   cp->ForkPIDs = (volatile pid_t*)malloc(sizeof(volatile pid_t) *
@@ -1475,6 +1492,23 @@ static int kwsysProcessInitialize(kwsysProcess* cp)
   memset(cp->CommandExitCodes, 0,
          sizeof(int) * (size_t)(cp->NumberOfCommands));
 
+  /* Allocate process result information for each process.  */
+  free(cp->ProcessResults);
+  cp->ProcessResults = (kwsysProcessResults*)malloc(
+    sizeof(kwsysProcessResults) * (size_t)(cp->NumberOfCommands));
+  if (!cp->ProcessResults) {
+    return 0;
+  }
+  memset(cp->ProcessResults, 0,
+         sizeof(kwsysProcessResults) * (size_t)(cp->NumberOfCommands));
+  for (i = 0; i < cp->NumberOfCommands; i++) {
+    cp->ProcessResults[i].ExitException = kwsysProcess_Exception_None;
+    cp->ProcessResults[i].State = kwsysProcess_State_Starting;
+    cp->ProcessResults[i].ExitCode = 1;
+    cp->ProcessResults[i].ExitValue = 1;
+    strcpy(cp->ProcessResults[i].ExitExceptionString, "No exception");
+  }
+
   /* Allocate memory to save the real working directory.  */
   if (cp->WorkingDirectory) {
 #if defined(MAXPATHLEN)
@@ -2008,9 +2042,10 @@ static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1,
 }
 
 #define KWSYSPE_CASE(type, str)                                               \
-  cp->ExitException = kwsysProcess_Exception_##type;                          \
-  strcpy(cp->ExitExceptionString, str)
-static void kwsysProcessSetExitException(kwsysProcess* cp, int sig)
+  cp->ProcessResults[idx].ExitException = kwsysProcess_Exception_##type;      \
+  strcpy(cp->ProcessResults[idx].ExitExceptionString, str)
+static void kwsysProcessSetExitExceptionByIndex(kwsysProcess* cp, int sig,
+                                                int idx)
 {
   switch (sig) {
 #ifdef SIGSEGV
@@ -2196,8 +2231,8 @@ static void kwsysProcessSetExitException(kwsysProcess* cp, int sig)
 #endif
 #endif
     default:
-      cp->ExitException = kwsysProcess_Exception_Other;
-      sprintf(cp->ExitExceptionString, "Signal %d", sig);
+      cp->ProcessResults[idx].ExitException = kwsysProcess_Exception_Other;
+      sprintf(cp->ProcessResults[idx].ExitExceptionString, "Signal %d", sig);
       break;
   }
 }
diff --git a/ProcessWin32.c b/ProcessWin32.c
index 06d91ae18f5fbd549cdc343aa8a43f3b1e6c16c9..a9f68b35b71321311a53d7f37462c05101244e09 100644
--- a/ProcessWin32.c
+++ b/ProcessWin32.c
@@ -118,6 +118,8 @@ static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1,
 static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1,
                                                  kwsysProcessTime in2);
 static void kwsysProcessSetExitException(kwsysProcess* cp, int code);
+static void kwsysProcessSetExitExceptionByIndex(kwsysProcess* cp, int code,
+                                                int idx);
 static void kwsysProcessKillTree(int pid);
 static void kwsysProcessDisablePipeThreads(kwsysProcess* cp);
 static int kwsysProcessesInitialize(void);
@@ -180,6 +182,26 @@ struct kwsysProcessPipeData_s
   HANDLE Write;
 };
 
+/* A structure containing results data for each process.  */
+typedef struct kwsysProcessResults_s kwsysProcessResults;
+struct kwsysProcessResults_s
+{
+  /* The status of the process.  */
+  int State;
+
+  /* The exceptional behavior that terminated the process, if any.  */
+  int ExitException;
+
+  /* The process exit code.  */
+  DWORD ExitCode;
+
+  /* The process return code, if any.  */
+  int ExitValue;
+
+  /* Description for the ExitException.  */
+  char ExitExceptionString[KWSYSPE_PIPE_BUFFER_SIZE + 1];
+};
+
 /* Structure containing data used to implement the child's execution.  */
 struct kwsysProcess_s
 {
@@ -245,15 +267,6 @@ struct kwsysProcess_s
 
   /* ------------- Data managed per call to Execute ------------- */
 
-  /* The exceptional behavior that terminated the process, if any.  */
-  int ExitException;
-
-  /* The process exit code.  */
-  DWORD ExitCode;
-
-  /* The process return code, if any.  */
-  int ExitValue;
-
   /* Index of last pipe to report data, if any.  */
   int CurrentIndex;
 
@@ -285,8 +298,8 @@ struct kwsysProcess_s
   /* Buffer for error messages.  */
   char ErrorMessage[KWSYSPE_PIPE_BUFFER_SIZE + 1];
 
-  /* Description for the ExitException.  */
-  char ExitExceptionString[KWSYSPE_PIPE_BUFFER_SIZE + 1];
+  /* process results.  */
+  kwsysProcessResults* ProcessResults;
 
   /* Windows process information data.  */
   PROCESS_INFORMATION* ProcessInformation;
@@ -513,6 +526,7 @@ void kwsysProcess_Delete(kwsysProcess* cp)
   if (cp->CommandExitCodes) {
     free(cp->CommandExitCodes);
   }
+  free(cp->ProcessResults);
   free(cp);
 }
 
@@ -839,17 +853,23 @@ int kwsysProcess_GetState(kwsysProcess* cp)
 
 int kwsysProcess_GetExitException(kwsysProcess* cp)
 {
-  return cp ? cp->ExitException : kwsysProcess_Exception_Other;
+  return (cp && cp->ProcessResults && (cp->NumberOfCommands > 0))
+    ? cp->ProcessResults[cp->NumberOfCommands - 1].ExitException
+    : kwsysProcess_Exception_Other;
 }
 
 int kwsysProcess_GetExitValue(kwsysProcess* cp)
 {
-  return cp ? cp->ExitValue : -1;
+  return (cp && cp->ProcessResults && (cp->NumberOfCommands > 0))
+    ? cp->ProcessResults[cp->NumberOfCommands - 1].ExitValue
+    : -1;
 }
 
 int kwsysProcess_GetExitCode(kwsysProcess* cp)
 {
-  return cp ? cp->ExitCode : 0;
+  return (cp && cp->ProcessResults && (cp->NumberOfCommands > 0))
+    ? cp->ProcessResults[cp->NumberOfCommands - 1].ExitCode
+    : 0;
 }
 
 const char* kwsysProcess_GetErrorString(kwsysProcess* cp)
@@ -864,10 +884,10 @@ const char* kwsysProcess_GetErrorString(kwsysProcess* cp)
 
 const char* kwsysProcess_GetExceptionString(kwsysProcess* cp)
 {
-  if (!cp) {
+  if (!(cp && cp->ProcessResults && (cp->NumberOfCommands > 0))) {
     return "GetExceptionString called with NULL process management structure";
   } else if (cp->State == kwsysProcess_State_Exception) {
-    return cp->ExitExceptionString;
+    return cp->ProcessResults[cp->NumberOfCommands - 1].ExitExceptionString;
   }
   return "No exception";
 }
@@ -1312,19 +1332,24 @@ int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout)
     /* The timeout expired.  */
     cp->State = kwsysProcess_State_Expired;
   } else {
-    /* The children exited.  Report the outcome of the last process.  */
-    cp->ExitCode = cp->CommandExitCodes[cp->NumberOfCommands - 1];
-    if ((cp->ExitCode & 0xF0000000) == 0xC0000000) {
-      /* Child terminated due to exceptional behavior.  */
-      cp->State = kwsysProcess_State_Exception;
-      cp->ExitValue = 1;
-      kwsysProcessSetExitException(cp, cp->ExitCode);
-    } else {
-      /* Child exited without exception.  */
-      cp->State = kwsysProcess_State_Exited;
-      cp->ExitException = kwsysProcess_Exception_None;
-      cp->ExitValue = cp->ExitCode;
+    /* The children exited.  Report the outcome of the child processes.  */
+    for (i = 0; i < cp->NumberOfCommands; ++i) {
+      cp->ProcessResults[i].ExitCode = cp->CommandExitCodes[i];
+      if ((cp->ProcessResults[i].ExitCode & 0xF0000000) == 0xC0000000) {
+        /* Child terminated due to exceptional behavior.  */
+        cp->ProcessResults[i].State = kwsysProcess_State_Exception;
+        cp->ProcessResults[i].ExitValue = 1;
+        kwsysProcessSetExitExceptionByIndex(cp, cp->ProcessResults[i].ExitCode,
+                                            i);
+      } else {
+        /* Child exited without exception.  */
+        cp->ProcessResults[i].State = kwsysProcess_State_Exited;
+        cp->ProcessResults[i].ExitException = kwsysProcess_Exception_None;
+        cp->ProcessResults[i].ExitValue = cp->ProcessResults[i].ExitCode;
+      }
     }
+    /* support legacy state status value */
+    cp->State = cp->ProcessResults[cp->NumberOfCommands - 1].State;
   }
 
   return 1;
@@ -1507,19 +1532,31 @@ void kwsysProcessPipeThreadWakePipe(kwsysProcess* cp, kwsysProcessPipeData* td)
 /* Initialize a process control structure for kwsysProcess_Execute.  */
 int kwsysProcessInitialize(kwsysProcess* cp)
 {
+  int i;
   /* Reset internal status flags.  */
   cp->TimeoutExpired = 0;
   cp->Terminated = 0;
   cp->Killed = 0;
-  cp->ExitException = kwsysProcess_Exception_None;
-  cp->ExitCode = 1;
-  cp->ExitValue = 1;
 
-  /* Reset error data.  */
-  cp->ErrorMessage[0] = 0;
-  strcpy(cp->ExitExceptionString, "No exception");
+  free(cp->ProcessResults);
+  /* Allocate process result information for each process.  */
+  cp->ProcessResults = (kwsysProcessResults*)malloc(
+    sizeof(kwsysProcessResults) * (cp->NumberOfCommands));
+  if (!cp->ProcessResults) {
+    return 0;
+  }
+  ZeroMemory(cp->ProcessResults,
+             sizeof(kwsysProcessResults) * cp->NumberOfCommands);
+  for (i = 0; i < cp->NumberOfCommands; i++) {
+    cp->ProcessResults[i].ExitException = kwsysProcess_Exception_None;
+    cp->ProcessResults[i].State = kwsysProcess_State_Starting;
+    cp->ProcessResults[i].ExitCode = 1;
+    cp->ProcessResults[i].ExitValue = 1;
+    strcpy(cp->ProcessResults[i].ExitExceptionString, "No exception");
+  }
 
   /* Allocate process information for each process.  */
+  free(cp->ProcessInformation);
   cp->ProcessInformation = (PROCESS_INFORMATION*)malloc(
     sizeof(PROCESS_INFORMATION) * cp->NumberOfCommands);
   if (!cp->ProcessInformation) {
@@ -1559,7 +1596,6 @@ int kwsysProcessInitialize(kwsysProcess* cp)
     }
   }
   {
-    int i;
     for (i = 0; i < 3; ++i) {
       cp->PipeChildStd[i] = INVALID_HANDLE_VALUE;
     }
@@ -1981,9 +2017,10 @@ kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1,
 }
 
 #define KWSYSPE_CASE(type, str)                                               \
-  cp->ExitException = kwsysProcess_Exception_##type;                          \
-  strcpy(cp->ExitExceptionString, str)
-static void kwsysProcessSetExitException(kwsysProcess* cp, int code)
+  cp->ProcessResults[idx].ExitException = kwsysProcess_Exception_##type;      \
+  strcpy(cp->ProcessResults[idx].ExitExceptionString, str)
+static void kwsysProcessSetExitExceptionByIndex(kwsysProcess* cp, int code,
+                                                int idx)
 {
   switch (code) {
     case STATUS_CONTROL_C_EXIT:
@@ -2062,9 +2099,9 @@ static void kwsysProcessSetExitException(kwsysProcess* cp, int code)
 
     case STATUS_NO_MEMORY:
     default:
-      cp->ExitException = kwsysProcess_Exception_Other;
-      _snprintf(cp->ExitExceptionString, KWSYSPE_PIPE_BUFFER_SIZE,
-                "Exit code 0x%x\n", code);
+      cp->ProcessResults[idx].ExitException = kwsysProcess_Exception_Other;
+      _snprintf(cp->ProcessResults[idx].ExitExceptionString,
+                KWSYSPE_PIPE_BUFFER_SIZE, "Exit code 0x%x\n", code);
       break;
   }
 }