Fix for it to compile on "all" windows platforms...

This commit is contained in:
Andy Cedilnik 2002-09-29 21:55:10 -04:00
parent 4fe98d8068
commit 375c695ba1
2 changed files with 156 additions and 39 deletions

View File

@ -25,6 +25,19 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <windows.h> #include <windows.h>
#if defined(__BORLANDC__)
# define STRICMP stricmp
# define TO_INTPTR(x) ((long)(x))
#else // Visual studio
# if ( _MSC_VER >= 1300 )
# include <stddef.h>
# define TO_INTPTR(x) ((intptr_t)(x))
# else // Visual Studio 6
# define TO_INTPTR(x) ((long)(x))
# endif // Visual studio .NET
# define STRICMP _stricmp
#endif // Borland
#define POPEN_1 1 #define POPEN_1 1
#define POPEN_2 2 #define POPEN_2 2
#define POPEN_3 3 #define POPEN_3 3
@ -34,6 +47,7 @@
#define win32_error(x,y) std::cout << "Win32_Error(" << x << ", " << y << ")" << std::endl, false #define win32_error(x,y) std::cout << "Win32_Error(" << x << ", " << y << ")" << std::endl, false
bool cmWin32ProcessExecution::StartProcess( bool cmWin32ProcessExecution::StartProcess(
const char* cmd, const char* path, bool verbose) const char* cmd, const char* path, bool verbose)
{ {
@ -47,6 +61,25 @@ bool cmWin32ProcessExecution::Wait(int timeout)
return this->PrivateClose(timeout); return this->PrivateClose(timeout);
} }
#define PERROR(str) //::ErrorMessage(__LINE__, str)
static void ErrorMessage(int line, char *str) //display detailed error info
{
DWORD lastmsg = GetLastError();
LPVOID msg;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
lastmsg,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &msg,
0,
NULL
);
printf("%d - %s: %s (%d)\n",line,str,msg, lastmsg);
LocalFree(msg);
::SetLastError(ERROR_SUCCESS);
}
/* /*
* Internal dictionary mapping popen* file pointers to process handles, * Internal dictionary mapping popen* file pointers to process handles,
* for use when retrieving the process exit code. See _PyPclose() below * for use when retrieving the process exit code. See _PyPclose() below
@ -62,19 +95,27 @@ static BOOL RealPopenCreateProcess(const char *cmdstring,
HANDLE hStderr, HANDLE hStderr,
HANDLE *hProcess) HANDLE *hProcess)
{ {
PERROR("Start");
//std::cout << "Run: " << cmdstring << std::endl;
PERROR("Start");
PROCESS_INFORMATION piProcInfo; PROCESS_INFORMATION piProcInfo;
PERROR("PROCESS_INFORMATION");
STARTUPINFO siStartInfo; STARTUPINFO siStartInfo;
PERROR("STARTUPINFO");
char *s1,*s2, *s3 = " /c "; char *s1,*s2, *s3 = " /c ";
int i; int i;
int x; int x;
if (i = GetEnvironmentVariable("COMSPEC",NULL,0)) if (i = GetEnvironmentVariable("COMSPEC",NULL,0))
{ {
PERROR("GetEnvironmentVariable");
char *comshell; char *comshell;
s1 = (char *)_alloca(i); s1 = (char *)_alloca(i);
if (!(x = GetEnvironmentVariable("COMSPEC", s1, i))) if (!(x = GetEnvironmentVariable("COMSPEC", s1, i)))
{
PERROR("GetEnvironmentVariable");
return x; return x;
}
/* Explicitly check if we are using COMMAND.COM. If we are /* Explicitly check if we are using COMMAND.COM. If we are
* then use the w9xpopen hack. * then use the w9xpopen hack.
@ -85,7 +126,7 @@ static BOOL RealPopenCreateProcess(const char *cmdstring,
++comshell; ++comshell;
if (GetVersion() < 0x80000000 && if (GetVersion() < 0x80000000 &&
_stricmp(comshell, "command.com") != 0) STRICMP(comshell, "command.com") != 0)
{ {
/* NT/2000 and not using command.com. */ /* NT/2000 and not using command.com. */
x = i + (int)strlen(s3) + (int)strlen(cmdstring) + 1; x = i + (int)strlen(s3) + (int)strlen(cmdstring) + 1;
@ -187,11 +228,13 @@ static BOOL RealPopenCreateProcess(const char *cmdstring,
&siStartInfo, &siStartInfo,
&piProcInfo) ) &piProcInfo) )
{ {
PERROR("CreateProcess");
/* Close the handles now so anyone waiting is woken. */ /* Close the handles now so anyone waiting is woken. */
CloseHandle(piProcInfo.hThread); CloseHandle(piProcInfo.hThread);
PERROR("Close Handle");
/* Return process handle */ /* Return process handle */
*hProcess = piProcInfo.hProcess; *hProcess = piProcInfo.hProcess;
//std::cout << "Process created..." << std::endl;
return TRUE; return TRUE;
} }
win32_error("CreateProcess", s2); win32_error("CreateProcess", s2);
@ -212,7 +255,7 @@ bool cmWin32ProcessExecution::PrivateOpen(const char *cmdstring,
SECURITY_ATTRIBUTES saAttr; SECURITY_ATTRIBUTES saAttr;
BOOL fSuccess; BOOL fSuccess;
int fd1, fd2, fd3; int fd1, fd2, fd3;
FILE *f1, *f2, *f3; //FILE *f1, *f2, *f3;
long file_count; long file_count;
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
@ -220,8 +263,11 @@ bool cmWin32ProcessExecution::PrivateOpen(const char *cmdstring,
saAttr.lpSecurityDescriptor = NULL; saAttr.lpSecurityDescriptor = NULL;
if (!CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0)) if (!CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
{
return win32_error("CreatePipe", NULL); return win32_error("CreatePipe", NULL);
}
PERROR("CreatePipe");
/* Create new output read handle and the input write handle. Set /* Create new output read handle and the input write handle. Set
* the inheritance properties to FALSE. Otherwise, the child inherits * the inheritance properties to FALSE. Otherwise, the child inherits
* the these handles; resulting in non-closeable handles to the pipes * the these handles; resulting in non-closeable handles to the pipes
@ -232,10 +278,13 @@ bool cmWin32ProcessExecution::PrivateOpen(const char *cmdstring,
DUPLICATE_SAME_ACCESS); DUPLICATE_SAME_ACCESS);
if (!fSuccess) if (!fSuccess)
return win32_error("DuplicateHandle", NULL); return win32_error("DuplicateHandle", NULL);
PERROR("DuplicateHandle");
/* Close the inheritable version of ChildStdin /* Close the inheritable version of ChildStdin
that we're using. */ that we're using. */
CloseHandle(hChildStdinWr); CloseHandle(hChildStdinWr);
PERROR("CloseHandle");
if (!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) if (!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))
return win32_error("CreatePipe", NULL); return win32_error("CreatePipe", NULL);
@ -245,24 +294,29 @@ bool cmWin32ProcessExecution::PrivateOpen(const char *cmdstring,
FALSE, DUPLICATE_SAME_ACCESS); FALSE, DUPLICATE_SAME_ACCESS);
if (!fSuccess) if (!fSuccess)
return win32_error("DuplicateHandle", NULL); return win32_error("DuplicateHandle", NULL);
PERROR("DuplicateHandle");
/* Close the inheritable version of ChildStdout /* Close the inheritable version of ChildStdout
that we're using. */ that we're using. */
CloseHandle(hChildStdoutRd); CloseHandle(hChildStdoutRd);
PERROR("CloseHandle");
if (n != POPEN_4) if (n != POPEN_4)
{ {
if (!CreatePipe(&hChildStderrRd, &hChildStderrWr, &saAttr, 0)) if (!CreatePipe(&hChildStderrRd, &hChildStderrWr, &saAttr, 0))
return win32_error("CreatePipe", NULL); return win32_error("CreatePipe", NULL);
fSuccess = DuplicateHandle(GetCurrentProcess(), PERROR("CreatePipe");
fSuccess = DuplicateHandle(GetCurrentProcess(),
hChildStderrRd, hChildStderrRd,
GetCurrentProcess(), GetCurrentProcess(),
&hChildStderrRdDup, 0, &hChildStderrRdDup, 0,
FALSE, DUPLICATE_SAME_ACCESS); FALSE, DUPLICATE_SAME_ACCESS);
if (!fSuccess) if (!fSuccess)
return win32_error("DuplicateHandle", NULL); return win32_error("DuplicateHandle", NULL);
PERROR("DuplicateHandle");
/* Close the inheritable version of ChildStdErr that we're using. */ /* Close the inheritable version of ChildStdErr that we're using. */
CloseHandle(hChildStderrRd); CloseHandle(hChildStderrRd);
PERROR("CloseHandle");
} }
switch (n) switch (n)
@ -272,43 +326,47 @@ bool cmWin32ProcessExecution::PrivateOpen(const char *cmdstring,
{ {
case _O_WRONLY | _O_TEXT: case _O_WRONLY | _O_TEXT:
/* Case for writing to child Stdin in text mode. */ /* Case for writing to child Stdin in text mode. */
fd1 = _open_osfhandle((intptr_t)hChildStdinWrDup, mode); fd1 = _open_osfhandle(TO_INTPTR(hChildStdinWrDup), mode);
f1 = _fdopen(fd1, "w"); //f1 = _fdopen(fd1, "w");
/* We don't care about these pipes anymore, /* We don't care about these pipes anymore,
so close them. */ so close them. */
CloseHandle(hChildStdoutRdDup); CloseHandle(hChildStdoutRdDup);
CloseHandle(hChildStderrRdDup); CloseHandle(hChildStderrRdDup);
PERROR("CloseHandle");
break; break;
case _O_RDONLY | _O_TEXT: case _O_RDONLY | _O_TEXT:
/* Case for reading from child Stdout in text mode. */ /* Case for reading from child Stdout in text mode. */
fd1 = _open_osfhandle((intptr_t)hChildStdoutRdDup, mode); fd1 = _open_osfhandle(TO_INTPTR(hChildStdoutRdDup), mode);
f1 = _fdopen(fd1, "r"); //f1 = _fdopen(fd1, "r");
/* We don't care about these pipes anymore, /* We don't care about these pipes anymore,
so close them. */ so close them. */
CloseHandle(hChildStdinWrDup); CloseHandle(hChildStdinWrDup);
CloseHandle(hChildStderrRdDup); CloseHandle(hChildStderrRdDup);
PERROR("CloseHandle");
break; break;
case _O_RDONLY | _O_BINARY: case _O_RDONLY | _O_BINARY:
/* Case for readinig from child Stdout in /* Case for readinig from child Stdout in
binary mode. */ binary mode. */
fd1 = _open_osfhandle((intptr_t)hChildStdoutRdDup, mode); fd1 = _open_osfhandle(TO_INTPTR(hChildStdoutRdDup), mode);
f1 = _fdopen(fd1, "rb"); //f1 = _fdopen(fd1, "rb");
/* We don't care about these pipes anymore, /* We don't care about these pipes anymore,
so close them. */ so close them. */
CloseHandle(hChildStdinWrDup); CloseHandle(hChildStdinWrDup);
CloseHandle(hChildStderrRdDup); CloseHandle(hChildStderrRdDup);
PERROR("CloseHandle");
break; break;
case _O_WRONLY | _O_BINARY: case _O_WRONLY | _O_BINARY:
/* Case for writing to child Stdin in binary mode. */ /* Case for writing to child Stdin in binary mode. */
fd1 = _open_osfhandle((intptr_t)hChildStdinWrDup, mode); fd1 = _open_osfhandle(TO_INTPTR(hChildStdinWrDup), mode);
f1 = _fdopen(fd1, "wb"); //f1 = _fdopen(fd1, "wb");
/* We don't care about these pipes anymore, /* We don't care about these pipes anymore,
so close them. */ so close them. */
CloseHandle(hChildStdoutRdDup); CloseHandle(hChildStdoutRdDup);
CloseHandle(hChildStderrRdDup); CloseHandle(hChildStderrRdDup);
PERROR("CloseHandle");
break; break;
} }
file_count = 1; file_count = 1;
@ -331,13 +389,17 @@ bool cmWin32ProcessExecution::PrivateOpen(const char *cmdstring,
m2 = "wb"; m2 = "wb";
} }
fd1 = _open_osfhandle((intptr_t)hChildStdinWrDup, mode); fd1 = _open_osfhandle(TO_INTPTR(hChildStdinWrDup), mode);
f1 = _fdopen(fd1, m2); //f1 = _fdopen(fd1, m2);
fd2 = _open_osfhandle((intptr_t)hChildStdoutRdDup, mode); fd2 = _open_osfhandle(TO_INTPTR(hChildStdoutRdDup), mode);
f2 = _fdopen(fd2, m1); //f2 = _fdopen(fd2, m1);
PERROR("_open_osfhandle");
if (n != 4) if (n != 4)
{
CloseHandle(hChildStderrRdDup); CloseHandle(hChildStderrRdDup);
PERROR("CloseHandle");
}
file_count = 2; file_count = 2;
break; break;
@ -359,12 +421,14 @@ bool cmWin32ProcessExecution::PrivateOpen(const char *cmdstring,
m2 = "wb"; m2 = "wb";
} }
fd1 = _open_osfhandle((intptr_t)hChildStdinWrDup, mode);
f1 = _fdopen(fd1, m2); fd1 = _open_osfhandle(TO_INTPTR(hChildStdinWrDup), mode);
fd2 = _open_osfhandle((intptr_t)hChildStdoutRdDup, mode); //f1 = _fdopen(fd1, m2);
f2 = _fdopen(fd2, m1); fd2 = _open_osfhandle(TO_INTPTR(hChildStdoutRdDup), mode);
fd3 = _open_osfhandle((intptr_t)hChildStderrRdDup, mode); //f2 = _fdopen(fd2, m1);
f3 = _fdopen(fd3, m1); fd3 = _open_osfhandle(TO_INTPTR(hChildStderrRdDup), mode);
//f3 = _fdopen(fd3, m1);
PERROR("_open_osfhandle");
file_count = 3; file_count = 3;
break; break;
@ -414,29 +478,34 @@ bool cmWin32ProcessExecution::PrivateOpen(const char *cmdstring,
if (!CloseHandle(hChildStdinRd)) if (!CloseHandle(hChildStdinRd))
return win32_error("CloseHandle", NULL); return win32_error("CloseHandle", NULL);
PERROR("CloseHandle");
if (!CloseHandle(hChildStdoutWr)) if (!CloseHandle(hChildStdoutWr))
return win32_error("CloseHandle", NULL); return win32_error("CloseHandle", NULL);
PERROR("CloseHandle");
if ((n != 4) && (!CloseHandle(hChildStderrWr))) if ((n != 4) && (!CloseHandle(hChildStderrWr)))
return win32_error("CloseHandle", NULL); return win32_error("CloseHandle", NULL);
PERROR("CloseHandle");
this->m_ProcessHandle = hProcess; this->m_ProcessHandle = hProcess;
if ( f1 ) if ( fd1 >= 0 )
{ {
this->m_StdIn = f1; // this->m_StdIn = f1;
this->m_pStdIn = fd1; this->m_pStdIn = fd1;
} }
if ( f2 ) if ( fd2 >= 0 )
{ {
this->m_StdOut = f2; // this->m_StdOut = f2;
this->m_pStdOut = fd2; this->m_pStdOut = fd2;
} }
if ( f3 ) if ( fd3 >= 0 )
{ {
this->m_StdErr = f3; // this->m_StdErr = f3;
this->m_pStdErr = fd3; this->m_pStdErr = fd3;
} }
//std::cout << "Process created for real..." << std::endl;
//std::cout << fd1 << " " << fd2 << " " << fd3 << std::endl;
return true; return true;
} }
@ -502,6 +571,7 @@ bool cmWin32ProcessExecution::PrivateClose(int timeout)
} }
if (fserr.st_size > 0) if (fserr.st_size > 0)
{ {
//std::cout << "Some error" << std::endl;
int dist = fserr.st_size; int dist = fserr.st_size;
char buffer[1023]; char buffer[1023];
int len = read(this->m_pStdErr, buffer, 1023); int len = read(this->m_pStdErr, buffer, 1023);
@ -514,6 +584,7 @@ bool cmWin32ProcessExecution::PrivateClose(int timeout)
} }
if (fsout.st_size > 0) if (fsout.st_size > 0)
{ {
//std::cout << "Some output" << std::endl;
int dist = fsout.st_size; int dist = fsout.st_size;
char buffer[1023]; char buffer[1023];
int len = read(this->m_pStdOut, buffer, 1023); int len = read(this->m_pStdOut, buffer, 1023);
@ -528,9 +599,13 @@ bool cmWin32ProcessExecution::PrivateClose(int timeout)
GetExitCodeProcess(hProcess,&exitCode); GetExitCodeProcess(hProcess,&exitCode);
if (exitCode != STILL_ACTIVE) if (exitCode != STILL_ACTIVE)
{ {
//std::cout << "STILL_ACTIVE = " << STILL_ACTIVE << std::endl;
//std::cout << "Process is not active any more: " << exitCode << std::endl;
break; break;
} }
} }
//std::cout << "Waiting for process to close" << std::endl;
if (WaitForSingleObject(hProcess, INFINITE) != WAIT_FAILED && if (WaitForSingleObject(hProcess, INFINITE) != WAIT_FAILED &&
GetExitCodeProcess(hProcess, &exit_code)) GetExitCodeProcess(hProcess, &exit_code))
@ -554,6 +629,8 @@ bool cmWin32ProcessExecution::PrivateClose(int timeout)
} }
result = -1; result = -1;
} }
//std::cout << "Process closed with error code: " << result << std::endl;
/* Free up the native handle at this point */ /* Free up the native handle at this point */
CloseHandle(hProcess); CloseHandle(hProcess);

