4 #define WIN32_LEAN_AND_MEAN
8 #include <sys/select.h>
24 #define POM_showWindow 8
34 #define null ((void *)0)
36 typedef unsigned int FileSeekMode;
37 typedef unsigned int PipeOpenMode;
38 typedef unsigned char byte;
39 typedef unsigned short uint16;
40 typedef unsigned int uint;
43 #define forArgsPassing 2
44 int __ecereNameSpace__ecere__sys__Tokenize(char * string, int maxTokens, char * tokens[], unsigned int esc);
45 char * __ecereNameSpace__ecere__sys__CopyString(const char * string);
46 void __ecereNameSpace__ecere__com__eSystem_Delete(void * memory);
47 unsigned short * __ecereNameSpace__ecere__sys__UTF8toUTF16(const char * source, int * wordCount);
51 #if defined(__WIN32__)
52 HANDLE inputHandle, outputHandle;
55 FILE * input, * output;
59 bool eof:1, gotExitCode:1;
62 void DualPipe_Destructor(_DualPipe * dp)
64 #if defined(__WIN32__)
67 CloseHandle(dp->outputHandle);
68 dp->outputHandle = null;
72 CloseHandle(dp->inputHandle);
73 dp->inputHandle = null;
76 CloseHandle(dp->hProcess);
81 void DualPipe_CloseInput(_DualPipe * dp)
83 #if defined(__WIN32__)
86 CloseHandle(dp->inputHandle);
87 dp->inputHandle = null;
92 void DualPipe_CloseOutput(_DualPipe * dp)
94 #if defined(__WIN32__)
97 CloseHandle(dp->outputHandle);
98 dp->outputHandle = null;
103 int DualPipe_Read(_DualPipe * dp, byte * buffer, uint size, uint count)
105 #if defined(__WIN32__)
107 dp->eof = !ReadFile(dp->inputHandle, buffer, size*count, (DWORD *)&read, null);
111 result = read(fileno(dp->input), buffer, size * count);
112 if(!result || (result < 0 && errno != EAGAIN))
114 return (result > 0) ? (result / size) : 0;
118 int DualPipe_Write(_DualPipe * dp, const byte * buffer, uint size, uint count)
120 #if defined(__WIN32__)
121 unsigned int written;
122 WriteFile(dp->outputHandle, buffer, size * count, (DWORD *)&written, null);
123 return written / size;
128 bool DualPipe_Getc(_DualPipe * dp, char * ch)
130 #if defined(__WIN32__)
132 dp->eof = !ReadFile(dp->inputHandle, ch, 1, (DWORD *)&read, null);
133 return !dp->eof && read != 0;
138 bool DualPipe_Putc(_DualPipe * dp, char ch)
140 #if defined(__WIN32__)
141 unsigned int written;
142 WriteFile(dp->outputHandle, &ch, 1, (DWORD *)&written, null);
148 bool DualPipe_Puts(_DualPipe * dp, const char * string)
150 #if defined(__WIN32__)
151 unsigned int written;
152 int len = strlen(string);
153 WriteFile(dp->outputHandle, string, len, (DWORD *)&written, null);
154 return written == len;
159 bool DualPipe_Seek(_DualPipe * dp, int pos, FileSeekMode mode)
161 #if defined(__WIN32__)
166 result = SetFilePointer(dp->inputHandle, pos, null, FILE_BEGIN) != -1;
169 result = SetFilePointer(dp->inputHandle, pos, null, FILE_CURRENT) != -1;
172 result = SetFilePointer(dp->inputHandle, pos, null, FILE_END) != -1;
180 uint DualPipe_Tell(_DualPipe * dp)
182 #if defined(__WIN32__)
183 return (uint)SetFilePointer(dp->inputHandle, 0, null, FILE_CURRENT);
188 bool DualPipe_Eof(_DualPipe * dp)
190 #if defined(__WIN32__)
193 return !dp->input || dp->eof || feof(dp->input);
197 // Not yet supported... Will ever be?
198 bool DualPipe_GetSize(_DualPipe * dp)
203 bool DualPipe_Peek(_DualPipe * dp)
205 #if defined(__WIN32__)
207 int result = PeekNamedPipe(dp->inputHandle, null, 0, null, (DWORD *)&avail, null);
212 dp->eof = !ReadFile(dp->inputHandle, buffer, 0, (DWORD *)&read, null);
214 return avail ? true : false;
216 bool result = false; //true; // false
217 if(!DualPipe_Eof(dp))
221 int fd = fileno(dp->input);
226 return select(fd+1, &rs, null, null, &tv) > 0;
232 void DualPipe_Terminate(_DualPipe * dp)
234 #if defined(__WIN32__)
235 TerminateProcess(dp->hProcess, 0);
238 kill(dp->pid, SIGTERM);
242 int DualPipe_GetExitCode(_DualPipe * dp)
244 #if !defined(__WIN32__)
248 waitpid(dp->pid, &status, 0);
249 dp->exitCode = WEXITSTATUS(status);
250 dp->gotExitCode = true;
252 /*#if defined(__linux__)
253 // Until we support this _extension_ syntax: (moved this to a C file...)
254 // return (((( _extension_ (((union { __typeof(status) __in; int __i; }) { .__in = (status) }).__i))) & 0xff00) >> 8);
255 // return ((__extension__({ union { __typeof(status) __in; int __i; } __u; __u.__in = (status); __u.__i; }) ) & 0xFF00) >> 8;
259 //return __WEXITSTATUS(status);
262 // NOTE: This was inconsistent with Linux version waiting... Testing Suite would not return proper values
263 WaitForSingleObject(dp->hProcess, INFINITE);
264 GetExitCodeProcess(dp->hProcess, (DWORD *)&exitCode);
269 int DualPipe_GetProcessID(_DualPipe * dp)
272 // Requires Windows Vista or Windows XP SP1.
273 // return GetProcessId(hProcess);
276 void DualPipe_Wait(_DualPipe * dp)
278 #if defined(__WIN32__)
279 WaitForSingleObject(dp->hProcess, INFINITE);
284 waitpid(dp->pid, &status, 0);
285 dp->exitCode = WEXITSTATUS(status);
286 dp->gotExitCode = true;
291 _DualPipe * _DualPipeOpen(PipeOpenMode mode, const char * commandLine, const char * env, void ** inputPtr, void ** outputPtr)
293 _DualPipe * f = null;
297 #if !defined(__WIN32__)
299 FILE * input = null, * output = null;
300 int hInput[2] = { 0 }, hOutput[2] = { 0 };
304 if((mode & POM_error) || (mode & POM_output))
308 if((mode & POM_input))
317 if(hInput[PIPE_READ])
319 close(hInput[PIPE_READ]);
320 output = fdopen(hInput[PIPE_WRITE],"w");
322 if(hOutput[PIPE_WRITE])
324 close(hOutput[PIPE_WRITE]);
325 input = fdopen(hOutput[PIPE_READ],"r");
333 char * commandLineCopy = __ecereNameSpace__ecere__sys__CopyString(commandLine);
335 if(hInput[PIPE_WRITE])
336 close(hInput[PIPE_WRITE]);
337 if(hOutput[PIPE_READ])
338 close(hOutput[PIPE_READ]);
340 if((mode & POM_error) && hOutput[PIPE_WRITE] != STDERR_FILENO)
341 dup2(hOutput[PIPE_WRITE], STDERR_FILENO);
343 if((mode & POM_output) && hOutput[PIPE_WRITE] != STDOUT_FILENO)
344 dup2(hOutput[PIPE_WRITE], STDOUT_FILENO);
345 if(hOutput[PIPE_WRITE] && hOutput[PIPE_WRITE] != STDOUT_FILENO)
346 close(hOutput[PIPE_WRITE]);
348 if((mode & POM_input) && hInput[PIPE_READ] != STDIN_FILENO)
350 dup2(hInput[PIPE_READ], STDIN_FILENO);
351 close(hInput[PIPE_READ]);
354 #if 0 //#ifdef _DEBUG
355 fprintf(stderr, "\n_DualPipeOpen (in child): %s\n\n", commandLineCopy);
357 numTokens = __ecereNameSpace__ecere__sys__Tokenize(commandLineCopy, sizeof(tokens) / sizeof(tokens[0]) - 1, tokens, forArgsPassing);
358 #if 0 //#ifdef _DEBUG
359 { int c; for(c=0; c<numTokens; c++) fprintf(stderr, "argv[%d]: %s\n", c, tokens[c]); fprintf(stderr, "\n"); }
361 tokens[numTokens] = null;
364 char * envTokens[129];
365 char * envCopy = __ecereNameSpace__ecere__sys__CopyString(env);
366 int numEnvTokens = __ecereNameSpace__ecere__sys__Tokenize(envCopy, sizeof(envTokens) / sizeof(envTokens[0]) - 1, envTokens, false);
367 envTokens[numEnvTokens] = null;
369 if(execve(tokens[0], tokens, envTokens) < 0)
371 __ecereNameSpace__ecere__com__eSystem_Delete(commandLineCopy);
372 __ecereNameSpace__ecere__com__eSystem_Delete(envCopy);
375 __ecereNameSpace__ecere__com__eSystem_Delete(commandLineCopy);
376 __ecereNameSpace__ecere__com__eSystem_Delete(envCopy);
381 if(execvp(tokens[0], (char **)tokens) < 0)
383 __ecereNameSpace__ecere__com__eSystem_Delete(commandLineCopy);
386 __ecereNameSpace__ecere__com__eSystem_Delete(commandLineCopy);
392 f = calloc(1, sizeof(_DualPipe));
393 *inputPtr = f->input = input;
394 *outputPtr = f->output = output;
400 if(hInput[PIPE_READ])
401 close(hInput[PIPE_READ]);
402 if(hInput[PIPE_WRITE])
403 close(hInput[PIPE_WRITE]);
404 if(hOutput[PIPE_WRITE])
405 close(hOutput[PIPE_WRITE]);
406 if(hOutput[PIPE_READ])
407 close(hOutput[PIPE_READ]);
412 HANDLE hOutput[2] = { 0 },hOutputRead = 0;
413 HANDLE hInput[2] = { 0 }, hInputWrite = 0;
414 HANDLE hError[2] = { 0 }, hErrorRead = 0;
415 HANDLE hStdErr = 0, hStdIn = 0, hStdOut = 0;
416 SECURITY_ATTRIBUTES sa;
417 PROCESS_INFORMATION pi = { 0 };
418 STARTUPINFO si = { 0 };
419 uint16 * _wcommandLine = __ecereNameSpace__ecere__sys__UTF8toUTF16(commandLine, null);
421 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
422 sa.lpSecurityDescriptor = null;
423 sa.bInheritHandle = TRUE;
425 // Force redirecting if GUI application
426 if(!(mode & POM_error))
427 hStdErr = GetStdHandle(STD_ERROR_HANDLE);
428 if(!(mode & POM_input))
429 hStdIn = GetStdHandle(STD_INPUT_HANDLE);
430 if(!(mode & POM_output))
431 hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
433 if((mode & POM_output) || !hStdOut)
434 CreatePipe(&hOutput[PIPE_READ],&hOutput[PIPE_WRITE],&sa,0);
436 if(( (mode & POM_error) && !(mode & POM_output)) ||
437 (!(mode & POM_error) && !hStdErr))
438 CreatePipe(&hError[PIPE_READ], &hError[PIPE_WRITE],&sa,0);
440 if((mode & POM_input) || !hStdIn)
441 CreatePipe(&hInput[PIPE_READ], &hInput[PIPE_WRITE], &sa,0);
443 if(hInput[PIPE_READ])
444 DuplicateHandle(GetCurrentProcess(),hInput[PIPE_WRITE],GetCurrentProcess(),&hInputWrite,0,FALSE,DUPLICATE_SAME_ACCESS);
446 if((mode & POM_error) && (mode & POM_output))
448 DuplicateHandle(GetCurrentProcess(),hOutput[PIPE_READ],GetCurrentProcess(),&hOutputRead,0,FALSE,DUPLICATE_SAME_ACCESS);
449 DuplicateHandle(GetCurrentProcess(),hOutput[PIPE_WRITE],GetCurrentProcess(),&hError[PIPE_WRITE],0,TRUE,DUPLICATE_SAME_ACCESS);
453 if(hOutput[PIPE_WRITE])
454 DuplicateHandle(GetCurrentProcess(),hOutput[PIPE_READ],GetCurrentProcess(),&hOutputRead,0,FALSE,DUPLICATE_SAME_ACCESS);
455 if(hError[PIPE_WRITE])
456 DuplicateHandle(GetCurrentProcess(),hError[PIPE_READ],GetCurrentProcess(),&hErrorRead,0,FALSE,DUPLICATE_SAME_ACCESS);
459 if(hOutput[PIPE_READ])
460 CloseHandle(hOutput[PIPE_READ]);
461 if(hError[PIPE_READ])
462 CloseHandle(hError[PIPE_READ]);
463 if(hInput[PIPE_WRITE])
464 CloseHandle(hInput[PIPE_WRITE]);
466 // Set up the start up info struct.
467 si.cb = sizeof(STARTUPINFO);
468 si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
469 si.wShowWindow = (mode & POM_showWindow) ? SW_SHOW : SW_HIDE;
470 si.hStdOutput = hOutput[PIPE_WRITE] ? hOutput[PIPE_WRITE] : hStdOut;
471 si.hStdInput = hInput [PIPE_READ] ? hInput [PIPE_READ] : hStdIn;
472 if((mode & POM_error) && (mode & POM_output))
473 si.hStdError = hOutput[PIPE_WRITE];
474 else if((mode & POM_error))
475 si.hStdError = hError[PIPE_WRITE];
477 si.hStdError = hError[PIPE_WRITE] ? hError[PIPE_WRITE] : hStdErr;
479 if(CreateProcess(null,_wcommandLine,null,null,TRUE, 0,(void *)env,null ,&si,&pi))
481 CloseHandle(pi.hThread);
483 f = calloc(1, sizeof(_DualPipe));
484 f->inputHandle = hOutputRead;
485 f->outputHandle = hInputWrite;
486 f->hProcess = pi.hProcess;
487 f->pid = pi.dwProcessId;
494 CloseHandle(hOutputRead);
496 CloseHandle(hInputWrite);
498 CloseHandle(hErrorRead);
501 if(hInput [PIPE_READ]) CloseHandle(hInput [PIPE_READ]);
502 if(hOutput[PIPE_WRITE]) CloseHandle(hOutput[PIPE_WRITE]);
503 if(hError [PIPE_WRITE]) CloseHandle(hError [PIPE_WRITE]);
504 __ecereNameSpace__ecere__com__eSystem_Delete(_wcommandLine);