ProcessWin32.c 86 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(Encoding.h)
6

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

14 15 16
/*

Implementation for Windows
17

18 19 20
On windows, a thread is created to wait for data on each pipe.  The
threads are synchronized with the main thread to simulate the use of
a UNIX-style select system call.
21

22 23
*/

24
#ifdef _MSC_VER
25
#  pragma warning(push, 1)
26
#endif
27
#include <windows.h> /* Windows API */
28
#if defined(_MSC_VER) && _MSC_VER >= 1800
29
#  define KWSYS_WINDOWS_DEPRECATED_GetVersionEx
30
#endif
31 32 33
#include <io.h>     /* _unlink */
#include <stdio.h>  /* sprintf */
#include <string.h> /* strlen, strdup */
34
#ifdef __WATCOMC__
35
#  define _unlink unlink
36
#endif
37 38

#ifndef _MAX_FNAME
39
#  define _MAX_FNAME 4096
40 41
#endif
#ifndef _MAX_PATH
42
#  define _MAX_PATH 4096
43 44
#endif

45
#ifdef _MSC_VER
46 47 48
#  pragma warning(pop)
#  pragma warning(disable : 4514)
#  pragma warning(disable : 4706)
49
#endif
50

51
#if defined(__BORLANDC__)
52 53
#  pragma warn - 8004 /* assigned a value that is never used  */
#  pragma warn - 8060 /* Assignment inside if() condition.  */
54 55
#endif

56 57
/* There are pipes for the process pipeline's stdout and stderr.  */
#define KWSYSPE_PIPE_COUNT 2
58 59
#define KWSYSPE_PIPE_STDOUT 0
#define KWSYSPE_PIPE_STDERR 1
60 61

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

64 65
/* Debug output macro.  */
#if 0
66 67 68 69 70 71
#  define KWSYSPE_DEBUG(x)                                                    \
    ((void*)cp == (void*)0x00226DE0                                           \
       ? (fprintf(stderr, "%d/%p/%d ", (int)GetCurrentProcessId(), cp,        \
                  __LINE__),                                                  \
          fprintf x, fflush(stderr), 1)                                       \
       : (1))
72
#else
73
#  define KWSYSPE_DEBUG(x) (void)1
74 75
#endif

76 77
typedef LARGE_INTEGER kwsysProcessTime;

78 79 80
typedef struct kwsysProcessCreateInformation_s
{
  /* Windows child startup control data.  */
81
  STARTUPINFOW StartupInfo;
82 83 84 85 86

  /* Original handles before making inherited duplicates.  */
  HANDLE hStdInput;
  HANDLE hStdOutput;
  HANDLE hStdError;
87 88
} kwsysProcessCreateInformation;

89
typedef struct kwsysProcessPipeData_s kwsysProcessPipeData;
90 91 92
static DWORD WINAPI kwsysProcessPipeThreadRead(LPVOID ptd);
static void kwsysProcessPipeThreadReadPipe(kwsysProcess* cp,
                                           kwsysProcessPipeData* td);
93
static DWORD WINAPI kwsysProcessPipeThreadWake(LPVOID ptd);
94 95
static void kwsysProcessPipeThreadWakePipe(kwsysProcess* cp,
                                           kwsysProcessPipeData* td);
96
static int kwsysProcessInitialize(kwsysProcess* cp);
97 98
static DWORD kwsysProcessCreate(kwsysProcess* cp, int index,
                                kwsysProcessCreateInformation* si);
99
static void kwsysProcessDestroy(kwsysProcess* cp, int event);
100
static DWORD kwsysProcessSetupOutputPipeFile(PHANDLE handle, const char* name);
101 102
static void kwsysProcessSetupSharedPipe(DWORD nStdHandle, PHANDLE handle);
static void kwsysProcessSetupPipeNative(HANDLE native, PHANDLE handle);
103
static void kwsysProcessCleanupHandle(PHANDLE h);
104
static void kwsysProcessCleanup(kwsysProcess* cp, DWORD error);
105
static void kwsysProcessCleanErrorMessage(kwsysProcess* cp);
106 107
static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout,
                                      kwsysProcessTime* timeoutTime);