View File

@ -27,7 +27,6 @@
#include "cmStandardIncludes.h" #include "cmStandardIncludes.h"
#include "windows.h" #include "windows.h"
#include "stdio.h"
class cmMakefile; class cmMakefile;
@ -45,21 +44,59 @@ public:
this->SetConsoleSpawn("w9xpopen.exe"); this->SetConsoleSpawn("w9xpopen.exe");
this->Initialize(); this->Initialize();
} }
/**
* Initialize the process execution datastructure. Do not call while
* running the process.
*/
void Initialize() void Initialize()
{ {
this->m_ProcessHandle = 0; this->m_ProcessHandle = 0;
this->m_ExitValue = -1; this->m_ExitValue = -1;
this->m_StdIn = 0; // Comment this out. Maybe we will need it in the future.
this->m_StdOut = 0; // file IO access to the process might be cool.
this->m_StdErr = 0; //this->m_StdIn = 0;
//this->m_StdOut = 0;
//this->m_StdErr = 0;
this->m_pStdIn = -1;
this->m_pStdOut = -1;
this->m_pStdErr = -1;
} }
/**
* Start the process in the directory path. Make sure that the
* executable is either in the path or specify the full path. The
* argument verbose specifies wether or not to display output while
* it is being generated.
*/
bool StartProcess(const char*, const char* path, bool verbose); bool StartProcess(const char*, const char* path, bool verbose);
/**
* Wait for the process to finish. If timeout is specified, it will
* break the process after timeout expires. (Timeout code is not yet
* implemented.
*/
bool Wait(int timeout); bool Wait(int timeout);
/**
* Get the output of the process (mixed stdout and stderr) as
* std::string.
*/
const std::string GetOutput() const { return this->m_Output; } const std::string GetOutput() const { return this->m_Output; }
/**
* Get the return value of the process. If the process is still
* running, the return value is -1.
*/
int GetExitValue() const { return this->m_ExitValue; } int GetExitValue() const { return this->m_ExitValue; }
/**
* On Windows 9x there is a bug in the process execution code which
* may result in blocking. That is why this workaround is
* used. Specify the console spawn, which should run the
* Windows9xHack code.
*/
void SetConsoleSpawn(const char* prog) { this->m_ConsoleSpawn = prog; } void SetConsoleSpawn(const char* prog) { this->m_ConsoleSpawn = prog; }
static int Windows9xHack(const char* command); static int Windows9xHack(const char* command);
private: private:
@ -67,10 +104,13 @@ private:
bool PrivateClose(int timeout); bool PrivateClose(int timeout);
HANDLE m_ProcessHandle; HANDLE m_ProcessHandle;
FILE* m_StdIn;
FILE* m_StdOut; // Comment this out. Maybe we will need it in the future.
FILE* m_StdErr; // file IO access to the process might be cool.
// FILE* m_StdIn;
// FILE* m_StdOut;
// FILE* m_StdErr;
int m_pStdIn; int m_pStdIn;
int m_pStdOut; int m_pStdOut;
int m_pStdErr; int m_pStdErr;