ProcessUNIX.c 84.2 KB
Newer Older
1
2
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing#kwsys for details.  */
3
4
#include "kwsysPrivate.h"
#include KWSYS_HEADER(Process.h)
5
#include KWSYS_HEADER(System.h)
6

7
8
9
/* Work-around CMake dependency scanning limitation.  This must
   duplicate the above list of headers.  */
#if 0
10
11
#  include "Process.h.in"
#  include "System.h.in"
12
13
#endif

14
15
16
/*

Implementation for UNIX
17

18
19
20
21
22
23
24
25
26
On UNIX, a child process is forked to exec the program.  Three output
pipes are read by the parent process using a select call to block
until data are ready.  Two of the pipes are stdout and stderr for the
child.  The third is a special pipe populated by a signal handler to
indicate that a child has terminated.  This is used in conjunction
with the timeout on the select call to implement a timeout for program
even when it closes stdout and stderr and at the same time avoiding
races.

27
28
*/

29
30
31
32
33
34
35
36
37
38
39
/*

TODO:

We cannot create the pipeline of processes in suspended states.  How
do we cleanup processes already started when one fails to load?  Right
now we are just killing them, which is probably not the right thing to
do.

*/

40
41
42
#if defined(__CYGWIN__)
/* Increase the file descriptor limit for select() before including
   related system headers. (Default: 64) */
43
#  define FD_SETSIZE 16384
44
45
#endif

46
47
48
49
50
51
#include <assert.h>    /* assert */
#include <ctype.h>     /* isspace */
#include <dirent.h>    /* DIR, dirent */
#include <errno.h>     /* errno */
#include <fcntl.h>     /* fcntl */
#include <signal.h>    /* sigaction */
52
#include <stddef.h>    /* ptrdiff_t */
53
54
55
#include <stdio.h>     /* snprintf */
#include <stdlib.h>    /* malloc, free */
#include <string.h>    /* strdup, strerror, memset */
56
#include <sys/stat.h>  /* open mode */
57
58
59
60
#include <sys/time.h>  /* struct timeval */
#include <sys/types.h> /* pid_t, fd_set */
#include <sys/wait.h>  /* waitpid */
#include <time.h>      /* gettimeofday */
61
#include <unistd.h>    /* pipe, close, fork, execvp, select, _exit */
62

63
#if defined(__VMS)
64
#  define KWSYSPE_VMS_NONBLOCK , O_NONBLOCK
65
#else
66
#  define KWSYSPE_VMS_NONBLOCK
67
68
#endif

69
70
71
72
73
74
75
76
77
78
79
80
#if defined(KWSYS_C_HAS_PTRDIFF_T) && KWSYS_C_HAS_PTRDIFF_T
typedef ptrdiff_t kwsysProcess_ptrdiff_t;
#else
typedef int kwsysProcess_ptrdiff_t;
#endif

#if defined(KWSYS_C_HAS_SSIZE_T) && KWSYS_C_HAS_SSIZE_T
typedef ssize_t kwsysProcess_ssize_t;
#else
typedef int kwsysProcess_ssize_t;
#endif

81
#if defined(__BEOS__) && !defined(__ZETA__)
82
/* BeOS 5 doesn't have usleep(), but it has snooze(), which is identical. */
83
#  include <be/kernel/OS.h>
84
85
86
87
88
static inline void kwsysProcess_usleep(unsigned int msec)
{
  snooze(msec);
}
#else
89
#  define kwsysProcess_usleep usleep
90
91
92
93
94
95
96
97
98
99
100
101
#endif

/*
 * BeOS's select() works like WinSock: it's for networking only, and
 * doesn't work with Unix file handles...socket and file handles are
 * different namespaces (the same descriptor means different things in
 * each context!)
 *
 * So on Unix-like systems where select() is flakey, we'll set the
 * pipes' file handles to be non-blocking and just poll them directly
 * without select().
 */
102
103
#if !defined(__BEOS__) && !defined(__VMS) && !defined(__MINT__) &&            \
  !defined(KWSYSPE_USE_SELECT)
104
#  define KWSYSPE_USE_SELECT 1
105
106
#endif

107
108
/* Some platforms do not have siginfo on their signal handlers.  */
#if defined(SA_SIGINFO) && !defined(__BEOS__)
109
#  define KWSYSPE_USE_SIGINFO 1
110
111
#endif