108
static int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime,
109
                                      double* userTimeout,
110
                                      kwsysProcessTime* timeoutLength);
111
static kwsysProcessTime kwsysProcessTimeGetCurrent(void);
112 113 114 115
static DWORD kwsysProcessTimeToDWORD(kwsysProcessTime t);
static double kwsysProcessTimeToDouble(kwsysProcessTime t);
static kwsysProcessTime kwsysProcessTimeFromDouble(double d);
static int kwsysProcessTimeLess(kwsysProcessTime in1, kwsysProcessTime in2);
116 117 118 119
static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1,
                                            kwsysProcessTime in2);
static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1,
                                                 kwsysProcessTime in2);
120
static void kwsysProcessSetExitException(kwsysProcess* cp, int code);
121 122
static void kwsysProcessSetExitExceptionByIndex(kwsysProcess* cp, int code,
                                                int idx);
123
static void kwsysProcessKillTree(int pid);
124
static void kwsysProcessDisablePipeThreads(kwsysProcess* cp);
125 126 127
static int kwsysProcessesInitialize(void);
static int kwsysTryEnterCreateProcessSection(void);
static void kwsysLeaveCreateProcessSection(void);
128 129
static int kwsysProcessesAdd(HANDLE hProcess, DWORD dwProcessId,
                             int newProcessGroup);
130 131
static void kwsysProcessesRemove(HANDLE hProcess);
static BOOL WINAPI kwsysCtrlHandler(DWORD dwCtrlType);
132

133 134 135
/* A structure containing synchronization data for each thread.  */
typedef struct kwsysProcessPipeSync_s kwsysProcessPipeSync;
struct kwsysProcessPipeSync_s
136
{
137
  /* Handle to the thread.  */
138
  HANDLE Thread;
139

140
  /* Semaphore indicating to the thread that a process has started.  */
141
  HANDLE Ready;
142

143 144
  /* Semaphore indicating to the thread that it should begin work.  */
  HANDLE Go;
145

146
  /* Semaphore indicating thread has reset for another process.  */
147
  HANDLE Reset;
148
};
149

150 151 152 153 154 155 156
/* A structure containing data for each pipe's threads.  */
struct kwsysProcessPipeData_s
{
  /* ------------- Data managed per instance of kwsysProcess ------------- */

  /* Synchronization data for reading thread.  */
  kwsysProcessPipeSync Reader;
157

158 159
  /* Synchronization data for waking thread.  */
  kwsysProcessPipeSync Waker;
160

161 162 163 164 165
  /* Index of this pipe.  */
  int Index;

  /* The kwsysProcess instance owning this pipe.  */
  kwsysProcess* Process;
166

167
  /* ------------- Data managed per call to Execute ------------- */
168

169
  /* Buffer for data read in this pipe's thread.  */
170
  char DataBuffer[KWSYSPE_PIPE_BUFFER_SIZE];
171

172 173
  /* The length of the data stored in the buffer.  */
  DWORD DataLength;
174

175 176
  /* Whether the pipe has been closed.  */
  int Closed;
177

178 179
  /* Handle for the read end of this pipe. */
  HANDLE Read;
180

181 182
  /* Handle for the write end of this pipe. */
  HANDLE Write;
183
};
184

185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
/* 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];
};

205 206 207 208
/* Structure containing data used to implement the child's execution.  */
struct kwsysProcess_s
{
  /* ------------- Data managed per instance of kwsysProcess ------------- */
209

210
  /* The status of the process structure.  */
211
  int State;
212

213
  /* The command lines to execute.  */
214
  wchar_t** Commands;
215 216 217 218
  int NumberOfCommands;

