#pragma once #include "common.hpp" #include "components/logger.hpp" #include "components/types.hpp" #include "errors.hpp" #include "utils/file.hpp" POLYBAR_NS DEFINE_ERROR(command_error); enum class output_policy { REDIRECTED, IGNORED, }; /** * Wrapper used to execute command in a subprocess. * In-/output streams are opened to enable ipc. * If the command is created using command, the child streams are * redirected and you can read the program output or write into the program input. * * If the command is created using command, the output is not redirected and * you can't communicate with the child program. * * Example usage: * * @code cpp * commandauto(m_log, "cat /etc/rc.local"); * cmd->exec(); * cmd->tail([](string s) { std::cout << s << std::endl; }); * @endcode * * @code cpp * commandauto(m_log, "for i in 1 2 3; do echo $i; done"); * cmd->exec(); * cout << cmd->readline(); // 1 * cout << cmd->readline() << cmd->readline(); // 23 * @endcode * * @code cpp * commandauto(m_log, "ping kernel.org"); * int status = cmd->exec(); * @endcode */ template class command; template <> class command { public: explicit command(const logger& logger, string cmd); command(const command&) = delete; ~command(); command& operator=(const command&) = delete; int exec(bool wait_for_completion = true); void terminate(); bool is_running(); int wait(); pid_t get_pid(); int get_exit_status(); protected: const logger& m_log; string m_cmd; pid_t m_forkpid{-1}; int m_forkstatus{-1}; }; template <> class command : private command { public: explicit command(const logger& logger, string cmd); command(const command&) = delete; ~command(); command& operator=(const command&) = delete; int exec(bool wait_for_completion = true, const vector>& env = {}); using command::terminate; using command::is_running; using command::wait; using command::get_pid; using command::get_exit_status; void tail(std::function cb); string readline(); int get_stdout(int c); int get_stdin(int c); protected: int m_stdout[2]{0, 0}; int m_stdin[2]{0, 0}; unique_ptr> m_stdout_reader{nullptr}; }; POLYBAR_NS_END