ENH: Added SetPipeShared method to allow stdout and stderr pipes to be shared with the parent process.

This commit is contained in:
Brad King 2003-12-16 17:20:01 -05:00
parent ab0a30e2b3
commit 802601b606
3 changed files with 171 additions and 15 deletions

View File

@ -31,6 +31,7 @@
#define kwsysProcess_SetTimeout kwsys(Process_SetTimeout)
#define kwsysProcess_SetWorkingDirectory kwsys(Process_SetWorkingDirectory)
#define kwsysProcess_SetPipeFile kwsys(Process_SetPipeFile)
#define kwsysProcess_SetPipeShared kwsys(Process_SetPipeShared)
#define kwsysProcess_Option_HideWindow kwsys(Process_Option_HideWindow)
#define kwsysProcess_GetOption kwsys(Process_GetOption)
#define kwsysProcess_SetOption kwsys(Process_SetOption)
@ -129,6 +130,14 @@ kwsysEXPORT int kwsysProcess_SetWorkingDirectory(kwsysProcess* cp,
kwsysEXPORT int kwsysProcess_SetPipeFile(kwsysProcess* cp, int pipe,
const char* file);
/**
* Set whether the given pipe in the child is shared with the parent
* process. The default is no for Pipe_STDOUT and Pipe_STDERR and yes
* for Pipe_STDIN.
*/
kwsysEXPORT void kwsysProcess_SetPipeShared(kwsysProcess* cp, int pipe,
int shared);
/**
* Get/Set a platform-specific option. Possible options are:
*
@ -301,6 +310,7 @@ kwsysEXPORT void kwsysProcess_Kill(kwsysProcess* cp);
# undef kwsysProcess_SetTimeout
# undef kwsysProcess_SetWorkingDirectory
# undef kwsysProcess_SetPipeFile
# undef kwsysProcess_SetPipeShared
# undef kwsysProcess_Option_HideWindow
# undef kwsysProcess_GetOption
# undef kwsysProcess_SetOption

View File

@ -169,6 +169,11 @@ struct kwsysProcess_s
char* PipeFileSTDOUT;
char* PipeFileSTDERR;
/* Whether each pipe is shared with the parent process. */
int PipeSharedSTDIN;
int PipeSharedSTDOUT;
int PipeSharedSTDERR;
/* The real working directory of this process. */
int RealWorkingDirectoryLength;
char* RealWorkingDirectory;
@ -184,7 +189,13 @@ kwsysProcess* kwsysProcess_New()
return 0;
}
memset(cp, 0, sizeof(kwsysProcess));
/* Share stdin with the parent process by default. */
cp->PipeSharedSTDIN = 1;
/* Set initial status. */
cp->State = kwsysProcess_State_Starting;
return cp;
}
@ -393,9 +404,38 @@ int kwsysProcess_SetPipeFile(kwsysProcess* cp, int pipe, const char* file)
}
strcpy(*pfile, file);
}
/* If we are redirecting the pipe, do not share it. */
if(*pfile)
{
kwsysProcess_SetPipeShared(cp, pipe, 0);
}
return 1;
}
/*--------------------------------------------------------------------------*/
void kwsysProcess_SetPipeShared(kwsysProcess* cp, int pipe, int shared)
{
if(!cp)
{
return;
}
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;
}
/* If we are sharing the pipe, do not redirect it to a file. */
if(shared)
{
kwsysProcess_SetPipeFile(cp, pipe, 0);
}
}
/*--------------------------------------------------------------------------*/
int kwsysProcess_GetOption(kwsysProcess* cp, int optionId)
{
@ -545,6 +585,14 @@ void kwsysProcess_Execute(kwsysProcess* cp)
}
}
/* Replace the stderr pipe with the parent's if requested. In this
case the select call will report that stderr is closed
immediately. */
if(cp->PipeSharedSTDERR)
{
kwsysProcessCleanupDescriptor(&si.StdErr);
si.StdErr = 2;
}
/* The timeout period starts now. */
cp->StartTime = kwsysProcessTimeGetCurrent();
@ -553,7 +601,7 @@ void kwsysProcess_Execute(kwsysProcess* cp)
/* Create the pipeline of processes. */
{
int readEnd = 0;
int readEnd = -1;
for(i=0; i < cp->NumberOfCommands; ++i)
{
if(!kwsysProcessCreate(cp, i, &si, &readEnd))
@ -562,13 +610,19 @@ void kwsysProcess_Execute(kwsysProcess* cp)
/* Release resources that may have been allocated for this
process before an error occurred. */
if(i > 0 || si.StdIn > 0)
kwsysProcessCleanupDescriptor(&readEnd);
if(si.StdIn != 0)
{
kwsysProcessCleanupDescriptor(&si.StdIn);
}
kwsysProcessCleanupDescriptor(&readEnd);
kwsysProcessCleanupDescriptor(&si.StdOut);
kwsysProcessCleanupDescriptor(&si.StdErr);
if(si.StdOut != 1)
{
kwsysProcessCleanupDescriptor(&si.StdOut);
}
if(si.StdErr != 2)
{
kwsysProcessCleanupDescriptor(&si.StdErr);
}
kwsysProcessCleanupDescriptor(&si.TermPipe);
kwsysProcessCleanupDescriptor(&si.ErrorPipe[0]);
kwsysProcessCleanupDescriptor(&si.ErrorPipe[1]);
@ -1106,10 +1160,14 @@ static int kwsysProcessCreate(kwsysProcess* cp, int index,
return 0;
}
}
else
else if(cp->PipeSharedSTDIN)
{
si->StdIn = 0;
}
else
{
si->StdIn = -1;
}
/* Setup the process's stdout. */
{
@ -1140,6 +1198,15 @@ static int kwsysProcessCreate(kwsysProcess* cp, int index,
}
}
/* Replace the stdout pipe with the parent's if requested. In this
case the select call will report that stderr is closed
immediately. */
if(index == cp->NumberOfCommands-1 && cp->PipeSharedSTDOUT)
{
kwsysProcessCleanupDescriptor(&si->StdOut);
si->StdOut = 1;
}
/* Create the error reporting pipe. */
if(pipe(si->ErrorPipe) < 0)
{
@ -1165,12 +1232,22 @@ static int kwsysProcessCreate(kwsysProcess* cp, int index,
close(si->ErrorPipe[0]);
/* Setup the stdin, stdout, and stderr pipes. */
if(index > 0 || si->StdIn > 0)
if(si->StdIn > 0)
{
dup2(si->StdIn, 0);
}
dup2(si->StdOut, 1);
dup2(si->StdErr, 2);
else if(si->StdIn < 0)
{
close(0);
}
if(si->StdOut != 1)
{
dup2(si->StdOut, 1);
}
if(si->StdErr != 2)
{
dup2(si->StdErr, 2);
}
/* Clear the close-on-exec flag for stdin, stdout, and stderr.
Also clear it for the termination pipe. All other pipe handles

View File

@ -184,6 +184,11 @@ struct kwsysProcess_s
char* PipeFileSTDOUT;
char* PipeFileSTDERR;
/* Whether each pipe is shared with the parent process. */
int PipeSharedSTDIN;
int PipeSharedSTDOUT;
int PipeSharedSTDERR;
/* Handle to automatically delete the Win9x forwarding executable. */
HANDLE Win9xHandle;
@ -264,6 +269,9 @@ kwsysProcess* kwsysProcess_New()
}
ZeroMemory(cp, sizeof(*cp));
/* Share stdin with the parent process by default. */
cp->PipeSharedSTDIN = 1;
/* Set initial status. */
cp->State = kwsysProcess_State_Starting;
@ -805,9 +813,39 @@ int kwsysProcess_SetPipeFile(kwsysProcess* cp, int pipe, const char* file)
}
strcpy(*pfile, file);
}
/* If we are redirecting the pipe, do not share it. */
if(*pfile)
{
kwsysProcess_SetPipeShared(cp, pipe, 0);
}
return 1;
}
/*--------------------------------------------------------------------------*/
void kwsysProcess_SetPipeShared(kwsysProcess* cp, int pipe, int shared)
{
if(!cp)
{
return;
}
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;
}
/* If we are sharing the pipe, do not redirect it to a file. */
if(shared)
{
kwsysProcess_SetPipeFile(cp, pipe, 0);
}
}
/*--------------------------------------------------------------------------*/
int kwsysProcess_GetOption(kwsysProcess* cp, int optionId)
{
@ -973,6 +1011,15 @@ void kwsysProcess_Execute(kwsysProcess* cp)
}
}
/* Replace the stderr pipe with the parent process's if requested.
In this case the pipe thread will still run but never report
data. */
if(cp->PipeSharedSTDERR)
{
kwsysProcessCleanupHandle(&si.StartupInfo.hStdError);
si.StartupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
}
/* Create the pipeline of processes. */
{
HANDLE readEnd = 0;
@ -989,12 +1036,18 @@ void kwsysProcess_Execute(kwsysProcess* cp)
/* Release resources that may have been allocated for this
process before an error occurred. */
kwsysProcessCleanupHandle(&readEnd);
if(i > 0)
if(si.StartupInfo.hStdInput != GetStdHandle(STD_INPUT_HANDLE))
{
kwsysProcessCleanupHandle(&si.StartupInfo.hStdInput);
}
kwsysProcessCleanupHandle(&si.StartupInfo.hStdOutput);
kwsysProcessCleanupHandle(&si.StartupInfo.hStdError);
if(si.StartupInfo.hStdOutput != GetStdHandle(STD_OUTPUT_HANDLE))
{
kwsysProcessCleanupHandle(&si.StartupInfo.hStdOutput);
}
if(si.StartupInfo.hStdOutput != GetStdHandle(STD_ERROR_HANDLE))
{
kwsysProcessCleanupHandle(&si.StartupInfo.hStdError);
}
kwsysProcessCleanupHandle(&si.ErrorPipeRead);
kwsysProcessCleanupHandle(&si.ErrorPipeWrite);
return;
@ -1533,10 +1586,14 @@ int kwsysProcessCreate(kwsysProcess* cp, int index,
}
si->StartupInfo.hStdInput = fin;
}
else
else if(cp->PipeSharedSTDIN)
{
si->StartupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
}
else
{
si->StartupInfo.hStdInput = INVALID_HANDLE_VALUE;
}
/* Setup the process's stdout. */
{
@ -1578,6 +1635,15 @@ int kwsysProcessCreate(kwsysProcess* cp, int index,
}
}
/* Replace the stdout pipe with the parent process's if requested.
In this case the pipe thread will still run but never report
data. */
if(index == cp->NumberOfCommands-1 && cp->PipeSharedSTDOUT)
{
kwsysProcessCleanupHandle(&si->StartupInfo.hStdOutput);
si->StartupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
}
/* Create the child process. */
{
BOOL r;
@ -1678,8 +1744,11 @@ int kwsysProcessCreate(kwsysProcess* cp, int index,
kwsysProcessCleanupHandle(&si->StartupInfo.hStdInput);
}
/* The parent process does not need the inhertied pipe write end. */
kwsysProcessCleanupHandle(&si->StartupInfo.hStdOutput);
if(si->StartupInfo.hStdOutput != GetStdHandle(STD_OUTPUT_HANDLE))
{
/* The parent process does not need the inhertied pipe write end. */
kwsysProcessCleanupHandle(&si->StartupInfo.hStdOutput);
}
return 1;
}