summaryrefslogtreecommitdiff
path: root/src/syscall/env_unix.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/syscall/env_unix.go')
-rw-r--r--src/syscall/env_unix.go48
1 files changed, 39 insertions, 9 deletions
diff --git a/src/syscall/env_unix.go b/src/syscall/env_unix.go
index ad354ed05..b5ded9c76 100644
--- a/src/syscall/env_unix.go
+++ b/src/syscall/env_unix.go
@@ -20,14 +20,18 @@ 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)
@@ -36,7 +40,13 @@ func copyenv() {
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 {
@@ -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
}
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
}