This commit is contained in:
@ -6,6 +6,8 @@
|
||||
#include <sys/wait.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
namespace runner {
|
||||
|
||||
int execute_cmd(
|
||||
const std::string& command,
|
||||
const std::vector<std::string>& args,
|
||||
@ -16,79 +18,162 @@ int execute_cmd(
|
||||
sSSHInfo* sshinfo,
|
||||
std::string* output
|
||||
) {
|
||||
// SSH execution is not implemented in this demo
|
||||
if (sshinfo) {
|
||||
std::cerr << "Remote SSH execution is not implemented in this demo.\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
// Build remote command string
|
||||
std::ostringstream remote_cmd;
|
||||
// Set environment variables
|
||||
for (const auto& kv : env) {
|
||||
setenv(kv.first.c_str(), kv.second.c_str(), 1);
|
||||
remote_cmd << kv.first << "='" << kv.second << "' ";
|
||||
}
|
||||
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);
|
||||
// Change working directory
|
||||
if (!working_dir.empty()) {
|
||||
remote_cmd << "cd '" << working_dir << "' && ";
|
||||
}
|
||||
if (!interactive) {
|
||||
// Detach from terminal if not interactive
|
||||
setsid();
|
||||
}
|
||||
std::vector<char*> argv;
|
||||
argv.push_back(const_cast<char*>(command.c_str()));
|
||||
// Command and args
|
||||
remote_cmd << command;
|
||||
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);
|
||||
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 {
|
||||
|
||||
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 (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
|
Reference in New Issue
Block a user