Skip to content

Instantly share code, notes, and snippets.

@qookei
Created February 22, 2021 23:19
Show Gist options
  • Select an option

  • Save qookei/ab108385a79ec3e66f686076e1ea0bba to your computer and use it in GitHub Desktop.

Select an option

Save qookei/ab108385a79ec3e66f686076e1ea0bba to your computer and use it in GitHub Desktop.
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <dlfcn.h>
#include <readline/readline.h>
#include <readline/history.h>
#include <cstdlib>
// returns stdout and stderr combined
std::string run(std::string exe, std::vector<std::string> args, std::string stdin_s, int &ec) {
int stdin_pipe[2];
int stdout_pipe[2];
pipe(stdin_pipe);
pipe(stdout_pipe);
pid_t child = fork();
std::string stdout_s;
if (!child) {
dup2(stdin_pipe[0], STDIN_FILENO);
dup2(stdout_pipe[1], STDOUT_FILENO);
dup2(stdout_pipe[1], STDERR_FILENO);
std::vector<char *> arg_ptrs;
std::transform(args.begin(), args.end(), std::back_inserter(arg_ptrs), [] (auto &v) { return v.data(); });
arg_ptrs.push_back(nullptr);
close(stdin_pipe[0]);
close(stdin_pipe[1]);
close(stdout_pipe[0]);
close(stdout_pipe[1]);
execv(exe.data(), arg_ptrs.data());
} else {
close(stdout_pipe[1]);
close(stdin_pipe[0]);
write(stdin_pipe[1], stdin_s.data(), stdin_s.size());
close(stdin_pipe[1]);
int wstatus;
wait(&wstatus);
ec = WIFEXITED(wstatus) ? WEXITSTATUS(wstatus) : -1;
ssize_t n;
char buf[4096];
while ((n = read(stdout_pipe[0], buf, 4096)) > 0) {
stdout_s += std::string_view{buf, size_t(n)};
}
close(stdout_pipe[0]);
}
return stdout_s;
}
int main() {
using_history();
while (true) {
auto input = readline(">>> ");
if (!input) // EOF
break;
add_history(input);
std::string line{input};
std::free(input);
std::string code = "#include <bits/stdc++.h>\n"
+ ("[[gnu::constructor]] void dont_mind_me_great_code_here___() {"
+ line + "}");
int ec;
auto out = run("/usr/bin/clang++",
{"clang++", "-std=c++20", "-shared",
"-fuse-ld=lld", "-x", "c++", "-",
"-o", "/dev/stdout"}, code, ec);
if (ec != 0) {
std::cout << out << std::flush;
} else {
int fd = memfd_create("so", MFD_CLOEXEC);
write(fd, out.data(), out.size());
char buf[512];
snprintf(buf, 512, "/proc/self/fd/%d", fd);
void *dl = dlopen(buf, RTLD_NOW);
dlclose(dl);
close(fd);
std::cout << std::endl;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment