2016-06-15 03:32:35 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "common.hpp"
|
|
|
|
#include "components/logger.hpp"
|
|
|
|
#include "utils/threading.hpp"
|
|
|
|
|
|
|
|
LEMONBUDDY_NS
|
|
|
|
|
|
|
|
namespace command_util {
|
2016-11-02 19:22:45 +00:00
|
|
|
DEFINE_ERROR(command_error);
|
|
|
|
DEFINE_CHILD_ERROR(command_strerror, command_error);
|
|
|
|
|
2016-06-15 03:32:35 +00:00
|
|
|
/**
|
2016-10-15 11:15:56 +00:00
|
|
|
* Wrapper used to execute command in a subprocess.
|
|
|
|
* In-/output streams are opened to enable ipc.
|
|
|
|
*
|
2016-06-15 03:32:35 +00:00
|
|
|
* Example usage:
|
2016-10-15 11:15:56 +00:00
|
|
|
*
|
2016-06-15 03:32:35 +00:00
|
|
|
* @code cpp
|
2016-10-15 11:15:56 +00:00
|
|
|
* auto cmd = command_util::make_command("cat /etc/rc.local");
|
2016-06-15 03:32:35 +00:00
|
|
|
* cmd->exec();
|
2016-10-15 11:15:56 +00:00
|
|
|
* cmd->tail([](string s) { std::cout << s << std::endl; });
|
|
|
|
* @endcode
|
2016-06-15 03:32:35 +00:00
|
|
|
*
|
2016-10-15 11:15:56 +00:00
|
|
|
* @code cpp
|
|
|
|
* auto cmd = command_util::make_command(
|
2016-10-28 16:51:07 +00:00
|
|
|
* "while read -r line; do echo data from parent process: $line; done");
|
2016-10-15 11:15:56 +00:00
|
|
|
* cmd->exec(false);
|
2016-06-15 03:32:35 +00:00
|
|
|
* cmd->writeline("Test");
|
2016-10-15 11:15:56 +00:00
|
|
|
* cout << cmd->readline();
|
|
|
|
* cmd->wait();
|
|
|
|
* @endcode
|
2016-06-15 03:32:35 +00:00
|
|
|
*
|
2016-10-15 11:15:56 +00:00
|
|
|
* @code cpp
|
2016-10-28 16:51:07 +00:00
|
|
|
* auto cmd = command_util::make_command("for i in 1 2 3; do echo $i; done");
|
2016-10-15 11:15:56 +00:00
|
|
|
* cmd->exec();
|
|
|
|
* cout << cmd->readline(); // 1
|
|
|
|
* cout << cmd->readline() << cmd->readline(); // 23
|
|
|
|
* @endcode
|
2016-06-15 03:32:35 +00:00
|
|
|
*/
|
|
|
|
class command {
|
|
|
|
public:
|
2016-11-02 19:22:45 +00:00
|
|
|
explicit command(const logger& logger, string cmd);
|
|
|
|
|
|
|
|
~command();
|
|
|
|
|
|
|
|
int exec(bool wait_for_completion = true);
|
|
|
|
void terminate();
|
|
|
|
bool is_running();
|
|
|
|
int wait();
|
|
|
|
|
|
|
|
void tail(callback<string> callback);
|
|
|
|
int writeline(string data);
|
|
|
|
string readline();
|
|
|
|
|
|
|
|
int get_stdout(int c);
|
|
|
|
int get_stdin(int c);
|
|
|
|
pid_t get_pid();
|
|
|
|
int get_exit_status();
|
2016-06-15 03:32:35 +00:00
|
|
|
|
|
|
|
protected:
|
|
|
|
const logger& m_log;
|
|
|
|
|
|
|
|
string m_cmd;
|
|
|
|
|
|
|
|
int m_stdout[2];
|
|
|
|
int m_stdin[2];
|
|
|
|
|
|
|
|
pid_t m_forkpid;
|
|
|
|
int m_forkstatus;
|
|
|
|
|
|
|
|
threading_util::spin_lock m_pipelock;
|
|
|
|
};
|
|
|
|
|
2016-10-15 11:15:56 +00:00
|
|
|
using command_t = unique_ptr<command>;
|
|
|
|
|
2016-06-15 03:32:35 +00:00
|
|
|
template <typename... Args>
|
2016-10-15 11:15:56 +00:00
|
|
|
command_t make_command(Args&&... args) {
|
2016-10-28 16:51:07 +00:00
|
|
|
return make_unique<command>(configure_logger().create<const logger&>(), forward<Args>(args)...);
|
2016-06-15 03:32:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-14 08:21:18 +00:00
|
|
|
using command = command_util::command;
|
|
|
|
using command_t = command_util::command_t;
|
|
|
|
|
2016-06-15 03:32:35 +00:00
|
|
|
LEMONBUDDY_NS_END
|