  /* The exit code of each command.  */
  DWORD* CommandExitCodes;
219

220
  /* The working directory for the child process.  */
221
  wchar_t* WorkingDirectory;
222

223 224 225 226 227 228
  /* Whether to create the child as a detached process.  */
  int OptionDetach;

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

229 230
  /* Whether to hide the child process's window.  */
  int HideWindow;
231

232 233 234
  /* Whether to treat command lines as verbatim.  */
  int Verbatim;

235 236 237
  /* Whether to merge stdout/stderr of the child.  */
  int MergeOutput;

238 239 240
  /* Whether to create the process in a new process group.  */
  int CreateProcessGroup;

241 242
  /* Mutex to protect the shared index used by threads to report data.  */
  HANDLE SharedIndexMutex;
243

244 245
  /* Semaphore used by threads to signal data ready.  */
  HANDLE Full;
246

247 248
  /* Whether we are currently deleting this kwsysProcess instance.  */
  int Deleting;
249

250
  /* Data specific to each pipe and its thread.  */
251 252
  kwsysProcessPipeData Pipe[KWSYSPE_PIPE_COUNT];

253 254 255 256 257
  /* Name of files to which stdin and stdout pipes are attached.  */
  char* PipeFileSTDIN;
  char* PipeFileSTDOUT;
  char* PipeFileSTDERR;

258 259 260 261 262
  /* Whether each pipe is shared with the parent process.  */
  int PipeSharedSTDIN;
  int PipeSharedSTDOUT;
  int PipeSharedSTDERR;

263 264 265 266 267
  /* Native pipes provided by the user.  */
  HANDLE PipeNativeSTDIN[2];
  HANDLE PipeNativeSTDOUT[2];
  HANDLE PipeNativeSTDERR[2];

268
  /* ------------- Data managed per call to Execute ------------- */
269

270 271
  /* Index of last pipe to report data, if any.  */
  int CurrentIndex;
272 273

  /* Index shared by threads to report data.  */
274
  int SharedIndex;
275

276 277
  /* The timeout length.  */
  double Timeout;
278

279 280
  /* Time at which the child started.  */
  kwsysProcessTime StartTime;
281

282 283
  /* Time at which the child will timeout.  Negative for no timeout.  */
  kwsysProcessTime TimeoutTime;
284

285 286
  /* Flag for whether the process was killed.  */
  int Killed;
287

288 289
  /* Flag for whether the timeout expired.  */
  int TimeoutExpired;
290

291 292
  /* Flag for whether the process has terminated.  */
  int Terminated;
293

294 295 296
  /* The number of pipes still open during execution and while waiting
     for pipes to close after process termination.  */
  int PipesLeft;
297

298
  /* Buffer for error messages.  */
299
  char ErrorMessage[KWSYSPE_PIPE_BUFFER_SIZE + 1];
300

301 302
  /* process results.  */
  kwsysProcessResults* ProcessResults;
303

304
  /* Windows process information data.  */
305 306 307 308 309
  PROCESS_INFORMATION* ProcessInformation;

  /* Data and process termination events for which to wait.  */
  PHANDLE ProcessEvents;
  int ProcessEventsLength;
310 311 312

  /* Real working directory of our own process.  */
  DWORD RealWorkingDirectoryLength;
313
  wchar_t* RealWorkingDirectory;
314 315 316 317

  /* Own handles for the child's ends of the pipes in the parent process.
     Used temporarily during process creation.  */
  HANDLE PipeChildStd[3];
318 319
};

