summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2017-01-17 00:38:26 -0800
committerOri Bernstein <ori@eigenstate.org>2017-01-17 00:40:41 -0800
commit94ee9832f5861c4d09afa12338720eb3a479c342 (patch)
tree0f2700787300217db22a132fc2e33eafa022dd97
parentb4fed18974bfdfc41a813578cb56b5a54964395b (diff)
downloadmc-94ee9832f5861c4d09afa12338720eb3a479c342.tar.gz
Add the ability to do setenv() on posixy systems.
-rw-r--r--lib/std/env+posixy.myr89
-rw-r--r--lib/sys/sys+freebsd-x64.myr3
-rw-r--r--lib/sys/sys+linux-x64.myr3
-rw-r--r--lib/sys/sys+openbsd-x64.myr3
-rw-r--r--lib/sys/sys+osx-x64.myr3
-rw-r--r--rt/start-freebsd.s14
6 files changed, 90 insertions, 25 deletions
diff --git a/lib/std/env+posixy.myr b/lib/std/env+posixy.myr
index 09f1e5a..3919388 100644
--- a/lib/std/env+posixy.myr
+++ b/lib/std/env+posixy.myr
@@ -1,17 +1,33 @@
use sys
+use "alloc"
+use "cstrconv"
+use "die"
use "extremum"
+use "fmt"
+use "memops"
use "option"
+use "sldup"
+use "slcp"
use "sleq"
pkg std =
- const getenv : (name : byte[:] -> option(byte[:]))
- const getenvv : (name : byte[:], default : byte[:] -> byte[:])
+ const getenv : (name : byte[:] -> option(byte[:]))
+ const getenvv : (name : byte[:], default : byte[:] -> byte[:])
+ const setenv : (name : byte[:], val : byte[:] -> void)
;;
+const Zenvp = (0 : byte#)
+
+var envduped : bool = false
+var environ : byte#[:]
+
const getenv = {name
- var n
- for env in sys.__environment
+ var n, env
+
+ envinit()
+ for envp in environ
+ env = cstrconvp(envp)
n = min(name.len, env.len)
if sleq(name, env[:n]) && sleq(env[n:n+1], "=")
-> `Some env[n+1:]
@@ -26,3 +42,68 @@ const getenvv = {name, default
| `None: -> default
;;
}
+
+const setenv = {name, val
+ var n, e, env, idx
+
+ envdup()
+ idx = 0
+ for envp in environ
+ env = cstrconvp(envp)
+ n = min(name.len, env.len)
+ if sleq(name, env[:n]) && sleq(env[n:n+1], "=")
+ break
+ ;;
+ idx++
+ ;;
+ if idx == environ.len
+ slgrow(&environ, environ.len + 1)
+ else
+ e = cstrconvp(environ[idx])
+ std.slfree(e)
+ ;;
+
+ e = fmt("{}={}\0", name, val)
+ environ[idx] = (e : byte#)
+ sys.__cenvp = (environ : byte##)
+}
+
+const envinit = {
+ var len
+
+ if environ.len != 0
+ -> void
+ ;;
+ environ = sys.__cenvp[:1]
+ len = 0
+ while true
+ len++
+ environ = sys.__cenvp[:len + 1]
+ if environ[len] == Zenvp
+ environ = sys.__cenvp[:len]
+ break
+ ;;
+ ;;
+}
+
+const envdup = {
+ var e, s, dup
+
+ if envduped
+ -> void
+ ;;
+ envduped = true
+ envinit()
+ dup = std.slalloc(environ.len + 1)
+ for var i = 0; i < environ.len; i++
+ s = cstrconvp(environ[i])
+ e = std.slalloc(s.len + 1)
+ slcp(e[:e.len - 1], s)
+ e[e.len - 1] = 0
+
+ dup[i] = (e : byte#)
+ ;;
+ dup[dup.len - 1] = Zenvp
+ environ = dup[:dup.len - 1]
+ sys.__cenvp = (environ : byte##)
+}
diff --git a/lib/sys/sys+freebsd-x64.myr b/lib/sys/sys+freebsd-x64.myr
index c612a03..122ed21 100644
--- a/lib/sys/sys+freebsd-x64.myr
+++ b/lib/sys/sys+freebsd-x64.myr
@@ -881,8 +881,7 @@ pkg sys =
-> int)
/* filled by start code */
- extern const __cenvp : byte##
- extern const __environment : byte[:][:]
+ extern var __cenvp : byte##
;;
/*
diff --git a/lib/sys/sys+linux-x64.myr b/lib/sys/sys+linux-x64.myr
index 8bcafc8..c89a26b 100644
--- a/lib/sys/sys+linux-x64.myr
+++ b/lib/sys/sys+linux-x64.myr
@@ -781,8 +781,7 @@ pkg sys =
const uname : (buf : utsname# -> int)
/* exported values: initialized by start code */
- extern const __environment : byte[:][:]
- extern const __cenvp : byte##
+ extern var __cenvp : byte##
;;
/*
diff --git a/lib/sys/sys+openbsd-x64.myr b/lib/sys/sys+openbsd-x64.myr
index 707887d..a0c46fd 100644
--- a/lib/sys/sys+openbsd-x64.myr
+++ b/lib/sys/sys+openbsd-x64.myr
@@ -598,8 +598,7 @@ pkg sys =
-> int)
/* filled by start code */
- extern const __cenvp : byte##
- extern const __environment : byte[:][:]
+ extern var __cenvp : byte##
;;
/*
diff --git a/lib/sys/sys+osx-x64.myr b/lib/sys/sys+osx-x64.myr
index 1e593d7..9d2b747 100644
--- a/lib/sys/sys+osx-x64.myr
+++ b/lib/sys/sys+osx-x64.myr
@@ -818,8 +818,7 @@ pkg sys =
-> int)
/* filled by start code */
- extern const __cenvp : byte##
- extern const __environment : byte[:][:]
+ extern var __cenvp : byte##
;;
/*
diff --git a/rt/start-freebsd.s b/rt/start-freebsd.s
index 92f5435..186a76c 100644
--- a/rt/start-freebsd.s
+++ b/rt/start-freebsd.s
@@ -1,11 +1,4 @@
.data
-/* std._environment : byte[:][:] */
-.globl sys$__environment
-sys$__environment:
-.envbase:
-.quad 0 /* env size */
-.envlen:
-.quad 0 /* env ptr */
.globl sys$__cenvp
sys$__cenvp:
@@ -38,14 +31,9 @@ _start:
leaq 16(%rdi,%rax,8), %rbx /* envp = argv + 8*argc + 8 */
/* store envp for some syscalls to use without spurious conversion. */
movq %rbx,sys$__cenvp(%rip)
- movq %r9,%rax
- movq %rsp, %rcx
- movq %r9,.envlen(%rip)
- movq %rdx,.envbase(%rip)
- call cvt
- movq %rcx,%rdx
/* convert argc, argv to byte[:][:] for args. */
+ movq %rsp, %rcx
movq (%rdi), %rax /* argc */
leaq 8(%rdi), %rbx /* argv */
movq (%rdi), %rsi /* saved argc */