diff options
Diffstat (limited to 'libgo/go/syscall/env_unix.go')
-rw-r--r-- | libgo/go/syscall/env_unix.go | 62 |
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 } |