320
kwsysProcess* kwsysProcess_New(void)
321 322 323 324 325 326 327 328
{
  int i;

  /* Process control structure.  */
  kwsysProcess* cp;

  /* Windows version number data.  */
  OSVERSIONINFO osv;
329

330 331 332 333 334
  /* Initialize list of processes before we get any farther.  It's especially
     important that the console Ctrl handler be added BEFORE starting the
     first process.  This prevents the risk of an orphaned process being
     started by the main thread while the default Ctrl handler is in
     progress.  */
335
  if (!kwsysProcessesInitialize()) {
336
    return 0;
337
  }
338

339 340
  /* Allocate a process control structure.  */
  cp = (kwsysProcess*)malloc(sizeof(kwsysProcess));
341
  if (!cp) {
342 343
    /* Could not allocate memory for the control structure.  */
    return 0;
344
  }
345
  ZeroMemory(cp, sizeof(*cp));
346

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

350
  /* Set initial status.  */
351
  cp->State = kwsysProcess_State_Starting;
352

353 354 355 356
  /* Choose a method of running the child based on version of
     windows.  */
  ZeroMemory(&osv, sizeof(osv));
  osv.dwOSVersionInfoSize = sizeof(osv);
357
#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
358 359 360 361 362 363
#  pragma warning(push)
#  ifdef __INTEL_COMPILER
#    pragma warning(disable : 1478)
#  else
#    pragma warning(disable : 4996)
#  endif
364
#endif
365
  GetVersionEx(&osv);
366
#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
367
#  pragma warning(pop)
368
#endif
369
  if (osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
370 371 372
    /* Win9x no longer supported.  */
    kwsysProcess_Delete(cp);
    return 0;
373
  }
374

375
  /* Initially no thread owns the mutex.  Initialize semaphore to 1.  */
376
  if (!(cp->SharedIndexMutex = CreateSemaphore(0, 1, 1, 0))) {
377 378
    kwsysProcess_Delete(cp);
    return 0;
379
  }
380

381
  /* Initially no data are available.  Initialize semaphore to 0.  */
382
  if (!(cp->Full = CreateSemaphore(0, 0, 1, 0))) {
383 384
    kwsysProcess_Delete(cp);
    return 0;
385
  }
386 387

  /* Create the thread to read each pipe.  */
388 389
  for (i = 0; i < KWSYSPE_PIPE_COUNT; ++i) {
    DWORD dummy = 0;
390

391 392
    /* Assign the thread its index.  */
    cp->Pipe[i].Index = i;
393

394 395
    /* Give the thread a pointer back to the kwsysProcess instance.  */
    cp->Pipe[i].Process = cp;
396

397
    /* No process is yet running.  Initialize semaphore to 0.  */
398
    if (!(cp->Pipe[i].Reader.Ready = CreateSemaphore(0, 0, 1, 0))) {
399 400
      kwsysProcess_Delete(cp);
      return 0;
401
    }
402

403
    /* The pipe is not yet reset.  Initialize semaphore to 0.  */
404
    if (!(cp->Pipe[i].Reader.Reset = CreateSemaphore(0, 0, 1, 0))) {
405 406
      kwsysProcess_Delete(cp);
      return 0;
407
    }
408

409
    /* The thread's buffer is initially empty.  Initialize semaphore to 1.  */
410
    if (!(cp->Pipe[i].Reader.Go = CreateSemaphore(0, 1, 1, 0))) {
411 412
      kwsysProcess_Delete(cp);
      return 0;
413
    }
414

415 416 417
    /* Create the reading thread.  It will block immediately.  The
       thread will not make deeply nested calls, so we need only a
       small stack.  */
418 419
    if (!(cp->Pipe[i].Reader.Thread = CreateThread(
            0, 1024, kwsysProcessPipeThreadRead, &cp->Pipe[i], 0, &dummy))) {
420 421
      kwsysProcess_Delete(cp);
      return 0;
422
    }
423

424
    /* No process is yet running.  Initialize semaphore to 0.  */
425
    if (!(cp->Pipe[i].Waker.Ready = CreateSemaphore(0, 0, 1, 0))) {
426 427
      kwsysProcess_Delete(cp);
      return 0;
428
    }
429

430
    /* The pipe is not yet reset.  Initialize semaphore to 0.  */
431
    if (!(cp->Pipe[i].Waker.Reset = CreateSemaphore(0, 0, 1, 0))) {
432 433
      kwsysProcess_Delete(cp);
      return 0;
434
    }
435

436
    /* The waker should not wake immediately.  Initialize semaphore to 0.  */
437
    if (!(cp->Pipe[i].Waker.Go = CreateSemaphore(0, 0, 1, 0))) {
438 439
      kwsysProcess_Delete(cp);
      return 0;
440
    }
441 442 443 444

    /* Create the waking thread.  It will block immediately.  The
       thread will not make deeply nested calls, so we need only a
       small stack.  */
445 446
    if (!(cp->Pipe[i].Waker.Thread = CreateThread(
            0, 1024, kwsysProcessPipeThreadWake, &cp->Pipe[i], 0, &dummy))) {
447 448
      kwsysProcess_Delete(cp);
      return 0;
449
    }
450 451
  }
  for (i = 0; i < 3; ++i) {
452
    cp->PipeChildStd[i] = INVALID_HANDLE_VALUE;
453
  }
454

455 456 457 458 459 460 461
  return cp;
}