112
/* The number of pipes for the child's output.  The standard stdout
113
114
115
116
   and stderr pipes are the first two.  One more pipe is used to
   detect when the child process has terminated.  The third pipe is
   not given to the child process, so it cannot close it until it
   terminates.  */
117
118
119
#define KWSYSPE_PIPE_COUNT 3
#define KWSYSPE_PIPE_STDOUT 0
#define KWSYSPE_PIPE_STDERR 1
120
#define KWSYSPE_PIPE_SIGNAL 2
121
122
123
124

/* The maximum amount to read from a pipe at a time.  */
#define KWSYSPE_PIPE_BUFFER_SIZE 1024

125
126
127
128
129
130
131
132
133
134
/* Keep track of times using a signed representation.  Switch to the
   native (possibly unsigned) representation only when calling native
   functions.  */
typedef struct timeval kwsysProcessTimeNative;
typedef struct kwsysProcessTime_s kwsysProcessTime;
struct kwsysProcessTime_s
{
  long tv_sec;
  long tv_usec;
};
135

136
137
typedef struct kwsysProcessCreateInformation_s
{
138
139
140
141
  int StdIn;
  int StdOut;
  int StdErr;
  int ErrorPipe[2];
142
143
} kwsysProcessCreateInformation;

144
static void kwsysProcessVolatileFree(volatile void* p);
145
static int kwsysProcessInitialize(kwsysProcess* cp);
146
147
static void kwsysProcessCleanup(kwsysProcess* cp, int error);
static void kwsysProcessCleanupDescriptor(int* pfd);
148
static void kwsysProcessClosePipes(kwsysProcess* cp);
149
static int kwsysProcessSetNonBlocking(int fd);
150
static int kwsysProcessCreate(kwsysProcess* cp, int prIndex,
151
                              kwsysProcessCreateInformation* si);
152
static void kwsysProcessDestroy(kwsysProcess* cp);
153
static int kwsysProcessSetupOutputPipeFile(int* p, const char* name);
154
static int kwsysProcessSetupOutputPipeNative(int* p, int des[2]);
155
156
static int kwsysProcessGetTimeoutTime(kwsysProcess* cp,
                                      const double* userTimeout,
157
158
                                      kwsysProcessTime* timeoutTime);
static int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime,
159
                                      const double* userTimeout,
160
161
                                      kwsysProcessTimeNative* timeoutLength,
                                      int zeroIsExpired);
162
static kwsysProcessTime kwsysProcessTimeGetCurrent(void);
163
164
165
static double kwsysProcessTimeToDouble(kwsysProcessTime t);
static kwsysProcessTime kwsysProcessTimeFromDouble(double d);
static int kwsysProcessTimeLess(kwsysProcessTime in1, kwsysProcessTime in2);
166
167
168
169
static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1,
                                            kwsysProcessTime in2);
static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1,
                                                 kwsysProcessTime in2);
170
171
static void kwsysProcessSetExitExceptionByIndex(kwsysProcess* cp, int sig,
                                                int idx);
172
static void kwsysProcessChildErrorExit(int errorPipe);
173
static void kwsysProcessRestoreDefaultSignalHandlers(void);
174
175
static pid_t kwsysProcessFork(kwsysProcess* cp,
                              kwsysProcessCreateInformation* si);
176
static void kwsysProcessKill(pid_t process_id);
177
#if defined(__VMS)
178
static int kwsysProcessSetVMSFeature(const char* name, int value);
179
#endif
180
181
static int kwsysProcessesAdd(kwsysProcess* cp);
static void kwsysProcessesRemove(kwsysProcess* cp);
182
#if KWSYSPE_USE_SIGINFO
183
184
static void kwsysProcessesSignalHandler(int signum, siginfo_t* info,
                                        void* ucontext);
185
186
187
#else
static void kwsysProcessesSignalHandler(int signum);
#endif
188

