| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730 | 
							- /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
 
-    file Copyright.txt or https://cmake.org/licensing#kwsys for details.  */
 
- #include "kwsysPrivate.h"
 
- #include KWSYS_HEADER(Process.h)
 
- #include KWSYS_HEADER(Encoding.h)
 
- /* Work-around CMake dependency scanning limitation.  This must
 
-    duplicate the above list of headers.  */
 
- #if 0
 
- #  include "Encoding.h.in"
 
- #  include "Process.h.in"
 
- #endif
 
- #include <assert.h>
 
- #include <limits.h>
 
- #include <stdio.h>
 
- #include <stdlib.h>
 
- #include <string.h>
 
- #if defined(_WIN32)
 
- #  include <windows.h>
 
- #else
 
- #  include <signal.h>
 
- #  include <unistd.h>
 
- #endif
 
- #if defined(__BORLANDC__)
 
- #  pragma warn - 8060 /* possibly incorrect assignment */
 
- #endif
 
- /* Platform-specific sleep functions. */
 
- #if defined(__BEOS__) && !defined(__ZETA__)
 
- /* BeOS 5 doesn't have usleep(), but it has snooze(), which is identical. */
 
- #  include <be/kernel/OS.h>
 
- static inline void testProcess_usleep(unsigned int usec)
 
- {
 
-   snooze(usec);
 
- }
 
- #elif defined(_WIN32)
 
- /* Windows can only sleep in millisecond intervals. */
 
- static void testProcess_usleep(unsigned int usec)
 
- {
 
-   Sleep(usec / 1000);
 
- }
 
- #else
 
- #  define testProcess_usleep usleep
 
- #endif
 
- #if defined(_WIN32)
 
- static void testProcess_sleep(unsigned int sec)
 
- {
 
-   Sleep(sec * 1000);
 
- }
 
- #else
 
- static void testProcess_sleep(unsigned int sec)
 
- {
 
-   sleep(sec);
 
- }
 
- #endif
 
- int runChild(const char* cmd[], int state, int exception, int value, int share,
 
-              int output, int delay, double timeout, int poll, int repeat,
 
-              int disown, int createNewGroup, unsigned int interruptDelay);
 
- static int test1(int argc, const char* argv[])
 
- {
 
-   /* This is a very basic functional test of kwsysProcess.  It is repeated
 
-      numerous times to verify that there are no resource leaks in kwsysProcess
 
-      that eventually lead to an error.  Many versions of OS X will fail after
 
-      256 leaked file handles, so 257 iterations seems to be a good test.  On
 
-      the other hand, too many iterations will cause the test to time out -
 
-      especially if the test is instrumented with e.g. valgrind.
 
-      If you have problems with this test timing out on your system, or want to
 
-      run more than 257 iterations, you can change the number of iterations by
 
-      setting the KWSYS_TEST_PROCESS_1_COUNT environment variable.  */
 
-   (void)argc;
 
-   (void)argv;
 
-   fprintf(stdout, "Output on stdout from test returning 0.\n");
 
-   fprintf(stderr, "Output on stderr from test returning 0.\n");
 
-   return 0;
 
- }
 
- static int test2(int argc, const char* argv[])
 
- {
 
-   (void)argc;
 
-   (void)argv;
 
-   fprintf(stdout, "Output on stdout from test returning 123.\n");
 
-   fprintf(stderr, "Output on stderr from test returning 123.\n");
 
-   return 123;
 
- }
 
- static int test3(int argc, const char* argv[])
 
- {
 
-   (void)argc;
 
-   (void)argv;
 
-   fprintf(stdout, "Output before sleep on stdout from timeout test.\n");
 
-   fprintf(stderr, "Output before sleep on stderr from timeout test.\n");
 
-   fflush(stdout);
 
-   fflush(stderr);
 
-   testProcess_sleep(15);
 
-   fprintf(stdout, "Output after sleep on stdout from timeout test.\n");
 
-   fprintf(stderr, "Output after sleep on stderr from timeout test.\n");
 
-   return 0;
 
- }
 
