38 #include "blocxx/BLOCXX_config.h"
47 #if !defined(BLOCXX_WIN32)
57 #ifdef BLOCXX_HAVE_SYS_RESOURCE_H
58 #include <sys/resource.h>
60 #ifdef BLOCXX_HAVE_SYS_TYPES_H
61 #include <sys/types.h>
63 #ifdef BLOCXX_HAVE_UNISTD_H
73 #if defined(sigaction)
77 #define SIG_DFL (void(*)())0
80 namespace BLOCXX_NAMESPACE
106 return proc->processStatus();
120 char const * exec_path,
121 char const *
const argv[],
char const *
const envp[],
134 char const * exec_path,
135 char const *
const argv[],
char const *
const envp[],
143 return spawnImpl(exec_path, argv, envp, pre_exec);
148 char const *
const argv[],
char const *
const envp[]
158 return spawn(argv[0], argv, envp, pre_exec);
186 #define BLOCXX_MIN(x, y) (x) < (y) ? (x) : (y)
190 class StringOutputGatherer :
public OutputCallback
193 StringOutputGatherer(String& stdoutput, String& erroutput,
int outputLimit)
199 StringOutputGatherer(String& stdoutput,
int outputLimit)
206 virtual void doHandleData(
const char* data,
size_t dataLen,
208 size_t streamIndex, Array<char>& inputBuffer)
217 output += String(data, lentocopy);
220 "Exec::StringOutputGatherer::doHandleData(): buffer full");
223 output += String(data, dataLen);
231 class SingleStringInputCallback :
public InputCallback
234 SingleStringInputCallback(
const String& s)
239 virtual void doGetData(Array<char>& inputBuffer,
const ProcessRef& theProc,
size_t streamIndex)
241 if (
m_s.length() > 0)
243 inputBuffer.insert(inputBuffer.end(),
m_s.c_str(),
m_s.c_str() +
m_s.length());
246 else if (theProc->in()->isOpen())
248 theProc->in()->close();
258 char const *
const command[],
260 char const *
const envVars[],
267 return g_execMockObject.get()->executeProcessAndGatherOutput(command, output, envVars, timeout, outputLimit, input);
270 output, timeout, outputLimit, input);
275 char const *
const command[],
278 char const *
const envVars[],
285 return g_execMockObject.get()->executeProcessAndGatherOutput2(command, output,
286 erroutput, envVars, timeout, outputLimit, input);
290 output, erroutput, timeout, outputLimit, input);
296 String& output,
int& processstatus,
297 int timeoutsecs,
int outputlimit,
301 if (timeoutsecs != -1)
322 SingleStringInputCallback singleStringInputCallback(input);
324 StringOutputGatherer gatherer(output, outputLimit);
326 proc->waitCloseTerm();
327 return proc->processStatus();
340 SingleStringInputCallback singleStringInputCallback(input);
342 StringOutputGatherer gatherer(output, erroutput, outputLimit);
344 proc->waitCloseTerm();
345 return proc->processStatus();
360 StringOutputGatherer gatherer(output, outputLimit);
361 SingleStringInputCallback singleStringInputCallback = SingleStringInputCallback(
String());
375 doHandleData(data, dataLen, outputSource, theProc, streamIndex, inputBuffer);
387 doGetData(inputBuffer, theProc, streamIndex);
392 struct ProcessOutputState
417 int numOpenPipes(procs.
size() * 2);
420 for (
size_t i = 0;
i < processStates.size(); ++
i)
422 input.
getData(inputs[
i], procs[i], i);
423 processStates[
i].availableDataLen = inputs[
i].size();
424 if (!procs[i]->out()->isOpen())
426 processStates[
i].outIsOpen =
false;
428 if (!procs[i]->err()->isOpen())
430 processStates[
i].errIsOpen =
false;
432 if (!procs[i]->in()->isOpen())
434 processStates[
i].inIsOpen =
false;
441 while (numOpenPipes > 0)
444 std::map<int, int> inputIndexProcessIndex;
445 std::map<int, int> outputIndexProcessIndex;
446 for (
size_t i = 0;
i < procs.
size(); ++
i)
453 inputIndexProcessIndex[selObjs.
size() - 1] =
i;
460 inputIndexProcessIndex[selObjs.
size() - 1] =
i;
467 outputIndexProcessIndex[selObjs.
size() - 1] =
i;
491 int availableToFind = selectrval;
496 for (
size_t i = 0;
i < selObjs.
size() && availableToFind > 0; ++
i)
498 if (!selObjs[
i].readAvailable)
506 int streamIndex = inputIndexProcessIndex[
i];
508 if (processStates[streamIndex].
outIsOpen)
510 if (procs[streamIndex]->out()->getReadSelectObj() == selObjs[
i].s)
512 readstream = procs[streamIndex]->out();
516 if (!readstream && processStates[streamIndex].
errIsOpen)
518 if (procs[streamIndex]->err()->getReadSelectObj() == selObjs[
i].s)
520 readstream = procs[streamIndex]->err();
530 int readrc = readstream->
read(buff,
sizeof(buff) - 1);
533 if (readstream == procs[streamIndex]->out())
535 processStates[streamIndex].outIsOpen =
false;
536 procs[streamIndex]->out()->close();
540 processStates[streamIndex].errIsOpen =
false;
541 procs[streamIndex]->err()->close();
545 else if (readrc == -1)
557 streamIndex, inputs[streamIndex]);
562 for (
size_t i = 0;
i < selObjs.
size() && availableToFind > 0; ++
i)
564 if (!selObjs[
i].writeAvailable)
572 int streamIndex = outputIndexProcessIndex[
i];
574 if (processStates[streamIndex].
inIsOpen)
576 writestream = procs[streamIndex]->in();
584 size_t offset = inputs[streamIndex].
size() - processStates[streamIndex].availableDataLen;
585 int writerc = writestream->
write(&inputs[streamIndex][offset], processStates[streamIndex].
availableDataLen);
586 if (writerc == -1 && errno == EPIPE)
588 processStates[streamIndex].inIsOpen =
false;
589 procs[streamIndex]->in()->close();
591 else if (writerc == -1)
595 else if (writerc != 0)
597 inputs[streamIndex].erase(inputs[streamIndex].begin(), inputs[streamIndex].begin() + writerc);
598 input.
getData(inputs[streamIndex], procs[streamIndex], streamIndex);
599 processStates[streamIndex].availableDataLen = inputs[streamIndex].size();
609 const Timeout& timeout,
int outputLimit)
614 StringOutputGatherer gatherer(output, outputLimit);
615 SingleStringInputCallback singleStringInputCallback = SingleStringInputCallback(input);