2 #define WIN32_LEAN_AND_MEAN
30 #define null ((void *)0)
32 typedef unsigned int FileSeekMode;
33 typedef unsigned int PipeOpenMode;
34 typedef unsigned char byte;
35 typedef unsigned short uint16;
36 typedef unsigned int uint;
39 int __ecereNameSpace__ecere__sys__Tokenize(char * string, int maxTokens, char * tokens[], unsigned int escapeBackSlashes);
40 char * __ecereNameSpace__ecere__sys__CopyString(char * string);
41 void __ecereNameSpace__ecere__com__eSystem_Delete(void * memory);
42 unsigned short * __ecereNameSpace__ecere__sys__UTF8toUTF16(char * source, int * wordCount);
46 #if defined(__WIN32__)
47 HANDLE inputHandle, outputHandle;
50 FILE * input, * output;
56 void DualPipe_Destructor(_DualPipe * dp)
58 #if defined(__WIN32__)
61 CloseHandle(dp->outputHandle);
62 dp->outputHandle = null;
66 CloseHandle(dp->inputHandle);
67 dp->inputHandle = null;
70 CloseHandle(dp->hProcess);
75 void DualPipe_CloseInput(_DualPipe * dp)
77 #if defined(__WIN32__)
80 CloseHandle(dp->inputHandle);
81 dp->inputHandle = null;
86 void DualPipe_CloseOutput(_DualPipe * dp)
88 #if defined(__WIN32__)
91 CloseHandle(dp->outputHandle);
92 dp->outputHandle = null;
97 int DualPipe_Read(_DualPipe * dp, byte * buffer, uint size, uint count)
99 #if defined(__WIN32__)
101 dp->eof = !ReadFile(dp->inputHandle, buffer, size*count, (DWORD *)&read, null);
105 result = read(fileno(dp->input), buffer, size * count);
106 if(!result || (result < 0 && errno != EAGAIN))
108 return (result > 0) ? (result / size) : 0;
112 int DualPipe_Write(_DualPipe * dp, byte * buffer, uint size, uint count)
114 #if defined(__WIN32__)
115 unsigned int written;
116 WriteFile(dp->outputHandle, buffer, size * count, (DWORD *)&written, null);
117 return written / size;
122 bool DualPipe_Getc(_DualPipe * dp, char * ch)
124 #if defined(__WIN32__)
126 dp->eof = !ReadFile(dp->inputHandle, ch, 1, (DWORD *)&read, null);
127 return !dp->eof && read != 0;
132 bool DualPipe_Putc(_DualPipe * dp, char ch)
134 #if defined(__WIN32__)
135 unsigned int written;
136 WriteFile(dp->outputHandle, &ch, 1, (DWORD *)&written, null);
142 bool DualPipe_Puts(_DualPipe * dp, char * string)
144 #if defined(__WIN32__)
145 unsigned int written;
146 int len = strlen(string);
147 WriteFile(dp->outputHandle, string, len, (DWORD *)&written, null);
148 return written == len;
153 bool DualPipe_Seek(_DualPipe * dp, int pos, FileSeekMode mode)
155 #if defined(__WIN32__)
160 result = SetFilePointer(dp->inputHandle, pos, null, FILE_BEGIN) != -1;
163 result = SetFilePointer(dp->inputHandle, pos, null, FILE_CURRENT) != -1;
166 result = SetFilePointer(dp->inputHandle, pos, null, FILE_END) != -1;
174 uint DualPipe_Tell(_DualPipe * dp)
176 #if defined(__WIN32__)
177 return (uint)SetFilePointer(dp->inputHandle, 0, null, FILE_CURRENT);
182 bool DualPipe_Eof(_DualPipe * dp)
184 #if defined(__WIN32__)
187 return !dp->input || dp->eof || feof(dp->input);
191 // Not yet supported... Will ever be?
192 bool DualPipe_GetSize(_DualPipe * dp)
197 bool DualPipe_Peek(_DualPipe * dp)
199 #if defined(__WIN32__)
201 int result = PeekNamedPipe(dp->inputHandle, null, 0, null, (DWORD *)&avail, null);
206 dp->eof = !ReadFile(dp->inputHandle, buffer, 0, (DWORD *)&read, null);
208 return avail ? true : false;
210 bool result = false; //true; // false
211 if(!DualPipe_Eof(dp))
215 int fd = fileno(dp->input);
220 return select(fd+1, &rs, null, null, &tv) > 0;
226 void DualPipe_Terminate(_DualPipe * dp)
228 #if defined(__WIN32__)
229 TerminateProcess(dp->hProcess, 0);
232 kill(dp->pid, SIGTERM);
236 int DualPipe_GetExitCode(_DualPipe * dp)
238 #if !defined(__WIN32__)
240 waitpid(dp->pid, &status, 0);
241 /*#if defined(__linux__)
242 // Until we support this _extension_ syntax: (moved this to a C file...)
243 // return (((( _extension_ (((union { __typeof(status) __in; int __i; }) { .__in = (status) }).__i))) & 0xff00) >> 8);
244 // return ((__extension__({ union { __typeof(status) __in; int __i; } __u; __u.__in = (status); __u.__i; }) ) & 0xFF00) >> 8;
246 return WEXITSTATUS(status);
248 //return __WEXITSTATUS(status);
251 // NOTE: This was inconsistent with Linux version waiting... Testing Suite would not return proper values
252 WaitForSingleObject(dp->hProcess, INFINITE);
253 GetExitCodeProcess(dp->hProcess, (DWORD *)&exitCode);
258 int DualPipe_GetProcessID(_DualPipe * dp)
261 // Requires Windows Vista or Windows XP SP1.
262 // return GetProcessId(hProcess);
265 void DualPipe_Wait(_DualPipe * dp)
267 #if defined(__WIN32__)
268 WaitForSingleObject(dp->hProcess, INFINITE);
271 waitpid(dp->pid, 0, 0);
275 _DualPipe * _DualPipeOpen(PipeOpenMode mode, char * commandLine, char * env, void ** inputPtr, void ** outputPtr)
277 _DualPipe * f = null;
281 #if !defined(__WIN32__)
283 FILE * input = null, * output = null;
284 int hInput[2] = { 0 }, hOutput[2] = { 0 };
287 if((mode & POM_error) || (mode & POM_output))
290 if((mode & POM_input))
297 if(hInput[PIPE_READ])
299 close(hInput[PIPE_READ]);
300 output = fdopen(hInput[PIPE_WRITE],"w");
302 if(hOutput[PIPE_WRITE])
304 close(hOutput[PIPE_WRITE]);
305 input = fdopen(hOutput[PIPE_READ],"r");
313 char * commandLineCopy = __ecereNameSpace__ecere__sys__CopyString(commandLine);
315 if(hInput[PIPE_WRITE])
316 close(hInput[PIPE_WRITE]);
317 if(hOutput[PIPE_READ])
318 close(hOutput[PIPE_READ]);
320 if((mode & POM_error) && hOutput[PIPE_WRITE] != STDERR_FILENO)
321 dup2(hOutput[PIPE_WRITE], STDERR_FILENO);
323 if((mode & POM_output) && hOutput[PIPE_WRITE] != STDOUT_FILENO)
324 dup2(hOutput[PIPE_WRITE], STDOUT_FILENO);
325 if(hOutput[PIPE_WRITE] && hOutput[PIPE_WRITE] != STDOUT_FILENO)
326 close(hOutput[PIPE_WRITE]);
328 if((mode & POM_input) && hInput[PIPE_READ] != STDIN_FILENO)
330 dup2(hInput[PIPE_READ], STDIN_FILENO);
331 close(hInput[PIPE_READ]);
334 numTokens = __ecereNameSpace__ecere__sys__Tokenize(commandLineCopy, sizeof(tokens) / sizeof(tokens[0]) - 1, tokens, false);
335 tokens[numTokens] = null;
338 char * envTokens[129];
339 char * envCopy = __ecereNameSpace__ecere__sys__CopyString(env);
340 int numEnvTokens = __ecereNameSpace__ecere__sys__Tokenize(envCopy, sizeof(envTokens) / sizeof(envTokens[0]) - 1, envTokens, false);
341 envTokens[numEnvTokens] = null;
343 if(execve(tokens[0], tokens, envTokens) < 0)
345 __ecereNameSpace__ecere__com__eSystem_Delete(commandLineCopy);
346 __ecereNameSpace__ecere__com__eSystem_Delete(envCopy);
349 __ecereNameSpace__ecere__com__eSystem_Delete(commandLineCopy);
350 __ecereNameSpace__ecere__com__eSystem_Delete(envCopy);
355 if(execvp(tokens[0], (char **)tokens) < 0)
357 __ecereNameSpace__ecere__com__eSystem_Delete(commandLineCopy);
360 __ecereNameSpace__ecere__com__eSystem_Delete(commandLineCopy);
366 f = calloc(1, sizeof(_DualPipe));
367 *inputPtr = f->input = input;
368 *outputPtr = f->output = output;
374 HANDLE hOutput[2] = { 0 },hOutputRead = 0;
375 HANDLE hInput[2] = { 0 }, hInputWrite = 0;
376 HANDLE hError[2] = { 0 }, hErrorRead = 0;
377 HANDLE hStdErr = 0, hStdIn = 0, hStdOut = 0;
378 SECURITY_ATTRIBUTES sa;
379 PROCESS_INFORMATION pi = { 0 };
380 STARTUPINFO si = { 0 };
381 uint16 * _wcommandLine = __ecereNameSpace__ecere__sys__UTF8toUTF16(commandLine, null);
383 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
384 sa.lpSecurityDescriptor = null;
385 sa.bInheritHandle = TRUE;
387 // Force redirecting if GUI application
388 if(!(mode & POM_error))
389 hStdErr = GetStdHandle(STD_ERROR_HANDLE);
390 if(!(mode & POM_input))
391 hStdIn = GetStdHandle(STD_INPUT_HANDLE);
392 if(!(mode & POM_output))
393 hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
395 if((mode & POM_output) || !hStdOut)
396 CreatePipe(&hOutput[PIPE_READ],&hOutput[PIPE_WRITE],&sa,0);
398 if(( (mode & POM_error) && !(mode & POM_output)) ||
399 (!(mode & POM_error) && !hStdErr))
400 CreatePipe(&hError[PIPE_READ], &hError[PIPE_WRITE],&sa,0);
402 if((mode & POM_input) || !hStdIn)
403 CreatePipe(&hInput[PIPE_READ], &hInput[PIPE_WRITE], &sa,0);
405 if(hInput[PIPE_READ])
406 DuplicateHandle(GetCurrentProcess(),hInput[PIPE_WRITE],GetCurrentProcess(),&hInputWrite,0,FALSE,DUPLICATE_SAME_ACCESS);
408 if((mode & POM_error) && (mode & POM_output))
410 DuplicateHandle(GetCurrentProcess(),hOutput[PIPE_READ],GetCurrentProcess(),&hOutputRead,0,FALSE,DUPLICATE_SAME_ACCESS);
411 DuplicateHandle(GetCurrentProcess(),hOutput[PIPE_WRITE],GetCurrentProcess(),&hError[PIPE_WRITE],0,TRUE,DUPLICATE_SAME_ACCESS);
415 if(hOutput[PIPE_WRITE])
416 DuplicateHandle(GetCurrentProcess(),hOutput[PIPE_READ],GetCurrentProcess(),&hOutputRead,0,FALSE,DUPLICATE_SAME_ACCESS);
417 if(hError[PIPE_WRITE])
418 DuplicateHandle(GetCurrentProcess(),hError[PIPE_READ],GetCurrentProcess(),&hErrorRead,0,FALSE,DUPLICATE_SAME_ACCESS);
421 if(hOutput[PIPE_READ])
422 CloseHandle(hOutput[PIPE_READ]);
423 if(hError[PIPE_READ])
424 CloseHandle(hError[PIPE_READ]);
425 if(hInput[PIPE_WRITE])
426 CloseHandle(hInput[PIPE_WRITE]);
428 // Set up the start up info struct.
429 si.cb = sizeof(STARTUPINFO);
430 si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
431 si.hStdOutput = hOutput[PIPE_WRITE] ? hOutput[PIPE_WRITE] : hStdOut;
432 si.hStdInput = hInput [PIPE_READ] ? hInput [PIPE_READ] : hStdIn;
433 if((mode & POM_error) && (mode & POM_output))
434 si.hStdError = hOutput[PIPE_WRITE];
435 else if((mode & POM_error))
436 si.hStdError = hError[PIPE_WRITE];
438 si.hStdError = hError[PIPE_WRITE] ? hError[PIPE_WRITE] : hStdErr;
440 if(CreateProcess(null,_wcommandLine,null,null,TRUE, 0,env,null ,&si,&pi))
442 CloseHandle(pi.hThread);
444 f = calloc(1, sizeof(_DualPipe));
445 f->inputHandle = hOutputRead;
446 f->outputHandle = hInputWrite;
447 f->hProcess = pi.hProcess;
448 f->pid = pi.dwProcessId;
455 CloseHandle(hOutputRead);
457 CloseHandle(hInputWrite);
459 CloseHandle(hErrorRead);
462 if(hInput [PIPE_READ]) CloseHandle(hInput [PIPE_READ]);
463 if(hOutput[PIPE_WRITE]) CloseHandle(hOutput[PIPE_WRITE]);
464 if(hError [PIPE_WRITE]) CloseHandle(hError [PIPE_WRITE]);
465 __ecereNameSpace__ecere__com__eSystem_Delete(_wcommandLine);