diff options
author | Brad Fitzpatrick <bradfitz@golang.org> | 2014-10-01 11:17:15 -0700 |
---|---|---|
committer | Brad Fitzpatrick <bradfitz@golang.org> | 2014-10-01 11:17:15 -0700 |
commit | 85cdc49e8abed5c48d9b24eedff85e44e38269b9 (patch) | |
tree | 7b3433248b7b481c281ddba1bbf70c3b6851c4d6 /src/syscall/env_unix.go | |
parent | 1a1341afed8454c40d86b20aa3950b75c60068ea (diff) | |
download | go-git-85cdc49e8abed5c48d9b24eedff85e44e38269b9.tar.gz |
os, syscall: add Unsetenv
Also address a TODO, making Clearenv pass through to cgo.
Based largely on Minux's earlier https://golang.org/cl/82040044
Fixes #6423
LGTM=iant, alex.brainman, r, rsc
R=rsc, iant, r, alex.brainman
CC=golang-codereviews
https://golang.org/cl/148370043
Diffstat (limited to 'src/syscall/env_unix.go')
-rw-r--r-- | src/syscall/env_unix.go | 44 |
1 files changed, 36 insertions, 8 deletions
diff --git a/src/syscall/env_unix.go b/src/syscall/env_unix.go index 01ac38af13..b5ded9c763 100644 --- a/src/syscall/env_unix.go +++ b/src/syscall/env_unix.go @@ -20,16 +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 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() ) func runtime_envs() []string // in package runtime -// setenv_c is provided by the runtime, but is a no-op if cgo isn't -// loaded. +// 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) @@ -38,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 } @@ -46,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 { @@ -106,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 } |