shithub: mc

Download patch

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 */