189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
/* 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];
};

209
210
211
/* Structure containing data used to implement the child's execution.  */
struct kwsysProcess_s
{
212
213
  /* The command lines to execute.  */
  char*** Commands;
214
  volatile int NumberOfCommands;
215

216
217
  /* Descriptors for the read ends of the child's output pipes and
     the signal pipe. */
218
  int PipeReadEnds[KWSYSPE_PIPE_COUNT];
219

220
221
222
223
  /* Descriptors for the child's ends of the pipes.
     Used temporarily during process creation.  */
  int PipeChildStd[3];

224
225
226
  /* Write descriptor for child termination signal pipe.  */
  int SignalPipe;

227
228
229
  /* Buffer for pipe data.  */
  char PipeBuffer[KWSYSPE_PIPE_BUFFER_SIZE];

230
231
232
233
  /* Process IDs returned by the calls to fork.  Everything is volatile
     because the signal handler accesses them.  You must be very careful
     when reaping PIDs or modifying this array to avoid race conditions.  */
  volatile pid_t* volatile ForkPIDs;
234

235
  /* Flag for whether the children were terminated by a failed select.  */
236
  int SelectError;
237

238
  /* The timeout length.  */
239
  double Timeout;
240
241
242

  /* The working directory for the process. */
  char* WorkingDirectory;
243

244
245
246
247
248
249
  /* Whether to create the child as a detached process.  */
  int OptionDetach;

  /* Whether the child was created as a detached process.  */
  int Detached;

250
251
252
  /* Whether to treat command lines as verbatim.  */
  int Verbatim;

253
254
255
  /* Whether to merge stdout/stderr of the child.  */
  int MergeOutput;

256
257
258
  /* Whether to create the process in a new process group.  */
  volatile sig_atomic_t CreateProcessGroup;

259
260
  /* Time at which the child started.  Negative for no timeout.  */
  kwsysProcessTime StartTime;
261

262
263
  /* Time at which the child will timeout.  Negative for no timeout.  */
  kwsysProcessTime TimeoutTime;
264

265
266
  /* Flag for whether the timeout expired.  */
  int TimeoutExpired;
267

268
269
  /* The number of pipes left open during execution.  */
  int PipesLeft;
270

271
#if KWSYSPE_USE_SELECT
272
273
  /* File descriptor set for call to select.  */
  fd_set PipeSet;
274
#endif
275

276
277
278
  /* The number of children still executing.  */
  int CommandsLeft;

279
  /* The status of the process structure.  Must be atomic because
280
281
     the signal handler checks this to avoid a race.  */
  volatile sig_atomic_t State;
282

283
  /* Whether the process was killed.  */
284
  volatile sig_atomic_t Killed;
285

286
  /* Buffer for error message in case of failure.  */
287
  char ErrorMessage[KWSYSPE_PIPE_BUFFER_SIZE + 1];
288

289
290
  /* process results.  */
  kwsysProcessResults* ProcessResults;
291

292
293
  /* The exit codes of each child process in the pipeline.  */
  int* CommandExitCodes;
294
295
296
297
298
299

  /* Name of files to which stdin and stdout pipes are attached.  */
  char* PipeFileSTDIN;
  char* PipeFileSTDOUT;
  char* PipeFileSTDERR;

300
301
302
303
304
  /* Whether each pipe is shared with the parent process.  */
  int PipeSharedSTDIN;
  int PipeSharedSTDOUT;
  int PipeSharedSTDERR;

305
306
307
308
309
  /* Native pipes provided by the user.  */
  int PipeNativeSTDIN[2];
  int PipeNativeSTDOUT[2];
  int PipeNativeSTDERR[2];

310
311
312
  /* The real working directory of this process.  */
  int RealWorkingDirectoryLength;
  char* RealWorkingDirectory;
313
314
};

315
kwsysProcess* kwsysProcess_New(void)
316
317
318
{
  /* Allocate a process control structure.  */
  kwsysProcess* cp = (kwsysProcess*)malloc(sizeof(kwsysProcess));
319
  if (!cp) {
320
    return 0;
321
  }
322
  memset(cp, 0, sizeof(kwsysProcess));
323
324
325
326

  /* Share stdin with the parent process by default.  */
  cp->PipeSharedSTDIN = 1;

327
328
329
330
331
332
333
334
  /* No native pipes by default.  */
  cp->PipeNativeSTDIN[0] = -1;
  cp->PipeNativeSTDIN[1] = -1;
  cp->PipeNativeSTDOUT[0] = -1;
  cp->PipeNativeSTDOUT[1] = -1;
  cp->PipeNativeSTDERR[0] = -1;
  cp->PipeNativeSTDERR[1] = -1;

335
  /* Set initial status.  */
336
  cp->State = kwsysProcess_State_Starting;
337

338
339
340
341
342
  return cp;
}

