1 #ifndef CPPAD_CG_LINUX_SYSTEM_INCLUDED 2 #define CPPAD_CG_LINUX_SYSTEM_INCLUDED 18 #if CPPAD_CG_SYSTEM_LINUX 20 #include <sys/types.h> 43 inline FDHandler() : fd(0), closed(true) {
46 inline explicit FDHandler(
int fd) : fd(fd), closed(false) {
70 inline void create() {
73 throw CGException(
"Failed to create pipe");
84 #ifdef CPPAD_CG_SYSTEM_APPLE 86 const std::string SystemInfo<T>::DYNAMIC_LIB_EXTENSION =
".dylib";
89 const std::string SystemInfo<T>::DYNAMIC_LIB_EXTENSION =
".so";
93 const std::string SystemInfo<T>::STATIC_LIB_EXTENSION =
".a";
95 inline std::string getWorkingDirectory() {
98 char* ret = getcwd(buffer, 1024);
100 const char* error = strerror(errno);
101 throw CGException(
"Failed to get current working directory: ", error);
108 int ret = mkdir(folder.c_str(), 0755);
110 if (errno != EEXIST) {
111 const char* error = strerror(errno);
112 throw CGException(
"Failed to create directory '", folder +
"': ", error);
117 inline std::string
createPath(
const std::string& baseFolder,
118 const std::string& file) {
119 if (!baseFolder.empty() && baseFolder.back() ==
'/') {
120 return baseFolder + file;
122 return baseFolder +
"/" + file;
126 inline std::string
escapePath(
const std::string& path) {
127 return std::string(
"\"") + path +
"\"";
130 inline std::string filenameFromPath(
const std::string& path) {
131 size_t pos = path.rfind(
'/');
132 if (pos != std::string::npos) {
133 if (pos == path.size() - 1) {
136 return path.substr(pos + 1);
143 inline std::string directoryFromPath(
const std::string& path) {
144 size_t found = path.find_last_of(
'/');
145 if (found != std::string::npos) {
146 return path.substr(0, found + 1);
155 return path[0] ==
'/';
161 if (stat(path.c_str(), &info) != 0) {
163 }
else if (info.st_mode & S_IFDIR) {
170 inline bool isFile(
const std::string& path) {
173 if (stat(path.c_str(), &sts) == 0 && errno == 0) {
174 return S_ISREG(sts.st_mode);
175 }
else if (errno == ENOENT) {
183 const std::vector<std::string>& args,
184 std::string* stdOutErrMessage,
185 const std::string* stdInMessage) {
186 std::string execName = filenameFromPath(executable);
191 PipeHandler pipeStdOutErr;
192 if(stdOutErrMessage !=
nullptr) {
193 pipeStdOutErr.create();
197 if (stdInMessage !=
nullptr) {
205 throw CGException(
"Failed to fork process");
212 pipeMsg.read.close();
214 if (stdInMessage !=
nullptr) {
215 pipeSrc.write.close();
218 if (dup2(pipeSrc.read.fd, STDIN_FILENO) == -1) {
219 perror(
"redirecting stdin");
224 if(stdOutErrMessage !=
nullptr) {
225 pipeStdOutErr.read.close();
228 if (dup2(pipeStdOutErr.write.fd, STDOUT_FILENO) == -1) {
229 perror(
"redirecting stdout");
234 if (dup2(pipeStdOutErr.write.fd, STDERR_FILENO) == -1) {
235 perror(
"redirecting stderr");
240 auto toCharArray = [](
const std::string & args) {
241 const size_t s = args.size() + 1;
242 char* args2 =
new char[s];
243 for (
size_t c = 0; c < s - 1; c++) {
244 args2[c] = args.at(c);
250 std::vector<char*> args2(args.size() + 2);
251 args2[0] = toCharArray(execName);
252 for (
size_t i = 0; i < args.size(); i++) {
253 args2[i + 1] = toCharArray(args[i]);
255 args2.back() = (
char *)
nullptr;
257 int eCode = execv(executable.c_str(), &args2[0]);
259 for (
size_t i = 0; i < args.size(); i++) {
263 if(stdOutErrMessage !=
nullptr) {
264 pipeStdOutErr.write.close();
269 #ifndef CPPAD_CG_SYSTEM_APPLE 270 std::string error = executable +
": " + strerror_r(errno, buf, 511);
272 std::string error = executable +
": ";
273 strerror_r(errno, buf, 511);
274 error += std::string(buf);
276 ssize_t size = error.size() + 1;
277 if (write(pipeMsg.write.fd, error.c_str(), size) != size) {
278 std::cerr <<
"Failed to send message to parent process" << std::endl;
280 std::cerr <<
"*** ERROR: exec failed" << std::endl;
290 pipeMsg.write.close();
291 if(stdOutErrMessage !=
nullptr) {
292 pipeStdOutErr.write.close();
295 auto readCErrorMsg = []() {
299 #ifndef CPPAD_CG_SYSTEM_APPLE 300 return std::string(strerror_r(error, buf, 512));
302 strerror_r(error, buf, 512);
303 return std::string(buf);
307 std::string writeError;
308 if (stdInMessage !=
nullptr) {
310 pipeSrc.read.close();
312 ssize_t writeFlag = write(pipeSrc.write.fd, stdInMessage->c_str(), stdInMessage->size());
314 writeError = readCErrorMsg() +
" ";
315 pipeSrc.write.close();
321 std::ostringstream messageErr;
322 std::ostringstream messageStdOutErr;
327 if(stdOutErrMessage !=
nullptr) {
328 while ((n = read(pipeStdOutErr.read.fd, buffer, sizeof (buffer))) > 0) {
329 messageStdOutErr.write(buffer, n);
331 if (size > 1e4)
break;
335 while ((n = read(pipeMsg.read.fd, buffer, sizeof (buffer))) > 0) {
336 messageErr.write(buffer, n);
338 if (size > 1e4)
break;
341 if (waitpid(pid, &status, 0) < 0) {
342 throw CGException(
"Waitpid failed for pid ", pid,
" [", readCErrorMsg(),
"]");
344 }
while (!WIFEXITED(status) && !WIFSIGNALED(status));
346 pipeMsg.read.close();
347 if(stdOutErrMessage !=
nullptr) {
348 pipeStdOutErr.read.close();
351 if (!writeError.empty()) {
352 std::ostringstream s;
353 s <<
"Failed to write to pipe";
354 if (size > 0) s <<
": " << messageErr.str();
355 else s <<
": " << writeError;
356 throw CGException(s.str());
359 if (WIFEXITED(status)) {
360 if (WEXITSTATUS(status) != EXIT_SUCCESS) {
361 std::ostringstream s;
362 s <<
"Executable '" << executable <<
"' (pid " << pid <<
") exited with code " << WEXITSTATUS(status);
363 if (size > 0) s <<
": " << messageErr.str();
364 throw CGException(s.str());
366 }
else if (WIFSIGNALED(status)) {
367 std::ostringstream s;
368 s <<
"Executable '" << executable <<
"' (pid " << pid <<
") terminated by signal " << WTERMSIG(status);
369 if (size > 0) s <<
": " << messageErr.str();
370 throw CGException(s.str());
373 if (stdOutErrMessage !=
nullptr) {
374 *stdOutErrMessage = messageStdOutErr.str();
void callExecutable(const std::string &executable, const std::vector< std::string > &args, std::string *stdOutErrMessage=nullptr, const std::string *stdInMessage=nullptr)
std::string createPath(const std::string &baseFolder, const std::string &file)
bool isDirectory(const std::string &path)
std::string escapePath(const std::string &path)
bool isAbsolutePath(const std::string &path)
void createFolder(const std::string &folder)
bool isFile(const std::string &path)