void kwsysProcess_Delete(kwsysProcess* cp)
{
  int i;

462
  /* Make sure we have an instance.  */
463
  if (!cp) {
464
    return;
465
  }
466

467
  /* If the process is executing, wait for it to finish.  */
468 469
  if (cp->State == kwsysProcess_State_Executing) {
    if (cp->Detached) {
470
      kwsysProcess_Disown(cp);
471
    } else {
472
      kwsysProcess_WaitForExit(cp, 0);
473
    }
474
  }
475

476 477
  /* We are deleting the kwsysProcess instance.  */
  cp->Deleting = 1;
478

479
  /* Terminate each of the threads.  */
480
  for (i = 0; i < KWSYSPE_PIPE_COUNT; ++i) {
481
    /* Terminate this reading thread.  */
482
    if (cp->Pipe[i].Reader.Thread) {
483 484
      /* Signal the thread we are ready for it.  It will terminate
         immediately since Deleting is set.  */
485
      ReleaseSemaphore(cp->Pipe[i].Reader.Ready, 1, 0);
486

487
      /* Wait for the thread to exit.  */
488
      WaitForSingleObject(cp->Pipe[i].Reader.Thread, INFINITE);
489

490
      /* Close the handle to the thread. */
491
      kwsysProcessCleanupHandle(&cp->Pipe[i].Reader.Thread);
492
    }
493

494
    /* Terminate this waking thread.  */
495
    if (cp->Pipe[i].Waker.Thread) {
496 497
      /* Signal the thread we are ready for it.  It will terminate
         immediately since Deleting is set.  */
498
      ReleaseSemaphore(cp->Pipe[i].Waker.Ready, 1, 0);
499 500

      /* Wait for the thread to exit.  */
501
      WaitForSingleObject(cp->Pipe[i].Waker.Thread, INFINITE);
502 503

      /* Close the handle to the thread. */
504
      kwsysProcessCleanupHandle(&cp->Pipe[i].Waker.Thread);
505
    }
506

507
    /* Cleanup the pipe's semaphores.  */
508 509 510 511 512 513
    kwsysProcessCleanupHandle(&cp->Pipe[i].Reader.Ready);
    kwsysProcessCleanupHandle(&cp->Pipe[i].Reader.Go);
    kwsysProcessCleanupHandle(&cp->Pipe[i].Reader.Reset);
    kwsysProcessCleanupHandle(&cp->Pipe[i].Waker.Ready);
    kwsysProcessCleanupHandle(&cp->Pipe[i].Waker.Go);
    kwsysProcessCleanupHandle(&cp->Pipe[i].Waker.Reset);
514
  }
515

516 517 518
  /* Close the shared semaphores.  */
  kwsysProcessCleanupHandle(&cp->SharedIndexMutex);
  kwsysProcessCleanupHandle(&cp->Full);
519

520 521
  /* Free memory.  */
  kwsysProcess_SetCommand(cp, 0);
522
  kwsysProcess_SetWorkingDirectory(cp, 0);
523 524 525
  kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDIN, 0);
  kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDOUT, 0);
  kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDERR, 0);
526
  free(cp->CommandExitCodes);
527
  free(cp->ProcessResults);
528 529 530
  free(cp);
}