void kwsysProcess_Delete(kwsysProcess* cp)
{
343
  /* Make sure we have an instance.  */
344
  if (!cp) {
345
    return;
346
  }
347

348
  /* If the process is executing, wait for it to finish.  */
349
350
  if (cp->State == kwsysProcess_State_Executing) {
    if (cp->Detached) {
351
      kwsysProcess_Disown(cp);
352
    } else {
353
      kwsysProcess_WaitForExit(cp, 0);
354
    }
355
  }
356

357
358
  /* Free memory.  */
  kwsysProcess_SetCommand(cp, 0);
359
  kwsysProcess_SetWorkingDirectory(cp, 0);
360
361
362
  kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDIN, 0);
  kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDOUT, 0);
  kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDERR, 0);
363
  free(cp->CommandExitCodes);
364
  free(cp->ProcessResults);
365
366
367
  free(cp);
}

368
int kwsysProcess_SetCommand(kwsysProcess* cp, char const* const* command)
369
{
370
  int i;
371
  if (!cp) {
372
    return 0;
373
374
  }
  for (i = 0; i < cp->NumberOfCommands; ++i) {
375
    char** c = cp->Commands[i];
376
    while (*c) {
377
      free(*c++);
378
    }
379
380
    free(cp->Commands[i]);
  }
381
  cp->NumberOfCommands = 0;
382
  if (cp->Commands) {
383
384
    free(cp->Commands);
    cp->Commands = 0;
385
386
  }
  if (command) {
387
    return kwsysProcess_AddCommand(cp, command);
388
  }
389
390
391
392
393
394
395
396
397
  return 1;
}

int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command)
{
  int newNumberOfCommands;
  char*** newCommands;

  /* Make sure we have a command to add.  */
398
  if (!cp || !command || !*command) {
399
    return 0;
400
  }
401
402
403

  /* Allocate a new array for command pointers.  */
  newNumberOfCommands = cp->NumberOfCommands + 1;
404
405
  if (!(newCommands =
          (char***)malloc(sizeof(char**) * (size_t)(newNumberOfCommands)))) {
406
407
    /* Out of memory.  */
    return 0;
408
  }
409
410
411

  /* Copy any existing commands into the new array.  */
  {
412
413
414
    int i;
    for (i = 0; i < cp->NumberOfCommands; ++i) {
      newCommands[i] = cp->Commands[i];
415
416
417
418
    }
  }

  /* Add the new command.  */
419
  if (cp->Verbatim) {
420
421
422
    /* In order to run the given command line verbatim we need to
       parse it.  */
    newCommands[cp->NumberOfCommands] =
423
      kwsysSystem_Parse_CommandForUnix(*command, 0);
424
425
    if (!newCommands[cp->NumberOfCommands] ||
        !newCommands[cp->NumberOfCommands][0]) {
426
      /* Out of memory or no command parsed.  */
427
428
      free(newCommands);
      return 0;
429
    }
430
  } else {
431
432
    /* Copy each argument string individually.  */
    char const* const* c = command;
433
434
    kwsysProcess_ptrdiff_t n = 0;
    kwsysProcess_ptrdiff_t i = 0;
435
436
    while (*c++) {
    }
437
    n = c - command - 1;
Francois Bertel's avatar
Francois Bertel committed
438
    newCommands[cp->NumberOfCommands] =
439
440
      (char**)malloc((size_t)(n + 1) * sizeof(char*));
    if (!newCommands[cp->NumberOfCommands]) {
441
442
443
      /* Out of memory.  */
      free(newCommands);
      return 0;
444
445
    }
    for (i = 0; i < n; ++i) {
446
      assert(command[i]); /* Quiet Clang scan-build. */
447
      newCommands[cp->NumberOfCommands][i] = strdup(command[i]);
448
      if (!newCommands[cp->NumberOfCommands][i]) {
449
450
        break;
      }
451
452
    }
    if (i < n) {
453
      /* Out of memory.  */
454
455
456
      for (; i > 0; --i) {
        free(newCommands[cp->NumberOfCommands][i - 1]);
      }
457
458
      free(newCommands);
      return 0;
459
    }
460
461
    newCommands[cp->NumberOfCommands][n] = 0;
  }
462
463
464
465
466
467
468

  /* Successfully allocated new command array.  Free the old array. */
  free(cp->Commands);
  cp->Commands = newCommands;
  cp->NumberOfCommands = newNumberOfCommands;

  return 1;
469
470
471
472
}

