Fixed ssh commands.

This commit is contained in:
Your Name 2025-05-11 21:55:25 +12:00
parent bcf0f18006
commit 1d2e223547

View File

@ -12,28 +12,34 @@
#include "contrib/base64.hpp" #include "contrib/base64.hpp"
#include "utils/utils.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. return (ret != -1 && WIFEXITED(ret) && (WEXITSTATUS(ret) == 0)); // ret is -1 if the command failed to execute.
} }
namespace dropshell { namespace dropshell
bool execute_local_command_interactive(const sCommand &command)
{ {
bool execute_local_command_interactive(const sCommand &command)
{
if (command.get_command_to_run().empty()) if (command.get_command_to_run().empty())
return false; return false;
std::string full_command = command.construct_cmd(cStyle::Raw); // Get the command string std::string full_command = command.construct_cmd(cStyle::Raw); // Get the command string
pid_t pid = fork(); pid_t pid = fork();
if (pid == -1) { if (pid == -1)
{
// Fork failed // Fork failed
perror("fork failed"); perror("fork failed");
return false; return false;
} else if (pid == 0) { }
else if (pid == 0)
{
int rval = system(full_command.c_str()); int rval = system(full_command.c_str());
exit(rval); exit(rval);
} else { }
else
{
// Parent process // Parent process
int ret; int ret;
// Wait for the child process to complete // Wait for the child process to complete
@ -41,40 +47,44 @@ bool execute_local_command_interactive(const sCommand &command)
return EXITSTATUSCHECK(ret); return EXITSTATUSCHECK(ret);
} }
} }
bool execute_local_command_and_capture_output(const sCommand& command, std::string * output) bool execute_local_command_and_capture_output(const sCommand &command, std::string *output)
{ {
ASSERT(output != nullptr, "Output string must be provided"); ASSERT(output != nullptr, "Output string must be provided");
if (command.get_command_to_run().empty()) if (command.get_command_to_run().empty())
return false; return false;
cStyle style = cStyle::Raw; cStyle style = cStyle::Raw;
std::string full_cmd = command.construct_cmd(style) + " 2>&1"; std::string full_cmd = command.construct_cmd(style) + " 2>&1";
FILE *pipe = popen(full_cmd.c_str(), "r"); FILE *pipe = popen(full_cmd.c_str(), "r");
if (!pipe) { if (!pipe)
{
return false; return false;
} }
char buffer[128]; char buffer[128];
while (fgets(buffer, sizeof(buffer), pipe) != nullptr) { while (fgets(buffer, sizeof(buffer), pipe) != nullptr)
{
(*output) += buffer; (*output) += buffer;
} }
int ret = pclose(pipe); int ret = pclose(pipe);
return EXITSTATUSCHECK(ret); return EXITSTATUSCHECK(ret);
} }
bool execute_local_command(const sCommand & command, std::string * output /* = nullptr */, cMode mode /* = cMode::None */) 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"); ASSERT(hasFlag(mode, cMode::RawCommand), "Raw command mode is required for local command execution");
if (hasFlag(mode, cMode::Interactive)) { if (hasFlag(mode, cMode::Interactive))
ASSERT(! hasFlag(mode, cMode::CaptureOutput), "Interactive mode and capture output mode cannot be used together"); {
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(output == nullptr, "Interactive mode and an output string cannot be used together");
ASSERT(is_raw(mode), "Interactive mode requires raw command mode"); 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)) { if (hasFlag(mode, cMode::CaptureOutput))
{
ASSERT(output != nullptr, "Capture output mode requires an output string to be provided"); 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(is_raw(mode), "Capture output mode requires raw command mode");
ASSERT(!hasFlag(mode, cMode::Silent), "Silent mode is not allowed with capture output mode"); ASSERT(!hasFlag(mode, cMode::Silent), "Silent mode is not allowed with capture output mode");
@ -90,15 +100,16 @@ bool execute_local_command(const sCommand & command, std::string * output /* = n
int ret = system(full_cmd.c_str()); int ret = system(full_cmd.c_str());
bool ok = EXITSTATUSCHECK(ret); bool ok = EXITSTATUSCHECK(ret);
if (!ok) { if (!ok)
{
std::cerr << "Error: Failed to execute command: " << std::endl; std::cerr << "Error: Failed to execute command: " << std::endl;
std::cerr << full_cmd << std::endl; std::cerr << full_cmd << std::endl;
} }
return ok; return ok;
} }
bool execute_ssh_command(const sSSHInfo &ssh_info, const sCommand &command, cMode mode, std::string *output) bool execute_ssh_command(const sSSHInfo &ssh_info, const sCommand &command, cMode mode, std::string *output)
{ {
if (command.get_command_to_run().empty()) if (command.get_command_to_run().empty())
return false; return false;
@ -115,47 +126,54 @@ bool execute_ssh_command(const sSSHInfo &ssh_info, const sCommand &command, cMod
cMode localmode = mode + cMode::RawCommand; cMode localmode = mode + cMode::RawCommand;
bool rval = execute_local_command(ssh_command, output, localmode); bool rval = execute_local_command(ssh_command, output, localmode);
if (!rval) { if (!rval)
std::cerr <<std::endl<<std::endl; {
std::cerr << std::endl
<< std::endl;
std::cerr << "Error: Failed to execute ssh command:" << 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 << "\033[90m" << ssh_command.get_command_to_run() << "\033[0m" << std::endl;
std::cerr <<std::endl<<std::endl; std::cerr << std::endl
<< std::endl;
} }
return rval; return rval;
} }
std::string makesafecmd(const std::string &command) std::string makesafecmd(const std::string &command)
{ {
if (command.empty()) if (command.empty())
return ""; return "";
std::string encoded = base64_encode(dequote(trim(command))); std::string encoded = base64_encode(dequote(trim(command)));
std::string commandstr = "echo " + encoded + " | base64 -d | bash"; std::string commandstr = "echo " + encoded + " | base64 -d | bash";
return commandstr; return commandstr;
} }
std::string sCommand::construct_cmd(cStyle style) const std::string sCommand::construct_cmd(cStyle style) const
{ {
if (mCmd.empty()) if (mCmd.empty())
return ""; return "";
if (mDir.empty() && mVars.empty())
return (is_safe(style) ? makesafecmd(mCmd) : mCmd);
// need to construct to change directory and set environment variables
std::string cmdstr; std::string cmdstr;
cmdstr += "bash -c '";
if (!mDir.empty()) if (!mDir.empty())
cmdstr += "cd " + quote(mDir) + " && "; cmdstr += "cd " + quote(mDir) + " ; ";
for (const auto& env_var : mVars) { if (!mVars.empty())
for (const auto &env_var : mVars)
cmdstr += env_var.first + "=" + quote(dequote(trim(env_var.second))) + " "; cmdstr += env_var.first + "=" + quote(dequote(trim(env_var.second))) + " ";
}
cmdstr += mCmd; cmdstr += mCmd;
cmdstr += "'";
if (is_safe(style)) if (is_safe(style))
cmdstr = makesafecmd(cmdstr); cmdstr = makesafecmd(cmdstr);
else
cmdstr = "bash -c '" + cmdstr + "'";
return cmdstr; return cmdstr;
} }
} // namespace dropshell } // namespace dropshell