diff --git a/src/utils/execute.cpp b/src/utils/execute.cpp index 6a3f367..f0fd6e7 100644 --- a/src/utils/execute.cpp +++ b/src/utils/execute.cpp @@ -12,150 +12,168 @@ #include "contrib/base64.hpp" #include "utils/utils.hpp" - -bool EXITSTATUSCHECK(int ret) { +bool EXITSTATUSCHECK(int ret) +{ return (ret != -1 && WIFEXITED(ret) && (WEXITSTATUS(ret) == 0)); // ret is -1 if the command failed to execute. } -namespace dropshell { -bool execute_local_command_interactive(const sCommand &command) +namespace dropshell { - if (command.get_command_to_run().empty()) - return false; - std::string full_command = command.construct_cmd(cStyle::Raw); // Get the command string + bool execute_local_command_interactive(const sCommand &command) + { + if (command.get_command_to_run().empty()) + return false; + std::string full_command = command.construct_cmd(cStyle::Raw); // Get the command string - pid_t pid = fork(); + pid_t pid = fork(); - if (pid == -1) { - // Fork failed - perror("fork failed"); - return false; - } else if (pid == 0) { - int rval = system(full_command.c_str()); - exit(rval); - } else { - // Parent process - int ret; - // Wait for the child process to complete - waitpid(pid, &ret, 0); + if (pid == -1) + { + // Fork failed + perror("fork failed"); + return false; + } + else if (pid == 0) + { + int rval = system(full_command.c_str()); + exit(rval); + } + else + { + // Parent process + int ret; + // Wait for the child process to complete + waitpid(pid, &ret, 0); + return EXITSTATUSCHECK(ret); + } + } + + bool execute_local_command_and_capture_output(const sCommand &command, std::string *output) + { + ASSERT(output != nullptr, "Output string must be provided"); + if (command.get_command_to_run().empty()) + return false; + cStyle style = cStyle::Raw; + std::string full_cmd = command.construct_cmd(style) + " 2>&1"; + FILE *pipe = popen(full_cmd.c_str(), "r"); + if (!pipe) + { + return false; + } + char buffer[128]; + while (fgets(buffer, sizeof(buffer), pipe) != nullptr) + { + (*output) += buffer; + } + int ret = pclose(pipe); return EXITSTATUSCHECK(ret); } -} -bool execute_local_command_and_capture_output(const sCommand& command, std::string * output) -{ - ASSERT(output != nullptr, "Output string must be provided"); - if (command.get_command_to_run().empty()) - return false; - cStyle style = cStyle::Raw; - std::string full_cmd = command.construct_cmd(style) + " 2>&1"; - FILE *pipe = popen(full_cmd.c_str(), "r"); - if (!pipe) { - return false; - } - char buffer[128]; - while (fgets(buffer, sizeof(buffer), pipe) != nullptr) { - (*output) += buffer; - } - int ret = pclose(pipe); - return EXITSTATUSCHECK(ret); -} + bool execute_local_command(const sCommand &command, std::string *output /* = nullptr */, cMode mode /* = cMode::None */) + { + ASSERT(hasFlag(mode, cMode::RawCommand), "Raw command mode is required for local command execution"); -bool execute_local_command(const sCommand & command, std::string * output /* = nullptr */, cMode mode /* = cMode::None */) -{ - ASSERT(hasFlag(mode, cMode::RawCommand), "Raw command mode is required for local command execution"); + if (hasFlag(mode, cMode::Interactive)) + { + ASSERT(!hasFlag(mode, cMode::CaptureOutput), "Interactive mode and capture output mode cannot be used together"); + ASSERT(output == nullptr, "Interactive mode and an output string cannot be used together"); + ASSERT(is_raw(mode), "Interactive mode requires raw command mode"); - if (hasFlag(mode, cMode::Interactive)) { - ASSERT(! hasFlag(mode, cMode::CaptureOutput), "Interactive mode and capture output mode cannot be used together"); - ASSERT(output == nullptr, "Interactive mode and an output string cannot be used together"); - ASSERT(is_raw(mode), "Interactive mode requires raw command mode"); + return execute_local_command_interactive(command); + } - return execute_local_command_interactive(command); + if (hasFlag(mode, cMode::CaptureOutput)) + { + ASSERT(output != nullptr, "Capture output mode requires an output string to be provided"); + ASSERT(is_raw(mode), "Capture output mode requires raw command mode"); + ASSERT(!hasFlag(mode, cMode::Silent), "Silent mode is not allowed with capture output mode"); + + return execute_local_command_and_capture_output(command, output); + } + + if (command.get_command_to_run().empty()) + return false; + cStyle style = cStyle::Raw; + bool silent = hasFlag(mode, cMode::Silent); + std::string full_cmd = command.construct_cmd(style) + " 2>&1" + (silent ? " > /dev/null" : ""); + int ret = system(full_cmd.c_str()); + + bool ok = EXITSTATUSCHECK(ret); + if (!ok) + { + std::cerr << "Error: Failed to execute command: " << std::endl; + std::cerr << full_cmd << std::endl; + } + return ok; } - if (hasFlag(mode, cMode::CaptureOutput)) { - ASSERT(output != nullptr, "Capture output mode requires an output string to be provided"); - ASSERT(is_raw(mode), "Capture output mode requires raw command mode"); - ASSERT(!hasFlag(mode, cMode::Silent), "Silent mode is not allowed with capture output mode"); + bool execute_ssh_command(const sSSHInfo &ssh_info, const sCommand &command, cMode mode, std::string *output) + { + if (command.get_command_to_run().empty()) + return false; - return execute_local_command_and_capture_output(command, output); + ASSERT(!(hasFlag(mode, cMode::Interactive) && !is_raw(mode)), "Interactive mode requires raw command mode"); + ASSERT(!(hasFlag(mode, cMode::CaptureOutput) && output == nullptr), "Capture output mode must be used with an output string"); + + std::stringstream ssh_cmd; + ssh_cmd << "ssh -p " << ssh_info.port << " " << (hasFlag(mode, cMode::Interactive) ? "-tt " : "") + << ssh_info.user << "@" << ssh_info.host; + + std::string cmdstr = command.construct_cmd(is_raw(mode) ? cStyle::Raw : cStyle::Safe); + sCommand ssh_command(ssh_cmd.str() + " " + cmdstr); + + cMode localmode = mode + cMode::RawCommand; + bool rval = execute_local_command(ssh_command, output, localmode); + + if (!rval) + { + std::cerr << std::endl + << std::endl; + std::cerr << "Error: Failed to execute ssh command:" << std::endl; + std::cerr << "\033[90m" << ssh_command.get_command_to_run() << "\033[0m" << std::endl; + std::cerr << std::endl + << std::endl; + } + return rval; } - if (command.get_command_to_run().empty()) - return false; - cStyle style = cStyle::Raw; - bool silent = hasFlag(mode, cMode::Silent); - std::string full_cmd = command.construct_cmd(style) + " 2>&1" + (silent ? " > /dev/null" : ""); - int ret = system(full_cmd.c_str()); - - bool ok = EXITSTATUSCHECK(ret); - if (!ok) { - std::cerr << "Error: Failed to execute command: " << std::endl; - std::cerr << full_cmd << std::endl; - } - return ok; -} - -bool execute_ssh_command(const sSSHInfo &ssh_info, const sCommand &command, cMode mode, std::string *output) -{ - if (command.get_command_to_run().empty()) - return false; - - ASSERT(!(hasFlag(mode, cMode::Interactive) && !is_raw(mode)), "Interactive mode requires raw command mode"); - ASSERT(!(hasFlag(mode, cMode::CaptureOutput) && output == nullptr), "Capture output mode must be used with an output string"); - - std::stringstream ssh_cmd; - ssh_cmd << "ssh -p " << ssh_info.port << " " << (hasFlag(mode, cMode::Interactive) ? "-tt " : "") - << ssh_info.user << "@" << ssh_info.host; - - std::string cmdstr = command.construct_cmd(is_raw(mode) ? cStyle::Raw : cStyle::Safe); - sCommand ssh_command(ssh_cmd.str() + " " + cmdstr); - - cMode localmode = mode + cMode::RawCommand; - bool rval = execute_local_command(ssh_command, output, localmode); - - if (!rval) { - std::cerr <