void kwsysProcess_SetTimeout(kwsysProcess* cp, double timeout)
{
473
  if (!cp) {
474
    return;
475
  }
476
  cp->Timeout = timeout;
477
  if (cp->Timeout < 0) {
478
    cp->Timeout = 0;
479
  }
480
481
  // Force recomputation of TimeoutTime.
  cp->TimeoutTime.tv_sec = -1;
482
483
}

484
int kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, const char* dir)
485
{
486
  if (!cp) {
487
    return 0;
488
489
  }
  if (cp->WorkingDirectory == dir) {
490
    return 1;
491
492
  }
  if (cp->WorkingDirectory && dir && strcmp(cp->WorkingDirectory, dir) == 0) {
493
    return 1;
494
495
  }
  if (cp->WorkingDirectory) {
496
497
    free(cp->WorkingDirectory);
    cp->WorkingDirectory = 0;
498
499
  }
  if (dir) {
500
    cp->WorkingDirectory = strdup(dir);
501
    if (!cp->WorkingDirectory) {
502
      return 0;
503
    }
504
  }
505
506
507
  return 1;
}

508
int kwsysProcess_SetPipeFile(kwsysProcess* cp, int prPipe, const char* file)
509
510
{
  char** pfile;
511
  if (!cp) {
512
    return 0;
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
  }
  switch (prPipe) {
    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) {
528
529
    free(*pfile);
    *pfile = 0;
530
531
  }
  if (file) {
532
    *pfile = strdup(file);
533
    if (!*pfile) {
534
535
      return 0;
    }
536
  }
537

538
539
  /* If we are redirecting the pipe, do not share it or use a native
     pipe.  */
540
  if (*pfile) {
541
    kwsysProcess_SetPipeNative(cp, prPipe, 0);
542
    kwsysProcess_SetPipeShared(cp, prPipe, 0);
543
  }
544
  return 1;
545
546
}

547
void kwsysProcess_SetPipeShared(kwsysProcess* cp, int prPipe, int shared)
548
{
549
  if (!cp) {
550
    return;
551
  }
552

553
554
555
556
557
558
559
560
561
562
563
564
565
  switch (prPipe) {
    case kwsysProcess_Pipe_STDIN:
      cp->PipeSharedSTDIN = shared ? 1 : 0;
      break;
    case kwsysProcess_Pipe_STDOUT:
      cp->PipeSharedSTDOUT = shared ? 1 : 0;
      break;
    case kwsysProcess_Pipe_STDERR:
      cp->PipeSharedSTDERR = shared ? 1 : 0;
      break;
    default:
      return;
  }
566

567
568
  /* If we are sharing the pipe, do not redirect it to a file or use a
     native pipe.  */
569
  if (shared) {
570
    kwsysProcess_SetPipeFile(cp, prPipe, 0);
571
    kwsysProcess_SetPipeNative(cp, prPipe, 0);
572
  }
573
574
}

575
void kwsysProcess_SetPipeNative(kwsysProcess* cp, int prPipe, const int p[2])
576
577
578
{
  int* pPipeNative = 0;

579
  if (!cp) {
580
    return;
581
  }
582

583
584
585
586
587
588
589
590
591
592
593
594
595
  switch (prPipe) {
    case kwsysProcess_Pipe_STDIN:
      pPipeNative = cp->PipeNativeSTDIN;
      break;
    case kwsysProcess_Pipe_STDOUT:
      pPipeNative = cp->PipeNativeSTDOUT;
      break;
    case kwsysProcess_Pipe_STDERR:
      pPipeNative = cp->PipeNativeSTDERR;
      break;
    default:
      return;
  }
596
597

  /* Copy the native pipe descriptors provided.  */
598
  if (p) {
599
600
    pPipeNative[0] = p[0];
    pPipeNative[1] = p[1];
601
  } else {
602
603
    pPipeNative[0] = -1;
    pPipeNative[1] = -1;
604
  }
605
606
607

  /* If we are using a native pipe, do not share it or redirect it to
     a file.  */
608
  if (p) {
609
610
    kwsysProcess_SetPipeFile(cp, prPipe, 0);
    kwsysProcess_SetPipeShared(cp, prPipe, 0);
611
  }
612
613
}