531
int kwsysProcess_SetCommand(kwsysProcess* cp, char const* const* command)
532
{
533
  int i;
534
  if (!cp) {
535
    return 0;
536 537
  }
  for (i = 0; i < cp->NumberOfCommands; ++i) {
538
    free(cp->Commands[i]);
539
  }
540
  cp->NumberOfCommands = 0;
541
  if (cp->Commands) {
542 543
    free(cp->Commands);
    cp->Commands = 0;
544 545
  }
  if (command) {
546
    return kwsysProcess_AddCommand(cp, command);
547
  }
548 549 550 551 552 553
  return 1;
}

int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command)
{
  int newNumberOfCommands;
554
  wchar_t** newCommands;
555 556

  /* Make sure we have a command to add.  */
557
  if (!cp || !command || !*command) {
558
    return 0;
559
  }
560

561 562
  /* Allocate a new array for command pointers.  */
  newNumberOfCommands = cp->NumberOfCommands + 1;
563 564
  if (!(newCommands =
          (wchar_t**)malloc(sizeof(wchar_t*) * newNumberOfCommands))) {
565 566
    /* Out of memory.  */
    return 0;
567
  }
568 569 570

  /* Copy any existing commands into the new array.  */
  {
571 572 573
    int i;
    for (i = 0; i < cp->NumberOfCommands; ++i) {
      newCommands[i] = cp->Commands[i];
574 575 576
    }
  }

577
  if (cp->Verbatim) {
578 579
    /* Copy the verbatim command line into the buffer.  */
    newCommands[cp->NumberOfCommands] = kwsysEncoding_DupToWide(*command);
580
  } else {
581 582 583 584 585 586
    /* Encode the arguments so CommandLineToArgvW can decode
       them from the command line string in the child.  */
    char buffer[32768]; /* CreateProcess max command-line length.  */
    char* end = buffer + sizeof(buffer);
    char* out = buffer;
    char const* const* a;
587
    for (a = command; *a; ++a) {
588 589 590
      int quote = !**a; /* Quote the empty string.  */
      int slashes = 0;
      char const* c;
591 592 593 594 595 596 597 598 599 600 601
      if (a != command && out != end) {
        *out++ = ' ';
      }
      for (c = *a; !quote && *c; ++c) {
        quote = (*c == ' ' || *c == '\t');
      }
      if (quote && out != end) {
        *out++ = '"';
      }
      for (c = *a; *c; ++c) {
        if (*c == '\\') {
602
          ++slashes;
603 604
        } else {
          if (*c == '"') {
605
            // Add n+1 backslashes to total 2n+1 before internal '"'.
606 607
            while (slashes-- >= 0 && out != end) {
              *out++ = '\\';
608 609
            }
          }
610 611 612 613
          slashes = 0;
        }
        if (out != end) {
          *out++ = *c;
614
        }
615 616
      }
      if (quote) {
617
        // Add n backslashes to total 2n before ending '"'.
618 619 620 621 622
        while (slashes-- > 0 && out != end) {
          *out++ = '\\';
        }
        if (out != end) {
          *out++ = '"';
623 624
        }
      }
625 626
    }
    if (out != end) {
627 628
      *out = '\0';
      newCommands[cp->NumberOfCommands] = kwsysEncoding_DupToWide(buffer);
629
    } else {
630 631
      newCommands[cp->NumberOfCommands] = 0;
    }
632 633
  }
  if (!newCommands[cp->NumberOfCommands]) {
634
    /* Out of memory or command line too long.  */
635 636
    free(newCommands);
    return 0;
637
  }
638

639 640 641 642 643
  /* Save the new array of commands.  */
  free(cp->Commands);
  cp->Commands = newCommands;
  cp->NumberOfCommands = newNumberOfCommands;
  return 1;
644 645 646 647
}

void kwsysProcess_SetTimeout(kwsysProcess* cp, double timeout)
{
648
  if (!cp) {
649
    return;
650
  }
651
  cp->Timeout = timeout;
652
  if (cp->Timeout < 0) {
653
    cp->Timeout = 0;
654
  }
655 656
  // Force recomputation of TimeoutTime.
  cp->TimeoutTime.QuadPart = -1;
657 658
}