- static int test4(int argc, const char* argv[])
 
- {
 
- #ifndef CRASH_USING_ABORT
 
-   /* Prepare a pointer to an invalid address.  Don't use null, because
 
-   dereferencing null is undefined behaviour and compilers are free to
 
-   do whatever they want. ex: Clang will warn at compile time, or even
 
-   optimize away the write. We hope to 'outsmart' them by using
 
-   'volatile' and a slightly larger address, based on a runtime value. */
 
-   volatile int* invalidAddress = 0;
 
-   invalidAddress += argc ? 1 : 2;
 
- #endif
 
- #if defined(_WIN32)
 
-   /* Avoid error diagnostic popups since we are crashing on purpose.  */
 
-   SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
 
- #elif defined(__BEOS__) || defined(__HAIKU__)
 
-   /* Avoid error diagnostic popups since we are crashing on purpose.  */
 
-   disable_debugger(1);
 
- #endif
 
-   (void)argc;
 
-   (void)argv;
 
-   fprintf(stdout, "Output before crash on stdout from crash test.\n");
 
-   fprintf(stderr, "Output before crash on stderr from crash test.\n");
 
-   fflush(stdout);
 
-   fflush(stderr);
 
- #ifdef CRASH_USING_ABORT
 
-   abort();
 
- #else
 
-   assert(invalidAddress); /* Quiet Clang scan-build. */
 
-   /* Provoke deliberate crash by writing to the invalid address. */
 
-   *invalidAddress = 0;
 
- #endif
 
-   fprintf(stdout, "Output after crash on stdout from crash test.\n");
 
-   fprintf(stderr, "Output after crash on stderr from crash test.\n");
 
-   return 0;
 
- }
 
- static int test5(int argc, const char* argv[])
 
- {
 
-   int r;
 
-   const char* cmd[4];
 
-   (void)argc;
 
-   cmd[0] = argv[0];
 
-   cmd[1] = "run";
 
-   cmd[2] = "4";
 
-   cmd[3] = 0;
 
-   fprintf(stdout, "Output on stdout before recursive test.\n");
 
-   fprintf(stderr, "Output on stderr before recursive test.\n");
 
-   fflush(stdout);
 
-   fflush(stderr);
 
-   r = runChild(cmd, kwsysProcess_State_Exception,
 
- #ifdef CRASH_USING_ABORT
 
-                kwsysProcess_Exception_Other,
 
- #else
 
-                kwsysProcess_Exception_Fault,
 
- #endif
 
-                1, 1, 1, 0, 15, 0, 1, 0, 0, 0);
 
-   fprintf(stdout, "Output on stdout after recursive test.\n");
 
-   fprintf(stderr, "Output on stderr after recursive test.\n");
 
-   fflush(stdout);
 
-   fflush(stderr);
 
-   return r;
 
- }
 
- #define TEST6_SIZE (4096 * 2)
 
- static void test6(int argc, const char* argv[])
 
- {
 
-   int i;
 
-   char runaway[TEST6_SIZE + 1];
 
-   (void)argc;
 
-   (void)argv;
 
-   for (i = 0; i < TEST6_SIZE; ++i) {
 
-     runaway[i] = '.';
 
-   }
 
-   runaway[TEST6_SIZE] = '\n';
 
-   /* Generate huge amounts of output to test killing.  */
 
-   for (;;) {
 
-     fwrite(runaway, 1, TEST6_SIZE + 1, stdout);
 
-     fflush(stdout);
 
-   }
 
- }
 
- /* Define MINPOLL to be one more than the number of times output is
 
-    written.  Define MAXPOLL to be the largest number of times a loop
 
-    delaying 1/10th of a second should ever have to poll.  */
 
- #define MINPOLL 5
 
- #define MAXPOLL 20
 
