aboutsummaryrefslogtreecommitdiffstats
path: root/sdk/proc/spawn.c
diff options
context:
space:
mode:
authorWilliam Harrington <kb0iic@berzerkula.org>2025-01-14 16:06:02 -0600
committerWilliam Harrington <kb0iic@berzerkula.org>2025-01-14 16:06:02 -0600
commit0cc9b20c15460213e488bf5e70963b941482f628 (patch)
treebb0143245583ec846630f39bfa2258dba640ccd7 /sdk/proc/spawn.c
parent0e084ade5069756d487b5c948c48b777e37c00c9 (diff)
Add source.
Diffstat (limited to 'sdk/proc/spawn.c')
-rw-r--r--sdk/proc/spawn.c92
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;
+}
+