version 1.4w10UCIb20
[polyglot.git] / pipe.cpp
1 #ifdef _WIN32
2 #include "pipe.h"
3 #include "util.h"
4
5 // functions
6
7 DWORD WINAPI ThreadProc(LPVOID lpParam){
8     PipeStruct *p=(PipeStruct *) lpParam;
9     while(!p->EOF_()){
10         p->ReadInput();
11     }
12     return 0;
13 }
14
15
16
17 void PipeStruct::Open(const char *szProcFile) {
18     DWORD dwMode;
19     HANDLE hStdinRead, hStdinWrite, hStdoutRead, hStdoutWrite;
20     SECURITY_ATTRIBUTES sa;
21     STARTUPINFO si;
22     PROCESS_INFORMATION pi;
23     state=0;
24     if (szProcFile == NULL) {
25         hInput = GetStdHandle(STD_INPUT_HANDLE);
26         hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
27         bConsole = GetConsoleMode(hInput, &dwMode);
28         bPipe=FALSE;
29     } else {
30         sa.nLength = sizeof(SECURITY_ATTRIBUTES);
31         sa.bInheritHandle = TRUE;
32         sa.lpSecurityDescriptor = NULL;
33         CreatePipe(&hStdinRead, &hStdinWrite, &sa, 0);
34         CreatePipe(&hStdoutRead, &hStdoutWrite, &sa, 0);
35         si.cb = sizeof(STARTUPINFO);
36         si.lpReserved = si.lpDesktop = si.lpTitle = NULL;
37         si.dwFlags = STARTF_USESTDHANDLES;
38         si.cbReserved2 = 0;
39         si.lpReserved2 = NULL;
40         si.hStdInput = hStdinRead;
41         si.hStdOutput = hStdoutWrite;
42         si.hStdError = hStdoutWrite;
43         if(CreateProcess(NULL,
44                          (LPSTR) szProcFile,
45                          NULL,
46                          NULL,
47                          TRUE,
48                          DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP,
49                          NULL,
50                          NULL,
51                          &si,
52                          &pi)){
53             hProcess=pi.hProcess;
54             CloseHandle(pi.hThread);
55             CloseHandle(hStdinRead);
56             CloseHandle(hStdoutWrite);
57             hInput = hStdoutRead;
58             hOutput = hStdinWrite;
59             bConsole = FALSE;
60             bPipe=TRUE;
61         }else{
62             my_fatal("PipeStruct::Open(): %s",my_error());
63         }
64     }
65     if (bConsole) {
66         SetConsoleMode(hInput,
67                        dwMode & ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT));
68         FlushConsoleInputBuffer(hInput);
69     } 
70     nReadEnd = 0;
71     InitializeCriticalSection(&CriticalSection);
72     hEvent=CreateEvent(NULL,           // default security
73                        FALSE,          // auto reset
74                        FALSE,          // not signaled
75                        NULL            // nameless
76                        );
77     hThread=CreateThread(NULL,         // default security
78                          0,            // default stacksize
79                          ThreadProc,   // worker function
80                          this,         // tell worker about ourselves
81                          0,            // run immediately
82                          NULL          // nameless
83                          );          
84     
85     set_Active();
86 }
87
88
89 void PipeStruct::Close(void) const {
90     CloseHandle(hOutput);
91 }
92
93 void PipeStruct::Kill(void) const {
94     CloseHandle(hInput);
95     CloseHandle(hOutput);
96     DWORD lpexit;
97     
98     if(GetExitCodeProcess(hProcess,&lpexit)){
99         if(lpexit==STILL_ACTIVE)
100                 //must be java,hammer it down!
101             TerminateProcess(hProcess,lpexit);
102     }
103         CloseHandle(hProcess);
104 }
105
106 bool PipeStruct::EOF_(void){   // EOF is defined
107     int ret;
108     EnterCriticalSection(&CriticalSection);
109     ret=state&PIPE_EOF;
110     LeaveCriticalSection(&CriticalSection);
111     return ret;
112 }
113
114 void PipeStruct::set_EOF_(void){
115     EnterCriticalSection(&CriticalSection);
116     state|=PIPE_EOF;
117     LeaveCriticalSection(&CriticalSection);
118 }
119
120 bool PipeStruct::Active(void){
121     int ret;
122     EnterCriticalSection(&CriticalSection);
123     ret=state&PIPE_ACTIVE;
124     LeaveCriticalSection(&CriticalSection);
125     return ret;
126 }
127
128 void PipeStruct::set_Active(void){
129     EnterCriticalSection(&CriticalSection);
130     state|=PIPE_ACTIVE;
131     LeaveCriticalSection(&CriticalSection);
132 }
133
134
135
136 int PipeStruct::ReadLine(void){
137     DWORD dwBytes;
138     int ret;
139     int start=0;
140     int start1;    
141     
142     if(!bPipe){
143         fgets(lpReadBuffer,LINE_INPUT_MAX_CHAR,stdin);
144         start=strlen(lpReadBuffer);
145         if(!start){
146             set_EOF_();
147             lpReadBuffer[0]='\0';
148         }
149         return start;
150     }else{
151         while(TRUE){
152                 // Unfortunately we need to use polling here.
153                 // Otherwise Windows returns single bytes if
154                 // the engine runs at low priority.
155                 // This kills performance.
156             while(TRUE){
157                 ret=PeekNamedPipe(hInput,
158                                   NULL,    // don't read anything yet
159                                   0,       // no buffer
160                                   NULL,    // no we don't read anything!
161                                   &dwBytes,// now we're talking
162                                   NULL);   // nono we don't read anything
163                 if(!ret){
164                     set_EOF_();
165                     lpReadBuffer[0]='\0';
166                     return 0;
167                 }
168                 if(dwBytes>0){
169                     break;
170                 }else{
171                     Idle();
172                 }
173                 
174             }
175             ret=ReadFile(hInput,
176                          lpReadBuffer+start,
177                          LINE_INPUT_MAX_CHAR-start,
178                          &dwBytes,
179                          NULL);
180             if(!ret){
181                 set_EOF_();
182                 lpReadBuffer[0]='\0';
183                 return 0;
184             }else{
185                 start1=start;
186                 start+=dwBytes;
187                 if (memchr(lpReadBuffer+start1, '\n', dwBytes)){
188                     lpReadBuffer[start]='\0';
189                     return start;
190                 }
191             }
192         }
193     }
194 }
195
196 void PipeStruct::ReadInput(void) {
197   DWORD dwBytes;
198   int ret;
199   ret=ReadLine();
200   EnterCriticalSection(&CriticalSection);
201   if(!EOF_()){
202       if(ret+nReadEnd>=LINE_INPUT_MAX_CHAR){
203           my_fatal("PipeStruct::ReadInput(): buffer overflow\n");
204       }
205       memcpy(lpBuffer+nReadEnd,lpReadBuffer,ret);
206       nReadEnd += ret;
207   }
208   LeaveCriticalSection(&CriticalSection);
209   SetEvent(hEvent);
210 }
211
212 void PipeStruct::LineOutput(const char *szLineStr) const {
213   DWORD dwBytes;
214   int nStrLen;
215   char szWriteBuffer[LINE_INPUT_MAX_CHAR];
216   if(bPipe){
217       nStrLen = strlen(szLineStr);
218       memcpy(szWriteBuffer, szLineStr, nStrLen);
219       szWriteBuffer[nStrLen] = '\r';
220       szWriteBuffer[nStrLen + 1] = '\n';
221       WriteFile(hOutput, szWriteBuffer, nStrLen + 2, &dwBytes, NULL);
222   }else{
223       printf("%s\n",szLineStr);
224       fflush(stdout);
225   }
226 }
227
228 bool PipeStruct::GetBuffer(char *szLineStr) {
229   char *lpFeedEnd;
230   int nFeedEnd;
231   int ret;
232   EnterCriticalSection(&CriticalSection);
233   lpFeedEnd = (char *) memchr(lpBuffer, '\n', nReadEnd);
234   if (lpFeedEnd == NULL) {
235     ret=FALSE;
236   } else {
237     nFeedEnd = lpFeedEnd - lpBuffer;
238     memcpy(szLineStr, lpBuffer, nFeedEnd);
239     if (szLineStr[nFeedEnd - 1] == '\r') {
240       szLineStr[nFeedEnd - 1] = '\0';
241     } else {
242       szLineStr[nFeedEnd] = '\0';
243     }
244     nFeedEnd ++;
245     nReadEnd -= nFeedEnd;
246     memcpy(lpBuffer, lpBuffer + nFeedEnd, nReadEnd);
247     ret=TRUE;
248   }
249   LeaveCriticalSection(&CriticalSection);
250   return ret;
251 }
252
253 void PipeStruct::LineInput(char *szLineStr) {
254     while(!EOF_()){
255         if (GetBuffer(szLineStr)) {
256             break;
257         }else{
258             WaitForSingleObject(hEvent,INFINITE);
259         }
260     }
261 }
262 #endif