Source file src/pkg/syscall/env_unix.go
1 // Copyright 2010 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // +build darwin freebsd linux netbsd openbsd 6 7 // Unix environment variables. 8 9 package syscall 10 11 import "sync" 12 13 var ( 14 // envOnce guards initialization by copyenv, which populates env. 15 envOnce sync.Once 16 17 // envLock guards env and envs. 18 envLock sync.RWMutex 19 20 // env maps from an environment variable to its first occurrence in envs. 21 env map[string]int 22 23 // envs is provided by the runtime. elements are expected to be 24 // of the form "key=value". 25 envs []string 26 ) 27 28 // setenv_c is provided by the runtime, but is a no-op if cgo isn't 29 // loaded. 30 func setenv_c(k, v string) 31 32 func copyenv() { 33 env = make(map[string]int) 34 for i, s := range envs { 35 for j := 0; j < len(s); j++ { 36 if s[j] == '=' { 37 key := s[:j] 38 if _, ok := env[key]; !ok { 39 env[key] = i 40 } 41 break 42 } 43 } 44 } 45 } 46 47 func Getenv(key string) (value string, found bool) { 48 envOnce.Do(copyenv) 49 if len(key) == 0 { 50 return "", false 51 } 52 53 envLock.RLock() 54 defer envLock.RUnlock() 55 56 i, ok := env[key] 57 if !ok { 58 return "", false 59 } 60 s := envs[i] 61 for i := 0; i < len(s); i++ { 62 if s[i] == '=' { 63 return s[i+1:], true 64 } 65 } 66 return "", false 67 } 68 69 func Setenv(key, value string) error { 70 envOnce.Do(copyenv) 71 if len(key) == 0 { 72 return EINVAL 73 } 74 75 envLock.Lock() 76 defer envLock.Unlock() 77 78 i, ok := env[key] 79 kv := key + "=" + value 80 if ok { 81 envs[i] = kv 82 } else { 83 i = len(envs) 84 envs = append(envs, kv) 85 } 86 env[key] = i 87 setenv_c(key, value) 88 return nil 89 } 90 91 func Clearenv() { 92 envOnce.Do(copyenv) // prevent copyenv in Getenv/Setenv 93 94 envLock.Lock() 95 defer envLock.Unlock() 96 97 env = make(map[string]int) 98 envs = []string{} 99 // TODO(bradfitz): pass through to C 100 } 101 102 func Environ() []string { 103 envOnce.Do(copyenv) 104 envLock.RLock() 105 defer envLock.RUnlock() 106 a := make([]string, len(envs)) 107 copy(a, envs) 108 return a 109 }