- static int test7(int argc, const char* argv[])
 
- {
 
-   (void)argc;
 
-   (void)argv;
 
-   fprintf(stdout, "Output on stdout before sleep.\n");
 
-   fprintf(stderr, "Output on stderr before sleep.\n");
 
-   fflush(stdout);
 
-   fflush(stderr);
 
-   /* Sleep for 1 second.  */
 
-   testProcess_sleep(1);
 
-   fprintf(stdout, "Output on stdout after sleep.\n");
 
-   fprintf(stderr, "Output on stderr after sleep.\n");
 
-   fflush(stdout);
 
-   fflush(stderr);
 
-   return 0;
 
- }
 
- static int test8(int argc, const char* argv[])
 
- {
 
-   /* Create a disowned grandchild to test handling of processes
 
-      that exit before their children.  */
 
-   int r;
 
-   const char* cmd[4];
 
-   (void)argc;
 
-   cmd[0] = argv[0];
 
-   cmd[1] = "run";
 
-   cmd[2] = "108";
 
-   cmd[3] = 0;
 
-   fprintf(stdout, "Output on stdout before grandchild test.\n");
 
-   fprintf(stderr, "Output on stderr before grandchild test.\n");
 
-   fflush(stdout);
 
-   fflush(stderr);
 
-   r = runChild(cmd, kwsysProcess_State_Disowned, kwsysProcess_Exception_None,
 
-                1, 1, 1, 0, 10, 0, 1, 1, 0, 0);
 
-   fprintf(stdout, "Output on stdout after grandchild test.\n");
 
-   fprintf(stderr, "Output on stderr after grandchild test.\n");
 
-   fflush(stdout);
 
-   fflush(stderr);
 
-   return r;
 
- }
 
- static int test8_grandchild(int argc, const char* argv[])
 
- {
 
-   (void)argc;
 
-   (void)argv;
 
-   fprintf(stdout, "Output on stdout from grandchild before sleep.\n");
 
-   fprintf(stderr, "Output on stderr from grandchild before sleep.\n");
 
-   fflush(stdout);
 
-   fflush(stderr);
 
-   /* TODO: Instead of closing pipes here leave them open to make sure
 
-      the grandparent can stop listening when the parent exits.  This
 
-      part of the test cannot be enabled until the feature is
 
-      implemented.  */
 
-   fclose(stdout);
 
-   fclose(stderr);
 
-   testProcess_sleep(15);
 
-   return 0;
 
- }
 
- static int test9(int argc, const char* argv[])
 
- {
 
-   /* Test Ctrl+C behavior: the root test program will send a Ctrl+C to this
 
-      process.  Here, we start a child process that sleeps for a long time
 
-      while ignoring signals.  The test is successful if this process waits
 
-      for the child to return before exiting from the Ctrl+C handler.
 
-      WARNING:  This test will falsely pass if the share parameter of runChild
 
-      was set to 0 when invoking the test9 process.  */
 
-   int r;
 
-   const char* cmd[4];
 
-   (void)argc;
 
-   cmd[0] = argv[0];
 
-   cmd[1] = "run";
 
-   cmd[2] = "109";
 
-   cmd[3] = 0;
 
-   fprintf(stdout, "Output on stdout before grandchild test.\n");
 
-   fprintf(stderr, "Output on stderr before grandchild test.\n");
 
-   fflush(stdout);
 
-   fflush(stderr);
 
-   r = runChild(cmd, kwsysProcess_State_Exited, kwsysProcess_Exception_None, 0,
 
-                1, 1, 0, 30, 0, 1, 0, 0, 0);
 
-   /* This sleep will avoid a race condition between this function exiting
 
-      normally and our Ctrl+C handler exiting abnormally after the process
 
-      exits.  */
 
-   testProcess_sleep(1);
 
-   fprintf(stdout, "Output on stdout after grandchild test.\n");
 
-   fprintf(stderr, "Output on stderr after grandchild test.\n");
 
-   fflush(stdout);
 
-   fflush(stderr);
 
-   return r;
 
- }
 
