diff --git a/gebs.h b/gebs.h index 2bc01bb..4563b24 100644 --- a/gebs.h +++ b/gebs.h @@ -330,10 +330,13 @@ typedef Gebs_NString_List Gebs_Cmd; #define gebs_cmd_free gebs_list_free #define gebs_cmd_run_alloc gebs_cmd_run_sync_alloc +#define gebs_cmd_fd_run_alloc gebs_cmd_run_sync_alloc #define gebs_cmd_run(cmd) gebs_cmd_run_alloc(&gebs_default_allocator, (cmd)) +#define gebs_cmd_fd_run(fd, cmd) gebs_cmd_fd_run_alloc(&gebs_default_allocator, fd, (cmd)) int gebs_cmd_run_sync_alloc(Gebs_Allocator *alloc, Gebs_Cmd *cmd); +int gebs_cmd_fd_run_sync_alloc(Gebs_Allocator *alloc, int fd, Gebs_Cmd *cmd); #define GEBS_CMD(...) \ ({ \ @@ -349,11 +352,18 @@ int gebs_cmd_run_sync_alloc(Gebs_Allocator *alloc, Gebs_Cmd *cmd); int gebs_cmd_run_sync_collect_alloc(Gebs_Allocator *alloc, Gebs_Cmd *cmd, Gebs_String_Builder *sb_out); +int gebs_cmd_fd_run_sync_collect_alloc(Gebs_Allocator *alloc, int fd, + Gebs_Cmd *cmd, Gebs_String_Builder *sb_out); + #define gebs_cmd_run_collect_alloc gebs_cmd_run_sync_collect_alloc +#define gebs_cmd_fd_run_collect_alloc gebs_cmd_fd_run_sync_collect_alloc #define gebs_cmd_run_collect(cmd, out) \ gebs_cmd_run_collect_alloc(&gebs_default_allocator, (cmd), (out)) +#define gebs_cmd_fd_run_collect(fd, cmd, out) \ + gebs_cmd_fd_run_collect_alloc(&gebs_default_allocator, (fd), (cmd), (out)) + // ---------------------------------------------------------------------------- // The build system // ---------------------------------------------------------------------------- @@ -463,6 +473,53 @@ int gebs_cmd_run_sync_alloc(Gebs_Allocator *alloc, Gebs_Cmd *cmd) } } +int gebs_cmd_fd_run_sync_alloc(Gebs_Allocator *alloc, int fd, Gebs_Cmd *cmd) +{ + Gebs_String_Builder sb = {0}; + defer { gebs_sb_free_alloc(alloc, &sb); } + gebs_nsl_join_alloc(alloc, cmd, &sb, " "); + gebs_sb_finish_alloc(alloc, &sb); + GEBS_LOGI("cmd `%s`\n", sb.items); + + // Clone the list + Gebs_Cmd new_cmd = {0}; + defer { gebs_cmd_free_alloc(alloc, &new_cmd); } + for (size_t i = 0; i < cmd->count; i++) { + gebs_cmd_append_alloc(alloc, &new_cmd, cmd->items[i]); + } + gebs_cmd_append_alloc((alloc), &new_cmd, nil); + + pid_t pid = vfork(); + switch (pid) { + case -1: + GEBS_LOGE("Could not vfork\n"); + return -1; + case 0: { + const char *const envp[] = {NULL}; + fexecve(fd, (char * const *)new_cmd.items, (char * const *)envp); + exit(EXIT_FAILURE); + } break; + default: { + int wstatus; + do { + if (waitpid(pid, &wstatus, WUNTRACED | WCONTINUED) == -1) { + return -1; + } + + if (WIFEXITED(wstatus)) { + return WEXITSTATUS(wstatus); + } else if (WIFSIGNALED(wstatus)) { + GEBS_LOGI("%d killed by %d\n", pid, WTERMSIG(wstatus)); + return -1; + } else if (WIFSTOPPED(wstatus)) { + GEBS_LOGI("%d stopped by %d\n", pid, WSTOPSIG(wstatus)); + return -1; + } + } while(!WIFEXITED(wstatus) && !WIFSIGNALED(wstatus)); + } + } +} + int gebs_cmd_run_sync_collect_alloc(Gebs_Allocator *alloc, Gebs_Cmd *cmd, Gebs_String_Builder *sb_out) { Gebs_String_Builder sb = {0}; @@ -524,6 +581,69 @@ int gebs_cmd_run_sync_collect_alloc(Gebs_Allocator *alloc, Gebs_Cmd *cmd, Gebs_S } } +int gebs_cmd_fd_run_sync_collect_alloc(Gebs_Allocator *alloc, int fd, Gebs_Cmd *cmd, Gebs_String_Builder *sb_out) +{ + Gebs_String_Builder sb = {0}; + defer { gebs_sb_free_alloc(alloc, &sb); } + gebs_nsl_join_alloc(alloc, cmd, &sb, " "); + gebs_sb_finish_alloc(alloc, &sb); + GEBS_LOGI("cmd `%s`\n", sb.items); + + // Clone the list + Gebs_Cmd new_cmd = {0}; + defer { gebs_cmd_free_alloc(alloc, &new_cmd); } + for (size_t i = 0; i < cmd->count; i++) { + gebs_cmd_append_alloc(alloc, &new_cmd, cmd->items[i]); + } + gebs_cmd_append_alloc((alloc), &new_cmd, nil); + + int pipe_ends[2]; + pipe(pipe_ends); + + pid_t pid = vfork(); + switch (pid) { + case -1: + close(pipe_ends[0]); + close(pipe_ends[1]); + GEBS_LOGE("Could not vfork\n"); + return -1; + case 0: { + close(pipe_ends[0]); + dup2(pipe_ends[1], 1); + close(pipe_ends[1]); + + const char *const envp[] = {NULL}; + fexecve(fd, (char *const *)new_cmd.items, (char *const *)envp); + exit(EXIT_FAILURE); + } break; + default: { + close(pipe_ends[1]); + char c; + while (read(pipe_ends[0], &c, 1) > 0) { + gebs_sb_append_char_alloc(alloc, sb_out, c); + } + gebs_sb_finish_alloc(alloc, sb_out); + + int wstatus; + do { + if (waitpid(pid, &wstatus, WUNTRACED | WCONTINUED) == -1) { + return -1; + } + + if (WIFEXITED(wstatus)) { + return WEXITSTATUS(wstatus); + } else if (WIFSIGNALED(wstatus)) { + GEBS_LOGI("%d killed by %d\n", pid, WTERMSIG(wstatus)); + return -1; + } else if (WIFSTOPPED(wstatus)) { + GEBS_LOGI("%d stopped by %d\n", pid, WSTOPSIG(wstatus)); + return -1; + } + } while(!WIFEXITED(wstatus) && !WIFSIGNALED(wstatus)); + } + } +} + // ---------------------------------------------------------------------------- // Allocators // ---------------------------------------------------------------------------- @@ -832,6 +952,12 @@ void gebs_rebuild_self1_alloc(Gebs_Allocator *alloc, int argc, char ** argv, #define cmd_run_sync_collect_alloc gebs_cmd_run_sync_collect_alloc #define cmd_run_collect_alloc gebs_cmd_run_collect_alloc #define cmd_run_collect gebs_cmd_run_collect +#define cmd_fd_run_sync_collect_alloc gebs_cmd_fd_run_sync_collect_alloc +#define cmd_fd_run_collect_alloc gebs_cmd_fd_run_collect_alloc +#define cmd_fd_run_collect gebs_cmd_fd_run_collect +#define cmd_fd_run_sync_alloc gebs_cmd_fd_run_sync_alloc +#define cmd_fd_run_alloc gebs_cmd_fd_run_alloc +#define cmd_fd_run gebs_cmd_fd_run #define needs_rebuild gebs_needs_rebuild #define needs_rebuild_many gebs_needs_rebuild_many