7 DWORD WINAPI ThreadProc(LPVOID lpParam){
8 PipeStruct *p=(PipeStruct *) lpParam;
9 while(!p->EOF_input()){
10 if(p->nReadEnd<LINE_INPUT_MAX_CHAR-1){
13 // wait until there is room in buffer
22 void PipeStruct::Open(const char *szProcFile) {
23 DWORD dwMode, dwThreadId;
24 HANDLE hStdinRead, hStdinWrite, hStdoutRead, hStdoutWrite;
25 SECURITY_ATTRIBUTES sa;
27 PROCESS_INFORMATION pi;
30 if (szProcFile == NULL) {
31 hInput = GetStdHandle(STD_INPUT_HANDLE);
32 hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
33 bConsole = GetConsoleMode(hInput, &dwMode);
36 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
37 sa.bInheritHandle = TRUE;
38 sa.lpSecurityDescriptor = NULL;
39 CreatePipe(&hStdinRead, &hStdinWrite, &sa, 0);
40 CreatePipe(&hStdoutRead, &hStdoutWrite, &sa, 0);
41 si.cb = sizeof(STARTUPINFO);
42 si.lpReserved = si.lpDesktop = si.lpTitle = NULL;
43 si.dwFlags = STARTF_USESTDHANDLES;
45 si.lpReserved2 = NULL;
46 si.hStdInput = hStdinRead;
47 si.hStdOutput = hStdoutWrite;
48 si.hStdError = hStdoutWrite;
49 if(CreateProcess(NULL,
54 DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP,
60 CloseHandle(pi.hThread);
61 CloseHandle(hStdinRead);
62 CloseHandle(hStdoutWrite);
64 hOutput = hStdinWrite;
68 my_fatal("PipeStruct::Open(): %s",my_error());
72 SetConsoleMode(hInput,
73 dwMode & ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT));
74 FlushConsoleInputBuffer(hInput);
76 fdInput=_open_osfhandle((long) hInput,_O_RDONLY);
78 my_fatal("PipeStruct::Open(): %s",my_error());
80 fpInput=fdopen(fdInput,"r");
82 my_fatal("PipeStruct::Open(): %s",my_error());
86 InitializeCriticalSection(&CriticalSection);
87 hEvent=CreateEvent(NULL, // default security
89 FALSE, // not signaled
93 my_fatal("PipeStruct::Open(): %s",my_error());
95 hThread=CreateThread(NULL, // default security
96 0, // default stacksize
97 ThreadProc, // worker function
98 this, // tell worker about ourselves
100 &dwThreadId // dropped, but needed for the call to work in Win9x
103 my_fatal("PipeStruct::Open(): %s",my_error());
109 void PipeStruct::Close(void) const {
110 CloseHandle(hOutput);
113 void PipeStruct::Kill(void) const {
115 CloseHandle(hOutput);
118 if(GetExitCodeProcess(hProcess,&lpexit)){
119 if(lpexit==STILL_ACTIVE)
120 //must be java,hammer it down!
121 TerminateProcess(hProcess,lpexit);
123 CloseHandle(hProcess);
126 bool PipeStruct::EOF_input(void){ // EOF is defined
128 EnterCriticalSection(&CriticalSection);
130 LeaveCriticalSection(&CriticalSection);
134 void PipeStruct::set_EOF_input(void){
135 EnterCriticalSection(&CriticalSection);
137 LeaveCriticalSection(&CriticalSection);
140 bool PipeStruct::Active(void){
142 EnterCriticalSection(&CriticalSection);
143 ret=state&PIPE_ACTIVE;
144 LeaveCriticalSection(&CriticalSection);
148 void PipeStruct::set_Active(void){
149 EnterCriticalSection(&CriticalSection);
151 LeaveCriticalSection(&CriticalSection);
154 int PipeStruct::ReadData(void){
157 // No protection. Access to nReadEnd is atomic.
158 // It is not a problem that nReadEnd becomes smaller after the call.
159 // This just means we have read less than we could have.
160 ret=fgets(lpReadBuffer,LINE_INPUT_MAX_CHAR-nReadEnd,fpInput);
163 lpReadBuffer[0]='\0';
166 dwBytes=strlen(lpReadBuffer);
167 lpReadBuffer[dwBytes]='\0';
171 void PipeStruct::ReadInput(void) {
174 BOOL bSetEvent=FALSE;
175 // ReadData is outside the critical section otherwise everything
176 // would block during the blocking read
178 EnterCriticalSection(&CriticalSection);
180 if(ret+nReadEnd>=LINE_INPUT_MAX_CHAR){
181 my_fatal("PipeStruct::ReadInput(): Internal error: buffer overflow\n");
183 memcpy(lpBuffer+nReadEnd,lpReadBuffer,ret+1);
186 lpFeedEnd = (char *) memchr(lpBuffer, '\n', nReadEnd);
190 }else if(nReadEnd>=LINE_INPUT_MAX_CHAR-1){
191 my_fatal("PipeStruct::ReadInput(): LINE_INPUT_MAX_CHAR is equal to %d which is too small to contain a full line of engine output or GUI input.\n",LINE_INPUT_MAX_CHAR);
194 LeaveCriticalSection(&CriticalSection);
195 if(EOF_input() || bSetEvent){
200 bool PipeStruct::EOF_(void){
202 EnterCriticalSection(&CriticalSection);
203 if(lpFeedEnd != NULL){
205 }else if(EOF_input()){
210 LeaveCriticalSection(&CriticalSection);
214 bool PipeStruct::GetBuffer(char *szLineStr) {
217 EnterCriticalSection(&CriticalSection);
218 if (lpFeedEnd == NULL) {
221 nFeedEnd = lpFeedEnd - lpBuffer;
222 memcpy(szLineStr, lpBuffer, nFeedEnd);
223 if (szLineStr[nFeedEnd - 1] == '\r') {
224 szLineStr[nFeedEnd - 1] = '\0';
226 szLineStr[nFeedEnd] = '\0';
229 nReadEnd -= nFeedEnd;
230 memcpy(lpBuffer, lpBuffer + nFeedEnd, nReadEnd);
231 lpFeedEnd = (char *) memchr(lpBuffer, '\n', nReadEnd);
234 LeaveCriticalSection(&CriticalSection);
240 void PipeStruct::LineInput(char *szLineStr) {
242 if (GetBuffer(szLineStr)) {
245 WaitForSingleObject(hEvent,INFINITE);
250 void PipeStruct::LineOutput(const char *szLineStr) const {
253 char szWriteBuffer[LINE_INPUT_MAX_CHAR];
255 nStrLen = strlen(szLineStr);
256 memcpy(szWriteBuffer, szLineStr, nStrLen);
257 szWriteBuffer[nStrLen] = '\r';
258 szWriteBuffer[nStrLen + 1] = '\n';
259 WriteFile(hOutput, szWriteBuffer, nStrLen + 2, &dwBytes, NULL);
261 printf("%s\n",szLineStr);