ref: f0eabb72719d366449d6456a5843793c9b0d62ab
dir: /lib/std/spork.myr/
use "die" use "execvp" use "fmt" use "result" use "syswrap" use "errno" pkg std = const spork : (cmd : byte[:][:] -> result((pid, fd, fd), errno)) const espork : (cmd : byte[:][:] -> result((pid, fd, fd, fd), errno)) const sporkfd : (cmd : byte[:][:], infd : fd, outfd : fd, errfd : fd -> result(pid, errno)) ;; const spork = {cmd var infds : fd[2], outfds : fd[2] var err /* open up pipes */ err = pipe(&infds) if err != Enone -> `Err err ;; err = pipe(&outfds) if err != Enone -> `Err err ;; match sporkfd(cmd, infds[0], outfds[1], 2) | `Ok pid: /* close unused fd ends */ close(infds[0]); close(outfds[1]); -> `Ok (pid, infds[1], outfds[0]) | `Err m: -> `Err m ;; } const espork = {cmd var infds : fd[2], outfds : fd[2], errfds : fd[2] var err /* open up pipes */ err = pipe(&infds) if err != Enone -> `Err err ;; err = pipe(&outfds) if err != Enone -> `Err err ;; err = pipe(&errfds) if err != Enone -> `Err err ;; match sporkfd(cmd, infds[0], outfds[1], errfds[1]) | `Ok pid: /* close unused fd ends */ close(infds[0]); close(outfds[1]); close(errfds[1]); -> `Ok (pid, infds[1], outfds[0], errfds[0]) | `Err m: -> `Err m ;; } const sporkfd = {cmd, infd, outfd, errfd var pid, err pid = fork() /* error */ if pid < 0 -> `Err (pid : errno) /* child */ elif pid == 0 /* stdin/stdout for our communication. */ match dup2(infd, 0) | `Ok _: /* nothing */ | `Err e: -> `Err e ;; match dup2(outfd, 1) | `Ok _: /* nothing */ | `Err e: -> `Err e ;; match dup2(errfd, 2) | `Ok _: /* nothing */ | `Err e: -> `Err e ;; close(infd) close(outfd) close(errfd) err = execvp(cmd[0], cmd) if err != Enone -> `Err err ;; /* if fork succeeds, we never return */ die("unreachable") /* parent */ else -> `Ok pid ;; }