version 1.4w10UCIb22
[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     int fdInput;
24     state=0;
25     if (szProcFile == NULL) {
26         hInput = GetStdHandle(STD_INPUT_HANDLE);
27         hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
28         bConsole = GetConsoleMode(hInput, &dwMode);
29         bPipe=FALSE;
30     } else {
31         sa.nLength = sizeof(SECURITY_ATTRIBUTES);
32         sa.bInheritHandle = TRUE;
33         sa.lpSecurityDescriptor = NULL;
34         CreatePipe(&hStdinRead, &hStdinWrite, &sa, 0);
35         CreatePipe(&hStdoutRead, &hStdoutWrite, &sa, 0);
36         si.cb = sizeof(STARTUPINFO);
37         si.lpReserved = si.lpDesktop = si.lpTitle = NULL;
38         si.dwFlags = STARTF_USESTDHANDLES;
39         si.cbReserved2 = 0;
40         si.lpReserved2 = NULL;
41         si.hStdInput = hStdinRead;
42         si.hStdOutput = hStdoutWrite;
43         si.hStdError = hStdoutWrite;
44         if(CreateProcess(NULL,
45                          (LPSTR) szProcFile,
46                          NULL,
47                          NULL,
48                          TRUE,
49                          DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP,
50                          NULL,
51                          NULL,
52                          &si,
53                          &pi)){
54             hProcess=pi.hProcess;
55             CloseHandle(pi.hThread);
56             CloseHandle(hStdinRead);
57             CloseHandle(hStdoutWrite);
58             hInput = hStdoutRead;
59             hOutput = hStdinWrite;
60             bConsole = FALSE;
61             bPipe=TRUE;
62         }else{
63             my_fatal("PipeStruct::Open(): %s",my_error());
64         }
65     }
66     if (bConsole) {
67         SetConsoleMode(hInput,
68                        dwMode & ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT));
69         FlushConsoleInputBuffer(hInput);
70     } 
71     fdInput=_open_osfhandle((intptr_t) hInput,_O_RDONLY);
72     if(fdInput==-1){
73         my_fatal("PipeStruct::Open(): %s",my_error());
74     }
75     fpInput=fdopen(fdInput,"r");
76     if(fpInput==NULL){
77         my_fatal("PipeStruct::Open(): %s",my_error());
78     }
79     nReadEnd = 0;
80     lpFeedEnd = NULL;
81     InitializeCriticalSection(&CriticalSection);
82     hEvent=CreateEvent(NULL,           // default security
83                        FALSE,          // auto reset
84                        FALSE,          // not signaled
85                        NULL            // nameless
86                        );
87     hThread=CreateThread(NULL,         // default security
88                          0,            // default stacksize
89                          ThreadProc,   // worker function
90                          this,         // tell worker about ourselves
91                          0,            // run immediately
92                          NULL          // nameless
93                          );          
94     
95     set_Active();
96 }
97
98
99 void PipeStruct::Close(void) const {
100     CloseHandle(hOutput);
101 }
102
103 void PipeStruct::Kill(void) const {
104     CloseHandle(hInput);
105     CloseHandle(hOutput);
106     DWORD lpexit;
107     
108     if(GetExitCodeProcess(hProcess,&lpexit)){
109         if(lpexit==STILL_ACTIVE)
110                 //must be java,hammer it down!
111             TerminateProcess(hProcess,lpexit);
112     }
113         CloseHandle(hProcess);
114 }
115
116 bool PipeStruct::EOF_(void){   // EOF is defined
117     int ret;
118     EnterCriticalSection(&CriticalSection);
119     ret=state&PIPE_EOF;
120     LeaveCriticalSection(&CriticalSection);
121     return ret;
122 }
123
124 void PipeStruct::set_EOF_(void){
125     EnterCriticalSection(&CriticalSection);
126     state|=PIPE_EOF;
127     LeaveCriticalSection(&CriticalSection);
128 }
129
130 bool PipeStruct::Active(void){
131     int ret;
132     EnterCriticalSection(&CriticalSection);
133     ret=state&PIPE_ACTIVE;
134     LeaveCriticalSection(&CriticalSection);
135     return ret;
136 }
137
138 void PipeStruct::set_Active(void){
139     EnterCriticalSection(&CriticalSection);
140     state|=PIPE_ACTIVE;
141     LeaveCriticalSection(&CriticalSection);
142 }
143
144 int PipeStruct::ReadData(void){
145     DWORD dwBytes;
146     char * ret;
147     
148     ret=fgets(lpReadBuffer,LINE_INPUT_MAX_CHAR,fpInput);
149     dwBytes=strlen(lpReadBuffer);
150     if(!ret){
151         set_EOF_();
152         lpReadBuffer[0]='\0';
153         return 0;
154     }
155     lpReadBuffer[dwBytes]='\0';
156     return dwBytes;
157 }
158
159 void PipeStruct::ReadInput(void) {
160   DWORD dwBytes;
161   int ret;
162   BOOL bSetEvent=FALSE;
163   ret=ReadData();
164   EnterCriticalSection(&CriticalSection);
165   if(!EOF_()){
166       if(ret+nReadEnd>=LINE_INPUT_MAX_CHAR){
167           my_fatal("PipeStruct::ReadInput(): buffer overflow\n");
168       }
169       memcpy(lpBuffer+nReadEnd,lpReadBuffer,ret);
170       nReadEnd += ret;
171       if(!lpFeedEnd){
172           lpFeedEnd = (char *) memchr(lpBuffer, '\n', nReadEnd);
173       }
174       if(lpFeedEnd){
175           bSetEvent=TRUE;
176       }
177   }
178   LeaveCriticalSection(&CriticalSection);
179   if(EOF_() || bSetEvent){
180       SetEvent(hEvent);
181   }
182 }
183
184 bool PipeStruct::GetBuffer(char *szLineStr) {
185   int nFeedEnd;
186   int ret;
187   EnterCriticalSection(&CriticalSection);
188   if (lpFeedEnd == NULL) {
189     ret=FALSE;
190   } else {
191     nFeedEnd = lpFeedEnd - lpBuffer;
192     memcpy(szLineStr, lpBuffer, nFeedEnd);
193     if (szLineStr[nFeedEnd - 1] == '\r') {
194       szLineStr[nFeedEnd - 1] = '\0';
195     } else {
196       szLineStr[nFeedEnd] = '\0';
197     }
198     nFeedEnd ++;
199     nReadEnd -= nFeedEnd;
200     memcpy(lpBuffer, lpBuffer + nFeedEnd, nReadEnd);
201     lpFeedEnd = (char *) memchr(lpBuffer, '\n', nReadEnd);
202     ret=TRUE;
203   }
204   LeaveCriticalSection(&CriticalSection);
205   return ret;
206 }
207
208 void PipeStruct::LineInput(char *szLineStr) {
209     while(!EOF_()){
210         if (GetBuffer(szLineStr)) {
211             break;
212         }else{
213             WaitForSingleObject(hEvent,INFINITE);
214         }
215     }
216 }
217
218 void PipeStruct::LineOutput(const char *szLineStr) const {
219   DWORD dwBytes;
220   int nStrLen;
221   char szWriteBuffer[LINE_INPUT_MAX_CHAR];
222   if(bPipe){
223       nStrLen = strlen(szLineStr);
224       memcpy(szWriteBuffer, szLineStr, nStrLen);
225       szWriteBuffer[nStrLen] = '\r';
226       szWriteBuffer[nStrLen + 1] = '\n';
227       WriteFile(hOutput, szWriteBuffer, nStrLen + 2, &dwBytes, NULL);
228   }else{
229       printf("%s\n",szLineStr);
230       fflush(stdout);
231   }
232 }
233 #endif