- #if defined(_WIN32)
 
- static BOOL WINAPI test9_grandchild_handler(DWORD dwCtrlType)
 
- {
 
-   /* Ignore all Ctrl+C/Break signals.  We must use an actual handler function
 
-      instead of using SetConsoleCtrlHandler(NULL, TRUE) so that we can also
 
-      ignore Ctrl+Break in addition to Ctrl+C.  */
 
-   (void)dwCtrlType;
 
-   return TRUE;
 
- }
 
- #endif
 
- static int test9_grandchild(int argc, const char* argv[])
 
- {
 
-   /* The grandchild just sleeps for a few seconds while ignoring signals.  */
 
-   (void)argc;
 
-   (void)argv;
 
- #if defined(_WIN32)
 
-   if (!SetConsoleCtrlHandler(test9_grandchild_handler, TRUE)) {
 
-     return 1;
 
-   }
 
- #else
 
-   struct sigaction sa;
 
-   memset(&sa, 0, sizeof(sa));
 
-   sa.sa_handler = SIG_IGN;
 
-   sigemptyset(&sa.sa_mask);
 
-   if (sigaction(SIGINT, &sa, 0) < 0) {
 
-     return 1;
 
-   }
 
- #endif
 
-   fprintf(stdout, "Output on stdout from grandchild before sleep.\n");
 
-   fprintf(stderr, "Output on stderr from grandchild before sleep.\n");
 
-   fflush(stdout);
 
-   fflush(stderr);
 
-   /* Sleep for 9 seconds.  */
 
-   testProcess_sleep(9);
 
-   fprintf(stdout, "Output on stdout from grandchild after sleep.\n");
 
-   fprintf(stderr, "Output on stderr from grandchild after sleep.\n");
 
-   fflush(stdout);
 
-   fflush(stderr);
 
-   return 0;
 
- }
 
- static int test10(int argc, const char* argv[])
 
- {
 
-   /* Test Ctrl+C behavior: the root test program will send a Ctrl+C to this
 
-      process.  Here, we start a child process that sleeps for a long time and
 
-      processes signals normally.  However, this grandchild is created in a new
 
-      process group - ensuring that Ctrl+C we receive is sent to our process
 
-      groups.  We make sure it exits anyway.  */
 
-   int r;
 
-   const char* cmd[4];
 
-   (void)argc;
 
-   cmd[0] = argv[0];
 
-   cmd[1] = "run";
 
-   cmd[2] = "110";
 
-   cmd[3] = 0;
 
-   fprintf(stdout, "Output on stdout before grandchild test.\n");
 
-   fprintf(stderr, "Output on stderr before grandchild test.\n");
 
-   fflush(stdout);
 
-   fflush(stderr);
 
-   r =
 
-     runChild(cmd, kwsysProcess_State_Exception,
 
-              kwsysProcess_Exception_Interrupt, 0, 1, 1, 0, 30, 0, 1, 0, 1, 0);
 
-   fprintf(stdout, "Output on stdout after grandchild test.\n");
 
-   fprintf(stderr, "Output on stderr after grandchild test.\n");
 
-   fflush(stdout);
 
-   fflush(stderr);
 
-   return r;
 
- }
 
- static int test10_grandchild(int argc, const char* argv[])
 
- {
 
-   /* The grandchild just sleeps for a few seconds and handles signals.  */
 
-   (void)argc;
 
-   (void)argv;
 
-   fprintf(stdout, "Output on stdout from grandchild before sleep.\n");
 
-   fprintf(stderr, "Output on stderr from grandchild before sleep.\n");
 
-   fflush(stdout);
 
-   fflush(stderr);
 
-   /* Sleep for 6 seconds.  */
 
-   testProcess_sleep(6);
 
-   fprintf(stdout, "Output on stdout from grandchild after sleep.\n");
 
-   fprintf(stderr, "Output on stderr from grandchild after sleep.\n");
 
-   fflush(stdout);
 
-   fflush(stderr);
 
-   return 0;
 
- }
 
