ref: fbc01b056541c245dce94569d3564fd8812ec72b
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 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, 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, outfds, errfds) | `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, infds, outfds, errfds var pid, err pid = fork() /* error */ if pid < 0 -> `Err (pid : errno) /* child */ elif pid == 0 /* stdin/stdout for our communication. */ match dup2(infds[0], 0) | `Ok _: /* nothing */ | `Err e: -> `Err e ;; match dup2(outfds[1], 1) | `Ok _: /* nothing */ | `Err e: -> `Err e ;; match dup2(errfds[1], 2) | `Ok _: /* nothing */ | `Err e: -> `Err e ;; /* close the fds we duped */ if infds[0] != 0 close(infds[0]) ;; if outfds[1] != 1 close(outfds[1]) ;; if errfds[1] != 2 close(errfds[1]) ;; /* close the unused ends */ close(infds[1]) close(outfds[0]) close(errfds[0]) err = execvp(cmd[0], cmd) if err != Enone -> `Err err ;; /* if fork succeeds, we never return */ die("unreachable") /* parent */ else -> `Ok pid ;; }