GPT 4.1 trying
Some checks failed
Dropshell Test / Build_and_Test (push) Failing after 19s

This commit is contained in:
Your Name 2025-05-10 14:06:30 +12:00
parent c9c5108254
commit 39e083898f
4 changed files with 219 additions and 119 deletions

View File

@ -19,11 +19,6 @@ if ! pkg-config --exists openssl; then
exit 1 exit 1
fi fi
# Check for nlohmann_json
if ! pkg-config --exists nlohmann_json; then
echo "Warning: nlohmann_json not found via pkg-config. Make sure it is installed or available to CMake." >&2
fi
BUILD_DIR=build BUILD_DIR=build
mkdir -p "$BUILD_DIR" mkdir -p "$BUILD_DIR"
cd "$BUILD_DIR" cd "$BUILD_DIR"
@ -32,7 +27,7 @@ cmake ..
make -j$(nproc) make -j$(nproc)
if [ -f runner ]; then if [ -f runner ]; then
echo "Build successful. Run ./build/runner BASE64COMMAND to test." echo "Build successful. Run ./build/runner"
else else
echo "Build failed. Check the output above for errors." echo "Build failed. Check the output above for errors."
exit 1 exit 1

View File

@ -6,6 +6,8 @@
#include <sys/wait.h> #include <sys/wait.h>
#include <fcntl.h> #include <fcntl.h>
namespace runner {
int execute_cmd( int execute_cmd(
const std::string& command, const std::string& command,
const std::vector<std::string>& args, const std::vector<std::string>& args,
@ -16,79 +18,162 @@ int execute_cmd(
sSSHInfo* sshinfo, sSSHInfo* sshinfo,
std::string* output std::string* output
) { ) {
// SSH execution is not implemented in this demo
if (sshinfo) { if (sshinfo) {
std::cerr << "Remote SSH execution is not implemented in this demo.\n"; // Build remote command string
return -1; std::ostringstream remote_cmd;
}
int pipefd[2];
bool use_pipe = output && !interactive;
if (use_pipe && pipe(pipefd) == -1) {
perror("pipe");
return -1;
}
pid_t pid = fork();
if (pid == -1) {
perror("fork");
return -1;
}
if (pid == 0) {
// Child process
if (!working_dir.empty()) {
if (chdir(working_dir.c_str()) != 0) {
perror("chdir");
exit(-1);
}
}
// Set environment variables // Set environment variables
for (const auto& kv : env) { for (const auto& kv : env) {
setenv(kv.first.c_str(), kv.second.c_str(), 1); remote_cmd << kv.first << "='" << kv.second << "' ";
} }
if (use_pipe) { // Change working directory
close(pipefd[0]); if (!working_dir.empty()) {
dup2(pipefd[1], STDOUT_FILENO); remote_cmd << "cd '" << working_dir << "' && ";
dup2(pipefd[1], STDERR_FILENO);
close(pipefd[1]);
} else if (silent && !interactive) {
int devnull = open("/dev/null", O_WRONLY);
dup2(devnull, STDOUT_FILENO);
dup2(devnull, STDERR_FILENO);
close(devnull);
} }
if (!interactive) { // Command and args
// Detach from terminal if not interactive remote_cmd << command;
setsid();
}
std::vector<char*> argv;
argv.push_back(const_cast<char*>(command.c_str()));
for (const auto& arg : args) { for (const auto& arg : args) {
argv.push_back(const_cast<char*>(arg.c_str())); remote_cmd << " '" << arg << "'";
} }
std::string remote_cmd_str = remote_cmd.str();
// Build ssh command
std::vector<std::string> ssh_argv = {"ssh"};
if (!sshinfo->port.empty()) {
ssh_argv.push_back("-p");
ssh_argv.push_back(sshinfo->port);
}
std::string userhost = sshinfo->user.empty() ? sshinfo->host : (sshinfo->user + "@" + sshinfo->host);
ssh_argv.push_back(userhost);
ssh_argv.push_back(remote_cmd_str);
// Prepare for exec
std::vector<char*> argv;
for (auto& s : ssh_argv) argv.push_back(const_cast<char*>(s.c_str()));
argv.push_back(nullptr); argv.push_back(nullptr);
execvp(command.c_str(), argv.data());
perror("execvp"); int pipefd[2];
exit(-1); bool use_pipe = output && !interactive;
} else { if (use_pipe && pipe(pipefd) == -1) {
// Parent process perror("pipe");
if (use_pipe) {
close(pipefd[1]);
std::ostringstream oss;
char buf[4096];
ssize_t n;
while ((n = read(pipefd[0], buf, sizeof(buf))) > 0) {
oss.write(buf, n);
}
close(pipefd[0]);
*output = oss.str();
}
int status = 0;
waitpid(pid, &status, 0);
if (WIFEXITED(status)) {
return WEXITSTATUS(status);
} else {
return -1; return -1;
} }
pid_t pid = fork();
if (pid == -1) {
perror("fork");
return -1;
}
if (pid == 0) {
// Child process
if (use_pipe) {
close(pipefd[0]);
dup2(pipefd[1], STDOUT_FILENO);
dup2(pipefd[1], STDERR_FILENO);
close(pipefd[1]);
} else if (silent && !interactive) {
int devnull = open("/dev/null", O_WRONLY);
dup2(devnull, STDOUT_FILENO);
dup2(devnull, STDERR_FILENO);
close(devnull);
}
if (!interactive) {
setsid();
}
execvp("ssh", argv.data());
perror("execvp ssh");
exit(-1);
} else {
// Parent process
if (use_pipe) {
close(pipefd[1]);
std::ostringstream oss;
char buf[4096];
ssize_t n;
while ((n = read(pipefd[0], buf, sizeof(buf))) > 0) {
oss.write(buf, n);
}
close(pipefd[0]);
*output = oss.str();
}
int status = 0;
waitpid(pid, &status, 0);
if (WIFEXITED(status)) {
return WEXITSTATUS(status);
} else {
return -1;
}
}
} else {
int pipefd[2];
bool use_pipe = output && !interactive;
if (use_pipe && pipe(pipefd) == -1) {
perror("pipe");
return -1;
}
pid_t pid = fork();
if (pid == -1) {
perror("fork");
return -1;
}
if (pid == 0) {
// Child process
if (!working_dir.empty()) {
if (chdir(working_dir.c_str()) != 0) {
perror("chdir");
exit(-1);
}
}
// Set environment variables
for (const auto& kv : env) {
setenv(kv.first.c_str(), kv.second.c_str(), 1);
}
if (use_pipe) {
close(pipefd[0]);
dup2(pipefd[1], STDOUT_FILENO);
dup2(pipefd[1], STDERR_FILENO);
close(pipefd[1]);
} else if (silent && !interactive) {
int devnull = open("/dev/null", O_WRONLY);
dup2(devnull, STDOUT_FILENO);
dup2(devnull, STDERR_FILENO);
close(devnull);
}
if (!interactive) {
// Detach from terminal if not interactive
setsid();
}
std::vector<char*> argv;
argv.push_back(const_cast<char*>(command.c_str()));
for (const auto& arg : args) {
argv.push_back(const_cast<char*>(arg.c_str()));
}
argv.push_back(nullptr);
execvp(command.c_str(), argv.data());
perror("execvp");
exit(-1);
} else {
// Parent process
if (use_pipe) {
close(pipefd[1]);
std::ostringstream oss;
char buf[4096];
ssize_t n;
while ((n = read(pipefd[0], buf, sizeof(buf))) > 0) {
oss.write(buf, n);
}
close(pipefd[0]);
*output = oss.str();
}
int status = 0;
waitpid(pid, &status, 0);
if (WIFEXITED(status)) {
return WEXITSTATUS(status);
} else {
return -1;
}
}
} }
} }
} // namespace runner

View File

@ -3,6 +3,8 @@
#include <vector> #include <vector>
#include <map> #include <map>
namespace runner {
struct sSSHInfo { struct sSSHInfo {
std::string host; std::string host;
std::string user; std::string user;
@ -19,3 +21,5 @@ int execute_cmd(
sSSHInfo* sshinfo = nullptr, sSSHInfo* sshinfo = nullptr,
std::string* output = nullptr std::string* output = nullptr
); );
} // namespace runner

View File

@ -11,53 +11,69 @@
#include <openssl/bio.h> #include <openssl/bio.h>
#include <openssl/evp.h> #include <openssl/evp.h>
using json = nlohmann::json; // using json = nlohmann::json;
// std::string base64_decode(const std::string& encoded) {
// BIO* bio, *b64;
// int decodeLen = (encoded.length() * 3) / 4;
// std::string decoded(decodeLen, '\0');
// bio = BIO_new_mem_buf(encoded.data(), encoded.length());
// b64 = BIO_new(BIO_f_base64());
// bio = BIO_push(b64, bio);
// BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
// int len = BIO_read(bio, &decoded[0], encoded.length());
// decoded.resize(len > 0 ? len : 0);
// BIO_free_all(bio);
// return decoded;
// }
// int main(int argc, char* argv[]) {
// if (argc != 2) {
// std::cerr << "Usage: runner BASE64COMMAND\n";
// return -1;
// }
// std::string decoded = base64_decode(argv[1]);
// json j;
// try {
// j = json::parse(decoded);
// } catch (...) {
// std::cerr << "Invalid JSON in decoded command\n";
// return -1;
// }
// std::string command = j.value("command", "");
// std::vector<std::string> args = j.value("args", std::vector<std::string>{});
// std::string working_dir = j.value("working_dir", "");
// std::map<std::string, std::string> env = j.value("env", std::map<std::string, std::string>{});
// bool silent = j.value("silent", false);
// bool interactive = j.value("interactive", false);
// sSSHInfo* sshinfo = nullptr;
// sSSHInfo ssh;
// if (j.contains("sshinfo")) {
// ssh.host = j["sshinfo"].value("host", "");
// ssh.user = j["sshinfo"].value("user", "");
// ssh.port = j["sshinfo"].value("port", "");
// sshinfo = &ssh;
// }
// std::string output;
// int ret = execute_cmd(command, args, working_dir, env, silent, interactive, sshinfo, &output);
// if (!silent && !output.empty()) {
// std::cout << output;
// }
// return ret;
// }
std::string base64_decode(const std::string& encoded) {
BIO* bio, *b64;
int decodeLen = (encoded.length() * 3) / 4;
std::string decoded(decodeLen, '\0');
bio = BIO_new_mem_buf(encoded.data(), encoded.length());
b64 = BIO_new(BIO_f_base64());
bio = BIO_push(b64, bio);
BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
int len = BIO_read(bio, &decoded[0], encoded.length());
decoded.resize(len > 0 ? len : 0);
BIO_free_all(bio);
return decoded;
}
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
if (argc != 2) { std::string command = "docker";
std::cerr << "Usage: runner BASE64COMMAND\n"; std::vector<std::string> args = {"exec", "-it", "squashkiwi", "/bin/bash"};
return -1; std::string working_dir = ".";
} std::map<std::string, std::string> env = {};
std::string decoded = base64_decode(argv[1]); bool silent = false;
json j; bool interactive = true;
try { runner::sSSHInfo ssh;
j = json::parse(decoded); ssh.host = "10.10.10.13";
} catch (...) { ssh.user = "katie";
std::cerr << "Invalid JSON in decoded command\n"; ssh.port = "22";
return -1;
} runner::execute_cmd(command, args, working_dir, env, silent, interactive, &ssh);
std::string command = j.value("command", "");
std::vector<std::string> args = j.value("args", std::vector<std::string>{});
std::string working_dir = j.value("working_dir", "");
std::map<std::string, std::string> env = j.value("env", std::map<std::string, std::string>{});
bool silent = j.value("silent", false);
bool interactive = j.value("interactive", false);
sSSHInfo* sshinfo = nullptr;
sSSHInfo ssh;
if (j.contains("sshinfo")) {
ssh.host = j["sshinfo"].value("host", "");
ssh.user = j["sshinfo"].value("user", "");
ssh.port = j["sshinfo"].value("port", "");
sshinfo = &ssh;
}
std::string output;
int ret = execute_cmd(command, args, working_dir, env, silent, interactive, sshinfo, &output);
if (!silent && !output.empty()) {
std::cout << output;
}
return ret;
} }