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