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")
+}