- static int runChild2(kwsysProcess* kp, const char* cmd[], int state,
 
-                      int exception, int value, int share, int output,
 
-                      int delay, double timeout, int poll, int disown,
 
-                      int createNewGroup, unsigned int interruptDelay)
 
- {
 
-   int result = 0;
 
-   char* data = 0;
 
-   int length = 0;
 
-   double userTimeout = 0;
 
-   double* pUserTimeout = 0;
 
-   kwsysProcess_SetCommand(kp, cmd);
 
-   if (timeout >= 0) {
 
-     kwsysProcess_SetTimeout(kp, timeout);
 
-   }
 
-   if (share) {
 
-     kwsysProcess_SetPipeShared(kp, kwsysProcess_Pipe_STDOUT, 1);
 
-     kwsysProcess_SetPipeShared(kp, kwsysProcess_Pipe_STDERR, 1);
 
-   }
 
-   if (disown) {
 
-     kwsysProcess_SetOption(kp, kwsysProcess_Option_Detach, 1);
 
-   }
 
-   if (createNewGroup) {
 
-     kwsysProcess_SetOption(kp, kwsysProcess_Option_CreateProcessGroup, 1);
 
-   }
 
-   kwsysProcess_Execute(kp);
 
-   if (poll) {
 
-     pUserTimeout = &userTimeout;
 
-   }
 
-   if (interruptDelay) {
 
-     testProcess_sleep(interruptDelay);
 
-     kwsysProcess_Interrupt(kp);
 
-   }
 
-   if (!share && !disown) {
 
-     int p;
 
-     while ((p = kwsysProcess_WaitForData(kp, &data, &length, pUserTimeout))) {
 
-       if (output) {
 
-         if (poll && p == kwsysProcess_Pipe_Timeout) {
 
-           fprintf(stdout, "WaitForData timeout reached.\n");
 
-           fflush(stdout);
 
-           /* Count the number of times we polled without getting data.
 
-              If it is excessive then kill the child and fail.  */
 
-           if (++poll >= MAXPOLL) {
 
-             fprintf(stdout, "Poll count reached limit %d.\n", MAXPOLL);
 
-             kwsysProcess_Kill(kp);
 
-           }
 
-         } else {
 
-           fwrite(data, 1, (size_t)length, stdout);
 
-           fflush(stdout);
 
-         }
 
-       }
 
-       if (poll) {
 
-         /* Delay to avoid busy loop during polling.  */
 
-         testProcess_usleep(100000);
 
-       }
 
-       if (delay) {
 
- /* Purposely sleeping only on Win32 to let pipe fill up.  */
 
- #if defined(_WIN32)
 
-         testProcess_usleep(100000);
 
- #endif
 
-       }
 
-     }
 
-   }
 
-   if (disown) {
 
-     kwsysProcess_Disown(kp);
 
-   } else {
 
-     kwsysProcess_WaitForExit(kp, 0);
 
-   }
 
-   switch (kwsysProcess_GetState(kp)) {
 
-     case kwsysProcess_State_Starting:
 
-       printf("No process has been executed.\n");
 
-       break;
 
-     case kwsysProcess_State_Executing:
 
-       printf("The process is still executing.\n");
 
-       break;
 
-     case kwsysProcess_State_Expired:
 
-       printf("Child was killed when timeout expired.\n");
 
-       break;
 
-     case kwsysProcess_State_Exited:
 
-       printf("Child exited with value = %d\n", kwsysProcess_GetExitValue(kp));
 
-       result = ((exception != kwsysProcess_GetExitException(kp)) ||
 
-                 (value != kwsysProcess_GetExitValue(kp)));
 
-       break;
 
-     case kwsysProcess_State_Killed:
 
-       printf("Child was killed by parent.\n");
 
-       break;
 
-     case kwsysProcess_State_Exception:
 
-       printf("Child terminated abnormally: %s\n",
 
-              kwsysProcess_GetExceptionString(kp));
 
-       result = ((exception != kwsysProcess_GetExitException(kp)) ||
 
-                 (value != kwsysProcess_GetExitValue(kp)));
 
-       break;
 
-     case kwsysProcess_State_Disowned:
 
-       printf("Child was disowned.\n");
 
-       break;
 
-     case kwsysProcess_State_Error:
 
-       printf("Error in administrating child process: [%s]\n",
 
-              kwsysProcess_GetErrorString(kp));
 
-       break;
 
-   }
 
-   if (result) {
 
-     if (exception != kwsysProcess_GetExitException(kp)) {
 
-       fprintf(stderr,
 
-               "Mismatch in exit exception.  "
 
-               "Should have been %d, was %d.\n",
 
-               exception, kwsysProcess_GetExitException(kp));
 
-     }
 
-     if (value != kwsysProcess_GetExitValue(kp)) {
 
-       fprintf(stderr,
 
-               "Mismatch in exit value.  "
 
-               "Should have been %d, was %d.\n",
 
-               value, kwsysProcess_GetExitValue(kp));
 
-     }
 
-   }
 
-   if (kwsysProcess_GetState(kp) != state) {
 
-     fprintf(stderr,
 
-             "Mismatch in state.  "
 
-             "Should have been %d, was %d.\n",
 
-             state, kwsysProcess_GetState(kp));
 
-     result = 1;
 
-   }
 
-   /* We should have polled more times than there were data if polling
 
-      was enabled.  */
 
-   if (poll && poll < MINPOLL) {
 
-     fprintf(stderr, "Poll count is %d, which is less than %d.\n", poll,
 
-             MINPOLL);
 
-     result = 1;
 
-   }
 
-   return result;
 
- }
 
