diff options
author | ubq323 <ubq323@ubq323.website> | 2024-11-26 21:49:48 +0000 |
---|---|---|
committer | ubq323 <ubq323@ubq323.website> | 2024-11-26 21:49:48 +0000 |
commit | d74b39d248c0df708e62da2fbeea6e74552ec514 (patch) | |
tree | 95882b860eab74598821b0d71ec596717f1dfd3b /run.c | |
parent | 195d1526cc67f7b7d20dd3fe32b97840a4193223 (diff) |
things
Diffstat (limited to 'run.c')
-rw-r--r-- | run.c | 97 |
1 files changed, 91 insertions, 6 deletions
@@ -5,6 +5,7 @@ #include <fcntl.h> #include <string.h> #include <lua.h> +#include <lauxlib.h> #define CKE(val, name) do { if (val == -1) { perror(name); exit(1); } } while (0) @@ -63,14 +64,14 @@ void empipe(int pipefd[2]) { fcntl(pipefd[1], F_SETFD, FD_CLOEXEC); } -void run(int count, char **progs[], char *inputstr, size_t inputlen) { +char *run(int count, char **progs[], size_t inputlen, char *inputstr, size_t *outlen) { if (inputstr) count++; - int (*pipefds)[2] = malloc((count-1) * sizeof(int[2])); + int (*pipefds)[2] = malloc(count * 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++) 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]; + int input = (i == 0) ? -1 : pipefds[i-1][0]; + int output = 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); @@ -84,6 +85,25 @@ void run(int count, char **progs[], char *inputstr, size_t inputlen) { CKE(close(pipefds[i][0]), "close"); CKE(close(pipefds[i][1]), "close"); } + CKE(close(pipefds[count-1][1]), "close"); + + // if the program produces too much data, you will be killed + size_t readed = 0; + size_t cap = 1024*1024; + char *buf = malloc(cap*sizeof(char)); + size_t remaining = cap; + size_t amt = 0; + do { + amt = read(pipefds[count-1][0], buf+readed, remaining); + readed += amt; + remaining -= amt; + if (remaining == 0) { + buf = realloc(buf, cap + cap); + remaining += cap; + cap += cap; + } + } while (amt != 0); + CKE(close(pipefds[count-1][0]), "close"); for (int i = 0; i < count; i++) { int status; @@ -93,9 +113,74 @@ void run(int count, char **progs[], char *inputstr, size_t inputlen) { free(pipefds); free(pids); + + *outlen = readed; + return buf; +} + +#define FAIL(msg) do { luaL_where(L, 1); lua_pushliteral(L, msg); lua_concat(L, 2); fail = 1; goto finish; } while (0) +int do_the_thing(lua_State *L) { + int fail = 0; + char ***argvs = NULL; + char *outbuf = NULL; + size_t nprogs = 0; + if (lua_gettop(L) != 1) FAIL("run wants exactly one argument"); + if (lua_type(L, 1) != LUA_TTABLE) FAIL("run needs table argumnt"); + nprogs = lua_rawlen(L, 1); + if (nprogs == 0) FAIL("need at least one program to run"); + argvs = calloc(nprogs, sizeof(char**)); + for (int i = 0; i < nprogs; i++) { + int ty = lua_rawgeti(L, 1, i + 1); + if (ty != LUA_TTABLE) FAIL("program arglist must be table"); + size_t argc = lua_rawlen(L, 2); + if (argc == 0) FAIL("need at least one argument to program"); + argvs[i] = calloc(argc + 1, sizeof(char*)); + for (int j = 0; j < argc; j++) { + int ty = lua_rawgeti(L, 2, j + 1); + if (ty != LUA_TSTRING) FAIL("program argument must be string"); + size_t slen = 0; char *str = lua_tolstring(L, 3, &slen); + argvs[i][j] = calloc(slen + 1, sizeof(char)); + memcpy(argvs[i][j], str, slen); + argvs[i][j][slen] = '\0'; // just to make sure + lua_pop(L, 1); + } + argvs[i][argc] = NULL; // just to make sure + lua_pop(L, 1); + } + + char *inputstr = NULL; size_t inputlen = 0; + lua_pushliteral(L, "input"); + int ty = lua_rawget(L, 1); + switch (ty) { + case LUA_TNIL: break; + case LUA_TSTRING: + inputstr = lua_tolstring(L, 2, &inputlen); + break; + default: FAIL("input field must be string if present"); + } + + size_t outlen; + outbuf = run(nprogs, argvs, inputlen, inputstr, &outlen); + lua_pushlstring(L, outbuf, outlen); + +finish: + if (argvs != NULL) { + for (int i = 0; i < nprogs; i++) { + if (argvs[i] != NULL) { + for (int j = 0; argvs[i][j] != NULL; j++) { + free(argvs[i][j]); + } + free(argvs[i]); + } + } + free(argvs); + } + free(outbuf); + if (fail) return lua_error(L); + return 1; } int luaopen_run(lua_State *L) { - lua_pushliteral(L, "fuck"); + lua_pushcfunction(L, &do_the_thing); return 1; } |