summaryrefslogtreecommitdiff
path: root/libgo/go/syscall/env_unix.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/syscall/env_unix.go')
-rw-r--r--libgo/go/syscall/env_unix.go62
1 files changed, 46 insertions, 16 deletions
diff --git a/libgo/go/syscall/env_unix.go b/libgo/go/syscall/env_unix.go
index f64202ed11..b5ded9c763 100644
--- a/libgo/go/syscall/env_unix.go
+++ b/libgo/go/syscall/env_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly freebsd linux netbsd openbsd
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
// Unix environment variables.
@@ -20,23 +20,33 @@ var (
// env maps from an environment variable to its first occurrence in envs.
env map[string]int
- // envs is provided by the runtime. elements are expected to be
- // of the form "key=value".
- Envs []string
+ // envs is provided by the runtime. elements are expected to
+ // be of the form "key=value". An empty string means deleted
+ // (or a duplicate to be ignored).
+ envs []string = runtime_envs()
)
-// setenv_c is provided by the runtime, but is a no-op if cgo isn't
-// loaded.
+func runtime_envs() []string // in package runtime
+
+// setenv_c and unsetenv_c are provided by the runtime but are no-ops
+// if cgo isn't loaded.
func setenv_c(k, v string)
+func unsetenv_c(k string)
func copyenv() {
env = make(map[string]int)
- for i, s := range Envs {
+ for i, s := range envs {
for j := 0; j < len(s); j++ {
if s[j] == '=' {
key := s[:j]
if _, ok := env[key]; !ok {
- env[key] = i
+ env[key] = i // first mention of key
+ } else {
+ // Clear duplicate keys. This permits Unsetenv to
+ // safely delete only the first item without
+ // worrying about unshadowing a later one,
+ // which might be a security problem.
+ envs[i] = ""
}
break
}
@@ -44,6 +54,20 @@ func copyenv() {
}
}
+func Unsetenv(key string) error {
+ envOnce.Do(copyenv)
+
+ envLock.Lock()
+ defer envLock.Unlock()
+
+ if i, ok := env[key]; ok {
+ envs[i] = ""
+ delete(env, key)
+ }
+ unsetenv_c(key)
+ return nil
+}
+
func Getenv(key string) (value string, found bool) {
envOnce.Do(copyenv)
if len(key) == 0 {
@@ -57,7 +81,7 @@ func Getenv(key string) (value string, found bool) {
if !ok {
return "", false
}
- s := Envs[i]
+ s := envs[i]
for i := 0; i < len(s); i++ {
if s[i] == '=' {
return s[i+1:], true
@@ -88,10 +112,10 @@ func Setenv(key, value string) error {
i, ok := env[key]
kv := key + "=" + value
if ok {
- Envs[i] = kv
+ envs[i] = kv
} else {
- i = len(Envs)
- Envs = append(Envs, kv)
+ i = len(envs)
+ envs = append(envs, kv)
}
env[key] = i
setenv_c(key, value)
@@ -104,16 +128,22 @@ func Clearenv() {
envLock.Lock()
defer envLock.Unlock()
+ for k := range env {
+ unsetenv_c(k)
+ }
env = make(map[string]int)
- Envs = []string{}
- // TODO(bradfitz): pass through to C
+ envs = []string{}
}
func Environ() []string {
envOnce.Do(copyenv)
envLock.RLock()
defer envLock.RUnlock()
- a := make([]string, len(Envs))
- copy(a, Envs)
+ a := make([]string, 0, len(envs))
+ for _, env := range envs {
+ if env != "" {
+ a = append(a, env)
+ }
+ }
return a
}