Files
Odin/core/os/env_posix.odin
2026-02-09 16:27:53 +01:00

111 lines
2.3 KiB
Odin

#+private
#+build darwin, netbsd, freebsd, openbsd
package os
import "base:runtime"
import "core:strings"
import "core:sys/posix"
_lookup_env_alloc :: proc(key: string, allocator: runtime.Allocator) -> (value: string, found: bool) {
if key == "" {
return
}
temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator })
ckey := strings.clone_to_cstring(key, temp_allocator)
cval := posix.getenv(ckey)
if cval == nil {
return
}
found = true
value = strings.clone(string(cval), allocator) // NOTE(laytan): what if allocation fails?
return
}
_lookup_env_buf :: proc(buf: []u8, key: string) -> (value: string, error: Error) {
if key == "" {
return
}
if len(key) + 1 > len(buf) {
return "", .Buffer_Full
} else {
copy(buf, key)
buf[len(key)] = 0
}
cval := posix.getenv(cstring(raw_data(buf)))
if cval == nil {
return
}
if value = string(cval); value == "" {
return "", .Env_Var_Not_Found
} else {
if len(value) > len(buf) {
return "", .Buffer_Full
} else {
copy(buf, value)
return string(buf[:len(value)]), nil
}
}
}
_lookup_env :: proc{_lookup_env_alloc, _lookup_env_buf}
_set_env :: proc(key, value: string) -> (err: Error) {
temp_allocator := TEMP_ALLOCATOR_GUARD({})
ckey := strings.clone_to_cstring(key, temp_allocator) or_return
cval := strings.clone_to_cstring(value, temp_allocator) or_return
if posix.setenv(ckey, cval, true) != nil {
err = _get_platform_error_from_errno()
}
return
}
_unset_env :: proc(key: string) -> (ok: bool) {
temp_allocator := TEMP_ALLOCATOR_GUARD({})
ckey := strings.clone_to_cstring(key, temp_allocator)
ok = posix.unsetenv(ckey) == .OK
return
}
// NOTE(laytan): clearing the env is weird, why would you ever do that?
_clear_env :: proc() {
for entry := posix.environ[0]; entry != nil; entry = posix.environ[0] {
key := strings.truncate_to_byte(string(entry), '=')
_unset_env(key)
}
}
_environ :: proc(allocator: runtime.Allocator) -> (environ: []string, err: Error) {
n := 0
for entry := posix.environ[0]; entry != nil; n, entry = n+1, posix.environ[n] {}
r := make([dynamic]string, 0, n, allocator) or_return
defer if err != nil {
for e in r {
delete(e, allocator)
}
delete(r)
}
for i, entry := 0, posix.environ[0]; entry != nil; i, entry = i+1, posix.environ[i] {
append(&r, strings.clone(string(entry), allocator) or_return)
}
environ = r[:]
return
}