No WHATSUUUUPPP!
Some checks failed
Dropshell Test / Build_and_Test (push) Failing after 18s

This commit is contained in:
Your Name 2025-05-10 14:22:40 +12:00
parent bc45f60b6e
commit 5973d63d3e
2 changed files with 246 additions and 211 deletions

View File

@ -12,21 +12,13 @@
namespace runner { namespace runner {
int execute_cmd( namespace {
const std::string& command,
const std::vector<std::string>& args, ssh_session ssh_connect_and_auth(const sSSHInfo* sshinfo, const std::map<std::string, std::string>& env, std::string* error) {
const std::string& working_dir,
const std::map<std::string, std::string>& env,
bool silent,
bool interactive,
sSSHInfo* sshinfo,
std::string* output
) {
if (sshinfo) {
ssh_session session = ssh_new(); ssh_session session = ssh_new();
if (session == nullptr) { if (!session) {
if (output) *output = "Failed to create SSH session."; if (error) *error = "Failed to create SSH session.";
return -1; return nullptr;
} }
ssh_options_set(session, SSH_OPTIONS_HOST, sshinfo->host.c_str()); ssh_options_set(session, SSH_OPTIONS_HOST, sshinfo->host.c_str());
if (!sshinfo->port.empty()) { if (!sshinfo->port.empty()) {
@ -38,40 +30,27 @@ int execute_cmd(
} }
int rc = ssh_connect(session); int rc = ssh_connect(session);
if (rc != SSH_OK) { if (rc != SSH_OK) {
if (output) *output = std::string("SSH connection failed: ") + ssh_get_error(session); if (error) *error = std::string("SSH connection failed: ") + ssh_get_error(session);
ssh_free(session); ssh_free(session);
return -1; return nullptr;
} }
// Try public key, then password if needed
rc = ssh_userauth_publickey_auto(session, nullptr, nullptr); rc = ssh_userauth_publickey_auto(session, nullptr, nullptr);
if (rc != SSH_AUTH_SUCCESS) { if (rc != SSH_AUTH_SUCCESS) {
// Try password from env["SSHPASS"] if present
auto it = env.find("SSHPASS"); auto it = env.find("SSHPASS");
if (it != env.end()) { if (it != env.end()) {
rc = ssh_userauth_password(session, nullptr, it->second.c_str()); rc = ssh_userauth_password(session, nullptr, it->second.c_str());
} }
} }
if (rc != SSH_AUTH_SUCCESS) { if (rc != SSH_AUTH_SUCCESS) {
if (output) *output = std::string("SSH authentication failed: ") + ssh_get_error(session); if (error) *error = std::string("SSH authentication failed: ") + ssh_get_error(session);
ssh_disconnect(session); ssh_disconnect(session);
ssh_free(session); ssh_free(session);
return -1; return nullptr;
} }
ssh_channel channel = ssh_channel_new(session); return session;
if (channel == nullptr) {
if (output) *output = "Failed to create SSH channel.";
ssh_disconnect(session);
ssh_free(session);
return -1;
}
rc = ssh_channel_open_session(channel);
if (rc != SSH_OK) {
if (output) *output = std::string("Failed to open SSH channel: ") + ssh_get_error(session);
ssh_channel_free(channel);
ssh_disconnect(session);
ssh_free(session);
return -1;
} }
std::string ssh_build_remote_command(const std::string& command, const std::vector<std::string>& args, const std::string& working_dir, const std::map<std::string, std::string>& env) {
std::ostringstream remote_cmd; std::ostringstream remote_cmd;
for (const auto& kv : env) { for (const auto& kv : env) {
if (kv.first == "SSHPASS") continue; if (kv.first == "SSHPASS") continue;
@ -84,38 +63,29 @@ int execute_cmd(
for (const auto& arg : args) { for (const auto& arg : args) {
remote_cmd << " '" << arg << "'"; remote_cmd << " '" << arg << "'";
} }
std::string remote_cmd_str = remote_cmd.str(); return remote_cmd.str();
if (interactive) { }
rc = ssh_channel_request_pty(channel);
int ssh_interactive_shell_session(ssh_session session, ssh_channel channel, const std::string& remote_cmd_str, const std::string& command, std::string* output) {
int rc = ssh_channel_request_pty(channel);
if (rc != SSH_OK) { if (rc != SSH_OK) {
if (output) *output = std::string("Failed to request pty: ") + ssh_get_error(session); if (output) *output = std::string("Failed to request pty: ") + ssh_get_error(session);
ssh_channel_close(channel);
ssh_channel_free(channel);
ssh_disconnect(session);
ssh_free(session);
return -1; return -1;
} }
rc = ssh_channel_request_shell(channel); rc = ssh_channel_request_shell(channel);
if (rc != SSH_OK) { if (rc != SSH_OK) {
if (output) *output = std::string("Failed to request shell: ") + ssh_get_error(session); if (output) *output = std::string("Failed to request shell: ") + ssh_get_error(session);
ssh_channel_close(channel);
ssh_channel_free(channel);
ssh_disconnect(session);
ssh_free(session);
return -1; return -1;
} }
// Set local terminal to raw mode
struct termios orig_termios, raw_termios; struct termios orig_termios, raw_termios;
tcgetattr(STDIN_FILENO, &orig_termios); tcgetattr(STDIN_FILENO, &orig_termios);
raw_termios = orig_termios; raw_termios = orig_termios;
cfmakeraw(&raw_termios); cfmakeraw(&raw_termios);
tcsetattr(STDIN_FILENO, TCSANOW, &raw_termios); tcsetattr(STDIN_FILENO, TCSANOW, &raw_termios);
// If a command is provided, send it to the shell
if (!command.empty()) { if (!command.empty()) {
ssh_channel_write(channel, remote_cmd_str.c_str(), remote_cmd_str.size()); ssh_channel_write(channel, remote_cmd_str.c_str(), remote_cmd_str.size());
ssh_channel_write(channel, "\n", 1); ssh_channel_write(channel, "\n", 1);
} }
// Forward input/output using select()
int maxfd = STDIN_FILENO > STDOUT_FILENO ? STDIN_FILENO : STDOUT_FILENO; int maxfd = STDIN_FILENO > STDOUT_FILENO ? STDIN_FILENO : STDOUT_FILENO;
maxfd = maxfd > ssh_get_fd(session) ? maxfd : ssh_get_fd(session); maxfd = maxfd > ssh_get_fd(session) ? maxfd : ssh_get_fd(session);
char buffer[4096]; char buffer[4096];
@ -127,7 +97,6 @@ int execute_cmd(
FD_SET(ssh_get_fd(session), &fds_read); FD_SET(ssh_get_fd(session), &fds_read);
int ret = select(maxfd + 1, &fds_read, nullptr, nullptr, nullptr); int ret = select(maxfd + 1, &fds_read, nullptr, nullptr, nullptr);
if (ret < 0) break; if (ret < 0) break;
// Read from stdin, send to channel
if (FD_ISSET(STDIN_FILENO, &fds_read)) { if (FD_ISSET(STDIN_FILENO, &fds_read)) {
ssize_t n = read(STDIN_FILENO, buffer, sizeof(buffer)); ssize_t n = read(STDIN_FILENO, buffer, sizeof(buffer));
if (n > 0) { if (n > 0) {
@ -137,7 +106,6 @@ int execute_cmd(
done = true; done = true;
} }
} }
// Read from channel, write to stdout
if (FD_ISSET(ssh_get_fd(session), &fds_read)) { if (FD_ISSET(ssh_get_fd(session), &fds_read)) {
int n = ssh_channel_read(channel, buffer, sizeof(buffer), 0); int n = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
if (n > 0) { if (n > 0) {
@ -150,16 +118,14 @@ int execute_cmd(
done = true; done = true;
} }
} }
// Restore terminal
tcsetattr(STDIN_FILENO, TCSANOW, &orig_termios); tcsetattr(STDIN_FILENO, TCSANOW, &orig_termios);
} else { return 0;
rc = ssh_channel_request_exec(channel, remote_cmd_str.c_str()); }
int ssh_exec_command(ssh_session session, ssh_channel channel, const std::string& remote_cmd_str, bool silent, std::string* output) {
int rc = ssh_channel_request_exec(channel, remote_cmd_str.c_str());
if (rc != SSH_OK) { if (rc != SSH_OK) {
if (output) *output = std::string("Failed to exec remote command: ") + ssh_get_error(session); if (output) *output = std::string("Failed to exec remote command: ") + ssh_get_error(session);
ssh_channel_close(channel);
ssh_channel_free(channel);
ssh_disconnect(session);
ssh_free(session);
return -1; return -1;
} }
if (output) { if (output) {
@ -177,35 +143,36 @@ int execute_cmd(
write(1, buffer, nbytes); write(1, buffer, nbytes);
} }
} }
}
ssh_channel_send_eof(channel);
ssh_channel_close(channel);
ssh_channel_free(channel);
ssh_disconnect(session);
ssh_free(session);
return 0; return 0;
} else { }
int local_execute_cmd(
const std::string& command,
const std::vector<std::string>& args,
const std::string& working_dir,
const std::map<std::string, std::string>& env,
bool silent,
bool interactive,
std::string* output
) {
int pipefd[2]; int pipefd[2];
bool use_pipe = output && !interactive; bool use_pipe = output && !interactive;
if (use_pipe && pipe(pipefd) == -1) { if (use_pipe && pipe(pipefd) == -1) {
perror("pipe"); perror("pipe");
return -1; return -1;
} }
pid_t pid = fork(); pid_t pid = fork();
if (pid == -1) { if (pid == -1) {
perror("fork"); perror("fork");
return -1; return -1;
} }
if (pid == 0) { if (pid == 0) {
// Child process
if (!working_dir.empty()) { if (!working_dir.empty()) {
if (chdir(working_dir.c_str()) != 0) { if (chdir(working_dir.c_str()) != 0) {
perror("chdir"); perror("chdir");
exit(-1); exit(-1);
} }
} }
// Set environment variables
for (const auto& kv : env) { for (const auto& kv : env) {
setenv(kv.first.c_str(), kv.second.c_str(), 1); setenv(kv.first.c_str(), kv.second.c_str(), 1);
} }
@ -221,7 +188,6 @@ int execute_cmd(
close(devnull); close(devnull);
} }
if (!interactive) { if (!interactive) {
// Detach from terminal if not interactive
setsid(); setsid();
} }
std::vector<char*> argv; std::vector<char*> argv;
@ -234,7 +200,6 @@ int execute_cmd(
perror("execvp"); perror("execvp");
exit(-1); exit(-1);
} else { } else {
// Parent process
if (use_pipe) { if (use_pipe) {
close(pipefd[1]); close(pipefd[1]);
std::ostringstream oss; std::ostringstream oss;
@ -255,7 +220,57 @@ int execute_cmd(
} }
} }
} }
} // anonymous namespace
int execute_cmd(
const std::string& command,
const std::vector<std::string>& args,
const std::string& working_dir,
const std::map<std::string, std::string>& env,
bool silent,
bool interactive,
sSSHInfo* sshinfo,
std::string* output
) {
if (sshinfo) {
std::string error;
ssh_session session = ssh_connect_and_auth(sshinfo, env, &error);
if (!session) {
if (output) *output = error;
return -1;
}
ssh_channel channel = ssh_channel_new(session);
if (!channel) {
if (output) *output = "Failed to create SSH channel.";
ssh_disconnect(session);
ssh_free(session);
return -1;
}
int rc = ssh_channel_open_session(channel);
if (rc != SSH_OK) {
if (output) *output = std::string("Failed to open SSH channel: ") + ssh_get_error(session);
ssh_channel_free(channel);
ssh_disconnect(session);
ssh_free(session);
return -1;
}
std::string remote_cmd_str = ssh_build_remote_command(command, args, working_dir, env);
int ret = 0;
if (interactive) {
ret = ssh_interactive_shell_session(session, channel, remote_cmd_str, command, output);
} else {
ret = ssh_exec_command(session, channel, remote_cmd_str, silent, output);
}
ssh_channel_send_eof(channel);
ssh_channel_close(channel);
ssh_channel_free(channel);
ssh_disconnect(session);
ssh_free(session);
return ret;
} else {
return local_execute_cmd(command, args, working_dir, env, silent, interactive, output);
}
} }
} // namespace runner } // namespace runner

View File

@ -62,8 +62,7 @@
// return ret; // return ret;
// } // }
void test_docker() {
int main(int argc, char* argv[]) {
std::string command = "docker"; std::string command = "docker";
std::vector<std::string> args = {"exec", "-it", "squashkiwi", "/bin/bash"}; std::vector<std::string> args = {"exec", "-it", "squashkiwi", "/bin/bash"};
std::string working_dir = "."; std::string working_dir = ".";
@ -78,3 +77,24 @@ int main(int argc, char* argv[]) {
runner::execute_cmd(command, args, working_dir, env, silent, interactive, &ssh); runner::execute_cmd(command, args, working_dir, env, silent, interactive, &ssh);
} }
void test_ssh() {
std::string command = "bash";
std::vector<std::string> args = {"-c", "ls -l && echo $WHATSUP"};
std::string working_dir = "/home";
std::map<std::string, std::string> env = {{"WHATSUP", "Waaaaattttsssuuuppppp!"}};
bool silent = false;
bool interactive = false;
runner::sSSHInfo ssh;
ssh.host = "10.10.10.13";
ssh.user = "katie";
ssh.port = "22";
runner::execute_cmd(command, args, working_dir, env, silent, interactive, &ssh);
}
int main(int argc, char* argv[]) {
test_ssh();
}