shithub: mc

ref: 83bca2aaa7635be1ef17fdd5e3b02348b79f7dcc
dir: /lib/std/env+posixy.myr/

View raw version
use sys

use "alloc"
use "cstrconv"
use "die"
use "extremum"
use "fmt"
use "memops"
use "option"
use "sldup"
use "slcp"
use "sleq"
use "slpush"

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 sleq(name, env[:n]) && sleq(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

	envdup()
	idx = 0
	e = fmt("{}={}\0", name, val)
	for envp : environ
		if envp == Zenvp
			slpush(&environ, (0 : byte#))
			environ[idx] = (e : byte#)
			break
		;;
		env = cstrconvp(envp)
		n = min(name.len, env.len)
		if sleq(name, env[:n]) && sleq(env[n:n+1], "=")
			e = cstrconvp(environ[idx])
			std.slfree(e)
			environ[idx] = (e : byte#)
			break
		;;
		idx++
	;;
	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 + 1]
			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++
		if environ[i] != Zenvp
			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
	sys.__cenvp = (environ : byte##)
}