env_posix.odin 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. #+private
  2. #+build darwin, netbsd, freebsd, openbsd
  3. package os2
  4. import "base:runtime"
  5. import "core:strings"
  6. import "core:sys/posix"
  7. _lookup_env_alloc :: proc(key: string, allocator: runtime.Allocator) -> (value: string, found: bool) {
  8. if key == "" {
  9. return
  10. }
  11. temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator })
  12. ckey := strings.clone_to_cstring(key, temp_allocator)
  13. cval := posix.getenv(ckey)
  14. if cval == nil {
  15. return
  16. }
  17. found = true
  18. value = strings.clone(string(cval), allocator) // NOTE(laytan): what if allocation fails?
  19. return
  20. }
  21. _lookup_env_buf :: proc(buf: []u8, key: string) -> (value: string, error: Error) {
  22. if key == "" {
  23. return
  24. }
  25. if len(key) + 1 > len(buf) {
  26. return "", .Buffer_Full
  27. } else {
  28. copy(buf, key)
  29. }
  30. cval := posix.getenv(cstring(raw_data(buf)))
  31. if cval == nil {
  32. return
  33. }
  34. if value = string(cval); value == "" {
  35. return "", .Env_Var_Not_Found
  36. } else {
  37. if len(value) > len(buf) {
  38. return "", .Buffer_Full
  39. } else {
  40. copy(buf, value)
  41. return string(buf[:len(value)]), nil
  42. }
  43. }
  44. }
  45. _lookup_env :: proc{_lookup_env_alloc, _lookup_env_buf}
  46. _set_env :: proc(key, value: string) -> (err: Error) {
  47. temp_allocator := TEMP_ALLOCATOR_GUARD({})
  48. ckey := strings.clone_to_cstring(key, temp_allocator) or_return
  49. cval := strings.clone_to_cstring(value, temp_allocator) or_return
  50. if posix.setenv(ckey, cval, true) != nil {
  51. err = _get_platform_error_from_errno()
  52. }
  53. return
  54. }
  55. _unset_env :: proc(key: string) -> (ok: bool) {
  56. temp_allocator := TEMP_ALLOCATOR_GUARD({})
  57. ckey := strings.clone_to_cstring(key, temp_allocator)
  58. ok = posix.unsetenv(ckey) == .OK
  59. return
  60. }
  61. // NOTE(laytan): clearing the env is weird, why would you ever do that?
  62. _clear_env :: proc() {
  63. for i, entry := 0, posix.environ[0]; entry != nil; i, entry = i+1, posix.environ[i] {
  64. key := strings.truncate_to_byte(string(entry), '=')
  65. _unset_env(key)
  66. }
  67. }
  68. _environ :: proc(allocator: runtime.Allocator) -> (environ: []string, err: Error) {
  69. n := 0
  70. for entry := posix.environ[0]; entry != nil; n, entry = n+1, posix.environ[n] {}
  71. r := make([dynamic]string, 0, n, allocator) or_return
  72. defer if err != nil {
  73. for e in r {
  74. delete(e, allocator)
  75. }
  76. delete(r)
  77. }
  78. for i, entry := 0, posix.environ[0]; entry != nil; i, entry = i+1, posix.environ[i] {
  79. append(&r, strings.clone(string(entry), allocator) or_return)
  80. }
  81. environ = r[:]
  82. return
  83. }