659
int kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, const char* dir)
660
{
661
  if (!cp) {
662
    return 0;
663 664
  }
  if (cp->WorkingDirectory) {
665 666
    free(cp->WorkingDirectory);
    cp->WorkingDirectory = 0;
667 668
  }
  if (dir && dir[0]) {
669
    wchar_t* wdir = kwsysEncoding_DupToWide(dir);
670
    /* We must convert the working directory to a full path.  */
671
    DWORD length = GetFullPathNameW(wdir, 0, 0, 0);
672 673 674
    if (length > 0) {
      wchar_t* work_dir = malloc(length * sizeof(wchar_t));
      if (!work_dir) {
675
        free(wdir);
676
        return 0;
677 678
      }
      if (!GetFullPathNameW(wdir, length, work_dir, 0)) {
679 680
        free(work_dir);
        free(wdir);
681
        return 0;
682
      }
683
      cp->WorkingDirectory = work_dir;
684
    }
685 686
    free(wdir);
  }
687 688 689 690 691 692
  return 1;
}

int kwsysProcess_SetPipeFile(kwsysProcess* cp, int pipe, const char* file)
{
  char** pfile;
693
  if (!cp) {
694
    return 0;
695 696 697 698 699 700 701 702 703 704 705 706 707 708 709
  }
  switch (pipe) {
    case kwsysProcess_Pipe_STDIN:
      pfile = &cp->PipeFileSTDIN;
      break;
    case kwsysProcess_Pipe_STDOUT:
      pfile = &cp->PipeFileSTDOUT;
      break;
    case kwsysProcess_Pipe_STDERR:
      pfile = &cp->PipeFileSTDERR;
      break;
    default:
      return 0;
  }
  if (*pfile) {
710 711
    free(*pfile);
    *pfile = 0;
712 713
  }
  if (file) {
714
    *pfile = strdup(file);
715
    if (!*pfile) {
716 717
      return 0;
    }
718
  }
719

720 721
  /* If we are redirecting the pipe, do not share it or use a native
     pipe.  */
722
  if (*pfile) {
723
    kwsysProcess_SetPipeNative(cp, pipe, 0);
724
    kwsysProcess_SetPipeShared(cp, pipe, 0);
725
  }
726

727
  return 1;
728 729
}

730 731
void kwsysProcess_SetPipeShared(kwsysProcess* cp, int pipe, int shared)
{
732
  if (!cp) {
733
    return;
734
  }
735

736 737 738 739 740 741 742 743 744 745 746 747 748
  switch (pipe) {
    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;
  }
749

750 751
  /* If we are sharing the pipe, do not redirect it to a file or use a
     native pipe.  */
752
  if (shared) {
753
    kwsysProcess_SetPipeFile(cp, pipe, 0);
754
    kwsysProcess_SetPipeNative(cp, pipe, 0);
755
  }
756 757 758 759 760 761
}

void kwsysProcess_SetPipeNative(kwsysProcess* cp, int pipe, HANDLE p[2])
{
  HANDLE* pPipeNative = 0;

762
  if (!cp) {
763
    return;
764
  }
765

766 767 768 769 770 771 772 773 774 775 776 777 778
  switch (pipe) {
    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;
  }
779 780

  /* Copy the native pipe handles provided.  */
781
  if (p) {
782 783
    pPipeNative[0] = p[0];
    pPipeNative[1] = p[1];
784
  } else {
785 786
    pPipeNative[0] = 0;
    pPipeNative[1] = 0;
787
  }
788 789 790

  /* If we are using a native pipe, do not share it or redirect it to
     a file.  */
791
  if (p) {
792 793
    kwsysProcess_SetPipeFile(cp, pipe, 0);
    kwsysProcess_SetPipeShared(cp, pipe, 0);
794
  }
795 796
}

