shithub: mc

Download patch

ref: 2cf47897e67a6d07d2b29c6afdac6275571ea57d
parent: 2c8985573c67d496b8e0b717cbbdba819235ef33
author: Ori Bernstein <[email protected]>
date: Wed Jan 8 16:11:40 EST 2014

Add more process control syscalls.

--- a/libstd/Makefile
+++ b/libstd/Makefile
@@ -9,6 +9,7 @@
     endian.myr \
     env.myr \
     error.myr \
+    execvp.myr \
     extremum.myr \
     fmt.myr \
     hashfuncs.myr \
@@ -39,6 +40,7 @@
     units.myr \
     utf.myr \
     varargs.myr \
+    waitstatus.myr \
 
 ASMSRC= \
     start.s \
--- /dev/null
+++ b/libstd/execvp.myr
@@ -1,0 +1,50 @@
+use "sys.use"
+use "fmt.use"
+use "option.use"
+use "strsplit.use"
+use "alloc.use"
+use "env.use"
+
+pkg std = 
+	const execvp	: (cmd : byte[:], args : byte[:][:] -> int64)
+	const execvpe	: (cmd : byte[:], args : byte[:][:], env : byte[:][:] -> int64)
+;;
+
+const execvp = {cmd, args
+	var path
+	var split
+	var buf : byte[512]
+
+	match getenv("PATH")
+	| `Some p:	path = p
+	| `None:	path = "/usr/local/bin:/bin:/usr/bin"
+	;;
+
+	split = strsplit(path, ":")
+	for s in split
+		bfmt(buf[:], "%s/%s", s, cmd)
+		execv(cmd, args)
+	;;
+	slfree(split)
+	-> -1
+}
+
+const execvpe = {cmd, args, env
+	var path
+	var split
+	var buf : byte[512]
+
+	match getenv("PATH")
+	| `Some p:	path = p
+	| `None:	path = "/usr/local/bin:/bin:/usr/bin"
+	;;
+
+	split = strsplit(path, ":")
+	for s in split
+		bfmt(buf[:], "%s/%s", s, cmd)
+		execve(cmd, args, env)
+	;;
+	slfree(split)
+	-> -1
+}
+
--- a/libstd/start-linux.s
+++ b/libstd/start-linux.s
@@ -7,6 +7,10 @@
 .envlen:
 .quad 0 /* env ptr */
 
+.globl std$__cenvp
+std$__cenvp:
+.quad 0
+
 .text
 /*
  * counts the length of the string pointed to
@@ -68,9 +72,10 @@
 _start:
 	/* turn args into a slice */
 	movq	%rsp,%rbp
+
 	/* stack allocate sizeof(byte[:])*(argc + len(envp)) */
 	movq	(%rbp),%rax
-	leaq	16(%rbp,%rax,8), %rbx	/* envp = argv + 8*argc + 8 */
+	leaq	16(%rbp,%rax,8), %rbx	/* argp = argv + 8*argc + 8 */
         call    count
 	addq	%r9,%rax
 	imulq	$16,%rax
@@ -77,6 +82,9 @@
 	subq	%rax,%rsp
 	movq	%rsp, %rdx	/* saved args[:] */
 
+        /* store envp for some syscalls to use without converting */
+	movq	16(%rbp,%rax,8), %rbx	/* envp = argv + 8*argc + 8 */
+        movq    %rbx,std$__cenvp(%rip)
 	/* convert envp to byte[:][:] for std._environment */
 	movq	(%rbp),%rax
 	leaq	16(%rbp,%rax,8), %rbx	/* envp = argv + 8*argc + 8 */
--- a/libstd/start-osx.s
+++ b/libstd/start-osx.s
@@ -72,12 +72,9 @@
 start:
 	/* turn args into a slice */
 	movq	%rsp,%rbp
-        /* store envp for some syscalls to use without converting */
-	movq	16(%rbp,%rax,8), %rbx	/* envp = argv + 8*argc + 8 */
-        movq    %rbx,_std$__cenvp(%rip)
 	/* stack allocate sizeof(byte[:])*(argc + len(envp)) */
 	movq	(%rbp),%rax
-	leaq	16(%rbp,%rax,8), %rbx	/* envp = argv + 8*argc + 8 */
+	leaq	16(%rbp,%rax,8), %rbx	/* argp = argv + 8*argc + 8 */
         call    count
 	addq	%r9,%rax
 	imulq	$16,%rax
@@ -84,6 +81,9 @@
 	subq	%rax,%rsp
 	movq	%rsp, %rdx	/* saved args[:] */
 
+        /* store envp for some syscalls to use without converting */
+	movq	16(%rbp,%rax,8), %rbx	/* envp = argv + 8*argc + 8 */
+        movq    %rbx,_std$__cenvp(%rip)
 	/* convert envp to byte[:][:] for std._environment */
 	movq	(%rbp),%rax
 	leaq	16(%rbp,%rax,8), %rbx	/* envp = argv + 8*argc + 8 */
--- a/libstd/sys-linux.myr
+++ b/libstd/sys-linux.myr
@@ -1,4 +1,5 @@
 use "types.use"
+use "sleq.use"
 
 pkg std =
 	type scno	= int64	/* syscall */
@@ -28,6 +29,17 @@
 		nsec	: uint64
 	;;
 
