diff --git a/Makefile b/Makefile index e755e28..9d02f0c 100644 --- a/Makefile +++ b/Makefile @@ -58,4 +58,4 @@ clean: rm $(ODIR)/*.o $(ODIR_SHARED)/*.o clear: - rm libztd.a libztd.so + rm -rd libztd.a libztd.so doc diff --git a/include/shell.hpp b/include/shell.hpp index 82fe357..37ce167 100644 --- a/include/shell.hpp +++ b/include/shell.hpp @@ -3,8 +3,12 @@ #include #include +#include #include + +#include "wait.hpp" + /*! \file shell.hpp * @brief Shell functionality and interaction */ @@ -15,10 +19,18 @@ namespace ztd /*! @param command Shell command to execute @param to_console Output to console - @return Output of the command + @return Output of command */ std::string sh(const std::string& command, bool to_console=false); + //! @brief Execute a shell command and retrieve its return value + /*! + @param command Shell command to execute + Always outputs to console + @return Return value of command + */ + int shr(const std::string& command); + //! @brief Execute a shell command and retrieve its output and return value /*! @param command Shell command to execute @@ -40,11 +52,36 @@ namespace ztd */ int pclose2(FILE* fp, pid_t pid); - // class shell - // { - // public: - // private: - // }; + class shc + { + public: + shc(std::string const& cmd="", bool const cout=false); + virtual ~shc(); + + void run(); + int kill_int(); + + void wait_output(); + std::string get_output(); + + void wait_finish(); + + std::string command; + bool to_console; + + bool running; + pid_t pid; + + std::queue output; + int return_value; + + ztd::wait_pool wp_output; + ztd::wait_pool wp_finish; + + private: + static void run_process(shc* p); + }; + } #endif //SHELL_HPP diff --git a/src/shell.cpp b/src/shell.cpp index 2a2876e..2eaa25f 100644 --- a/src/shell.cpp +++ b/src/shell.cpp @@ -1,5 +1,7 @@ #include "shell.hpp" +#include + #include #include #include @@ -12,6 +14,11 @@ std::string ztd::sh(const std::string& command, bool to_console) return ztd::shp(command, to_console).first; } +int ztd::shr(const std::string& command) +{ + return WEXITSTATUS(system(command.c_str())); +} + std::pair ztd::shp(const std::string& command, bool to_console) { std::string ret; @@ -21,12 +28,11 @@ std::pair ztd::shp(const std::string& command, bool to_console while (getline(&buff, &buff_size, stream) > 0) { if(to_console) - { printf("%s", buff); - } + ret += buff; } - return std::make_pair(ret, pclose(stream)); + return std::make_pair(ret, WEXITSTATUS(pclose(stream))); } FILE* ztd::popen2(const char* command, const char* type, int* pid) @@ -98,3 +104,82 @@ int ztd::pclose2(FILE* fp, pid_t pid) return stat; } + +// SHC + +ztd::shc::shc(std::string const& cmd, bool const cout) +{ + this->command=cmd; + this->to_console=cout; +} +ztd::shc::~shc() +{ + if(this->running) + this->kill_int(); +} + +void ztd::shc::run() +{ + std::thread(ztd::shc::run_process, this).detach(); +} + +int ztd::shc::kill_int() +{ + if(running) + return kill(this->pid, SIGINT); + else + return 1; +} + +void ztd::shc::wait_output() +{ + while(this->output.size() <= 0) + this->wp_output.wait(); +} + +std::string ztd::shc::get_output() +{ + if(output.size() > 0) + { + std::string ret = this->output.front(); + this->output.pop(); + return ret; + } + else + return ""; +} + +void ztd::shc::wait_finish() +{ + while(this->running) + this->wp_finish.wait(); +} + +void ztd::shc::run_process(shc* p) +{ + if(p->running) + return; + + char* buff = NULL; + size_t buff_size = 0; + int pid = 0; + + FILE *stream = ztd::popen2(p->command.c_str(), "r", &pid); + p->pid = pid; + p->running = true; + + std::string ln; + while ( getline(&buff, &buff_size, stream) > 0 ) //retrieve device lines + { + if(p->to_console) + printf("%s", buff); + + ln = std::string(buff, buff_size); + p->output.push(ln); + p->wp_output.notify_all(); + } + + p->running = false; + p->wp_finish.notify_all(); + p->return_value = ztd::pclose2(stream, pid); +}