614
615
int kwsysProcess_GetOption(kwsysProcess* cp, int optionId)
{
616
  if (!cp) {
617
    return 0;
618
  }
619

620
621
622
623
624
625
626
  switch (optionId) {
    case kwsysProcess_Option_Detach:
      return cp->OptionDetach;
    case kwsysProcess_Option_MergeOutput:
      return cp->MergeOutput;
    case kwsysProcess_Option_Verbatim:
      return cp->Verbatim;
627
628
    case kwsysProcess_Option_CreateProcessGroup:
      return cp->CreateProcessGroup;
629
630
631
    default:
      return 0;
  }
632
633
634
635
}

void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, int value)
{
636
  if (!cp) {
637
    return;
638
  }
639

640
641
642
643
644
645
646
647
648
649
  switch (optionId) {
    case kwsysProcess_Option_Detach:
      cp->OptionDetach = value;
      break;
    case kwsysProcess_Option_MergeOutput:
      cp->MergeOutput = value;
      break;
    case kwsysProcess_Option_Verbatim:
      cp->Verbatim = value;
      break;
650
    case kwsysProcess_Option_CreateProcessGroup:
651
652
653
654
655
      cp->CreateProcessGroup = value;
      break;
    default:
      break;
  }
656
657
}

658
659
int kwsysProcess_GetState(kwsysProcess* cp)
{
660
  return cp ? cp->State : kwsysProcess_State_Error;
661
662
}

663
664
int kwsysProcess_GetExitException(kwsysProcess* cp)
{
665
666
667
  return (cp && cp->ProcessResults && (cp->NumberOfCommands > 0))
    ? cp->ProcessResults[cp->NumberOfCommands - 1].ExitException
    : kwsysProcess_Exception_Other;
668
669
}

670
671
int kwsysProcess_GetExitCode(kwsysProcess* cp)
{
672
673
674
  return (cp && cp->ProcessResults && (cp->NumberOfCommands > 0))
    ? cp->ProcessResults[cp->NumberOfCommands - 1].ExitCode
    : 0;
675
676
}

677
678
int kwsysProcess_GetExitValue(kwsysProcess* cp)
{
679
680
681
  return (cp && cp->ProcessResults && (cp->NumberOfCommands > 0))
    ? cp->ProcessResults[cp->NumberOfCommands - 1].ExitValue
    : -1;
682
683
}

684
685
const char* kwsysProcess_GetErrorString(kwsysProcess* cp)
{
686
  if (!cp) {
687
    return "Process management structure could not be allocated";
688
689
  }
  if (cp->State == kwsysProcess_State_Error) {
690
    return cp->ErrorMessage;
691
  }
692
693
694
695
696
  return "Success";
}

const char* kwsysProcess_GetExceptionString(kwsysProcess* cp)
{
697
  if (!(cp && cp->ProcessResults && (cp->NumberOfCommands > 0))) {
698
    return "GetExceptionString called with NULL process management structure";
699
700
  }
  if (cp->State == kwsysProcess_State_Exception) {
701
    return cp->ProcessResults[cp->NumberOfCommands - 1].ExitExceptionString;
702
  }
703
  return "No exception";
704
705
}

706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
/* 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

748
749
750
void kwsysProcess_Execute(kwsysProcess* cp)
{
  int i;
751

752
  /* Do not execute a second copy simultaneously.  */
753
  if (!cp || cp->State == kwsysProcess_State_Executing) {
754
    return;
755
  }
756

757
  /* Make sure we have something to run.  */
758
  if (cp->NumberOfCommands < 1) {
759
760
761
    strcpy(cp->ErrorMessage, "No command");
    cp->State = kwsysProcess_State_Error;
    return;
762
  }
763

764
  /* Initialize the control structure for a new process.  */
765
  if (!kwsysProcessInitialize(cp)) {
766
767
768
    strcpy(cp->ErrorMessage, "Out of memory");
    cp->State = kwsysProcess_State_Error;
    return;
769
  }
