runtime/native/src/pipe/pipe.cpp
2024-06-08 04:23:03 -04:00

71 lines
2.0 KiB
C++

#include <unistd.h>
#include <cerrno>
#include <cstring>
#include <string>
#include <sys/wait.h>
#include <trampoline/types.h>
#include "pipe.h"
#include "../log.h"
#include "../trampoline.h"
#include "../memory.h"
// Setup Pipes
#define PIPE_READ 0
#define PIPE_WRITE 1
static int arguments_pipe[2];
static int return_value_pipe[2];
static void safe_pipe(int *out) {
int ret = pipe(out);
if (ret != 0) {
ERR("Unable To Create Pipe: %s", strerror(errno));
}
}
void init_pipe_common() {
safe_pipe(arguments_pipe);
safe_pipe(return_value_pipe);
}
// Guest
void init_pipe_guest() {
// Close Unneeded Pipes
close(arguments_pipe[PIPE_READ]);
close(return_value_pipe[PIPE_WRITE]);
// Setup Environment
setenv(TRAMPOLINE_ARGUMENTS_PIPE_ENV, std::to_string(arguments_pipe[PIPE_WRITE]).c_str(), true);
setenv(TRAMPOLINE_RETURN_VALUE_PIPE_ENV, std::to_string(return_value_pipe[PIPE_READ]).c_str(), true);
}
// Host
void init_pipe_host(pid_t guest_pid) {
// Close Unneeded Pipes
close(arguments_pipe[PIPE_WRITE]);
close(return_value_pipe[PIPE_READ]);
// Wait For Commands
trampoline_pipe_arguments cmd = {};
while (read(arguments_pipe[PIPE_READ], &cmd, sizeof(trampoline_pipe_arguments)) > 0) {
static unsigned char args[MAX_TRAMPOLINE_ARGS_SIZE];
memory_reader(cmd.args_addr, args, cmd.length);
uint32_t ret = 0;
if (cmd.allow_early_return && cmd.length > 0) {
write(return_value_pipe[PIPE_WRITE], &ret, sizeof(uint32_t));
}
ret = trampoline(cmd.id, args);
if (!cmd.allow_early_return) {
write(return_value_pipe[PIPE_WRITE], &ret, sizeof(uint32_t));
}
}
// Reap Child
int status;
if (waitpid(guest_pid, &status, 0) == -1) {
ERR("Unable To Reap Child: %s", strerror(errno));
}
// Exit
if (WIFEXITED(status)) {
exit(WEXITSTATUS(status));
} else {
ERR("Unable To Determine Exit Code");
}
}