- /**
 
-  * Runs a child process and blocks until it returns.  Arguments as follows:
 
-  *
 
-  * cmd            = Command line to run.
 
-  * state          = Expected return value of kwsysProcess_GetState after exit.
 
-  * exception      = Expected return value of kwsysProcess_GetExitException.
 
-  * value          = Expected return value of kwsysProcess_GetExitValue.
 
-  * share          = Whether to share stdout/stderr child pipes with our pipes
 
-  *                  by way of kwsysProcess_SetPipeShared.  If false, new pipes
 
-  *                  are created.
 
-  * output         = If !share && !disown, whether to write the child's stdout
 
-  *                  and stderr output to our stdout.
 
-  * delay          = If !share && !disown, adds an additional short delay to
 
-  *                  the pipe loop to allow the pipes to fill up; Windows only.
 
-  * timeout        = Non-zero to sets a timeout in seconds via
 
-  *                  kwsysProcess_SetTimeout.
 
-  * poll           = If !share && !disown, we count the number of 0.1 second
 
-  *                  intervals where the child pipes had no new data.  We fail
 
-  *                  if not in the bounds of MINPOLL/MAXPOLL.
 
-  * repeat         = Number of times to run the process.
 
-  * disown         = If set, the process is disowned.
 
-  * createNewGroup = If set, the process is created in a new process group.
 
-  * interruptDelay = If non-zero, number of seconds to delay before
 
-  *                  interrupting the process.  Note that this delay will occur
 
-  *                  BEFORE any reading/polling of pipes occurs and before any
 
-  *                  detachment occurs.
 
-  */
 
- int runChild(const char* cmd[], int state, int exception, int value, int share,
 
-              int output, int delay, double timeout, int poll, int repeat,
 
-              int disown, int createNewGroup, unsigned int interruptDelay)
 