770

771
#if defined(__VMS)
772
  /* Make sure pipes behave like streams on VMS.  */
773
  if (!kwsysProcessSetVMSFeature("DECC$STREAM_PIPE", 1)) {
774
775
    kwsysProcessCleanup(cp, 1);
    return;
776
  }
777
#endif
778

779
780
781
  /* 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.  */
782
  if (cp->WorkingDirectory) {
783
    int r;
784
785
    if (!getcwd(cp->RealWorkingDirectory,
                (size_t)(cp->RealWorkingDirectoryLength))) {
786
787
      kwsysProcessCleanup(cp, 1);
      return;
788
    }
789
790
791

    /* Some platforms specify that the chdir call may be
       interrupted.  Repeat the call until it finishes.  */
792
793
    while (((r = chdir(cp->WorkingDirectory)) < 0) && (errno == EINTR)) {
    }
794
    if (r < 0) {
795
      kwsysProcessCleanup(cp, 1);
796
      return;
797
    }
798
  }
799

800
801
802
  /* If not running a detached child, add this object to the global
     set of process objects that wish to be notified when a child
     exits.  */
803
804
  if (!cp->OptionDetach) {
    if (!kwsysProcessesAdd(cp)) {
805
806
      kwsysProcessCleanup(cp, 1);
      return;
807
    }
808
  }
809

810
  /* Setup the stdin pipe for the first process.  */
811
  if (cp->PipeFileSTDIN) {
812
813
    /* Open a file for the child's stdin to read.  */
    cp->PipeChildStd[0] = open(cp->PipeFileSTDIN, O_RDONLY);
814
    if (cp->PipeChildStd[0] < 0) {
815
816
      kwsysProcessCleanup(cp, 1);
      return;
817
    }
818
819

    /* Set close-on-exec flag on the pipe's end.  */
820
    if (fcntl(cp->PipeChildStd[0], F_SETFD, FD_CLOEXEC) < 0) {
821
822
823
      kwsysProcessCleanup(cp, 1);
      return;
    }
824
  } else if (cp->PipeSharedSTDIN) {
825
    cp->PipeChildStd[0] = 0;
826
  } else if (cp->PipeNativeSTDIN[0] >= 0) {
827
828
829
830
831
    cp->PipeChildStd[0] = cp->PipeNativeSTDIN[0];

    /* Set close-on-exec flag on the pipe's ends.  The read end will
       be dup2-ed into the stdin descriptor after the fork but before
       the exec.  */
832
833
    if ((fcntl(cp->PipeNativeSTDIN[0], F_SETFD, FD_CLOEXEC) < 0) ||
        (fcntl(cp->PipeNativeSTDIN[1], F_SETFD, FD_CLOEXEC) < 0)) {
834
835
836
      kwsysProcessCleanup(cp, 1);
      return;
    }
837
  } else {
838
    cp->PipeChildStd[0] = -1;
839
  }
840
841
842
843

  /* Create the output pipe for the last process.
     We always create this so the pipe can be passed to select even if
     it will report closed immediately.  */
844
  {
845
846
847
848
849
    /* Create the pipe.  */
    int p[2];
    if (pipe(p KWSYSPE_VMS_NONBLOCK) < 0) {
      kwsysProcessCleanup(cp, 1);
      return;
850
    }
851

852
853
854
    /* Store the pipe.  */
    cp->PipeReadEnds[KWSYSPE_PIPE_STDOUT] = p[0];
    cp->PipeChildStd[1] = p[1];
855

856
857
858
859
860
    /* Set close-on-exec flag on the pipe's ends.  */
    if ((fcntl(p[0], F_SETFD, FD_CLOEXEC) < 0) ||
        (fcntl(p[1], F_SETFD, FD_CLOEXEC) < 0)) {
      kwsysProcessCleanup(cp, 1);
      return;
861
    }
862

863
864
865
866
867
    /* Set to non-blocking in case select lies, or for the polling
       implementation.  */
    if (!kwsysProcessSetNonBlocking(p[0])) {
      kwsysProcessCleanup(cp, 1);
      return;
868
    }
869
  }
870

