ENH: Added Process_SetPipeNative method to allow user code to override the pipes connected to the child pipeline.
This commit is contained in:
parent
9d566ee8bd
commit
6eef6638a5
|
@ -33,6 +33,7 @@
|
||||||
#define kwsysProcess_SetTimeout kwsys_ns(Process_SetTimeout)
|
#define kwsysProcess_SetTimeout kwsys_ns(Process_SetTimeout)
|
||||||
#define kwsysProcess_SetWorkingDirectory kwsys_ns(Process_SetWorkingDirectory)
|
#define kwsysProcess_SetWorkingDirectory kwsys_ns(Process_SetWorkingDirectory)
|
||||||
#define kwsysProcess_SetPipeFile kwsys_ns(Process_SetPipeFile)
|
#define kwsysProcess_SetPipeFile kwsys_ns(Process_SetPipeFile)
|
||||||
|
#define kwsysProcess_SetPipeNative kwsys_ns(Process_SetPipeNative)
|
||||||
#define kwsysProcess_SetPipeShared kwsys_ns(Process_SetPipeShared)
|
#define kwsysProcess_SetPipeShared kwsys_ns(Process_SetPipeShared)
|
||||||
#define kwsysProcess_Option_Detach kwsys_ns(Process_Option_Detach)
|
#define kwsysProcess_Option_Detach kwsys_ns(Process_Option_Detach)
|
||||||
#define kwsysProcess_Option_HideWindow kwsys_ns(Process_Option_HideWindow)
|
#define kwsysProcess_Option_HideWindow kwsys_ns(Process_Option_HideWindow)
|
||||||
|
@ -71,6 +72,7 @@
|
||||||
#define kwsysProcess_Pipe_STDOUT kwsys_ns(Process_Pipe_STDOUT)
|
#define kwsysProcess_Pipe_STDOUT kwsys_ns(Process_Pipe_STDOUT)
|
||||||
#define kwsysProcess_Pipe_STDERR kwsys_ns(Process_Pipe_STDERR)
|
#define kwsysProcess_Pipe_STDERR kwsys_ns(Process_Pipe_STDERR)
|
||||||
#define kwsysProcess_Pipe_Timeout kwsys_ns(Process_Pipe_Timeout)
|
#define kwsysProcess_Pipe_Timeout kwsys_ns(Process_Pipe_Timeout)
|
||||||
|
#define kwsysProcess_Pipe_Handle kwsys_ns(Process_Pipe_Handle)
|
||||||
#define kwsysProcess_WaitForExit kwsys_ns(Process_WaitForExit)
|
#define kwsysProcess_WaitForExit kwsys_ns(Process_WaitForExit)
|
||||||
#define kwsysProcess_Kill kwsys_ns(Process_Kill)
|
#define kwsysProcess_Kill kwsys_ns(Process_Kill)
|
||||||
|
|
||||||
|
@ -84,6 +86,13 @@ extern "C"
|
||||||
*/
|
*/
|
||||||
typedef struct kwsysProcess_s kwsysProcess;
|
typedef struct kwsysProcess_s kwsysProcess;
|
||||||
|
|
||||||
|
/* Platform-specific pipe handle type. */
|
||||||
|
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||||
|
typedef void* kwsysProcess_Pipe_Handle;
|
||||||
|
#else
|
||||||
|
typedef int kwsysProcess_Pipe_Handle;
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new Process instance.
|
* Create a new Process instance.
|
||||||
*/
|
*/
|
||||||
|
@ -145,6 +154,27 @@ kwsysEXPORT int kwsysProcess_SetPipeFile(kwsysProcess* cp, int pipe,
|
||||||
kwsysEXPORT void kwsysProcess_SetPipeShared(kwsysProcess* cp, int pipe,
|
kwsysEXPORT void kwsysProcess_SetPipeShared(kwsysProcess* cp, int pipe,
|
||||||
int shared);
|
int shared);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify a platform-specific native pipe for use as one of the child
|
||||||
|
* interface pipes. The native pipe is specified by an array of two
|
||||||
|
* descriptors or handles. The first entry in the array (index 0)
|
||||||
|
* should be the read end of the pipe. The second entry in the array
|
||||||
|
* (index 1) should be the write end of the pipe. If a null pointer
|
||||||
|
* is given the option will be disabled.
|
||||||
|
*
|
||||||
|
* For Pipe_STDIN the native pipe is connected to the first child in
|
||||||
|
* the pipeline as its stdin. After the children are created the
|
||||||
|
* write end of the pipe will be closed in the child process and the
|
||||||
|
* read end will be closed in the parent process.
|
||||||
|
*
|
||||||
|
* For Pipe_STDOUT and Pipe_STDERR the pipe is connected to the last
|
||||||
|
* child as its stdout or stderr. After the children are created the
|
||||||
|
* write end of the pipe will be closed in the parent process and the
|
||||||
|
* read end will be closed in the child process.
|
||||||
|
*/
|
||||||
|
kwsysEXPORT void kwsysProcess_SetPipeNative(kwsysProcess* cp, int pipe,
|
||||||
|
kwsysProcess_Pipe_Handle p[2]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get/Set a possibly platform-specific option. Possible options are:
|
* Get/Set a possibly platform-specific option. Possible options are:
|
||||||
*
|
*
|
||||||
|
@ -349,6 +379,7 @@ kwsysEXPORT void kwsysProcess_Kill(kwsysProcess* cp);
|
||||||
# undef kwsysProcess_SetTimeout
|
# undef kwsysProcess_SetTimeout
|
||||||
# undef kwsysProcess_SetWorkingDirectory
|
# undef kwsysProcess_SetWorkingDirectory
|
||||||
# undef kwsysProcess_SetPipeFile
|
# undef kwsysProcess_SetPipeFile
|
||||||
|
# undef kwsysProcess_SetPipeNative
|
||||||
# undef kwsysProcess_SetPipeShared
|
# undef kwsysProcess_SetPipeShared
|
||||||
# undef kwsysProcess_Option_Detach
|
# undef kwsysProcess_Option_Detach
|
||||||
# undef kwsysProcess_Option_HideWindow
|
# undef kwsysProcess_Option_HideWindow
|
||||||
|
@ -387,6 +418,7 @@ kwsysEXPORT void kwsysProcess_Kill(kwsysProcess* cp);
|
||||||
# undef kwsysProcess_Pipe_STDOUT
|
# undef kwsysProcess_Pipe_STDOUT
|
||||||
# undef kwsysProcess_Pipe_STDERR
|
# undef kwsysProcess_Pipe_STDERR
|
||||||
# undef kwsysProcess_Pipe_Timeout
|
# undef kwsysProcess_Pipe_Timeout
|
||||||
|
# undef kwsysProcess_Pipe_Handle
|
||||||
# undef kwsysProcess_WaitForExit
|
# undef kwsysProcess_WaitForExit
|
||||||
# undef kwsysProcess_Kill
|
# undef kwsysProcess_Kill
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -102,6 +102,7 @@ static int kwsysProcessCreate(kwsysProcess* cp, int prIndex,
|
||||||
kwsysProcessCreateInformation* si, int* readEnd);
|
kwsysProcessCreateInformation* si, int* readEnd);
|
||||||
static void kwsysProcessDestroy(kwsysProcess* cp);
|
static void kwsysProcessDestroy(kwsysProcess* cp);
|
||||||
static int kwsysProcessSetupOutputPipeFile(int* p, const char* name);
|
static int kwsysProcessSetupOutputPipeFile(int* p, const char* name);
|
||||||
|
static int kwsysProcessSetupOutputPipeNative(int* p, int des[2]);
|
||||||
static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout,
|
static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout,
|
||||||
kwsysProcessTime* timeoutTime);
|
kwsysProcessTime* timeoutTime);
|
||||||
static int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime,
|
static int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime,
|
||||||
|
@ -217,6 +218,11 @@ struct kwsysProcess_s
|
||||||
int PipeSharedSTDOUT;
|
int PipeSharedSTDOUT;
|
||||||
int PipeSharedSTDERR;
|
int PipeSharedSTDERR;
|
||||||
|
|
||||||
|
/* Native pipes provided by the user. */
|
||||||
|
int PipeNativeSTDIN[2];
|
||||||
|
int PipeNativeSTDOUT[2];
|
||||||
|
int PipeNativeSTDERR[2];
|
||||||
|
|
||||||
/* The real working directory of this process. */
|
/* The real working directory of this process. */
|
||||||
int RealWorkingDirectoryLength;
|
int RealWorkingDirectoryLength;
|
||||||
char* RealWorkingDirectory;
|
char* RealWorkingDirectory;
|
||||||
|
@ -470,9 +476,11 @@ int kwsysProcess_SetPipeFile(kwsysProcess* cp, int prPipe, const char* file)
|
||||||
strcpy(*pfile, file);
|
strcpy(*pfile, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we are redirecting the pipe, do not share it. */
|
/* If we are redirecting the pipe, do not share it or use a native
|
||||||
|
pipe. */
|
||||||
if(*pfile)
|
if(*pfile)
|
||||||
{
|
{
|
||||||
|
kwsysProcess_SetPipeNative(cp, prPipe, 0);
|
||||||
kwsysProcess_SetPipeShared(cp, prPipe, 0);
|
kwsysProcess_SetPipeShared(cp, prPipe, 0);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -494,10 +502,51 @@ void kwsysProcess_SetPipeShared(kwsysProcess* cp, int prPipe, int shared)
|
||||||
default: return;
|
default: return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we are sharing the pipe, do not redirect it to a file. */
|
/* If we are sharing the pipe, do not redirect it to a file or use a
|
||||||
|
native pipe. */
|
||||||
if(shared)
|
if(shared)
|
||||||
{
|
{
|
||||||
kwsysProcess_SetPipeFile(cp, prPipe, 0);
|
kwsysProcess_SetPipeFile(cp, prPipe, 0);
|
||||||
|
kwsysProcess_SetPipeNative(cp, prPipe, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
void kwsysProcess_SetPipeNative(kwsysProcess* cp, int prPipe, int p[2])
|
||||||
|
{
|
||||||
|
int* pPipeNative = 0;
|
||||||
|
|
||||||
|
if(!cp)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the native pipe descriptors provided. */
|
||||||
|
if(p)
|
||||||
|
{
|
||||||
|
pPipeNative[0] = p[0];
|
||||||
|
pPipeNative[1] = p[1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pPipeNative[0] = -1;
|
||||||
|
pPipeNative[1] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we are using a native pipe, do not share it or redirect it to
|
||||||
|
a file. */
|
||||||
|
if(p)
|
||||||
|
{
|
||||||
|
kwsysProcess_SetPipeFile(cp, prPipe, 0);
|
||||||
|
kwsysProcess_SetPipeShared(cp, prPipe, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -684,6 +733,19 @@ void kwsysProcess_Execute(kwsysProcess* cp)
|
||||||
si.StdErr = 2;
|
si.StdErr = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Replace the stderr pipe with the native pipe provided if any. In
|
||||||
|
this case the select call will report that stderr is closed
|
||||||
|
immediately. */
|
||||||
|
if(cp->PipeNativeSTDERR[1] >= 0)
|
||||||
|
{
|
||||||
|
if(!kwsysProcessSetupOutputPipeNative(&si.StdErr, cp->PipeNativeSTDERR))
|
||||||
|
{
|
||||||
|
kwsysProcessCleanup(cp, 1);
|
||||||
|
kwsysProcessCleanupDescriptor(&si.StdErr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* The timeout period starts now. */
|
/* The timeout period starts now. */
|
||||||
cp->StartTime = kwsysProcessTimeGetCurrent();
|
cp->StartTime = kwsysProcessTimeGetCurrent();
|
||||||
cp->TimeoutTime.tv_sec = -1;
|
cp->TimeoutTime.tv_sec = -1;
|
||||||
|
@ -1297,6 +1359,19 @@ static int kwsysProcessCreate(kwsysProcess* cp, int prIndex,
|
||||||
{
|
{
|
||||||
si->StdIn = 0;
|
si->StdIn = 0;
|
||||||
}
|
}
|
||||||
|
else if(cp->PipeNativeSTDIN[0] >= 0)
|
||||||
|
{
|
||||||
|
si->StdIn = 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. */
|
||||||
|
if((fcntl(cp->PipeNativeSTDIN[0], F_SETFD, FD_CLOEXEC) < 0) ||
|
||||||
|
(fcntl(cp->PipeNativeSTDIN[1], F_SETFD, FD_CLOEXEC) < 0))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
si->StdIn = -1;
|
si->StdIn = -1;
|
||||||
|
@ -1340,6 +1415,17 @@ static int kwsysProcessCreate(kwsysProcess* cp, int prIndex,
|
||||||
si->StdOut = 1;
|
si->StdOut = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Replace the stdout pipe with the native pipe provided if any. In
|
||||||
|
this case the select call will report that stdout is closed
|
||||||
|
immediately. */
|
||||||
|
if(prIndex == cp->NumberOfCommands-1 && cp->PipeNativeSTDOUT[1] >= 0)
|
||||||
|
{
|
||||||
|
if(!kwsysProcessSetupOutputPipeNative(&si->StdOut, cp->PipeNativeSTDOUT))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Create the error reporting pipe. */
|
/* Create the error reporting pipe. */
|
||||||
if(pipe(si->ErrorPipe) < 0)
|
if(pipe(si->ErrorPipe) < 0)
|
||||||
{
|
{
|
||||||
|
@ -1519,6 +1605,26 @@ static int kwsysProcessSetupOutputPipeFile(int* p, const char* name)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
static int kwsysProcessSetupOutputPipeNative(int* p, int des[2])
|
||||||
|
{
|
||||||
|
/* Close the existing descriptor. */
|
||||||
|
kwsysProcessCleanupDescriptor(p);
|
||||||
|
|
||||||
|
/* Set close-on-exec flag on the pipe's ends. The proper end will
|
||||||
|
be dup2-ed into the standard descriptor number after fork but
|
||||||
|
before exec. */
|
||||||
|
if((fcntl(des[0], F_SETFD, FD_CLOEXEC) < 0) ||
|
||||||
|
(fcntl(des[1], F_SETFD, FD_CLOEXEC) < 0))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Assign the replacement descriptor. */
|
||||||
|
*p = des[1];
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
/* Get the time at which either the process or user timeout will
|
/* Get the time at which either the process or user timeout will
|
||||||
expire. Returns 1 if the user timeout is first, and 0 otherwise. */
|
expire. Returns 1 if the user timeout is first, and 0 otherwise. */
|
||||||
|
|
|
@ -105,6 +105,8 @@ static int kwsysProcessCreate(kwsysProcess* cp, int index,
|
||||||
static void kwsysProcessDestroy(kwsysProcess* cp, int event);
|
static void kwsysProcessDestroy(kwsysProcess* cp, int event);
|
||||||
static int kwsysProcessSetupOutputPipeFile(PHANDLE handle, const char* name);
|
static int kwsysProcessSetupOutputPipeFile(PHANDLE handle, const char* name);
|
||||||
static int kwsysProcessSetupSharedPipe(DWORD nStdHandle, PHANDLE handle);
|
static int kwsysProcessSetupSharedPipe(DWORD nStdHandle, PHANDLE handle);
|
||||||
|
static int kwsysProcessSetupPipeNative(PHANDLE handle, HANDLE p[2],
|
||||||
|
int isWrite);
|
||||||
static void kwsysProcessCleanupHandle(PHANDLE h);
|
static void kwsysProcessCleanupHandle(PHANDLE h);
|
||||||
static void kwsysProcessCleanupHandleSafe(PHANDLE h, DWORD nStdHandle);
|
static void kwsysProcessCleanupHandleSafe(PHANDLE h, DWORD nStdHandle);
|
||||||
static void kwsysProcessCleanup(kwsysProcess* cp, int error);
|
static void kwsysProcessCleanup(kwsysProcess* cp, int error);
|
||||||
|
@ -247,6 +249,11 @@ struct kwsysProcess_s
|
||||||
int PipeSharedSTDOUT;
|
int PipeSharedSTDOUT;
|
||||||
int PipeSharedSTDERR;
|
int PipeSharedSTDERR;
|
||||||
|
|
||||||
|
/* Native pipes provided by the user. */
|
||||||
|
HANDLE PipeNativeSTDIN[2];
|
||||||
|
HANDLE PipeNativeSTDOUT[2];
|
||||||
|
HANDLE PipeNativeSTDERR[2];
|
||||||
|
|
||||||
/* Handle to automatically delete the Win9x forwarding executable. */
|
/* Handle to automatically delete the Win9x forwarding executable. */
|
||||||
HANDLE Win9xHandle;
|
HANDLE Win9xHandle;
|
||||||
|
|
||||||
|
@ -790,9 +797,11 @@ int kwsysProcess_SetPipeFile(kwsysProcess* cp, int pipe, const char* file)
|
||||||
strcpy(*pfile, file);
|
strcpy(*pfile, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we are redirecting the pipe, do not share it. */
|
/* If we are redirecting the pipe, do not share it or use a native
|
||||||
|
pipe. */
|
||||||
if(*pfile)
|
if(*pfile)
|
||||||
{
|
{
|
||||||
|
kwsysProcess_SetPipeNative(cp, pipe, 0);
|
||||||
kwsysProcess_SetPipeShared(cp, pipe, 0);
|
kwsysProcess_SetPipeShared(cp, pipe, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -815,10 +824,51 @@ void kwsysProcess_SetPipeShared(kwsysProcess* cp, int pipe, int shared)
|
||||||
default: return;
|
default: return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we are sharing the pipe, do not redirect it to a file. */
|
/* If we are sharing the pipe, do not redirect it to a file or use a
|
||||||
|
native pipe. */
|
||||||
if(shared)
|
if(shared)
|
||||||
{
|
{
|
||||||
kwsysProcess_SetPipeFile(cp, pipe, 0);
|
kwsysProcess_SetPipeFile(cp, pipe, 0);
|
||||||
|
kwsysProcess_SetPipeNative(cp, pipe, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
void kwsysProcess_SetPipeNative(kwsysProcess* cp, int pipe, HANDLE p[2])
|
||||||
|
{
|
||||||
|
HANDLE* pPipeNative = 0;
|
||||||
|
|
||||||
|
if(!cp)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the native pipe handles provided. */
|
||||||
|
if(p)
|
||||||
|
{
|
||||||
|
pPipeNative[0] = p[0];
|
||||||
|
pPipeNative[1] = p[1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pPipeNative[0] = 0;
|
||||||
|
pPipeNative[1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we are using a native pipe, do not share it or redirect it to
|
||||||
|
a file. */
|
||||||
|
if(p)
|
||||||
|
{
|
||||||
|
kwsysProcess_SetPipeFile(cp, pipe, 0);
|
||||||
|
kwsysProcess_SetPipeShared(cp, pipe, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1020,6 +1070,21 @@ void kwsysProcess_Execute(kwsysProcess* cp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Replace the stderr pipe with the native pipe provided if any. In
|
||||||
|
this case the pipe thread will still run but never report
|
||||||
|
data. */
|
||||||
|
if(cp->PipeNativeSTDERR[1])
|
||||||
|
{
|
||||||
|
if(!kwsysProcessSetupPipeNative(&si.StartupInfo.hStdError,
|
||||||
|
cp->PipeNativeSTDERR, 1))
|
||||||
|
{
|
||||||
|
kwsysProcessCleanup(cp, 1);
|
||||||
|
kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdError,
|
||||||
|
STD_ERROR_HANDLE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Create the pipeline of processes. */
|
/* Create the pipeline of processes. */
|
||||||
{
|
{
|
||||||
HANDLE readEnd = 0;
|
HANDLE readEnd = 0;
|
||||||
|
@ -1622,6 +1687,15 @@ int kwsysProcessCreate(kwsysProcess* cp, int index,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(cp->PipeNativeSTDIN[0])
|
||||||
|
{
|
||||||
|
/* Use the provided native pipe. */
|
||||||
|
if(!kwsysProcessSetupPipeNative(&si->StartupInfo.hStdInput,
|
||||||
|
cp->PipeNativeSTDIN, 0))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Explicitly give the child no stdin. */
|
/* Explicitly give the child no stdin. */
|
||||||
|
@ -1680,6 +1754,18 @@ int kwsysProcessCreate(kwsysProcess* cp, int index,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Replace the stdout pipe with the native pipe provided if any. In
|
||||||
|
this case the pipe thread will still run but never report
|
||||||
|
data. */
|
||||||
|
if(index == cp->NumberOfCommands-1 && cp->PipeNativeSTDOUT[1])
|
||||||
|
{
|
||||||
|
if(!kwsysProcessSetupPipeNative(&si->StartupInfo.hStdOutput,
|
||||||
|
cp->PipeNativeSTDOUT, 1))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Create the child process. */
|
/* Create the child process. */
|
||||||
{
|
{
|
||||||
BOOL r;
|
BOOL r;
|
||||||
|
@ -1928,6 +2014,25 @@ int kwsysProcessSetupSharedPipe(DWORD nStdHandle, PHANDLE handle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
int kwsysProcessSetupPipeNative(PHANDLE handle, HANDLE p[2], int isWrite)
|
||||||
|
{
|
||||||
|
/* Close the existing inherited handle. */
|
||||||
|
kwsysProcessCleanupHandle(handle);
|
||||||
|
|
||||||
|
/* Create an inherited duplicate of the handle. This also closes
|
||||||
|
the non-inherited version. */
|
||||||
|
if(!DuplicateHandle(GetCurrentProcess(), p[isWrite? 1:0],
|
||||||
|
GetCurrentProcess(), handle,
|
||||||
|
0, TRUE, (DUPLICATE_CLOSE_SOURCE |
|
||||||
|
DUPLICATE_SAME_ACCESS)))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
/* Close the given handle if it is open. Reset its value to 0. */
|
/* Close the given handle if it is open. Reset its value to 0. */
|
||||||
|
|
Loading…
Reference in New Issue