|
|
@@ -102,6 +102,7 @@ static int kwsysProcessCreate(kwsysProcess* cp, int prIndex,
|
|
|
kwsysProcessCreateInformation* si, int* readEnd);
|
|
|
static void kwsysProcessDestroy(kwsysProcess* cp);
|
|
|
static int kwsysProcessSetupOutputPipeFile(int* p, const char* name);
|
|
|
+static int kwsysProcessSetupOutputPipeNative(int* p, int des[2]);
|
|
|
static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout,
|
|
|
kwsysProcessTime* timeoutTime);
|
|
|
static int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime,
|
|
|
@@ -217,6 +218,11 @@ struct kwsysProcess_s
|
|
|
int PipeSharedSTDOUT;
|
|
|
int PipeSharedSTDERR;
|
|
|
|
|
|
+ /* Native pipes provided by the user. */
|
|
|
+ int PipeNativeSTDIN[2];
|
|
|
+ int PipeNativeSTDOUT[2];
|
|
|
+ int PipeNativeSTDERR[2];
|
|
|
+
|
|
|
/* The real working directory of this process. */
|
|
|
int RealWorkingDirectoryLength;
|
|
|
char* RealWorkingDirectory;
|
|
|
@@ -470,9 +476,11 @@ int kwsysProcess_SetPipeFile(kwsysProcess* cp, int prPipe, const char* 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)
|
|
|
{
|
|
|
+ kwsysProcess_SetPipeNative(cp, prPipe, 0);
|
|
|
kwsysProcess_SetPipeShared(cp, prPipe, 0);
|
|
|
}
|
|
|
return 1;
|
|
|
@@ -494,10 +502,51 @@ void kwsysProcess_SetPipeShared(kwsysProcess* cp, int prPipe, int shared)
|
|
|
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)
|
|
|
{
|
|
|
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;
|
|
|
}
|
|
|
|
|
|
+ /* 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. */
|
|
|
cp->StartTime = kwsysProcessTimeGetCurrent();
|
|
|
cp->TimeoutTime.tv_sec = -1;
|
|
|
@@ -1297,6 +1359,19 @@ static int kwsysProcessCreate(kwsysProcess* cp, int prIndex,
|
|
|
{
|
|
|
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
|
|
|
{
|
|
|
si->StdIn = -1;
|
|
|
@@ -1340,6 +1415,17 @@ static int kwsysProcessCreate(kwsysProcess* cp, int prIndex,
|
|
|
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. */
|
|
|
if(pipe(si->ErrorPipe) < 0)
|
|
|
{
|
|
|
@@ -1519,6 +1605,26 @@ static int kwsysProcessSetupOutputPipeFile(int* p, const char* name)
|
|
|
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
|
|
|
expire. Returns 1 if the user timeout is first, and 0 otherwise. */
|