871
  if (cp->PipeFileSTDOUT) {
872
    /* Use a file for stdout.  */
873
874
    if (!kwsysProcessSetupOutputPipeFile(&cp->PipeChildStd[1],
                                         cp->PipeFileSTDOUT)) {
875
876
877
      kwsysProcessCleanup(cp, 1);
      return;
    }
878
  } else if (cp->PipeSharedSTDOUT) {
879
880
881
    /* Use the parent stdout.  */
    kwsysProcessCleanupDescriptor(&cp->PipeChildStd[1]);
    cp->PipeChildStd[1] = 1;
882
  } else if (cp->PipeNativeSTDOUT[1] >= 0) {
883
    /* Use the given descriptor for stdout.  */
884
885
    if (!kwsysProcessSetupOutputPipeNative(&cp->PipeChildStd[1],
                                           cp->PipeNativeSTDOUT)) {
886
887
888
      kwsysProcessCleanup(cp, 1);
      return;
    }
889
  }
890

891
892
893
894
  /* Create stderr pipe to be shared by all processes in the pipeline.
     We always create this so the pipe can be passed to select even if
     it will report closed immediately.  */
  {
895
896
897
898
899
    /* Create the pipe.  */
    int p[2];
    if (pipe(p KWSYSPE_VMS_NONBLOCK) < 0) {
      kwsysProcessCleanup(cp, 1);
      return;
900
901
    }

902
903
904
    /* Store the pipe.  */
    cp->PipeReadEnds[KWSYSPE_PIPE_STDERR] = p[0];
    cp->PipeChildStd[2] = p[1];
905

906
907
908
909
910
    /* Set close-on-exec flag on the pipe's ends.  */
    if ((fcntl(p[0], F_SETFD, FD_CLOEXEC) < 0) ||
        (fcntl(p[1], F_SETFD, FD_CLOEXEC) < 0)) {
      kwsysProcessCleanup(cp, 1);
      return;
911
912
    }

913
914
915
916
917
    /* Set to non-blocking in case select lies, or for the polling
       implementation.  */
    if (!kwsysProcessSetNonBlocking(p[0])) {
      kwsysProcessCleanup(cp, 1);
      return;
918
    }
919
  }
920

921
  if (cp->PipeFileSTDERR) {
922
    /* Use a file for stderr.  */
923
924
    if (!kwsysProcessSetupOutputPipeFile(&cp->PipeChildStd[2],
                                         cp->PipeFileSTDERR)) {
925
926
927
      kwsysProcessCleanup(cp, 1);
      return;
    }
928
  } else if (cp->PipeSharedSTDERR) {
929
930
931
    /* Use the parent stderr.  */
    kwsysProcessCleanupDescriptor(&cp->PipeChildStd[2]);
    cp->PipeChildStd[2] = 2;
932
  } else if (cp->PipeNativeSTDERR[1] >= 0) {
933
    /* Use the given handle for stderr.  */
934
935
    if (!kwsysProcessSetupOutputPipeNative(&cp->PipeChildStd[2],
                                           cp->PipeNativeSTDERR)) {
936
937
938
      kwsysProcessCleanup(cp, 1);
      return;
    }
939
  }
940

941
942
943
944
  /* The timeout period starts now.  */
  cp->StartTime = kwsysProcessTimeGetCurrent();
  cp->TimeoutTime.tv_sec = -1;
  cp->TimeoutTime.tv_usec = -1;
945

946
947
  /* Create the pipeline of processes.  */
  {
948
949
950
951
952
953
954
955
956
957
958
959
960
961
    kwsysProcessCreateInformation si = { -1, -1, -1, { -1, -1 } };
    int nextStdIn = cp->PipeChildStd[0];
    for (i = 0; i < cp->NumberOfCommands; ++i) {
      /* Setup the process's pipes.  */
      si.StdIn = nextStdIn;
      if (i == cp->NumberOfCommands - 1) {
        nextStdIn = -1;
        si.StdOut = cp->PipeChildStd[1];
      } else {
        /* Create a pipe to sit between the children.  */
        int p[2] = { -1, -1 };
        if (pipe(p KWSYSPE_VMS_NONBLOCK) < 0) {
          if (nextStdIn != cp->PipeChildStd[0]) {
            kwsysProcessCleanupDescriptor(&nextStdIn);
962
          }
963
964
          kwsysProcessCleanup(cp, 1);
          return;