Add forgotten files 1.4.70b
[polyglot.git] / pipex_win32.c
index 13adfeb..41431b3 100644 (file)
@@ -59,15 +59,21 @@ static DWORD WINAPI ThreadProc(LPVOID lpParam){
 
 // 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);
@@ -88,7 +94,15 @@ void pipex_open(pipex_t *pipex, const char *szName, const char *szProcFile) {
         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,
@@ -107,8 +121,9 @@ void pipex_open(pipex_t *pipex, const char *szName, const char *szProcFile) {
             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,
@@ -144,9 +159,11 @@ void pipex_open(pipex_t *pipex, const char *szName, const char *szProcFile) {
     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[]){
@@ -167,7 +184,6 @@ void pipex_wait_event(pipex_t *pipex[]){
                            );
 }
 
-
 // pipex_send_eof()
 
 void pipex_send_eof(pipex_t *pipex)  {
@@ -177,17 +193,47 @@ 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()
@@ -206,10 +252,7 @@ static void pipex_set_eof_input(pipex_t *pipex){
     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()
 
@@ -382,6 +425,7 @@ bool pipex_readln(pipex_t *pipex, char *szLineStr) {
           WaitForSingleObject(pipex->hEvent,INFINITE);
       }
   }
+  my_log("%s->Adapter: EOF\n",pipex->name);
   szLineStr[0]='\0';
   return FALSE;
 }
@@ -418,12 +462,13 @@ void pipex_set_priority(pipex_t *pipex, int value){
 
 // 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");
@@ -435,22 +480,50 @@ void pipex_set_affinity(pipex_t *pipex, int value){
     }
 }
 
+// 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