797 798
int kwsysProcess_GetOption(kwsysProcess* cp, int optionId)
{
799
  if (!cp) {
800
    return 0;
801
  }
802

803 804 805 806 807 808 809 810 811
  switch (optionId) {
    case kwsysProcess_Option_Detach:
      return cp->OptionDetach;
    case kwsysProcess_Option_HideWindow:
      return cp->HideWindow;
    case kwsysProcess_Option_MergeOutput:
      return cp->MergeOutput;
    case kwsysProcess_Option_Verbatim:
      return cp->Verbatim;
812 813
    case kwsysProcess_Option_CreateProcessGroup:
      return cp->CreateProcessGroup;
814 815 816
    default:
      return 0;
  }
817 818 819 820
}

void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, int value)
{
821
  if (!cp) {
822
    return;
823
  }
824

825 826 827 828 829 830 831 832 833 834 835 836 837
  switch (optionId) {
    case kwsysProcess_Option_Detach:
      cp->OptionDetach = value;
      break;
    case kwsysProcess_Option_HideWindow:
      cp->HideWindow = value;
      break;
    case kwsysProcess_Option_MergeOutput:
      cp->MergeOutput = value;
      break;
    case kwsysProcess_Option_Verbatim:
      cp->Verbatim = value;
      break;
838
    case kwsysProcess_Option_CreateProcessGroup:
839 840 841 842 843
      cp->CreateProcessGroup = value;
      break;
    default:
      break;
  }
844 845
}

846 847
int kwsysProcess_GetState(kwsysProcess* cp)
{
848
  return cp ? cp->State : kwsysProcess_State_Error;
849 850
}

851 852
int kwsysProcess_GetExitException(kwsysProcess* cp)
{
853 854 855
  return (cp && cp->ProcessResults && (cp->NumberOfCommands > 0))
    ? cp->ProcessResults[cp->NumberOfCommands - 1].ExitException
    : kwsysProcess_Exception_Other;
856 857 858 859
}

int kwsysProcess_GetExitValue(kwsysProcess* cp)
{
860 861 862
  return (cp && cp->ProcessResults && (cp->NumberOfCommands > 0))
    ? cp->ProcessResults[cp->NumberOfCommands - 1].ExitValue
    : -1;
863 864
}

865 866
int kwsysProcess_GetExitCode(kwsysProcess* cp)
{
867 868 869
  return (cp && cp->ProcessResults && (cp->NumberOfCommands > 0))
    ? cp->ProcessResults[cp->NumberOfCommands - 1].ExitCode
    : 0;
870 871 872 873
}

const char* kwsysProcess_GetErrorString(kwsysProcess* cp)
{
874
  if (!cp) {
875
    return "Process management structure could not be allocated";
876
  } else if (cp->State == kwsysProcess_State_Error) {
877
    return cp->ErrorMessage;
878
  }
879 880 881 882 883
  return "Success";
}

const char* kwsysProcess_GetExceptionString(kwsysProcess* cp)
{
884
  if (!(cp && cp->ProcessResults && (cp->NumberOfCommands > 0))) {
885
    return "GetExceptionString called with NULL process management structure";
886
  } else if (cp->State == kwsysProcess_State_Exception) {
887
    return cp->ProcessResults[cp->NumberOfCommands - 1].ExitExceptionString;
888
  }
889
  return "No exception";
890 891
}

892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934
/* 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

935 936
void kwsysProcess_Execute(kwsysProcess* cp)
{
937
  int i;
938 939

  /* Do not execute a second time.  */
940
  if (!cp || cp->State == kwsysProcess_State_Executing) {
941
    return;
942
  }
943

944
  /* Make sure we have something to run.  */
945
  if (cp->NumberOfCommands < 1) {
946 947 948
    strcpy(cp->ErrorMessage, "No command");
    cp->State = kwsysProcess_State_Error;
    return;
949
  }
950

951
  /* Initialize the control structure for a new process.  */
952
  if (!kwsysProcessInitialize(cp)) {
953 954
    strcpy(cp->ErrorMessage, "Out of memory");
    cp->State = kwsysProcess_State_Error;
955
    return;