From 195d1526cc67f7b7d20dd3fe32b97840a4193223 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Tue, 26 Nov 2024 14:02:24 +0000 Subject: ok --- run.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 run.c diff --git a/run.c b/run.c new file mode 100644 index 0000000..ff2565c --- /dev/null +++ b/run.c @@ -0,0 +1,101 @@ +#include +#include +#include +#include +#include +#include +#include + +#define CKE(val, name) do { if (val == -1) { perror(name); exit(1); } } while (0) + +#ifdef DEBUG +#define DP(...) fprintf(stderr, __VA_ARGS__); +#else +#define DP(...) +#endif + +int filefork(char *argv[], int input, int output) { + int pid = fork(); + switch (pid) { + case -1: perror("fork"); exit(1); break; + case 0: + if (input != -1) { + CKE(close(STDIN_FILENO),"close stdin"); + CKE(dup2(input, STDIN_FILENO),"dup2 stdin"); + } + if (output != -1) { + CKE(close(STDOUT_FILENO),"close stdout"); + CKE(dup2(output, STDOUT_FILENO),"dup2 stdout"); + } + CKE(execvp(argv[0], argv), "exec"); + exit(1); + break; + default: return pid; + } +} + +int echofork(char *str, size_t len, int fd) { + int pid = fork(); + switch (pid) { + case -1: perror("fork"), exit(1); break; + case 0: + size_t remaining = len; + char *cur = str; + do { + ssize_t res = write(fd, cur, remaining); + if (res == -1) { perror("write"); exit(1); } + cur += res; + remaining -= res; + } while (remaining > 0); + exit(0); + default: return pid; + } +} + +char *p1[] = {"sed","-e","s/a/b/g",NULL}; +char *p2[] = {"tac",NULL}; +char *p3[] = {"sed","-e","s/fish/PIG/",NULL}; +char *p4[] = {"rev",NULL}; + +void empipe(int pipefd[2]) { + CKE(pipe(pipefd), "pipe"); + fcntl(pipefd[0], F_SETFD, FD_CLOEXEC); + fcntl(pipefd[1], F_SETFD, FD_CLOEXEC); +} + +void run(int count, char **progs[], char *inputstr, size_t inputlen) { + if (inputstr) count++; + int (*pipefds)[2] = malloc((count-1) * sizeof(int[2])); + pid_t *pids = malloc(count * sizeof(pid_t)); + for (int i = 0; i < count-1; i++) empipe(pipefds[i]); + for (int i = 0; i < count; i++) { + int input = (i == 0) ? -1 : pipefds[i-1][0]; + int output = (i == count-1) ? -1 : pipefds[i ][1]; + if (!inputstr) pids[i] = filefork(progs[i ], input, output); + else if (i==0) pids[i] = echofork(inputstr, inputlen, output); + else pids[i] = filefork(progs[i-1], input, output); + + DP("[%d] %d\n",i,pids[i]); + } + // pipes need to be closed everywhere they aren't being used. + // close them in the parent process here; CLOEXEC will take care of them everwhere else + // (duped fds won't have CLOEXEC set so those ones, ie the ones being used, won't be closed) + for (int i = 0; i < count-1; i++) { + CKE(close(pipefds[i][0]), "close"); + CKE(close(pipefds[i][1]), "close"); + } + + for (int i = 0; i < count; i++) { + int status; + pid_t rpid = waitpid(pids[i], &status, 0); + DP("-> %d %d\n",rpid,WEXITSTATUS(status)); + } + + free(pipefds); + free(pids); +} + +int luaopen_run(lua_State *L) { + lua_pushliteral(L, "fuck"); + return 1; +} -- cgit v1.2.3