1// Copyright 2010 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Windows environment variables.
6
7package syscall
8
9import (
10	"unsafe"
11)
12
13func Getenv(key string) (value string, found bool) {
14	keyp, err := UTF16PtrFromString(key)
15	if err != nil {
16		return "", false
17	}
18	n := uint32(100)
19	for {
20		b := make([]uint16, n)
21		n, err = GetEnvironmentVariable(keyp, &b[0], uint32(len(b)))
22		if n == 0 && err == ERROR_ENVVAR_NOT_FOUND {
23			return "", false
24		}
25		if n <= uint32(len(b)) {
26			return UTF16ToString(b[:n]), true
27		}
28	}
29}
30
31func Setenv(key, value string) error {
32	v, err := UTF16PtrFromString(value)
33	if err != nil {
34		return err
35	}
36	keyp, err := UTF16PtrFromString(key)
37	if err != nil {
38		return err
39	}
40	e := SetEnvironmentVariable(keyp, v)
41	if e != nil {
42		return e
43	}
44	runtimeSetenv(key, value)
45	return nil
46}
47
48func Unsetenv(key string) error {
49	keyp, err := UTF16PtrFromString(key)
50	if err != nil {
51		return err
52	}
53	e := SetEnvironmentVariable(keyp, nil)
54	if e != nil {
55		return e
56	}
57	runtimeUnsetenv(key)
58	return nil
59}
60
61func Clearenv() {
62	for _, s := range Environ() {
63		// Environment variables can begin with =
64		// so start looking for the separator = at j=1.
65		// https://devblogs.microsoft.com/oldnewthing/20100506-00/?p=14133
66		for j := 1; j < len(s); j++ {
67			if s[j] == '=' {
68				Unsetenv(s[0:j])
69				break
70			}
71		}
72	}
73}
74
75func Environ() []string {
76	envp, e := GetEnvironmentStrings()
77	if e != nil {
78		return nil
79	}
80	defer FreeEnvironmentStrings(envp)
81
82	r := make([]string, 0, 50) // Empty with room to grow.
83	const size = unsafe.Sizeof(*envp)
84	for *envp != 0 { // environment block ends with empty string
85		// find NUL terminator
86		end := unsafe.Pointer(envp)
87		for *(*uint16)(end) != 0 {
88			end = unsafe.Add(end, size)
89		}
90
91		entry := unsafe.Slice(envp, (uintptr(end)-uintptr(unsafe.Pointer(envp)))/size)
92		r = append(r, UTF16ToString(entry))
93		envp = (*uint16)(unsafe.Add(end, size))
94	}
95	return r
96}
97