3f8da2e297cb6fb3e496e14065264b6767f11fcb
[polyglot.git] / pipe.cpp
1 #ifdef _WIN32
2 #include "pipe.h"
3 #include "util.h"
4 void PipeStruct::Open(const char *szProcFile) {
5   DWORD dwMode;
6   HANDLE hStdinRead, hStdinWrite, hStdoutRead, hStdoutWrite;
7   SECURITY_ATTRIBUTES sa;
8   STARTUPINFO si;
9   PROCESS_INFORMATION pi;
10
11   if (szProcFile == NULL) {
12     hInput = GetStdHandle(STD_INPUT_HANDLE);
13     hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
14     bConsole = GetConsoleMode(hInput, &dwMode);
15   } else {
16     sa.nLength = sizeof(SECURITY_ATTRIBUTES);
17     sa.bInheritHandle = TRUE;
18     sa.lpSecurityDescriptor = NULL;
19     CreatePipe(&hStdinRead, &hStdinWrite, &sa, 0);
20     CreatePipe(&hStdoutRead, &hStdoutWrite, &sa, 0);
21     si.cb = sizeof(STARTUPINFO);
22     si.lpReserved = si.lpDesktop = si.lpTitle = NULL;
23     si.dwFlags = STARTF_USESTDHANDLES;
24     si.cbReserved2 = 0;
25     si.lpReserved2 = NULL;
26     si.hStdInput = hStdinRead;
27     si.hStdOutput = hStdoutWrite;
28     si.hStdError = hStdoutWrite;
29     if(!CreateProcess(NULL, (LPSTR) szProcFile, NULL, NULL, TRUE, DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP, NULL, NULL, &si, &pi)){
30         my_fatal("PipeStruct::Open(): Could not start \"%s\"\n",szProcFile);
31     }
32         hProcess=pi.hProcess;
33     //CloseHandle(pi.hProcess);//not here,baby,but in pipe.close 
34     CloseHandle(pi.hThread);
35     CloseHandle(hStdinRead);
36     CloseHandle(hStdoutWrite);
37     hInput = hStdoutRead;
38     hOutput = hStdinWrite;
39     bConsole = FALSE;
40   }
41   if (bConsole) {
42     SetConsoleMode(hInput, dwMode & ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT));
43     FlushConsoleInputBuffer(hInput);
44   } else {
45     nBytesLeft = 0;
46   }
47   nReadEnd = 0;
48 }
49
50 void PipeStruct::Close(void) const {
51   CloseHandle(hInput);
52   CloseHandle(hOutput);
53   DWORD lpexit;
54
55   my_log("POLYGLOT Closing child\n");
56   if(GetExitCodeProcess(hProcess,&lpexit)){
57         if(lpexit==STILL_ACTIVE)
58           my_log("POLYGLOT Process still active after \"quit\" ");
59         //must be java,hammer it down!
60         TerminateProcess(hProcess,lpexit);
61   }
62         CloseHandle(hProcess);
63 }
64
65 void PipeStruct::ReadInput(void) {
66   DWORD dwBytes;
67   if(!ReadFile(hInput, szBuffer + nReadEnd, LINE_INPUT_MAX_CHAR - nReadEnd, &dwBytes, NULL)){
68           // TODO move this comment to a more suitable place
69       my_log("POLYGLOT *** EOF from Engine or GUI ***\n");
70       exit(EXIT_SUCCESS); // if we are here there should be data!
71   }
72   nReadEnd += dwBytes;
73   if (nBytesLeft > 0) {
74     nBytesLeft -= dwBytes;
75   }
76 }
77
78 bool PipeStruct::CheckInput(void) {
79   DWORD dwEvents, dwBytes;
80   if (bConsole) { // a tty, or an un-redirected handle
81     GetNumberOfConsoleInputEvents(hInput, &dwEvents);
82     if (dwEvents > 1) {
83       return TRUE;
84     } else {
85       return FALSE;
86     }
87   } else { // a handle redirected to a pipe or a file
88     if (nBytesLeft > 0) {
89       return TRUE;
90     } else {
91       if (PeekNamedPipe(hInput, NULL, 0, NULL, &dwBytes, NULL)) {
92         nBytesLeft = dwBytes;
93         return nBytesLeft > 0; // a pipe
94       } else {
95         return TRUE; // a file, always TRUE
96       }
97     }
98   }
99 }
100
101 void PipeStruct::LineOutput(const char *szLineStr) const {
102   DWORD dwBytes;
103   int nStrLen;
104   char szWriteBuffer[LINE_INPUT_MAX_CHAR];
105   nStrLen = strlen(szLineStr);
106   memcpy(szWriteBuffer, szLineStr, nStrLen);
107   szWriteBuffer[nStrLen] = '\r';
108   szWriteBuffer[nStrLen + 1] = '\n';
109   WriteFile(hOutput, szWriteBuffer, nStrLen + 2, &dwBytes, NULL);
110 }
111
112
113
114 bool PipeStruct::GetBuffer(char *szLineStr) {
115   char *lpFeedEnd;
116   int nFeedEnd;
117   lpFeedEnd = (char *) memchr(szBuffer, '\n', nReadEnd);
118   if (lpFeedEnd == NULL) {
119     return FALSE;
120   } else {
121     nFeedEnd = lpFeedEnd - szBuffer;
122     memcpy(szLineStr, szBuffer, nFeedEnd);
123     if (szLineStr[nFeedEnd - 1] == '\r') {
124       szLineStr[nFeedEnd - 1] = '\0';
125     } else {
126       szLineStr[nFeedEnd] = '\0';
127     }
128     nFeedEnd ++;
129     nReadEnd -= nFeedEnd;
130     memcpy(szBuffer, szBuffer + nFeedEnd, nReadEnd);
131     return TRUE;
132   }
133 }
134
135 bool PipeStruct::LineInput(char *szLineStr) {
136   if (GetBuffer(szLineStr)) {
137     return TRUE;
138   }
139   if (CheckInput()) {
140     ReadInput();
141     if (GetBuffer(szLineStr)) {
142       return TRUE;
143     } else {
144       if (nReadEnd == LINE_INPUT_MAX_CHAR) {
145         memcpy(szLineStr, szBuffer, LINE_INPUT_MAX_CHAR - 1);
146         szLineStr[LINE_INPUT_MAX_CHAR - 1] = '\0';
147         szBuffer[0] = szBuffer[LINE_INPUT_MAX_CHAR - 1];
148         nReadEnd = 1;
149         return TRUE;
150       } else {
151         return FALSE;
152       }
153     }
154   } else {
155     return FALSE;
156   }
157 }
158 #endif