diff --git a/Libraries/LibC/spawn.cpp b/Libraries/LibC/spawn.cpp index 774af16d02..62b778105e 100644 --- a/Libraries/LibC/spawn.cpp +++ b/Libraries/LibC/spawn.cpp @@ -34,18 +34,23 @@ #include -#include +#include #include #include #include +#include +#include +#include +#include + +struct posix_spawn_file_actions_state { + Vector, 4> actions; +}; extern "C" { [[noreturn]] static void posix_spawn_child(const char* path, const posix_spawn_file_actions_t* file_actions, const posix_spawnattr_t* attr, char* const argv[], char* const envp[], int (*exec)(const char*, char* const[], char* const[])) { - if (file_actions) { - // FIXME - } if (attr) { short flags = attr->flags; if (flags & POSIX_SPAWN_RESETIDS) { @@ -94,6 +99,15 @@ extern "C" { // FIXME: POSIX_SPAWN_SETSCHEDULER } + if (file_actions) { + for (const auto& action : file_actions->state->actions) { + if (action() < 0) { + perror("posix_spawn file action"); + exit(127); + } + } + } + exec(path, argv, envp); perror("posix_spawn exec"); exit(127); @@ -127,33 +141,42 @@ int posix_spawnp(pid_t* out_pid, const char* path, const posix_spawn_file_action posix_spawn_child(path, file_actions, attr, argv, envp, execvpe); } - -#if 0 -// FIXME -int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t*, - int) +int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t* actions, int fd) { + actions->state->actions.append([fd]() { return close(fd); }); + return 0; } -int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t*, - int, int) +int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t* actions, int old_fd, int new_fd) { + actions->state->actions.append([old_fd, new_fd]() { return dup2(old_fd, new_fd); }); + return 0; } -int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t*, - int, const char*, int, mode_t) +int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t* actions, int want_fd, const char* path, int flags, mode_t mode) { + actions->state->actions.append([want_fd, path, flags, mode]() { + int opened_fd = open(path, flags, mode); + if (opened_fd < 0 || opened_fd == want_fd) + return opened_fd; + if (int rc = dup2(opened_fd, want_fd); rc < 0) + return rc; + return close(opened_fd); + }); + return 0; } -int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t*) +int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t* actions) { + delete actions->state; + return 0; } -int posix_spawn_file_actions_init(posix_spawn_file_actions_t*) +int posix_spawn_file_actions_init(posix_spawn_file_actions_t* actions) { + actions->state = new posix_spawn_file_actions_state; + return 0; } -#endif - int posix_spawnattr_destroy(posix_spawnattr_t*) { diff --git a/Libraries/LibC/spawn.h b/Libraries/LibC/spawn.h index 1fc1289f7f..03bd4c1899 100644 --- a/Libraries/LibC/spawn.h +++ b/Libraries/LibC/spawn.h @@ -52,8 +52,9 @@ enum { POSIX_SPAWN_SETSIGMASK = 1 << 5, }; +struct posix_spawn_file_actions_state; typedef struct { - // FIXME + struct posix_spawn_file_actions_state* state; } posix_spawn_file_actions_t; typedef struct { @@ -68,13 +69,11 @@ typedef struct { int posix_spawn(pid_t*, const char*, const posix_spawn_file_actions_t*, const posix_spawnattr_t*, char* const[], char* const[]); int posix_spawnp(pid_t*, const char*, const posix_spawn_file_actions_t*, const posix_spawnattr_t*, char* const[], char* const[]); -#if 0 int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t*, int); -int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t*, int, int); -int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t*, int, const char*, int, mode_t); +int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t*, int old_fd, int new_fd); +int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t*, int fd, const char*, int flags, mode_t); int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t*); int posix_spawn_file_actions_init(posix_spawn_file_actions_t*); -#endif int posix_spawnattr_destroy(posix_spawnattr_t*); int posix_spawnattr_getflags(const posix_spawnattr_t*, short*);