summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNico Weber <thakis@chromium.org>2020-06-19 10:46:45 -0400
committerAndreas Kling <kling@serenityos.org>2020-06-19 22:11:38 +0200
commit7ffcc5a8b262a1a83de74483ad0a4634f177e011 (patch)
treef5438d2f0b69bb6a01024eb39cfc116fc1da5deb
parent68f281c864aea9d6530a31f45b6a06fcb8545038 (diff)
downloadserenity-7ffcc5a8b262a1a83de74483ad0a4634f177e011.zip
LibC: Implement file actions for posix_spawn
-rw-r--r--Libraries/LibC/spawn.cpp57
-rw-r--r--Libraries/LibC/spawn.h9
2 files changed, 44 insertions, 22 deletions
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 <spawn.h>
-#include <assert.h>
+#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <AK/Function.h>
+#include <AK/Vector.h>
+
+struct posix_spawn_file_actions_state {
+ Vector<Function<int()>, 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*);