diff options
Diffstat (limited to 'sdk/proc/spawn.c')
-rw-r--r-- | sdk/proc/spawn.c | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/sdk/proc/spawn.c b/sdk/proc/spawn.c new file mode 100644 index 0000000..2b6d7db --- /dev/null +++ b/sdk/proc/spawn.c @@ -0,0 +1,92 @@ +/* + * Spawn services built on fork() for those libc's that lack spawning. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <proc/process.h> +#include <std/files.h> + +static void spawn_redirect(int io, int mode) +{ + int fd = open("/dev/null", mode); + + if(fd < 0) + exit(EX_OSFILE); + + if(fd != io) + { + dup2(fd, io); + close(fd); + } +} + +static int spawn_wait(pid_t pid, int mode) +{ + int waitflag = mode & P_WAIT; + + /* -1 on fork failure */ + + if(pid == -1) + return -1; + + if(!waitflag) + return pid; + + waitpid(pid, &waitflag, 0); + return WEXITSTATUS(waitflag); +} + +static void spawn_mode(int mode) +{ + int i; + + if(mode & P_BACKGROUND) + { + spawn_redirect(0, O_RDONLY); + spawn_redirect(1, O_WRONLY); + spawn_redirect(2, O_WRONLY); + } + + for(i = 3; i < OPEN_MAX; ++i) + close(i); + + if(mode & P_SESSION) + setsid(); +} + +int spawnv(const int mode, const char *path, char *const argv[]) +{ + pid_t pid = 0; + int status; + + if(!(mode & P_OVERLAY)) + pid = fork(); + + if(pid) + return spawn_wait(pid, mode); + + spawn_mode(mode); + execv(path, argv); + exit(EX_UNAVAILABLE); + return -1; +} + +int spawnvp(const int mode, const char *path, char *const argv[]) +{ + pid_t pid = 0; + int status; + + if(!(mode & P_OVERLAY)) + pid = fork(); + + if(pid) + return spawn_wait(pid, mode); + + spawn_mode(mode); + execvp(path, argv); + exit(EX_UNAVAILABLE); + return -1; +} + |