shithub: mc

Download patch

ref: 1779c6b7aedf6bb7665b8f650f37958340f3177c
parent: c8397e67b2c1f2a994c4399e0654fe145b97629a
author: Ori Bernstein <ori@eigenstate.org>
date: Sat Jun 23 18:36:57 EDT 2018

Add sporkdir variants.

	This allows running a command in a directory without
	modifying the global state of the program. This is
	useful in multithreaded programs that launch subcommands.

--- a/lib/std/spork.myr
+++ b/lib/std/spork.myr
@@ -10,6 +10,8 @@
 	const run	: (cmd : byte[:][:]	-> waitstatus)
 	const spork	: (cmd : byte[:][:]	-> result((pid, fd, fd), errno))
 	const espork	: (cmd : byte[:][:]	-> result((pid, fd, fd, fd), errno))
+	const sporkdir	: (cmd : byte[:][:], dir : byte[:]	-> result((pid, fd, fd), errno))
+	const esporkdir	: (cmd : byte[:][:], dir : byte[:]	-> result((pid, fd, fd, fd), errno))
 	const filterfd	: (fd : fd, cmd  : byte[:][:] -> result(pid, errno))
 ;;
 
@@ -28,8 +30,15 @@
 	;;
 }
 
-
 const spork = {cmd
+	-> sporkdir(cmd, "")
+}
+
+const espork = {cmd
+	-> esporkdir(cmd, "")
+}
+
+const sporkdir = {cmd, dir
 	var infds : fd[2], outfds : fd[2]
 	var err
 
@@ -46,7 +55,7 @@
 		goto sporkerr
 	;;
 
-	match sporkfd(cmd, infds, outfds, [-1, 2])
+	match sporkfd(cmd, dir, infds, outfds, [-1, 2])
 	| `Ok pid:
 		/* close unused fd ends */
 		close(infds[0]);
@@ -64,7 +73,7 @@
 	-> `Err err
 }
 
-const espork = {cmd
+const esporkdir = {cmd, dir
 	var infds : fd[2], outfds : fd[2], errfds : fd[2]
 	var err
 
@@ -86,7 +95,7 @@
 		goto sporkerr
 	;;
 
-	match sporkfd(cmd, infds, outfds, errfds)
+	match sporkfd(cmd, dir, infds, outfds, errfds)
 	| `Ok pid:
 		/* close unused fd ends */
 		close(infds[0]);
@@ -117,7 +126,7 @@
 		-> `Err err
 	;;
 
-	match sporkfd(cmd, [fd, -1], outfds, [-1, 2])
+	match sporkfd(cmd, "", [fd, -1], outfds, [-1, 2])
 	| `Ok pid:
 		dup2(outfds[0], fd)
 		close(outfds[0]);
@@ -128,7 +137,7 @@
 	;;
 }
 
-const sporkfd = {cmd, infds, outfds, errfds
+const sporkfd = {cmd, dir, infds, outfds, errfds
 	var pid
 
 	pid = fork()
@@ -181,6 +190,9 @@
 		close(outfds[0])
 		close(errfds[0])
 
+		if dir.len != 0 && !chdir(dir)
+			std.die("could not chdir")
+		;;
 		execvp(cmd[0], cmd)
 		/* if fork succeeds, we never return */
 		suicide()