Commit c485feba authored by Brad King's avatar Brad King

ENH: Added Process execution implementation.

parent 66101d64
......@@ -29,9 +29,19 @@ SET(KWSYS_NO_ANSI_STRING_STREAM ${CMAKE_NO_ANSI_STRING_STREAM})
SET(KWSYS_NO_ANSI_FOR_SCOPE ${CMAKE_NO_ANSI_FOR_SCOPE})
SET(CLASSES Directory RegularExpression SystemTools)
SET(HEADERS Configure)
SET(H Process)
SET(HXX Configure)
IF(NOT UNIX)
ADD_EXECUTABLE(${KWSYS_NAMESPACE}ProcessFwd9x ProcessFwd9x.c)
ADD_EXECUTABLE(${KWSYS_NAMESPACE}EncodeExecutable EncodeExecutable.c)
SET(SRCS ProcessWin32.c ${CMAKE_CURRENT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c)
SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c
PROPERTIES GENERATED 1)
ELSE(NOT UNIX)
SET(SRCS ProcessUNIX.c)
ENDIF(NOT UNIX)
SET(SRCS)
SET(KWSYS_INCLUDES)
FOREACH(c ${CLASSES})
SET(SRCS ${SRCS} ${c}.cxx)
......@@ -42,7 +52,15 @@ FOREACH(c ${CLASSES})
${PROJECT_BINARY_DIR}/../${KWSYS_NAMESPACE}/${c}.hxx)
ENDFOREACH(c)
FOREACH(h ${HEADERS})
FOREACH(h ${H})
CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/${h}.h.in
${PROJECT_BINARY_DIR}/../${KWSYS_NAMESPACE}/${h}.h
@ONLY IMMEDIATE)
SET(KWSYS_INCLUDES ${KWSYS_INCLUDES}
${PROJECT_BINARY_DIR}/../${KWSYS_NAMESPACE}/${h}.h)
ENDFOREACH(h)
FOREACH(h ${HXX})
CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/${h}.hxx.in
${PROJECT_BINARY_DIR}/../${KWSYS_NAMESPACE}/${h}.hxx
@ONLY IMMEDIATE)
......@@ -93,3 +111,29 @@ IF(KWSYS_DEFAULTS)
ADD_EXECUTABLE(test1 test1.cxx)
TARGET_LINK_LIBRARIES(test1 ${KWSYS_NAMESPACE})
ENDIF(KWSYS_DEFAULTS)
IF(NOT UNIX)
SET(BIN_DIR ${CMAKE_CURRENT_BINARY_DIR})
IF(EXECUTABLE_OUTPUT_PATH)
SET(BIN_DIR ${EXECUTABLE_OUTPUT_PATH})
ENDIF(EXECUTABLE_OUTPUT_PATH)
SET(MAKE_SYSTEM)
SET(CFG_INTDIR "/${CMAKE_CFG_INTDIR}")
IF(CMAKE_BUILD_TOOL MATCHES "make")
SET(CFG_INTDIR "")
ENDIF(CMAKE_BUILD_TOOL MATCHES "make")
SET(CMD ${BIN_DIR}${CFG_INTDIR}/${KWSYS_NAMESPACE}EncodeExecutable.exe)
SET(FWD ${BIN_DIR}${CFG_INTDIR}/${KWSYS_NAMESPACE}ProcessFwd9x.exe)
ADD_CUSTOM_COMMAND(
TARGET ${KWSYS_NAMESPACE}
SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/ProcessFwd9x.c
COMMAND ${CMD}
ARGS ${FWD} ${CMAKE_CURRENT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c
${KWSYS_NAMESPACE} ProcessFwd9x
OUTPUTS ${CMAKE_CURRENT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c
DEPENDS ${CMD} ${FWD})
ADD_DEPENDENCIES(${KWSYS_NAMESPACE} ${KWSYS_NAMESPACE}ProcessFwd9x
${KWSYS_NAMESPACE}EncodeExecutable)
ENDIF(NOT UNIX)
/*=========================================================================
Program: KWSys - Kitware System Library
Module: EncodeExecutable.c
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
See http://www.cmake.org/HTML/Copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include <stdio.h>
int main(int argc, char* argv[])
{
FILE* ifp;
FILE* ofp;
int i;
int n;
int count = 0;
unsigned char buffer[1024];
/* Check arguments. */
if(argc != 5)
{
fprintf(stderr, "Usage: %s <input> <output> <kwsys-name> <array>\n",
argv[0]);
return 1;
}
/* Open the input file. */
ifp = fopen(argv[1], "rb");
if(!ifp)
{
fprintf(stderr, "Cannot open input file: \"%s\"\n", argv[1]);
return 2;
}
ofp = fopen(argv[2], "w");
if(!ofp)
{
fprintf(stderr, "Cannot open output file: \"%s\"\n", argv[2]);
return 2;
}
/* Prepend header comment. */
fprintf(ofp, "/*\n * DO NOT EDIT\n * This file is generated by:\n");
fprintf(ofp, " * %s\n */\n\n", argv[0]);
fprintf(ofp, "#include <stdio.h>\n\n");
/* Split file up in 1024-byte chunks. */
while((n = fread(buffer, 1, 1024, ifp)) > 0)
{
fprintf(ofp, "static unsigned char kwsysEncodedArray%s_%d[%d] = {\n",
argv[4], count++, n);
for(i=0; i < n-1; ++i)
{
fprintf(ofp, "0x%02X", buffer[i]);
if(i%10 == 9)
{
fprintf(ofp, ",\n");
}
else
{
fprintf(ofp, ", ");
}
}
fprintf(ofp, "0x%02X};\n\n", buffer[n-1]);
}
fclose(ifp);
/* Provide a function to write the data to a file. */
fprintf(ofp, "extern int %sEncodedWriteArray%s(const char* fname)\n",
argv[3], argv[4]);
fprintf(ofp, "{\n");
fprintf(ofp, " FILE* ofp = fopen(fname, \"wb\");\n");
fprintf(ofp, " if(!ofp) { return 0; }\n");
for(i=0; i < count; ++i)
{
fprintf(ofp, " if(fwrite(kwsysEncodedArray%s_%d, 1,\n"
" sizeof(kwsysEncodedArray%s_%d), ofp) !=\n"
" sizeof(kwsysEncodedArray%s_%d))\n",
argv[4], i, argv[4], i, argv[4], i);
fprintf(ofp, " {\n");
fprintf(ofp, " fclose(ofp);\n");
fprintf(ofp, " _unlink(fname);\n");
fprintf(ofp, " return 0;\n");
fprintf(ofp, " }\n");
}
fprintf(ofp, " fclose(ofp);\n");
fprintf(ofp, " return 1;\n");
fprintf(ofp, "}\n");
fclose(ofp);
return 0;
}
/*=========================================================================
Program: KWSys - Kitware System Library
Module: Process.h.in
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
See http://www.cmake.org/HTML/Copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef @KWSYS_NAMESPACE@_Process_h
#define @KWSYS_NAMESPACE@_Process_h
#define kwsys(x) @KWSYS_NAMESPACE@##x
#define kwsysProcess_STDOUT kwsys(Process_STDOUT)
#define kwsysProcess_STDERR kwsys(Process_STDERR)
#define kwsysProcess_Timeout kwsys(Process_Timeout)
#define kwsysProcess_Starting kwsys(Process_Starting)
#define kwsysProcess_Executing kwsys(Process_Executing)
#define kwsysProcess_Expired kwsys(Process_Expired)
#define kwsysProcess_Exited kwsys(Process_Exited)
#define kwsysProcess_Killed kwsys(Process_Killed)
#define kwsysProcess_Signalled kwsys(Process_Signalled)
#define kwsysProcess_Error kwsys(Process_Error)
#define kwsysProcess_State kwsys(Process_State)
#define kwsysProcess_Pipes_e kwsys(Process_Pipes_e)
#define kwsysProcess_State_e kwsys(Process_State_e)
#define kwsysProcess_s kwsys(Process_s)
#define kwsysProcess kwsys(Process)
#define kwsysProcess_New kwsys(Process_New)
#define kwsysProcess_Delete kwsys(Process_Delete)
#define kwsysProcess_SetCommand kwsys(Process_SetCommand)
#define kwsysProcess_SetTimeout kwsys(Process_SetTimeout)
#define kwsysProcess_GetState kwsys(Process_GetState)
#define kwsysProcess_GetExitCode kwsys(Process_GetExitCode)
#define kwsysProcess_GetErrorString kwsys(Process_GetErrorString)
#define kwsysProcess_Execute kwsys(Process_Execute)
#define kwsysProcess_WaitForData kwsys(Process_WaitForData)
#define kwsysProcess_WaitForExit kwsys(Process_WaitForExit)
#define kwsysProcess_Kill kwsys(Process_Kill)
#if defined(__cplusplus)
extern "C"
{
#endif
typedef enum kwsysProcess_Pipes_e
{
kwsysProcess_STDOUT=1,
kwsysProcess_STDERR=2,
kwsysProcess_Timeout=255
} kwsysProcess_Pipes;
typedef enum kwsysProcess_State_e
{
kwsysProcess_Starting, /* Between New and Execute; No process run yet */
kwsysProcess_Executing, /* Process is running */
kwsysProcess_Expired, /* Process timeout expired and was killed */
kwsysProcess_Exited, /* Process exited */
kwsysProcess_Killed, /* Process was killed by Kill */
kwsysProcess_Signalled, /* Process was terminated by a signal (crash / ctrl-C) */
kwsysProcess_Error /* Internal error of Process */
} kwsysProcess_State;
typedef struct kwsysProcess_s kwsysProcess;
kwsysProcess* kwsysProcess_New();
void kwsysProcess_Delete(kwsysProcess* cp);
void kwsysProcess_SetCommand(kwsysProcess* cp, char const* const* command);
void kwsysProcess_SetTimeout(kwsysProcess* cp, double timeout);
/*
* Get the current internal state of the kwsysProcess instance
*/
int kwsysProcess_GetState(kwsysProcess* cp);
/*
* Get process return code or when signalled, get the signal code
*/
int kwsysProcess_GetExitCode(kwsysProcess* cp);
/*
* On kwsysProcess_Error get the error message
*/
const char* kwsysProcess_GetErrorString(kwsysProcess* cp);
void kwsysProcess_Execute(kwsysProcess* cp);
/*
* Block until data available on requested pipe or one of the timeouts expired,
* or the process exits. If the pipe is not specified, data on that pipe are
* ignored.
*
* pipes - a list of interested pipes - kwsysProcess_STDOUT | kwsysProcess_STDERR
* data - returns pointer to data if read, NULL otherwise
* length - length of the returned data
* userTimeout - timeout for the current kwsysProcess_WaitForData call
* the userTimeout will contain the remaining time
*
* Returns:
* 0 - Process exited or killed or process timeout expired with no data
* available, or no process running.
* PIPE id otherwise:
* kwsysProcess_STDOUT - if stdout is returned
* kwsysProcess_STDERR - if stderr is returned
* kwsysProcess_Timeout - if user timeout expired
*/
int kwsysProcess_WaitForData(kwsysProcess* cp, int pipes, char** data, int* length,
double* userTimeout);
/*
* Block until the process exits or the timeout expires. If no process is
* running, return immediatly.
*
* Returns:
* 0 - When user timeout expires
* 1 - Otherwise
*/
int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout);
/*
* Kills the process. kwsysProcess_WaitForExit should still be called
* after kwsysProcess_Kill.
*/
void kwsysProcess_Kill(kwsysProcess* cp);
#if defined(__cplusplus)
} /* extern "C" */
#endif
/* If we are building a kwsysProcess .c file, let it use these macros. */
#if !defined(KWSYS_IN_PROCESS_C)
# undef kwsys
# undef kwsysProcess_STDOUT
# undef kwsysProcess_STDERR
# undef kwsysProcess_Timeout
# undef kwsysProcess_Starting
# undef kwsysProcess_Executing
# undef kwsysProcess_Expired
# undef kwsysProcess_Exited
# undef kwsysProcess_Killed
# undef kwsysProcess_Signalled
# undef kwsysProcess_Error
# undef kwsysProcess_State
# undef kwsysProcess_Pipes_e
# undef kwsysProcess_State_e
# undef kwsysProcess_s
# undef kwsysProcess
# undef kwsysProcess_New
# undef kwsysProcess_Delete
# undef kwsysProcess_SetCommand
# undef kwsysProcess_SetTimeout
# undef kwsysProcess_GetState
# undef kwsysProcess_GetExitCode
# undef kwsysProcess_GetErrorString
# undef kwsysProcess_Execute
# undef kwsysProcess_WaitForData
# undef kwsysProcess_WaitForExit
# undef kwsysProcess_Kill
#endif
#endif
/*=========================================================================
Program: KWSys - Kitware System Library
Module: ProcessFwd9x.c
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
See http://www.cmake.org/HTML/Copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
/*
On Windows9x platforms, this executable is spawned between a parent
process and the child it is invoking to work around a bug. See the
Win32 implementation file for details.
*/
#include <windows.h>
#include <stdio.h>
int main()
{
/* Process startup information for the real child. */
STARTUPINFO si;
PROCESS_INFORMATION pi;
/* The result of waiting for the child to exit. */
DWORD waitResult;
/* The child's process return code. */
DWORD retVal;
/* The command line used to invoke this process. */
LPSTR commandLine = GetCommandLine();
/* Pointer that will be advanced to the beginning of the command
line of the real child process. */
LPSTR cmdLine = commandLine;
/* Handle to the error reporting pipe provided by the parent. This
is parsed off the command line. */
HANDLE errorPipe = 0;
/* Handle to the event the parent uses to tell us to kill the child.
This is parsed off the command line. */
HANDLE killEvent = 0;
/* An array of the handles on which we wait when the child is
running. */
HANDLE waitHandles[2] = {0, 0};
/* Move the pointer past the name of this executable. */
if(*cmdLine == '"')
{
++cmdLine;
while(*cmdLine && *cmdLine != '"') { ++cmdLine; }
if(*cmdLine) { ++cmdLine; }
}
else
{
while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
}
/* Parse the error pipe handle. */
while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
sscanf(cmdLine, "%d", &errorPipe);
/* Parse the kill event handle. */
while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
sscanf(cmdLine, "%d", &killEvent);
/* Skip to the beginning of the command line of the real child. */
while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
/* Create the subprocess. */
ZeroMemory(&si, sizeof(si));
ZeroMemory(&pi, sizeof(pi));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOWDEFAULT;
si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
if(!CreateProcess(0, cmdLine, 0, 0, TRUE, 0, 0, 0, &si, &pi))
{
/* Error creating the process. Report the error to the parent
process through the special error reporting pipe. */
LPVOID lpMsgBuf;
DWORD n;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
WriteFile(errorPipe, lpMsgBuf, strlen(lpMsgBuf)+1, &n, 0);
LocalFree( lpMsgBuf );
return 1;
}
CloseHandle(pi.hThread);
/* Wait for subprocess to exit or for kill event from parent. */
waitHandles[0] = killEvent;
waitHandles[1] = pi.hProcess;
waitResult = WaitForMultipleObjects(2, waitHandles, 0, INFINITE);
/* Check what happened. */
if(waitResult == WAIT_OBJECT_0)
{
/* We were asked to kill the child. */
TerminateProcess(pi.hProcess, -1);
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
return 1;
}
else if(GetExitCodeProcess(pi.hProcess, &retVal))
{
/* The child exited and we could get the return code. */
CloseHandle(pi.hProcess);
return retVal;
}
else
{
/* The child exited and we could not get the return code. Report
the problem to the parent process. */
DWORD n;
const char* msg = "Failed to get process return code.";
WriteFile(errorPipe, msg, strlen(msg)+1, &n, 0);
CloseHandle(pi.hProcess);
return -1;
}
}
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment