env_windows.odin 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. package os
  2. import win32 "core:sys/windows"
  3. // lookup_env gets the value of the environment variable named by the key
  4. // If the variable is found in the environment the value (which can be empty) is returned and the boolean is true
  5. // Otherwise the returned value will be empty and the boolean will be false
  6. // NOTE: the value will be allocated with the supplied allocator
  7. lookup_env :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) {
  8. if key == "" {
  9. return
  10. }
  11. wkey := win32.utf8_to_wstring(key)
  12. b := make([dynamic]u16, 100, context.temp_allocator)
  13. for {
  14. n := win32.GetEnvironmentVariableW(wkey, raw_data(b), u32(len(b)))
  15. if n == 0 {
  16. err := win32.GetLastError()
  17. if err == u32(ERROR_ENVVAR_NOT_FOUND) {
  18. return "", false
  19. }
  20. }
  21. if n <= u32(len(b)) {
  22. value = win32.utf16_to_utf8(b[:n], allocator)
  23. found = true
  24. return
  25. }
  26. resize(&b, len(b)*2)
  27. }
  28. }
  29. // get_env retrieves the value of the environment variable named by the key
  30. // It returns the value, which will be empty if the variable is not present
  31. // To distinguish between an empty value and an unset value, use lookup_env
  32. // NOTE: the value will be allocated with the supplied allocator
  33. get_env :: proc(key: string, allocator := context.allocator) -> (value: string) {
  34. value, _ = lookup_env(key, allocator)
  35. return
  36. }
  37. // set_env sets the value of the environment variable named by the key
  38. set_env :: proc(key, value: string) -> Errno {
  39. k := win32.utf8_to_wstring(key)
  40. v := win32.utf8_to_wstring(value)
  41. if !win32.SetEnvironmentVariableW(k, v) {
  42. return Errno(win32.GetLastError())
  43. }
  44. return 0
  45. }
  46. // unset_env unsets a single environment variable
  47. unset_env :: proc(key: string) -> Errno {
  48. k := win32.utf8_to_wstring(key)
  49. if !win32.SetEnvironmentVariableW(k, nil) {
  50. return Errno(win32.GetLastError())
  51. }
  52. return 0
  53. }
  54. // environ returns a copy of strings representing the environment, in the form "key=value"
  55. // NOTE: the slice of strings and the strings with be allocated using the supplied allocator
  56. environ :: proc(allocator := context.allocator) -> []string {
  57. envs := cast([^]win32.WCHAR)(win32.GetEnvironmentStringsW())
  58. if envs == nil {
  59. return nil
  60. }
  61. defer win32.FreeEnvironmentStringsW(envs)
  62. r := make([dynamic]string, 0, 50, allocator)
  63. for from, i := 0, 0; true; i += 1 {
  64. if c := envs[i]; c == 0 {
  65. if i <= from {
  66. break
  67. }
  68. append(&r, win32.utf16_to_utf8(envs[from:i], allocator))
  69. from = i + 1
  70. }
  71. }
  72. return r[:]
  73. }
  74. // clear_env deletes all environment variables
  75. clear_env :: proc() {
  76. envs := environ(context.temp_allocator)
  77. for env in envs {
  78. for j in 1..<len(env) {
  79. if env[j] == '=' {
  80. unset_env(env[0:j])
  81. break
  82. }
  83. }
  84. }
  85. }