diff --git a/Process.h.in b/Process.h.in
index b8349a66a148c0a6172560ec659f0c74450420d1..237001c604d2aaa31a2942ae7756b47d7e3a273c 100644
--- a/Process.h.in
+++ b/Process.h.in
@@ -42,7 +42,6 @@
 #define kwsysProcess_State_Expired kwsys_ns(Process_State_Expired)
 #define kwsysProcess_State_Killed kwsys_ns(Process_State_Killed)
 #define kwsysProcess_State_Disowned kwsys_ns(Process_State_Disowned)
-#define kwsysProcess_GetState kwsys_ns(Process_GetState)
 #define kwsysProcess_State_e kwsys_ns(Process_State_e)
 #define kwsysProcess_Exception_None kwsys_ns(Process_Exception_None)
 #define kwsysProcess_Exception_Fault kwsys_ns(Process_Exception_Fault)
@@ -50,12 +49,21 @@
 #define kwsysProcess_Exception_Interrupt kwsys_ns(Process_Exception_Interrupt)
 #define kwsysProcess_Exception_Numerical kwsys_ns(Process_Exception_Numerical)
 #define kwsysProcess_Exception_Other kwsys_ns(Process_Exception_Other)
-#define kwsysProcess_GetExitException kwsys_ns(Process_GetExitException)
 #define kwsysProcess_Exception_e kwsys_ns(Process_Exception_e)
+#define kwsysProcess_GetState kwsys_ns(Process_GetState)
+#define kwsysProcess_GetExitException kwsys_ns(Process_GetExitException)
 #define kwsysProcess_GetExitCode kwsys_ns(Process_GetExitCode)
 #define kwsysProcess_GetExitValue kwsys_ns(Process_GetExitValue)
 #define kwsysProcess_GetErrorString kwsys_ns(Process_GetErrorString)
 #define kwsysProcess_GetExceptionString kwsys_ns(Process_GetExceptionString)
+#define kwsysProcess_GetStateByIndex kwsys_ns(Process_GetStateByIndex)
+#define kwsysProcess_GetExitExceptionByIndex                                  \
+  kwsys_ns(Process_GetExitExceptionByIndex)
+#define kwsysProcess_GetExitCodeByIndex kwsys_ns(Process_GetExitCodeByIndex)
+#define kwsysProcess_GetExitValueByIndex kwsys_ns(Process_GetExitValueByIndex)
+#define kwsysProcess_GetExceptionStringByIndex                                \
+  kwsys_ns(Process_GetExceptionStringByIndex)
+#define kwsysProcess_GetExitCodeByIndex kwsys_ns(Process_GetExitCodeByIndex)
 #define kwsysProcess_Execute kwsys_ns(Process_Execute)
 #define kwsysProcess_Disown kwsys_ns(Process_Disown)
 #define kwsysProcess_WaitForData kwsys_ns(Process_WaitForData)
@@ -297,6 +305,67 @@ kwsysEXPORT const char* kwsysProcess_GetErrorString(kwsysProcess* cp);
  */
 kwsysEXPORT const char* kwsysProcess_GetExceptionString(kwsysProcess* cp);
 
+/**
+* Get the current state of the Process instance.  Possible states are:
+*
+*  kwsysProcess_StateByIndex_Starting  = Execute has not yet been called.
+*  kwsysProcess_StateByIndex_Exception = Child process exited abnormally.
+*  kwsysProcess_StateByIndex_Exited    = Child process exited normally.
+*  kwsysProcess_StateByIndex_Error     = Error getting the child return code.
+*/
+kwsysEXPORT int kwsysProcess_GetStateByIndex(kwsysProcess* cp, int idx);
+enum kwsysProcess_StateByIndex_e
+{
+  kwsysProcess_StateByIndex_Starting = kwsysProcess_State_Starting,
+  kwsysProcess_StateByIndex_Exception = kwsysProcess_State_Exception,
+  kwsysProcess_StateByIndex_Exited = kwsysProcess_State_Exited,
+  kwsysProcess_StateByIndex_Error = kwsysProcess_State_Error
+};
+
+/**
+* When GetState returns "Exception", this method returns a
+* platform-independent description of the exceptional behavior that
+* caused the child to terminate abnormally.  Possible exceptions are:
+*
+*  kwsysProcess_Exception_None      = No exceptional behavior occurred.
+*  kwsysProcess_Exception_Fault     = Child crashed with a memory fault.
+*  kwsysProcess_Exception_Illegal   = Child crashed with an illegal
+*                                     instruction.
+*  kwsysProcess_Exception_Interrupt = Child was interrupted by user
+*                                     (Cntl-C/Break).
+*  kwsysProcess_Exception_Numerical = Child crashed with a numerical
+*                                     exception.
+*  kwsysProcess_Exception_Other     = Child terminated for another reason.
+*/
+kwsysEXPORT int kwsysProcess_GetExitExceptionByIndex(kwsysProcess* cp,
+                                                     int idx);
+
+/**
+* When GetState returns "Exited" or "Exception", this method returns
+* the platform-specific raw exit code of the process.  UNIX platforms
+* should use WIFEXITED/WEXITSTATUS and WIFSIGNALED/WTERMSIG to access
+* this value.  Windows users should compare the value to the various
+* EXCEPTION_* values.
+*
+* If GetState returns "Exited", use GetExitValue to get the
+* platform-independent child return value.
+*/
+kwsysEXPORT int kwsysProcess_GetExitCodeByIndex(kwsysProcess* cp, int idx);
+
+/**
+* When GetState returns "Exited", this method returns the child's
+* platform-independent exit code (such as the value returned by the
+* child's main).
+*/
+kwsysEXPORT int kwsysProcess_GetExitValueByIndex(kwsysProcess* cp, int idx);
+
+/**
+* When GetState returns "Exception", this method returns a string
+* describing the problem.  Otherwise, it returns NULL.
+*/
+kwsysEXPORT const char* kwsysProcess_GetExceptionStringByIndex(
+  kwsysProcess* cp, int idx);
+
 /**
  * Start executing the child process.
  */
