#include "ml_io.h" #include #include #include #include #include #include std::string read_file_contents(const std::string &filename) { std::ifstream f; f.open(filename.c_str()); if (!f) throw std::runtime_error("could not open file (" + filename + ")"); f.seekg(0, std::ios::end); std::string contents; contents.reserve(f.tellg()); f.seekg(0, std::ios::beg); contents.assign(std::istreambuf_iterator(f), std::istreambuf_iterator()); f.close(); return contents; } bool write_file_contents(const std::string &filename, const std::string &content) { std::ofstream f(filename.c_str()); if (f) { f << content; f.close(); return true; } return false; } MlValue list_dir(const std::string &path) { std::vector entries; DIR *dirp = opendir(path.c_str()); if (dirp == NULL) { throw std::runtime_error("could not open dir (" + path + ")"); } struct dirent *dp; while ((dp = readdir(dirp)) != NULL) { entries.push_back(MlValue::string(dp->d_name)); } closedir(dirp); return MlValue(entries); } bool is_path_file(const std::string &path) { struct stat buf{}; stat(path.c_str(), &buf); return (bool) S_ISREG(buf.st_mode) || (bool) S_ISBLK(buf.st_mode) || (bool) S_ISCHR(buf.st_mode) || (bool) S_ISFIFO(buf.st_mode) || (bool) S_ISSOCK(buf.st_mode); } bool is_path_dir(const std::string &path) { struct stat buf{}; stat(path.c_str(), &buf); return (bool) S_ISDIR(buf.st_mode); } bool mk_path_dir(const std::string &path) { auto r = ::mkdir(path.c_str(), 0755); if (r == -1) { std::string err_msg = std::strerror(errno); std::cerr << "mkdir failed: " << std::strerror(errno) << std::endl; } return r == 0; } bool rm_path_dir(const std::string &path) { auto r = ::rmdir(path.c_str()); if (r == -1) { std::string err_msg = std::strerror(errno); std::cerr << "rmdir failed: " << std::strerror(errno) << std::endl; } return r == 0; } MlValue exec_system_cmd(const std::string &cmd) { // TODO handle reading of stderr // https://stackoverflow.com/questions/478898/how-do-i-execute-a-command-and-get-the-output-of-the-command-within-c-using-po // https://jineshkj.wordpress.com/2006/12/22/how-to-capture-stdin-stdout-and-stderr-of-child-program/ std::string cmd_output; int stat; char buffer[128]; FILE *pipe = popen(cmd.c_str(), "r"); if (!pipe) throw std::runtime_error("popen() failed!"); try { while (!feof(pipe)) { if (fgets(buffer, 128, pipe) != nullptr) cmd_output += buffer; } } catch (...) { stat = pclose(pipe); throw; } stat = pclose(pipe); int cmd_retval = WEXITSTATUS(stat); return std::vector { MlValue((long)cmd_retval), MlValue::string(cmd_output) }; } MlValue exec_system_cmd_fork(const std::vector &args) { int pid = fork(); if (pid == 0) { // Child process, execute the command std::vector exec_args; exec_args.reserve(args.size()); for (auto const& a : args) exec_args.emplace_back(const_cast(a.c_str())); exec_args.push_back(nullptr); // exec must end with null execvp(args[0].c_str(), exec_args.data()); std::cerr << "execvp error: " << errno << ", " << strerror(errno) << std::endl; exit(1); // indicate error, if here } else if (pid > 0) { // Parent process, child process is now independent return std::vector { MlValue((long)0), MlValue::string("") }; } else { // Fork error, still in parent process (there are no child process at this point) return std::vector { MlValue((long)errno), MlValue::string(strerror(errno) ) }; } }