summaryrefslogtreecommitdiff
path: root/lib/std/env+posixy.myr
blob: 94b5456913778710086311e3296537f16fa5fe9e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
use sys

use "alloc"
use "cstrconv"
use "die"
use "extremum"
use "fmt"
use "memops"
use "option"
use "sldup"
use "slcp"
use "traits"
use "hashfuncs"

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

	envdup()
	idx = 0
	for envp : environ
		env = cstrconvp(envp)
		n = min(name.len, env.len)
		if eq(name, env[:n]) && eq(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##)
}