- {
 
-   int result = 1;
 
-   kwsysProcess* kp = kwsysProcess_New();
 
-   if (!kp) {
 
-     fprintf(stderr, "kwsysProcess_New returned NULL!\n");
 
-     return 1;
 
-   }
 
-   while (repeat-- > 0) {
 
-     result = runChild2(kp, cmd, state, exception, value, share, output, delay,
 
-                        timeout, poll, disown, createNewGroup, interruptDelay);
 
-     if (result) {
 
-       break;
 
-     }
 
-   }
 
-   kwsysProcess_Delete(kp);
 
-   return result;
 
- }
 
- int main(int argc, const char* argv[])
 
- {
 
-   int n = 0;
 
- #ifdef _WIN32
 
-   int i;
 
-   char new_args[10][_MAX_PATH];
 
-   LPWSTR* w_av = CommandLineToArgvW(GetCommandLineW(), &argc);
 
-   for (i = 0; i < argc; i++) {
 
-     kwsysEncoding_wcstombs(new_args[i], w_av[i], _MAX_PATH);
 
-     argv[i] = new_args[i];
 
-   }
 
-   LocalFree(w_av);
 
- #endif
 
- #if 0
 
-     {
 
-     HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
 
-     DuplicateHandle(GetCurrentProcess(), out,
 
-                     GetCurrentProcess(), &out, 0, FALSE,
 
-                     DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
 
-     SetStdHandle(STD_OUTPUT_HANDLE, out);
 
-     }
 
-     {
 
-     HANDLE out = GetStdHandle(STD_ERROR_HANDLE);
 
-     DuplicateHandle(GetCurrentProcess(), out,
 
-                     GetCurrentProcess(), &out, 0, FALSE,
 
-                     DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
 
-     SetStdHandle(STD_ERROR_HANDLE, out);
 
-     }
 
- #endif
 
-   if (argc == 2) {
 
-     n = atoi(argv[1]);
 
-   } else if (argc == 3 && strcmp(argv[1], "run") == 0) {
 
-     n = atoi(argv[2]);
 
-   }
 
-   /* Check arguments.  */
 
-   if (((n >= 1 && n <= 10) || n == 108 || n == 109 || n == 110) && argc == 3) {
 
-     /* This is the child process for a requested test number.  */
 
-     switch (n) {
 
-       case 1:
 
-         return test1(argc, argv);
 
-       case 2:
 
-         return test2(argc, argv);
 
-       case 3:
 
-         return test3(argc, argv);
 
-       case 4:
 
-         return test4(argc, argv);
 
-       case 5:
 
-         return test5(argc, argv);
 
-       case 6:
 
-         test6(argc, argv);
 
-         return 0;
 
-       case 7:
 
-         return test7(argc, argv);
 
-       case 8:
 
-         return test8(argc, argv);
 
-       case 9:
 
-         return test9(argc, argv);
 
-       case 10:
 
-         return test10(argc, argv);
 
-       case 108:
 
-         return test8_grandchild(argc, argv);
 
-       case 109:
 
-         return test9_grandchild(argc, argv);
 
-       case 110:
 
-         return test10_grandchild(argc, argv);
 
-     }
 
-     fprintf(stderr, "Invalid test number %d.\n", n);
 
-     return 1;
 
-   }
 
-   if (n >= 1 && n <= 10) {
 
-     /* This is the parent process for a requested test number.  */
 
-     int states[10] = {
 
-       kwsysProcess_State_Exited,   kwsysProcess_State_Exited,
 
-       kwsysProcess_State_Expired,  kwsysProcess_State_Exception,
 
-       kwsysProcess_State_Exited,   kwsysProcess_State_Expired,
 
-       kwsysProcess_State_Exited,   kwsysProcess_State_Exited,
 
-       kwsysProcess_State_Expired,  /* Ctrl+C handler test */
 
-       kwsysProcess_State_Exception /* Process group test */
 
-     };
 
-     int exceptions[10] = {
 
-       kwsysProcess_Exception_None,  kwsysProcess_Exception_None,
 
-       kwsysProcess_Exception_None,
 
- #ifdef CRASH_USING_ABORT
 
-       kwsysProcess_Exception_Other,
 
- #else
 
-       kwsysProcess_Exception_Fault,
 
- #endif
 
-       kwsysProcess_Exception_None,  kwsysProcess_Exception_None,
 
-       kwsysProcess_Exception_None,  kwsysProcess_Exception_None,
 
-       kwsysProcess_Exception_None,  kwsysProcess_Exception_Interrupt
 
-     };
 
-     int values[10] = { 0, 123, 1, 1, 0, 0, 0, 0, 1, 1 };
 
-     int shares[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 };
 
-     int outputs[10] = { 1, 1, 1, 1, 1, 0, 1, 1, 1, 1 };
 
-     int delays[10] = { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 };
 
-     double timeouts[10] = { 10, 10, 10, 30, 30, 10, -1, 10, 6, 4 };
 
-     int polls[10] = { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 };
 
-     int repeat[10] = { 257, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
 
-     int createNewGroups[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 };
 
-     unsigned int interruptDelays[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 3, 2 };
 
-     int r;
 
-     const char* cmd[4];
 
- #ifdef _WIN32
 
-     char* argv0 = 0;
 
- #endif
 
-     char* test1IterationsStr = getenv("KWSYS_TEST_PROCESS_1_COUNT");
 
-     if (test1IterationsStr) {
 
-       long int test1Iterations = strtol(test1IterationsStr, 0, 10);
 
-       if (test1Iterations > 10 && test1Iterations != LONG_MAX) {
 
-         repeat[0] = (int)test1Iterations;
 
-       }
 
-     }
 
- #ifdef _WIN32
 
-     if (n == 0 && (argv0 = strdup(argv[0]))) {
 
-       /* Try converting to forward slashes to see if it works.  */
 
-       char* c;
 
-       for (c = argv0; *c; ++c) {
 
-         if (*c == '\\') {
 
-           *c = '/';
 
-         }
 
-       }
 
-       cmd[0] = argv0;
 
-     } else {
 
-       cmd[0] = argv[0];
 
-     }
 
- #else
 
-     cmd[0] = argv[0];
 
- #endif
 
-     cmd[1] = "run";
 
-     cmd[2] = argv[1];
 
-     cmd[3] = 0;
 
-     fprintf(stdout, "Output on stdout before test %d.\n", n);
 
-     fprintf(stderr, "Output on stderr before test %d.\n", n);
 
-     fflush(stdout);
 
-     fflush(stderr);
 
-     r = runChild(cmd, states[n - 1], exceptions[n - 1], values[n - 1],
 
-                  shares[n - 1], outputs[n - 1], delays[n - 1], timeouts[n - 1],
 
-                  polls[n - 1], repeat[n - 1], 0, createNewGroups[n - 1],
 
-                  interruptDelays[n - 1]);
 
-     fprintf(stdout, "Output on stdout after test %d.\n", n);
 
-     fprintf(stderr, "Output on stderr after test %d.\n", n);
 
-     fflush(stdout);
 
-     fflush(stderr);
 
- #if defined(_WIN32)
 
-     free(argv0);
 
- #endif
 
-     return r;
 
-   }
 
-   if (argc > 2 && strcmp(argv[1], "0") == 0) {
 
-     /* This is the special debugging test to run a given command
 
-        line.  */
 
-     const char** cmd = argv + 2;
 
-     int state = kwsysProcess_State_Exited;
 
-     int exception = kwsysProcess_Exception_None;
 
-     int value = 0;
 
-     double timeout = 0;
 
-     int r =
 
-       runChild(cmd, state, exception, value, 0, 1, 0, timeout, 0, 1, 0, 0, 0);
 
-     return r;
 
-   } else {
 
-     /* Improper usage.  */
 
-     fprintf(stdout, "Usage: %s <test number>\n", argv[0]);
 
-     return 1;
 
-   }
 
- }
 
 
  |