2 #define WIN32_LEAN_AND_MEAN
6 #include <sys/select.h>
22 #define POM_showWindow 8
32 #define null ((void *)0)
34 typedef unsigned int FileSeekMode;
35 typedef unsigned int PipeOpenMode;
36 typedef unsigned char byte;
37 typedef unsigned short uint16;
38 typedef unsigned int uint;
41 #define forArgsPassing 2
42 int __ecereNameSpace__ecere__sys__Tokenize(char * string, int maxTokens, char * tokens[], unsigned int esc);
43 char * __ecereNameSpace__ecere__sys__CopyString(const char * string);
44 void __ecereNameSpace__ecere__com__eSystem_Delete(void * memory);
45 unsigned short * __ecereNameSpace__ecere__sys__UTF8toUTF16(const char * source, int * wordCount);
49 #if defined(__WIN32__)
50 HANDLE inputHandle, outputHandle;
53 FILE * input, * output;
57 bool eof:1, gotExitCode:1;
60 void DualPipe_Destructor(_DualPipe * dp)
62 #if defined(__WIN32__)
65 CloseHandle(dp->outputHandle);
66 dp->outputHandle = null;
70 CloseHandle(dp->inputHandle);
71 dp->inputHandle = null;
74 CloseHandle(dp->hProcess);
79 void DualPipe_CloseInput(_DualPipe * dp)
81 #if defined(__WIN32__)
84 CloseHandle(dp->inputHandle);
85 dp->inputHandle = null;
90 void DualPipe_CloseOutput(_DualPipe * dp)
92 #if defined(__WIN32__)
95 CloseHandle(dp->outputHandle);
96 dp->outputHandle = null;
101 int DualPipe_Read(_DualPipe * dp, byte * buffer, uint size, uint count)
103 #if defined(__WIN32__)
105 dp->eof = !ReadFile(dp->inputHandle, buffer, size*count, (DWORD *)&read, null);
109 result = read(fileno(dp->input), buffer, size * count);
110 if(!result || (result < 0 && errno != EAGAIN))
112 return (result > 0) ? (result / size) : 0;
116 int DualPipe_Write(_DualPipe * dp, const byte * buffer, uint size, uint count)
118 #if defined(__WIN32__)
119 unsigned int written;
120 WriteFile(dp->outputHandle, buffer, size * count, (DWORD *)&written, null);
121 return written / size;
126 bool DualPipe_Getc(_DualPipe * dp, char * ch)
128 #if defined(__WIN32__)
130 dp->eof = !ReadFile(dp->inputHandle, ch, 1, (DWORD *)&read, null);
131 return !dp->eof && read != 0;
136 bool DualPipe_Putc(_DualPipe * dp, char ch)
138 #if defined(__WIN32__)
139 unsigned int written;
140 WriteFile(dp->outputHandle, &ch, 1, (DWORD *)&written, null);
146 bool DualPipe_Puts(_DualPipe * dp, const char * string)
148 #if defined(__WIN32__)
149 unsigned int written;
150 int len = strlen(string);
151 WriteFile(dp->outputHandle, string, len, (DWORD *)&written, null);
152 return written == len;
157 bool DualPipe_Seek(_DualPipe * dp, int pos, FileSeekMode mode)
159 #if defined(__WIN32__)
164 result = SetFilePointer(dp->inputHandle, pos, null, FILE_BEGIN) != -1;
167 result = SetFilePointer(dp->inputHandle, pos, null, FILE_CURRENT) != -1;
170 result = SetFilePointer(dp->inputHandle, pos, null, FILE_END) != -1;
178 uint DualPipe_Tell(_DualPipe * dp)
180 #if defined(__WIN32__)
181 return (uint)SetFilePointer(dp->inputHandle, 0, null, FILE_CURRENT);
186 bool DualPipe_Eof(_DualPipe * dp)
188 #if defined(__WIN32__)
191 return !dp->input || dp->eof || feof(dp->input);
195 // Not yet supported... Will ever be?
196 bool DualPipe_GetSize(_DualPipe * dp)
201 bool DualPipe_Peek(_DualPipe * dp)
203 #if defined(__WIN32__)
205 int result = PeekNamedPipe(dp->inputHandle, null, 0, null, (DWORD *)&avail, null);
210 dp->eof = !ReadFile(dp->inputHandle, buffer, 0, (DWORD *)&read, null);
212 return avail ? true : false;
214 bool result = false; //true; // false
215 if(!DualPipe_Eof(dp))
219 int fd = fileno(dp->input);
224 return select(fd+1, &rs, null, null, &tv) > 0;
230 void DualPipe_Terminate(_DualPipe * dp)
232 #if defined(__WIN32__)
233 TerminateProcess(dp->hProcess, 0);
236 kill(dp->pid, SIGTERM);
240 int DualPipe_GetExitCode(_DualPipe * dp)
242 #if !defined(__WIN32__)
246 waitpid(dp->pid, &status, 0);
247 dp->exitCode = WEXITSTATUS(status);
248 dp->gotExitCode = true;
250 /*#if defined(__linux__)
251 // Until we support this _extension_ syntax: (moved this to a C file...)
252 // return (((( _extension_ (((union { __typeof(status) __in; int __i; }) { .__in = (status) }).__i))) & 0xff00) >> 8);
253 // return ((__extension__({ union { __typeof(status) __in; int __i; } __u; __u.__in = (status); __u.__i; }) ) & 0xFF00) >> 8;
257 //return __WEXITSTATUS(status);
260 // NOTE: This was inconsistent with Linux version waiting... Testing Suite would not return proper values
261 WaitForSingleObject(dp->hProcess, INFINITE);
262 GetExitCodeProcess(dp->hProcess, (DWORD *)&exitCode);
267 int DualPipe_GetProcessID(_DualPipe * dp)
270 // Requires Windows Vista or Windows XP SP1.
271 // return GetProcessId(hProcess);
274 void DualPipe_Wait(_DualPipe * dp)
276 #if defined(__WIN32__)
277 WaitForSingleObject(dp->hProcess, INFINITE);
282 waitpid(dp->pid, &status, 0);
283 dp->exitCode = WEXITSTATUS(status);
284 dp->gotExitCode = true;
289 _DualPipe * _DualPipeOpen(PipeOpenMode mode, const char * commandLine, const char * env, void ** inputPtr, void ** outputPtr)
291 _DualPipe * f = null;
295 #if !defined(__WIN32__)
297 FILE * input = null, * output = null;
298 int hInput[2] = { 0 }, hOutput[2] = { 0 };
302 if((mode & POM_error) || (mode & POM_output))
306 if((mode & POM_input))
315 if(hInput[PIPE_READ])
317 close(hInput[PIPE_READ]);
318 output = fdopen(hInput[PIPE_WRITE],"w");
320 if(hOutput[PIPE_WRITE])
322 close(hOutput[PIPE_WRITE]);
323 input = fdopen(hOutput[PIPE_READ],"r");
331 char * commandLineCopy = __ecereNameSpace__ecere__sys__CopyString(commandLine);
333 if(hInput[PIPE_WRITE])
334 close(hInput[PIPE_WRITE]);
335 if(hOutput[PIPE_READ])
336 close(hOutput[PIPE_READ]);
338 if((mode & POM_error) && hOutput[PIPE_WRITE] != STDERR_FILENO)
339 dup2(hOutput[PIPE_WRITE], STDERR_FILENO);
341 if((mode & POM_output) && hOutput[PIPE_WRITE] != STDOUT_FILENO)
342 dup2(hOutput[PIPE_WRITE], STDOUT_FILENO);
343 if(hOutput[PIPE_WRITE] && hOutput[PIPE_WRITE] != STDOUT_FILENO)
344 close(hOutput[PIPE_WRITE]);
346 if((mode & POM_input) && hInput[PIPE_READ] != STDIN_FILENO)
348 dup2(hInput[PIPE_READ], STDIN_FILENO);
349 close(hInput[PIPE_READ]);
352 #if 0 //#ifdef _DEBUG
353 fprintf(stderr, "\n_DualPipeOpen (in child): %s\n\n", commandLineCopy);
355 numTokens = __ecereNameSpace__ecere__sys__Tokenize(commandLineCopy, sizeof(tokens) / sizeof(tokens[0]) - 1, tokens, forArgsPassing);
356 #if 0 //#ifdef _DEBUG
357 { int c; for(c=0; c<numTokens; c++) fprintf(stderr, "argv[%d]: %s\n", c, tokens[c]); fprintf(stderr, "\n"); }
359 tokens[numTokens] = null;
362 char * envTokens[129];
363 char * envCopy = __ecereNameSpace__ecere__sys__CopyString(env);
364 int numEnvTokens = __ecereNameSpace__ecere__sys__Tokenize(envCopy, sizeof(envTokens) / sizeof(envTokens[0]) - 1, envTokens, false);
365 envTokens[numEnvTokens] = null;
367 if(execve(tokens[0], tokens, envTokens) < 0)
369 __ecereNameSpace__ecere__com__eSystem_Delete(commandLineCopy);
370 __ecereNameSpace__ecere__com__eSystem_Delete(envCopy);
373 __ecereNameSpace__ecere__com__eSystem_Delete(commandLineCopy);
374 __ecereNameSpace__ecere__com__eSystem_Delete(envCopy);
379 if(execvp(tokens[0], (char **)tokens) < 0)
381 __ecereNameSpace__ecere__com__eSystem_Delete(commandLineCopy);
384 __ecereNameSpace__ecere__com__eSystem_Delete(commandLineCopy);
390 f = calloc(1, sizeof(_DualPipe));
391 *inputPtr = f->input = input;
392 *outputPtr = f->output = output;
398 if(hInput[PIPE_READ])
399 close(hInput[PIPE_READ]);
400 if(hInput[PIPE_WRITE])
401 close(hInput[PIPE_WRITE]);
402 if(hOutput[PIPE_WRITE])
403 close(hOutput[PIPE_WRITE]);
404 if(hOutput[PIPE_READ])
405 close(hOutput[PIPE_READ]);
410 HANDLE hOutput[2] = { 0 },hOutputRead = 0;
411 HANDLE hInput[2] = { 0 }, hInputWrite = 0;
412 HANDLE hError[2] = { 0 }, hErrorRead = 0;
413 HANDLE hStdErr = 0, hStdIn = 0, hStdOut = 0;
414 SECURITY_ATTRIBUTES sa;
415 PROCESS_INFORMATION pi = { 0 };
416 STARTUPINFO si = { 0 };
417 uint16 * _wcommandLine = __ecereNameSpace__ecere__sys__UTF8toUTF16(commandLine, null);
419 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
420 sa.lpSecurityDescriptor = null;
421 sa.bInheritHandle = TRUE;
423 // Force redirecting if GUI application
424 if(!(mode & POM_error))
425 hStdErr = GetStdHandle(STD_ERROR_HANDLE);
426 if(!(mode & POM_input))
427 hStdIn = GetStdHandle(STD_INPUT_HANDLE);
428 if(!(mode & POM_output))
429 hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
431 if((mode & POM_output) || !hStdOut)
432 CreatePipe(&hOutput[PIPE_READ],&hOutput[PIPE_WRITE],&sa,0);
434 if(( (mode & POM_error) && !(mode & POM_output)) ||
435 (!(mode & POM_error) && !hStdErr))
436 CreatePipe(&hError[PIPE_READ], &hError[PIPE_WRITE],&sa,0);
438 if((mode & POM_input) || !hStdIn)
439 CreatePipe(&hInput[PIPE_READ], &hInput[PIPE_WRITE], &sa,0);
441 if(hInput[PIPE_READ])
442 DuplicateHandle(GetCurrentProcess(),hInput[PIPE_WRITE],GetCurrentProcess(),&hInputWrite,0,FALSE,DUPLICATE_SAME_ACCESS);
444 if((mode & POM_error) && (mode & POM_output))
446 DuplicateHandle(GetCurrentProcess(),hOutput[PIPE_READ],GetCurrentProcess(),&hOutputRead,0,FALSE,DUPLICATE_SAME_ACCESS);
447 DuplicateHandle(GetCurrentProcess(),hOutput[PIPE_WRITE],GetCurrentProcess(),&hError[PIPE_WRITE],0,TRUE,DUPLICATE_SAME_ACCESS);
451 if(hOutput[PIPE_WRITE])
452 DuplicateHandle(GetCurrentProcess(),hOutput[PIPE_READ],GetCurrentProcess(),&hOutputRead,0,FALSE,DUPLICATE_SAME_ACCESS);
453 if(hError[PIPE_WRITE])
454 DuplicateHandle(GetCurrentProcess(),hError[PIPE_READ],GetCurrentProcess(),&hErrorRead,0,FALSE,DUPLICATE_SAME_ACCESS);
457 if(hOutput[PIPE_READ])
458 CloseHandle(hOutput[PIPE_READ]);
459 if(hError[PIPE_READ])
460 CloseHandle(hError[PIPE_READ]);
461 if(hInput[PIPE_WRITE])
462 CloseHandle(hInput[PIPE_WRITE]);
464 // Set up the start up info struct.
465 si.cb = sizeof(STARTUPINFO);
466 si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
467 si.wShowWindow = (mode & POM_showWindow) ? SW_SHOW : SW_HIDE;
468 si.hStdOutput = hOutput[PIPE_WRITE] ? hOutput[PIPE_WRITE] : hStdOut;
469 si.hStdInput = hInput [PIPE_READ] ? hInput [PIPE_READ] : hStdIn;
470 if((mode & POM_error) && (mode & POM_output))
471 si.hStdError = hOutput[PIPE_WRITE];
472 else if((mode & POM_error))
473 si.hStdError = hError[PIPE_WRITE];
475 si.hStdError = hError[PIPE_WRITE] ? hError[PIPE_WRITE] : hStdErr;
477 if(CreateProcess(null,_wcommandLine,null,null,TRUE, 0,(void *)env,null ,&si,&pi))
479 CloseHandle(pi.hThread);
481 f = calloc(1, sizeof(_DualPipe));
482 f->inputHandle = hOutputRead;
483 f->outputHandle = hInputWrite;
484 f->hProcess = pi.hProcess;
485 f->pid = pi.dwProcessId;
492 CloseHandle(hOutputRead);
494 CloseHandle(hInputWrite);
496 CloseHandle(hErrorRead);
499 if(hInput [PIPE_READ]) CloseHandle(hInput [PIPE_READ]);
500 if(hOutput[PIPE_WRITE]) CloseHandle(hOutput[PIPE_WRITE]);
501 if(hError [PIPE_WRITE]) CloseHandle(hError [PIPE_WRITE]);
502 __ecereNameSpace__ecere__com__eSystem_Delete(_wcommandLine);