in src/Subprocess.cpp [32:132]
DoSystemResult myDoSystemImpl(const char* cmd, int timeout,
SystemOutputType outType, const char* outFile,
SystemOutputType errType, const char* errFile,
const char* inFile, bool background, int consignals) {
if (background) {
if (outType == COLLECT) outType = IGNORE_OUTPUT;
if (errType == COLLECT) errType = IGNORE_OUTPUT;
}
bool replInput = !inFile[0];
std::string buf = "";
std::shared_ptr<std::ofstream> outFileStream, errFileStream;
if (outType == TO_FILE) {
outFileStream = std::make_shared<std::ofstream>(outFile, std::ios_base::out | std::ios_base::binary);
}
if (errType == TO_FILE) {
errFileStream = std::make_shared<std::ofstream>(errFile, std::ios_base::out | std::ios_base::binary);
}
std::shared_ptr<TinyProcessLib::Process> process = std::make_shared<TinyProcessLib::Process>(
cmd, "",
[outType, outFileStream = std::move(outFileStream), background, &buf] (const char* s, size_t len) {
switch (outType) {
case IGNORE_OUTPUT:
break;
case COLLECT:
buf.insert(buf.end(), s, s + len);
break;
case PRINT:
rpiService->executeOnMainThread([&] {
WithOutputHandler with = background ? WithOutputHandler(rpiService->replOutputHandler) : WithOutputHandler();
Rprintf("%s", std::string(s, s + len).c_str());
});
break;
case TO_FILE:
outFileStream->write(s, len);
break;
}
},
[errType, errFileStream = std::move(errFileStream), background, &buf] (const char* s, size_t len) {
switch (errType) {
case IGNORE_OUTPUT:
break;
case COLLECT:
buf.insert(buf.end(), s, s + len);
break;
case PRINT:
rpiService->executeOnMainThread([&] {
WithOutputHandler with = background ? WithOutputHandler(rpiService->replOutputHandler) : WithOutputHandler();
REprintf("%s", std::string(s, s + len).c_str());
});
break;
case TO_FILE:
errFileStream->write(s, len);
break;
}
},
!background || !replInput
);
if (!replInput) {
std::thread([process, f = std::string(inFile)] {
std::ifstream inStream(f, std::ios_base::in | std::ios_base::binary);
char buf[BUF_SIZE];
int unused;
while (!process->try_get_exit_status(unused) && inStream.good()) {
inStream.read(buf, BUF_SIZE);
auto size = inStream.gcount();
if (size > 0) process->write(buf, size);
}
process->close_stdin();
}).detach();
}
if (background) {
std::thread([process] {
process->get_exit_status();
}).detach();
return {"", 0, false};
}
volatile int exitCode = 0;
volatile bool timedOut = false;
std::thread terminationThread([&] {
exitCode = process->get_exit_status();
rpiService->subprocessHandlerStop();
});
std::unique_ptr<Timer> timeoutTimer = timeout == 0 ? nullptr : std::make_unique<Timer>([&] {
timedOut = true;
process->kill();
}, timeout);
rpiService->subprocessHandler(
replInput,
[&] (std::string const& s) {
if (s.empty()) {
process->close_stdin();
} else {
process->write(s);
}
},
[&] { process->kill(); }
);
terminationThread.join();
return { buf, timedOut ? 124 : exitCode, timedOut };
}