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