// pipex_open()
-void pipex_open(pipex_t *pipex, const char *szName, const char *szProcFile) {
+void pipex_open(pipex_t *pipex,
+ const char *szName,
+ const char *szWorkingDir,
+ const char *szProcFile) {
DWORD dwMode, dwThreadId;
HANDLE hStdinRead, hStdinWrite, hStdoutRead, hStdoutWrite, hThread;
SECURITY_ATTRIBUTES sa;
STARTUPINFO si;
PROCESS_INFORMATION pi;
int fdInput;
+ char *szCurrentDir;
pipex->state=0;
pipex->name=szName;
+ pipex->command=szProcFile;
+ pipex->quit_pending=FALSE;
pipex->hProcess=NULL;
if (szProcFile == NULL) {
pipex->hInput = GetStdHandle(STD_INPUT_HANDLE);
si.hStdInput = hStdinRead;
si.hStdOutput = hStdoutWrite;
si.hStdError = hStdoutWrite;
- if(CreateProcess(NULL,
+ if((szCurrentDir = (char*)_getcwd( NULL, 0 )) == NULL )
+ my_fatal("pipex_open(): no current directory: %s\n",
+ strerror(errno));
+ if(_chdir(szWorkingDir)){
+ my_fatal("pipex_open(): %s: %s\n",
+ szWorkingDir,
+ strerror(errno));
+ }
+ if(CreateProcess(NULL,
(LPSTR) szProcFile,
NULL,
NULL,
pipex->bConsole = FALSE;
pipex->bPipe=TRUE;
}else{
- my_fatal("pipex_open(): %s",win32_error());
+ my_fatal("pipex_open(): %s: %s",szProcFile,win32_error());
}
+ _chdir(szCurrentDir);
}
if (pipex->bConsole) {
SetConsoleMode(pipex->hInput,
if(!hThread){
my_fatal("pipex_open(): %s",win32_error());
}
+ pipex->dwWriteIndex=0;
pipex_set_active(pipex);
}
+
// pipex_wait_event(pipex)
void pipex_wait_event(pipex_t *pipex[]){
);
}
-
// pipex_send_eof()
void pipex_send_eof(pipex_t *pipex) {
// pipex_exit()
-void pipex_exit(pipex_t *pipex) {
+/* This routine waits for kill_timeout milliseconds for
+ * the process to exit by itself. If that doesn't
+ * happen it will kill the process.
+ */
+
+void pipex_exit(pipex_t *pipex, int kill_timeout) {
+ DWORD lpexit;
+ int elapsed_time;
+ bool exited;
CloseHandle(pipex->hInput);
CloseHandle(pipex->hOutput);
- DWORD lpexit;
-
- if(GetExitCodeProcess(pipex->hProcess,&lpexit)){
- if(lpexit==STILL_ACTIVE)
- //must be java,hammer it down!
- TerminateProcess(pipex->hProcess,lpexit);
+ // ExitProcess(pipex->hProcess,0);
+
+ my_log("POLYGLOT Waiting for child process to exit.\n");
+ elapsed_time=0;
+ exited=FALSE;
+
+ while(elapsed_time<kill_timeout){
+ GetExitCodeProcess(pipex->hProcess,&lpexit);
+ if(lpexit==STILL_ACTIVE){
+ my_log("POLYGLOT Child has not exited yet. Sleeping %dms.\n", WAIT_GRANULARITY);
+ my_sleep(WAIT_GRANULARITY);
+ elapsed_time+=WAIT_GRANULARITY;
+ }else{
+ exited=TRUE;
+ break;
+ }
+ }
+
+ if(!exited){
+ my_log("POLYGLOT Child wouldn't exit by itself. Terminating it.\n");
+ TerminateProcess(pipex->hProcess,lpexit);
}
- CloseHandle(pipex->hProcess);
+ CloseHandle(pipex->hProcess);
+
+ if(!pipex->quit_pending){
+ // suppress further errors
+ pipex->quit_pending=TRUE;
+ my_fatal("pipex_exit(): %s: child exited unexpectedly.\n",pipex->command);
+ }
+
}
// pipex_eof_input()
EnterCriticalSection(&(pipex->CriticalSection));
(pipex->state)|=PIPEX_EOF;
LeaveCriticalSection(&(pipex->CriticalSection));
- // not quit the right place
- my_log("%s->Adapter: EOF\n",pipex->name);
-
-}
+ }
// pipex_active()
WaitForSingleObject(pipex->hEvent,INFINITE);
}
}
+ my_log("%s->Adapter: EOF\n",pipex->name);
szLineStr[0]='\0';
return FALSE;
}
// pipex_set_affinit()
+typedef void (WINAPI *SPAM)(HANDLE, int);
void pipex_set_affinity(pipex_t *pipex, int value){
+ SPAM pSPAM;
+
if(pipex->hProcess) return;
if(value==-1) return;
- typedef void (WINAPI *SPAM)(HANDLE, int);
- SPAM pSPAM;
pSPAM = (SPAM) GetProcAddress(
GetModuleHandle(TEXT("kernel32.dll")),
"SetProcessAffinityMask");
}
}
+// pipex_write()
+
+void pipex_write(pipex_t *pipex, const char *szLineStr) {
+ int size,written;
+ size=sizeof(pipex->szWriteBuffer)-pipex->dwWriteIndex;
+ written=snprintf(pipex->szWriteBuffer + pipex->dwWriteIndex,
+ size,
+ "%s",
+ szLineStr);
+ // snprintf returns how many bytes should have been written
+ // (not including the trailing zero)
+ // old versions of glibc and msvcrt return -1 in
+ // case of truncated output.
+ if(written>=size || written<0){
+ my_fatal("engine_send(): write_buffer overflow\n");
+ }
+ pipex->dwWriteIndex+=written;
+
+}
+
+
// pipex_writeln()
void pipex_writeln(pipex_t *pipex, const char *szLineStr) {
DWORD dwBytes;
- int nStrLen;
- char szWriteBuffer[LINE_INPUT_MAX_CHAR];
- my_log("Adapter->%s: %s\n",pipex->name,szLineStr);
+ DWORD dwLengthWriteBuffer;
+ pipex_write(pipex, szLineStr);
+ my_log("Adapter->%s: %s\n",pipex->name,pipex->szWriteBuffer);
if(pipex->bPipe){
- nStrLen = strlen(szLineStr);
- memcpy(szWriteBuffer, szLineStr, nStrLen);
- szWriteBuffer[nStrLen] = '\r';
- szWriteBuffer[nStrLen + 1] = '\n';
- WriteFile(pipex->hOutput, szWriteBuffer, nStrLen + 2, &dwBytes, NULL);
+ dwLengthWriteBuffer = strlen(pipex->szWriteBuffer);
+ if(dwLengthWriteBuffer>=sizeof(pipex->szWriteBuffer)-3){
+ my_fatal("pipex_writeln(): write buffer overflow\n");
+ }
+ pipex->szWriteBuffer[dwLengthWriteBuffer] = '\r';
+ pipex->szWriteBuffer[dwLengthWriteBuffer + 1] = '\n';
+ // for easy debugging
+ pipex->szWriteBuffer[dwLengthWriteBuffer + 2] = '\0';
+ WriteFile(pipex->hOutput, pipex->szWriteBuffer,
+ dwLengthWriteBuffer + 2,
+ &dwBytes, NULL);
}else{
- printf("%s\n",szLineStr);
+ printf("%s\n",pipex->szWriteBuffer);
fflush(stdout);
}
+ pipex->dwWriteIndex = 0;
}
#endif