Source file src/pkg/syscall/env_unix.go
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 // +build darwin freebsd linux netbsd openbsd
6
7 // Unix environment variables.
8
9 package syscall
10
11 import "sync"
12
13 var (
14 // envOnce guards initialization by copyenv, which populates env.
15 envOnce sync.Once
16
17 // envLock guards env and envs.
18 envLock sync.RWMutex
19
20 // env maps from an environment variable to its first occurrence in envs.
21 env map[string]int
22
23 // envs is provided by the runtime. elements are expected to be
24 // of the form "key=value".
25 envs []string
26 )
27
28 // setenv_c is provided by the runtime, but is a no-op if cgo isn't
29 // loaded.
30 func setenv_c(k, v string)
31
32 func copyenv() {
33 env = make(map[string]int)
34 for i, s := range envs {
35 for j := 0; j < len(s); j++ {
36 if s[j] == '=' {
37 key := s[:j]
38 if _, ok := env[key]; !ok {
39 env[key] = i
40 }
41 break
42 }
43 }
44 }
45 }
46
47 func Getenv(key string) (value string, found bool) {
48 envOnce.Do(copyenv)
49 if len(key) == 0 {
50 return "", false
51 }
52
53 envLock.RLock()
54 defer envLock.RUnlock()
55
56 i, ok := env[key]
57 if !ok {
58 return "", false
59 }
60 s := envs[i]
61 for i := 0; i < len(s); i++ {
62 if s[i] == '=' {
63 return s[i+1:], true
64 }
65 }
66 return "", false
67 }
68
69 func Setenv(key, value string) error {
70 envOnce.Do(copyenv)
71 if len(key) == 0 {
72 return EINVAL
73 }
74
75 envLock.Lock()
76 defer envLock.Unlock()
77
78 i, ok := env[key]
79 kv := key + "=" + value
80 if ok {
81 envs[i] = kv
82 } else {
83 i = len(envs)
84 envs = append(envs, kv)
85 }
86 env[key] = i
87 setenv_c(key, value)
88 return nil
89 }
90
91 func Clearenv() {
92 envOnce.Do(copyenv) // prevent copyenv in Getenv/Setenv
93
94 envLock.Lock()
95 defer envLock.Unlock()
96
97 env = make(map[string]int)
98 envs = []string{}
99 // TODO(bradfitz): pass through to C
100 }
101
102 func Environ() []string {
103 envOnce.Do(copyenv)
104 envLock.RLock()
105 defer envLock.RUnlock()
106 a := make([]string, len(envs))
107 copy(a, envs)
108 return a
109 }