ref: 94ee9832f5861c4d09afa12338720eb3a479c342
parent: b4fed18974bfdfc41a813578cb56b5a54964395b
author: Ori Bernstein <ori@eigenstate.org>
date: Mon Jan 16 19:38:26 EST 2017
Add the ability to do setenv() on posixy systems.
--- 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:]
@@ -25,4 +41,69 @@
| `Some v: -> v
| `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##)
}
--- a/lib/sys/sys+freebsd-x64.myr
+++ b/lib/sys/sys+freebsd-x64.myr
@@ -881,8 +881,7 @@
-> int)
/* filled by start code */
- extern const __cenvp : byte##
- extern const __environment : byte[:][:]
+ extern var __cenvp : byte##
;;
/*
--- a/lib/sys/sys+linux-x64.myr
+++ b/lib/sys/sys+linux-x64.myr
@@ -781,8 +781,7 @@
const uname : (buf : utsname# -> int)
/* exported values: initialized by start code */
- extern const __environment : byte[:][:]
- extern const __cenvp : byte##
+ extern var __cenvp : byte##
;;
/*
--- a/lib/sys/sys+openbsd-x64.myr
+++ b/lib/sys/sys+openbsd-x64.myr
@@ -598,8 +598,7 @@
-> int)
/* filled by start code */
- extern const __cenvp : byte##
- extern const __environment : byte[:][:]
+ extern var __cenvp : byte##
;;
/*
--- a/lib/sys/sys+osx-x64.myr
+++ b/lib/sys/sys+osx-x64.myr
@@ -818,8 +818,7 @@
-> int)
/* filled by start code */
- extern const __cenvp : byte##
- extern const __environment : byte[:][:]
+ extern var __cenvp : byte##
;;
/*
--- 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 @@
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 */