shithub: mc

ref: ddb327c92ebe3f96c5c816ec61996440551de401
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"

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 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:]
		;;
	;;
	-> `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
	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##)
}