diff options
Diffstat (limited to 'newlib/libc/posix/posix_spawn.c')
-rw-r--r-- | newlib/libc/posix/posix_spawn.c | 89 |
1 files changed, 87 insertions, 2 deletions
diff --git a/newlib/libc/posix/posix_spawn.c b/newlib/libc/posix/posix_spawn.c index 85bfa6477..3506b0f8b 100644 --- a/newlib/libc/posix/posix_spawn.c +++ b/newlib/libc/posix/posix_spawn.c @@ -123,7 +123,13 @@ struct __posix_spawn_file_actions { typedef struct __posix_spawn_file_actions_entry { STAILQ_ENTRY(__posix_spawn_file_actions_entry) fae_list; - enum { FAE_OPEN, FAE_DUP2, FAE_CLOSE } fae_action; + enum { + FAE_OPEN, + FAE_DUP2, + FAE_CLOSE, + FAE_CHDIR, + FAE_FCHDIR + } fae_action; int fae_fildes; union { @@ -139,6 +145,10 @@ typedef struct __posix_spawn_file_actions_entry { int newfildes; #define fae_newfildes fae_data.dup2.newfildes } dup2; + char *dir; +#define fae_dir fae_data.dir + int dirfd; +#define fae_dirfd fae_data.dirfd } fae_data; } posix_spawn_file_actions_entry_t; @@ -235,7 +245,21 @@ process_file_actions_entry(posix_spawn_file_actions_entry_t *fae) /* Perform a close(), do not fail if already closed */ (void)_close(fae->fae_fildes); break; +#ifdef HAVE_CHDIR + case FAE_CHDIR: + /* Perform a chdir. */ + if (chdir (fae->fae_dir) == -1) + return (errno); + break; +#endif +#ifdef HAVE_FCHDIR + case FAE_FCHDIR: + /* Perform a chdir. */ + if (fchdir (fae->fae_dirfd) == -1) + return (errno); + break; } +#endif return (0); } @@ -407,8 +431,18 @@ posix_spawn_file_actions_destroy (posix_spawn_file_actions_t *fa) STAILQ_REMOVE_HEAD(&(*fa)->fa_list, fae_list); /* Deallocate file action entry */ - if (fae->fae_action == FAE_OPEN) + switch (fae->fae_action) { + case FAE_OPEN: free(fae->fae_path); + break; +#ifdef HAVE_CHDIR + case FAE_CHDIR: + free(fae->fae_dir); + break; +#endif + default: + break; + } free(fae); } @@ -496,6 +530,57 @@ posix_spawn_file_actions_addclose (posix_spawn_file_actions_t *fa, return (0); } +#ifdef HAVE_CHDIR +int +posix_spawn_file_actions_addchdir_np ( + posix_spawn_file_actions_t * __restrict fa, + const char * __restrict path) +{ + posix_spawn_file_actions_entry_t *fae; + int error; + + /* Allocate object */ + fae = malloc(sizeof(posix_spawn_file_actions_entry_t)); + if (fae == NULL) + return (errno); + + /* Set values and store in queue */ + fae->fae_action = FAE_CHDIR; + fae->fae_dir = strdup(path); + if (fae->fae_dir == NULL) { + error = errno; + free(fae); + return (error); + } + + STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list); + return (0); +} +#endif + +#ifdef HAVE_FCHDIR +int +posix_spawn_file_actions_addfchdir_np ( + posix_spawn_file_actions_t * __restrict fa, + int fd) +{ + posix_spawn_file_actions_entry_t *fae; + int error; + + /* Allocate object */ + fae = malloc(sizeof(posix_spawn_file_actions_entry_t)); + if (fae == NULL) + return (errno); + + /* Set values and store in queue */ + fae->fae_action = FAE_FCHDIR; + fae->fae_dirfd = fd; + + STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list); + return (0); +} +#endif + /* * Spawn attributes */ |