ref: 59b1d9b6c40d88d3b6373993662c3bce3541f3a0
dir: /lib/std/env+posixy.myr/
use sys
use "alloc"
use "cstrconv"
use "die"
use "extremum"
use "fmt"
use "sleq"
use "memops"
use "option"
use "slcp"
use "sldup"
use "slpush"
use "threadhooks"
use "traits"
pkg std =
	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, env
	envinit()
	for envp : environ
		if envp != Zenvp
			env = cstrconvp(envp)
			n = min(name.len, env.len)
			if eq(name, env[:n]) && eq(env[n:n+1], "=")
				-> `Some env[n+1:]
			;;
		;;
	;;
	-> `None
}
const getenvv = {name, default
	match getenv(name)
	| `Some v:	-> v
	| `None:	-> default
	;;
}
const setenv = {name, val
	var n, e, env, idx, found
	envinit()
	idx = 0
	found = false
	e = fmt("{}={}\0", name, val)
	lock(envlck)
	for envp : environ
		if envp == Zenvp
			break
		;;
		env = cstrconvp(envp)
		n = min(name.len, env.len - 1)
		if eq(name, env[:n]) && env[n] == ('=' : byte)
			found = true
			break
		;;
		idx++
	;;
	if found
		std.slfree(cstrconvp(environ[idx]))
	else
		idx = environ.len - 1
		std.slpush(&environ, Zenvp)
	;;
	environ[idx] = (e : byte#)
	sys.__cenvp = (environ : byte##)
	unlock(envlck)
}
const envinit = {
	var len, e, p
	lock(envlck)
	if environ.len != 0
		unlock(envlck)
		-> void
	;;
	/* 
	  Here, we duplicate the environment so we can
	  modify it. We take progressively bigger slices
	  as we go, until we find the terminating null.
	  It's a bit ugly, but what do?
	 */
	len = 0
	environ = [][:]
	while true
		p = sys.__cenvp[:len+1][len]
		if p != Zenvp
			e = sldup(cstrconvp(p))
			slpush(&e, 0)
			p = (e : byte#)
		;;
		std.slpush(&environ, p)
		if environ[len] == Zenvp
			break
		;;
		len++
	;;
	sys.__cenvp = (environ : byte##)
	unlock(envlck)
}