diff --git a/ProcessUNIX.c b/ProcessUNIX.c
index 1de81c7beebd426973f4cb0aee0434678b8786a1..9ebcfce592759922ce8fdb5cc02882ea2aae5e10 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,14 +695,56 @@ 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";
+}
+
+/* the index should be in array bound. */
+#define KWSYSPE_IDX_CHK(RET)                                                  \
+  if (!cp || idx >= cp->NumberOfCommands || idx < 0) {                        \
+    return RET;                                                               \
+  }
+
+int kwsysProcess_GetStateByIndex(kwsysProcess* cp, int idx)
+{
+  KWSYSPE_IDX_CHK(kwsysProcess_State_Error)
+  return cp->ProcessResults[idx].State;
+}
+
+int kwsysProcess_GetExitExceptionByIndex(kwsysProcess* cp, int idx)
+{
+  KWSYSPE_IDX_CHK(kwsysProcess_Exception_Other)
+  return cp->ProcessResults[idx].ExitException;
+}
+
+int kwsysProcess_GetExitValueByIndex(kwsysProcess* cp, int idx)
+{
+  KWSYSPE_IDX_CHK(-1)
+  return cp->ProcessResults[idx].ExitValue;
+}
+
+int kwsysProcess_GetExitCodeByIndex(kwsysProcess* cp, int idx)
+{
+  KWSYSPE_IDX_CHK(-1)
+  return cp->CommandExitCodes[idx];
+}
+
+const char* kwsysProcess_GetExceptionStringByIndex(kwsysProcess* cp, int idx)
+{
+  KWSYSPE_IDX_CHK("GetExceptionString called with NULL process management "
+                  "structure or index out of bound")
+  if (cp->ProcessResults[idx].State == kwsysProcess_StateByIndex_Exception) {
+    return cp->ProcessResults[idx].ExitExceptionString;
   }
   return "No exception";
 }
 
+#undef KWSYSPE_IDX_CHK
+
 void kwsysProcess_Execute(kwsysProcess* cp)
 {
   int i;
@@ -1263,7 +1323,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 +1353,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 +1360,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_StateByIndex_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_StateByIndex_Error;
+      }
+    }
+    /* support legacy state status value */
+    cp->State = cp->ProcessResults[cp->NumberOfCommands - 1].State;
   }
-
   /* Normal cleanup.  */
   kwsysProcessCleanup(cp, 0);
   return 1;
@@ -1445,11 +1508,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 +1534,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_StateByIndex_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 +2084,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 +2273,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..5183e3d2c96ec05345328a98689572b85429cab8 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,14 +884,57 @@ 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";
 }
 
+/* the index should be in array bound. */
+#define KWSYSPE_IDX_CHK(RET)                                                  \
+  if (!cp || idx >= cp->NumberOfCommands || idx < 0) {                        \
+    KWSYSPE_DEBUG((stderr, "array index out of bound\n"));                    \
+    return RET;                                                               \
+  }
+
+int kwsysProcess_GetStateByIndex(kwsysProcess* cp, int idx)
+{
+  KWSYSPE_IDX_CHK(kwsysProcess_State_Error)
+  return cp->ProcessResults[idx].State;
+}
+
+int kwsysProcess_GetExitExceptionByIndex(kwsysProcess* cp, int idx)
+{
+  KWSYSPE_IDX_CHK(kwsysProcess_Exception_Other)
+  return cp->ProcessResults[idx].ExitException;
+}
+
+int kwsysProcess_GetExitValueByIndex(kwsysProcess* cp, int idx)
+{
+  KWSYSPE_IDX_CHK(-1)
+  return cp->ProcessResults[idx].ExitValue;
+}
+
+int kwsysProcess_GetExitCodeByIndex(kwsysProcess* cp, int idx)
+{
+  KWSYSPE_IDX_CHK(-1)
+  return cp->CommandExitCodes[idx];
+}
+
+const char* kwsysProcess_GetExceptionStringByIndex(kwsysProcess* cp, int idx)
+{
+  KWSYSPE_IDX_CHK("GetExceptionString called with NULL process management "
+                  "structure or index out of bound")
+  if (cp->ProcessResults[idx].State == kwsysProcess_StateByIndex_Exception) {
+    return cp->ProcessResults[idx].ExitExceptionString;
+  }
+  return "No exception";
+}
+
+#undef KWSYSPE_IDX_CHK
+
 void kwsysProcess_Execute(kwsysProcess* cp)
 {
   int i;
@@ -1312,19 +1375,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_StateByIndex_Exception;
+        cp->ProcessResults[i].ExitValue = 1;
+        kwsysProcessSetExitExceptionByIndex(cp, cp->ProcessResults[i].ExitCode,
+                                            i);
+      } else {
+        /* Child exited without exception.  */
+        cp->ProcessResults[i].State = kwsysProcess_StateByIndex_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 +1575,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_StateByIndex_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 +1639,6 @@ int kwsysProcessInitialize(kwsysProcess* cp)
     }
   }
   {
-    int i;
     for (i = 0; i < 3; ++i) {
       cp->PipeChildStd[i] = INVALID_HANDLE_VALUE;
     }
@@ -1981,9 +2060,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 +2142,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;
   }
 }