summaryrefslogtreecommitdiff
path: root/lib/std/spork.myr
diff options
context:
space:
mode:
Diffstat (limited to 'lib/std/spork.myr')
-rw-r--r--lib/std/spork.myr62
1 files changed, 62 insertions, 0 deletions
diff --git a/lib/std/spork.myr b/lib/std/spork.myr
new file mode 100644
index 0000000..64e8fce
--- /dev/null
+++ b/lib/std/spork.myr
@@ -0,0 +1,62 @@
+use "die.use"
+use "execvp.use"
+use "fmt.use"
+use "result.use"
+use "syswrap.use"
+
+pkg std =
+ const spork : (cmd : byte[:][:] -> result((pid, fd, fd), int))
+ const sporkfd : (cmd : byte[:][:], infd : fd, outfd : fd -> result(pid, int))
+;;
+
+const spork = {cmd
+ var infds :fd[2], outfds : fd[2]
+ var err
+
+ /* open up pipes */
+ err = pipe(&infds)
+ if err != 0
+ -> `Fail (-err castto(int))
+ ;;
+ err = pipe(&outfds)
+ if err != 0
+ -> `Fail (-err castto(int))
+ ;;
+
+ match sporkfd(cmd, infds[0] castto(fd), outfds[1] castto(fd))
+ | `Ok pid:
+ /* close unused fd ends */
+ close(infds[0]);
+ close(outfds[1]);
+ -> `Ok (pid, infds[1], outfds[0])
+ | `Fail m:
+ -> `Fail m
+ ;;
+}
+
+const sporkfd = {cmd, infd, outfd
+ var pid
+
+ pid = fork()
+ /* error */
+ if pid == -1
+ -> `Fail -1
+ /* child */
+ elif pid == 0
+ /* stdin/stdout for our communication. */
+ if dup2(infd castto(fd), 0) != 0
+ fatal("unable to set stdin\n")
+ ;;
+ if dup2(outfd castto(fd), 1) != 1
+ fatal("unable to set stdout\n")
+ ;;
+ close(infd)
+ close(outfd)
+ execvp(cmd[0], cmd) < 0
+ fatal("failed to exec {}\n", cmd[0])
+ /* parent */
+ else
+ -> `Ok pid
+ ;;
+}
+