aboutsummaryrefslogtreecommitdiff
path: root/v_windows/v/vlib/os/environment.c.v
blob: 1b65a27920ed2bb0bd82677286672ecfdfc9c6b8 (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
// Copyright (c) 2019-2021 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
module os

fn C.getenv(&char) &char

// C.GetEnvironmentStringsW & C.FreeEnvironmentStringsW are defined only on windows
fn C.GetEnvironmentStringsW() &u16

fn C.FreeEnvironmentStringsW(&u16) int

// `getenv` returns the value of the environment variable named by the key.
pub fn getenv(key string) string {
	unsafe {
		$if windows {
			s := C._wgetenv(key.to_wide())
			if s == 0 {
				return ''
			}
			return string_from_wide(s)
		} $else {
			s := C.getenv(&char(key.str))
			if s == voidptr(0) {
				return ''
			}
			// NB: C.getenv *requires* that the result be copied.
			return cstring_to_vstring(s)
		}
	}
}

// os.setenv sets the value of an environment variable with `name` to `value`.
pub fn setenv(name string, value string, overwrite bool) int {
	$if windows {
		format := '$name=$value'
		if overwrite {
			unsafe {
				return C._putenv(&char(format.str))
			}
		} else {
			if getenv(name).len == 0 {
				unsafe {
					return C._putenv(&char(format.str))
				}
			}
		}
		return -1
	} $else {
		unsafe {
			return C.setenv(&char(name.str), &char(value.str), overwrite)
		}
	}
}

// os.unsetenv clears an environment variable with `name`.
pub fn unsetenv(name string) int {
	$if windows {
		format := '$name='
		return C._putenv(&char(format.str))
	} $else {
		return C.unsetenv(&char(name.str))
	}
}

// See: https://linux.die.net/man/5/environ for unix platforms.
// See: https://docs.microsoft.com/bg-bg/windows/win32/api/processenv/nf-processenv-getenvironmentstrings
// os.environ returns a map of all the current environment variables

fn unix_environ() &&char {
	// TODO: remove this helper function, when `&&char(C.environ)` works properly
	return voidptr(C.environ)
}

pub fn environ() map[string]string {
	mut res := map[string]string{}
	$if windows {
		mut estrings := C.GetEnvironmentStringsW()
		mut eline := ''
		for c := estrings; *c != 0; {
			eline = unsafe { string_from_wide(c) }
			eq_index := eline.index_byte(`=`)
			if eq_index > 0 {
				res[eline[0..eq_index]] = eline[eq_index + 1..]
			}
			unsafe {
				c = c + eline.len + 1
			}
		}
		C.FreeEnvironmentStringsW(estrings)
	} $else {
		start := unix_environ()
		mut i := 0
		for {
			x := unsafe { start[i] }
			if x == 0 {
				break
			}
			eline := unsafe { cstring_to_vstring(x) }
			eq_index := eline.index_byte(`=`)
			if eq_index > 0 {
				res[eline[0..eq_index]] = eline[eq_index + 1..]
			}
			i++
		}
	}
	return res
}