summaryrefslogtreecommitdiffstats
path: root/Source/kwsys/ProcessWin32.c
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2003-12-13 19:13:54 (GMT)
committerBrad King <brad.king@kitware.com>2003-12-13 19:13:54 (GMT)
commit1f40a4205b23f7c7f58b55a89cad0d0c5bd65bda (patch)
tree59853432dc4e6c607e478d09587e4cad9761b31e /Source/kwsys/ProcessWin32.c
parentdc96992e5680bad5d0ed226022f8d409269c6eae (diff)
downloadCMake-1f40a4205b23f7c7f58b55a89cad0d0c5bd65bda.zip
CMake-1f40a4205b23f7c7f58b55a89cad0d0c5bd65bda.tar.gz
CMake-1f40a4205b23f7c7f58b55a89cad0d0c5bd65bda.tar.bz2
ENH: Added SetPipeFile method to allow the process pipeline stdin, stdout, and stderr to be redirected from/to files.
Diffstat (limited to 'Source/kwsys/ProcessWin32.c')
-rw-r--r--Source/kwsys/ProcessWin32.c189
1 files changed, 183 insertions, 6 deletions
diff --git a/Source/kwsys/ProcessWin32.c b/Source/kwsys/ProcessWin32.c
index 6563fc9..90f54b60 100644
--- a/Source/kwsys/ProcessWin32.c
+++ b/Source/kwsys/ProcessWin32.c
@@ -80,6 +80,7 @@ static int kwsysProcessCreate(kwsysProcess* cp, int index,
kwsysProcessCreateInformation* si,
PHANDLE readEnd);
static void kwsysProcessDestroy(kwsysProcess* cp, int event);
+static int kwsysProcessSetupOutputPipeFile(PHANDLE handle, const char* name);
static void kwsysProcessCleanupHandle(PHANDLE h);
static void kwsysProcessCleanup(kwsysProcess* cp, int error);
static void kwsysProcessCleanErrorMessage(kwsysProcess* cp);
@@ -181,6 +182,11 @@ struct kwsysProcess_s
/* Data specific to each pipe and its thread. */
kwsysProcessPipeData Pipe[KWSYSPE_PIPE_COUNT];
+ /* Name of files to which stdin and stdout pipes are attached. */
+ char* PipeFileSTDIN;
+ char* PipeFileSTDOUT;
+ char* PipeFileSTDERR;
+
/* ------------- Data managed per call to Execute ------------- */
/* The exceptional behavior that terminated the process, if any. */
@@ -229,6 +235,10 @@ struct kwsysProcess_s
/* Data and process termination events for which to wait. */
PHANDLE ProcessEvents;
int ProcessEventsLength;
+
+ /* Real working directory of our own process. */
+ DWORD RealWorkingDirectoryLength;
+ char* RealWorkingDirectory;
};
/*--------------------------------------------------------------------------*/
@@ -456,6 +466,9 @@ void kwsysProcess_Delete(kwsysProcess* cp)
/* Free memory. */
kwsysProcess_SetCommand(cp, 0);
kwsysProcess_SetWorkingDirectory(cp, 0);
+ kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDIN, 0);
+ kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDOUT, 0);
+ kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDERR, 0);
if(cp->CommandExitCodes)
{
free(cp->CommandExitCodes);
@@ -715,11 +728,11 @@ void kwsysProcess_SetTimeout(kwsysProcess* cp, double timeout)
}
/*--------------------------------------------------------------------------*/
-void kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, const char* dir)
+int kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, const char* dir)
{
if(!cp)
{
- return;
+ return 0;
}
if(cp->WorkingDirectory)
{
@@ -733,13 +746,51 @@ void kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, const char* dir)
if(length > 0)
{
cp->WorkingDirectory = (char*)malloc(length);
+ if(!cp->WorkingDirectory)
+ {
+ return 0;
+ }
if(!GetFullPathName(dir, length, cp->WorkingDirectory, 0))
{
free(cp->WorkingDirectory);
cp->WorkingDirectory = 0;
+ return 0;
}
}
}
+ return 1;
+}
+
+/*--------------------------------------------------------------------------*/
+int kwsysProcess_SetPipeFile(kwsysProcess* cp, int pipe, const char* file)
+{
+ char** pfile;
+ if(!cp)
+ {
+ return 0;
+ }
+ 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)
+ {
+ free(*pfile);
+ *pfile = 0;
+ }
+ if(file)
+ {
+ *pfile = malloc(strlen(file)+1);
+ if(!*pfile)
+ {
+ return 0;
+ }
+ strcpy(*pfile, file);
+ }
+ return 1;
}
/*--------------------------------------------------------------------------*/
@@ -832,6 +883,20 @@ void kwsysProcess_Execute(kwsysProcess* cp)
return;
}
+ /* 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. */
+ if(cp->WorkingDirectory)
+ {
+ if(!GetCurrentDirectory(cp->RealWorkingDirectoryLength,
+ cp->RealWorkingDirectory))
+ {
+ kwsysProcessCleanup(cp, 1);
+ return;
+ }
+ SetCurrentDirectory(cp->WorkingDirectory);
+ }
+
/* Reset the Win9x resume and kill events. */
if(cp->Win9x)
{
@@ -880,6 +945,19 @@ void kwsysProcess_Execute(kwsysProcess* cp)
return;
}
+ /* Replace the stderr pipe with a file if requested. In this case
+ the pipe thread will still run but never report data. */
+ if(cp->PipeFileSTDERR)
+ {
+ if(!kwsysProcessSetupOutputPipeFile(&si.StartupInfo.hStdError,
+ cp->PipeFileSTDERR))
+ {
+ kwsysProcessCleanup(cp, 1);
+ kwsysProcessCleanupHandle(&si.StartupInfo.hStdError);
+ return;
+ }
+ }
+
/* Create the pipeline of processes. */
{
HANDLE readEnd = 0;
@@ -916,6 +994,14 @@ void kwsysProcess_Execute(kwsysProcess* cp)
processes in the pipeline. */
kwsysProcessCleanupHandle(&si.StartupInfo.hStdError);
+ /* Restore the working directory. */
+ if(cp->RealWorkingDirectory)
+ {
+ SetCurrentDirectory(cp->RealWorkingDirectory);
+ free(cp->RealWorkingDirectory);
+ cp->RealWorkingDirectory = 0;
+ }
+
/* The timeout period starts now. */
cp->StartTime = kwsysProcessTimeGetCurrent();
cp->TimeoutTime = kwsysProcessTimeFromDouble(-1);
@@ -1372,6 +1458,20 @@ int kwsysProcessInitialize(kwsysProcess* cp)
cp->ProcessEvents[0] = cp->Full;
cp->ProcessEventsLength = cp->NumberOfCommands+1;
+ /* Allocate space to save the real working directory of this process. */
+ if(cp->WorkingDirectory)
+ {
+ cp->RealWorkingDirectoryLength = GetCurrentDirectory(0, 0);
+ if(cp->RealWorkingDirectoryLength > 0)
+ {
+ cp->RealWorkingDirectory = malloc(cp->RealWorkingDirectoryLength);
+ if(!cp->RealWorkingDirectory)
+ {
+ return 0;
+ }
+ }
+ }
+
return 1;
}
@@ -1398,6 +1498,26 @@ int kwsysProcessCreate(kwsysProcess* cp, int index,
/* This function is done with this handle. */
*readEnd = 0;
}
+ else if(cp->PipeFileSTDIN)
+ {
+ /* Create a handle to read a file for stdin. */
+ HANDLE fin = CreateFile(cp->PipeFileSTDIN, GENERIC_READ,
+ FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
+ if(fin == INVALID_HANDLE_VALUE)
+ {
+ return 0;
+ }
+ /* Create an inherited duplicate of the handle. This also closes
+ the non-inherited version. */
+ if(!DuplicateHandle(GetCurrentProcess(), fin,
+ GetCurrentProcess(), &fin,
+ 0, TRUE, (DUPLICATE_CLOSE_SOURCE |
+ DUPLICATE_SAME_ACCESS)))
+ {
+ return 0;
+ }
+ si->StartupInfo.hStdInput = fin;
+ }
else
{
si->StartupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
@@ -1424,13 +1544,25 @@ int kwsysProcessCreate(kwsysProcess* cp, int index,
maybeClose = 0;
}
if(!DuplicateHandle(GetCurrentProcess(), writeEnd,
- GetCurrentProcess(), &si->StartupInfo.hStdOutput,
+ GetCurrentProcess(), &writeEnd,
0, TRUE, (maybeClose | DUPLICATE_SAME_ACCESS)))
{
return 0;
}
+ si->StartupInfo.hStdOutput = writeEnd;
}
+ /* Replace the stdout pipe with a file if requested. In this case
+ the pipe thread will still run but never report data. */
+ if(index == cp->NumberOfCommands-1 && cp->PipeFileSTDOUT)
+ {
+ if(!kwsysProcessSetupOutputPipeFile(&si->StartupInfo.hStdOutput,
+ cp->PipeFileSTDOUT))
+ {
+ return 0;
+ }
+ }
+
/* Create the child process. */
{
BOOL r;
@@ -1473,9 +1605,8 @@ int kwsysProcessCreate(kwsysProcess* cp, int index,
/* Create the child in a suspended state so we can wait until all
children have been created before running any one. */
r = CreateProcess(0, realCommand, 0, 0, TRUE,
- cp->Win9x? 0 : CREATE_SUSPENDED, 0,
- cp->WorkingDirectory, &si->StartupInfo,
- &cp->ProcessInformation[index]);
+ cp->Win9x? 0 : CREATE_SUSPENDED, 0, 0,
+ &si->StartupInfo, &cp->ProcessInformation[index]);
if(cp->Win9x)
{
@@ -1582,6 +1713,41 @@ void kwsysProcessDestroy(kwsysProcess* cp, int event)
}
/*--------------------------------------------------------------------------*/
+int kwsysProcessSetupOutputPipeFile(PHANDLE phandle, const char* name)
+{
+ HANDLE fout;
+ if(!name)
+ {
+ return 1;
+ }
+
+ /* Close the existing inherited handle. */
+ kwsysProcessCleanupHandle(phandle);
+
+ /* Create a handle to write a file for the pipe. */
+ fout = CreateFile(name, GENERIC_WRITE, FILE_SHARE_READ, 0,
+ CREATE_ALWAYS, 0, 0);
+ if(fout == INVALID_HANDLE_VALUE)
+ {
+ return 0;
+ }
+
+ /* Create an inherited duplicate of the handle. This also closes
+ the non-inherited version. */
+ if(!DuplicateHandle(GetCurrentProcess(), fout,
+ GetCurrentProcess(), &fout,
+ 0, TRUE, (DUPLICATE_CLOSE_SOURCE |
+ DUPLICATE_SAME_ACCESS)))
+ {
+ return 0;
+ }
+
+ /* Assign the replacement handle. */
+ *phandle = fout;
+ return 1;
+}
+
+/*--------------------------------------------------------------------------*/
/* Close the given handle if it is open. Reset its value to 0. */
void kwsysProcessCleanupHandle(PHANDLE h)
@@ -1652,6 +1818,12 @@ void kwsysProcessCleanup(kwsysProcess* cp, int error)
kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hProcess);
}
}
+
+ /* Restore the working directory. */
+ if(cp->RealWorkingDirectory)
+ {
+ SetCurrentDirectory(cp->RealWorkingDirectory);
+ }
}
/* Free memory. */
@@ -1665,6 +1837,11 @@ void kwsysProcessCleanup(kwsysProcess* cp, int error)
free(cp->ProcessEvents);
cp->ProcessEvents = 0;
}
+ if(cp->RealWorkingDirectory)
+ {
+ free(cp->RealWorkingDirectory);
+ cp->RealWorkingDirectory = 0;
+ }
/* Close each pipe. */
for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)