| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- // 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 darwin dragonfly freebsd linux nacl netbsd openbsd solaris
- // Unix environment variables.
- package unix
- import "sync"
- var (
- // envOnce guards initialization by copyenv, which populates env.
- envOnce sync.Once
- // envLock guards env and envs.
- envLock sync.RWMutex
- // 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
- )
- // setenv_c is provided by the runtime, but is a no-op if cgo isn't
- // loaded.
- func setenv_c(k, v string)
- func copyenv() {
- env = make(map[string]int)
- 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
- }
- break
- }
- }
- }
- }
- func Getenv(key string) (value string, found bool) {
- envOnce.Do(copyenv)
- if len(key) == 0 {
- return "", false
- }
- envLock.RLock()
- defer envLock.RUnlock()
- i, ok := env[key]
- if !ok {
- return "", false
- }
- s := envs[i]
- for i := 0; i < len(s); i++ {
- if s[i] == '=' {
- return s[i+1:], true
- }
- }
- return "", false
- }
- func Setenv(key, value string) error {
- envOnce.Do(copyenv)
- if len(key) == 0 {
- return EINVAL
- }
- for i := 0; i < len(key); i++ {
- if key[i] == '=' || key[i] == 0 {
- return EINVAL
- }
- }
- for i := 0; i < len(value); i++ {
- if value[i] == 0 {
- return EINVAL
- }
- }
- envLock.Lock()
- defer envLock.Unlock()
- i, ok := env[key]
- kv := key + "=" + value
- if ok {
- envs[i] = kv
- } else {
- i = len(envs)
- envs = append(envs, kv)
- }
- env[key] = i
- setenv_c(key, value)
- return nil
- }
- func Clearenv() {
- envOnce.Do(copyenv) // prevent copyenv in Getenv/Setenv
- envLock.Lock()
- defer envLock.Unlock()
- 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)
- return a
- }
|