shithub: mc

Download patch

ref: 6863b80514aa42c6983d412823970a8c80e0b0cc
parent: 0c36acb089dad1d5656d2af4508b5165f52dee3d
author: Ori Bernstein <[email protected]>
date: Wed Aug 20 10:45:43 EDT 2014

Add spork() and sporkfd() calls

        const spork : (cmd : byte[:][:]     -> (pid, fd, fd))
        const sporkfd   : (cmd : byte[:][:], infd : fd, outfd : fd -> pid)

    spork() will create a new process running 'cmd', initialize it's
    stdin and stdout file descriptors to new pipes, and return a
    tuple consisting, respectively, of the PID of the newly spawned
    process, the write end of the new process's stdin, and the read
    end of the stdout of the new process.

    sporkfd() is similar, although instead of creating new file
    descriptors for stdin and stdout in the spawned process, it
    will connect them to the passed file descriptors. infd
    must be readable, and outfd must be writable.

--- a/libstd/Makefile
+++ b/libstd/Makefile
@@ -40,6 +40,7 @@
     slput.myr \
     slurp.myr \
     sort.myr \
+    spork.myr \
     strfind.myr \
     strjoin.myr \
     strsplit.myr \
@@ -52,7 +53,6 @@
     utf.myr \
     varargs.myr \
     waitstatus.myr \
-    zip.myr \
 
 ASMSRC= \
     syscall.s \
--- /dev/null
+++ b/libstd/spork.myr
@@ -1,0 +1,54 @@
+use "die.use"
+use "execvp.use"
+use "fmt.use"
+use "sys.use"
+
+pkg std =
+	const spork	: (cmd : byte[:][:]	-> (pid, fd, fd))
+	const sporkfd	: (cmd : byte[:][:], infd : fd, outfd : fd	-> pid)
+;;
+
+const spork = {cmd
+	var infds : fd[2], outfds : fd[2]
+	var err
+	var pid
+
+
+	err = pipe(infds[:])
+	if err != 0
+		fatal(1, "Could not create pipes: err %l\n", -err)
+	;;
+	err = pipe(outfds[:])
+	if err != 0
+		fatal(1, "Could not create pipes: err %l\n", -err)
+	;;
+	/* close unused fd ends */
+	pid = sporkfd(cmd, infds[0], outfds[1])
+	close(infds[0]);
+	close(outfds[1]);
+	-> (pid, infds[1], outfds[0])
+}
+
+const sporkfd = {cmd, infd, outfd
+	var pid
+	pid = fork()
+	if pid == -1
+		fatal(1, "Could not fork to start slave\n")
+	elif pid == 0
+		/* stdin/stdout for our communication. */
+		if dup2(infd, 0) != 0
+			fatal(1, "unable to set stdin\n")
+		;;
+		if dup2(outfd, 1) != 1
+			fatal(1, "unable to set stdout\n")
+		;;
+		close(infd)
+		close(outfd)
+		if execvp(cmd[0], cmd) < 0
+			fatal(1, "failed to exec %s\n")
+		;;
+	else
+		-> pid
+	;;
+}
+
--- a/libstd/sys-linux.myr
+++ b/libstd/sys-linux.myr
@@ -542,11 +542,11 @@
 
 	/* process management */
 	const exit	: (status:int -> void)
-	const getpid	: ( -> int64)
-	const kill	: (pid:int64, sig:int64 -> int64)
-	const fork	: (-> int64)
-	const wait4	: (pid:int64, loc:int32#, opt : int64, usage:rusage#	-> int64)
-	const waitpid	: (pid:int64, loc:int32#, opt : int64	-> int64)
+	const getpid	: ( -> pid)
+	const kill	: (pid:pid, sig:int64 -> int64)
+	const fork	: (-> pid)
+	const wait4	: (pid:pid, loc:int32#, opt : int64, usage:rusage#	-> int64)
+	const waitpid	: (pid:pid, loc:int32#, opt : int64	-> int64)
 	const execv	: (cmd : byte[:], args : byte[:][:] -> int64)
 	const execve	: (cmd : byte[:], args : byte[:][:], env : byte[:][:] -> int64)
 
@@ -605,9 +605,9 @@
 
 /* process management */
 const exit	= {status;		syscall(Sysexit, status castto(int64))}
-const getpid	= {;			-> syscall(Sysgetpid, 1)}
+const getpid	= {;			-> syscall(Sysgetpid, 1) castto(pid)}
 const kill	= {pid, sig;		-> syscall(Syskill, pid, sig)}
-const fork	= {;			-> syscall(Sysfork)}
+const fork	= {;			-> syscall(Sysfork) castto(pid)}
 const wait4	= {pid, loc, opt, usage;	-> syscall(Syswait4, pid, loc, opt, usage)}
 const waitpid	= {pid, loc, opt;
 	var rusage