// Copyright 2010 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris plan9// Unix environment variables.package syscallimport ()var (// envOnce guards initialization by copyenv, which populates env.envOncesync.Once// envLock guards env and envs.envLocksync.RWMutex// env maps from an environment variable to its first occurrence in envs.envmap[string]int// 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 () []string// in package runtime// setenv_c and unsetenv_c are provided by the runtime but are no-ops// if cgo isn't loaded.func (, string)func ( string)func () {env = make(map[string]int)for , := rangeenvs {for := 0; < len(); ++ {if [] == '=' { := [:]if , := env[]; ! {env[] = // 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[] = "" }break } } }}func ( string) error {envOnce.Do(copyenv)envLock.Lock()deferenvLock.Unlock()if , := env[]; {envs[] = ""delete(env, ) }unsetenv_c()returnnil}func ( string) ( string, bool) {envOnce.Do(copyenv)iflen() == 0 {return"", false }envLock.RLock()deferenvLock.RUnlock() , := env[]if ! {return"", false } := envs[]for := 0; < len(); ++ {if [] == '=' {return [+1:], true } }return"", false}func (, string) error {envOnce.Do(copyenv)iflen() == 0 {returnEINVAL }for := 0; < len(); ++ {if [] == '=' || [] == 0 {returnEINVAL } }// On Plan 9, null is used as a separator, eg in $path.ifruntime.GOOS != "plan9" {for := 0; < len(); ++ {if [] == 0 {returnEINVAL } } }envLock.Lock()deferenvLock.Unlock() , := env[] := + "=" + if {envs[] = } else { = len(envs)envs = append(envs, ) }env[] = setenv_c(, )returnnil}func () {envOnce.Do(copyenv) // prevent copyenv in Getenv/SetenvenvLock.Lock()deferenvLock.Unlock()for := rangeenv {unsetenv_c() }env = make(map[string]int)envs = []string{}}func () []string {envOnce.Do(copyenv)envLock.RLock()deferenvLock.RUnlock() := make([]string, 0, len(envs))for , := rangeenvs {if != "" { = append(, ) } }return}