+	type timeval = struct
+		sec	: uint64
+		usec	: uint64
+	;;
+
+	type rusage = struct
+		utime	: timeval	/* user time */
+		stime	: timeval	/* system time */
+		_opaque	: uint64[14]	/* padding (darwin-specific data) */
+	;;
+
 	type statbuf = struct
 		 dev     : uint
 		 ino     : uint
@@ -435,8 +447,10 @@
 	const Sysprocess_vm_writev	: scno = 311
 
 	/* getting to the os */
-	extern const syscall : (sc:scno, args:... -> int64)
-	extern const cstring : (str : byte[:] -> byte#)
+	extern const syscall	: (sc:scno, args:... -> int64)
+	extern const cstring	: (str : byte[:] -> byte#)
+	extern const alloca	: (sz : size	-> byte#)
+	extern const __cenvp : byte##
 
 	/* process management */
 	const exit	: (status:int -> void)
@@ -445,7 +459,8 @@
 	const fork	: (-> int64)
 	const wait4	: (pid:int64, loc:int64#, opt : int64, usage:rusage#	-> int64)
 	const waitpid	: (pid:int64, loc:int64#, opt : int64	-> int64)
-	const execv	: (cmd : byte[:], args : byte[:][:])
+	const execv	: (cmd : byte[:], args : byte[:][:] -> int64)
+	const execve	: (cmd : byte[:], args : byte[:][:], env : byte[:][:] -> int64)
 
 
 	/* fd manipulation */
@@ -485,18 +500,48 @@
 const getpid	= {;			-> syscall(Sysgetpid, 1)}
 const kill	= {pid, sig;		-> syscall(Syskill, pid, sig)}
 const fork	= {;			-> syscall(Sysfork)}
-const wait4	= {pid, loc, opt, use;	-> syscall(Syswait4, pid, loc, opt, use)}
-const waitpid	= {pid, loc, opt;	-> 
+const wait4	= {pid, loc, opt, usage;	-> syscall(Syswait4, pid, loc, opt, usage)}
+const waitpid	= {pid, loc, opt;
 	var rusage
 	-> wait4(pid, loc, opt, &rusage)
 }
+
 const execv	= {cmd, args
-	var buf : byte#[1024] /* FIXME: right now, we only support 1023 args. */
-	for a in args
-		buf[i++] = cstring(buf)
+	var cargs, i
+
+	/* of course we fucking have to duplicate this code everywhere,
+	* since we want to stack allocate... */
+	cargs = (alloca(sizeof(byte#)*(args.len + 1)) castto(byte##))[:args.len]
+	for i = 0; i < args.len; i++
+		cargs[i] = cstring(args[i])
 	;;
+	cargs[args.len] = 0 castto(byte#)
+	-> syscall(Sysexecve, cmd castto(byte#), cargs, __cenvp)
 }
 
+const execve	= {cmd, args, env
+	var cargs, cenv, i
+
+	/* copy the args */
+	cargs = (alloca(sizeof(byte#)*(args.len + 1)) castto(byte##))[:args.len]
+	for i = 0; i < args.len; i++
+		cargs[i] = cstring(args[i])
+	;;
+	cargs[args.len] = 0 castto(byte#)
+
+	/*
+	 copy the env.
+	 of course we fucking have to duplicate this code everywhere,
+	 since we want to stack allocate... 
+	*/
+	cenv = (alloca(sizeof(byte#)*(env.len + 1)) castto(byte##))[:env.len]
+	for i = 0; i < env.len; i++
+		cenv[i] = cstring(env[i])
+	;;
+	cenv[env.len] = 0 castto(byte#)
+
+	-> syscall(Sysexecve, cmd castto(byte#), cargs, cenv)
+}
 
 /* fd manipulation */
 const open	= {path, opts, mode;	-> syscall(Sysopen, cstring(path), opts, mode) castto(fd)}
--- a/libstd/sys-osx.myr
+++ b/libstd/sys-osx.myr
@@ -496,8 +496,6 @@
 	const waitpid	: (pid:int64, loc:int64#, opt : int64	-> int64)
 	const execv	: (cmd : byte[:], args : byte[:][:] -> int64)
 	const execve	: (cmd : byte[:], args : byte[:][:], env : byte[:][:] -> int64)
-	const execvp	: (cmd : byte[:], args : byte[:][:] -> int64)
-	const execvpe	: (cmd : byte[:], args : byte[:][:], env : byte[:][:] -> int64)
 
 	/* fd manipulation */
 	const open	: (path:byte[:], opts:fdopt, mode:int64 -> fd)
--- /dev/null
+++ b/libstd/waitstatus.myr
@@ -1,0 +1,21 @@
+use "die.use"
+pkg std =
+	type waitstatus = union
+		`Waitexit int64
+		`Waitsig  int64
+		`Waitstop int64
+	;;
+
+	const waitstatus	: (st : int64 -> waitstatus)
+;;
+
+const waitstatus = {st
+	if st & 0x7f == 0 /* if exited */
+		-> `Waitexit ((st & 0xff00) >> 8)
+	elif ((st & 0xffff)-1) < 0xff /* if signaled */
+		-> `Waitsig ((st) & 0x7f)
+	elif (((st & 0xffff)*0x10001)>>8) > 0x7f00
+		-> `Waitstop ((st & 0xff00) >> 8)
+	;;
+	die("unreachable")
+}