#include #include #include #include #include #include "lib.h" // Load Pipes static std::variant get_pipe(const char *env) { const char *value = getenv(env); if (value == nullptr) { return Trampoline::Error::MISSING_PIPE; } try { const int val = std::stoi(value); if (val >= 0) { return val; } } catch (...) { } return Trampoline::Error::INVALID_PIPE; } #define set(var, env) \ val = get_pipe(env); \ if (std::holds_alternative(val)) { \ status = std::get(val); \ return; \ } \ var = std::get(val) PipeTrampoline::PipeTrampoline() { std::variant val; set(arguments_pipe, _MCPI_TRAMPOLINE_ARGUMENTS_ENV); set(return_value_pipe, _MCPI_TRAMPOLINE_RETURN_VALUE_ENV); // Success status = Error::NONE; } #undef set // Call Trampoline::Error PipeTrampoline::call(const uint32_t id, uint32_t *ret_ptr, const uint32_t length, const unsigned char *args) { // Check if (status != Error::NONE) { return status; } // Write Command const trampoline_pipe_arguments cmd = { .id = id, .allow_early_return = ret_ptr == nullptr, .length = length }; if (write(arguments_pipe, &cmd, sizeof(trampoline_pipe_arguments)) != sizeof(trampoline_pipe_arguments)) { return Error::PIPE_WRITE; } // Write Arguments size_t position = 0; while (position < length) { const ssize_t ret = write(arguments_pipe, args + position, length - position); if (ret == -1) { return Error::PIPE_WRITE; } else { position += ret; } } // Return Value if (ret_ptr != nullptr && read(return_value_pipe, ret_ptr, sizeof(uint32_t)) != sizeof(uint32_t)) { return Error::PIPE_READ; } // Success return Error::NONE; }