)
var (
- // envOnce guards initialization by copyenv, which populates env.
+ // envOnce guards copyenv, which populates env.
envOnce sync.Once
// envLock guards env.
envLock sync.RWMutex
// env maps from an environment variable to its value.
- env map[string]string
+ env = make(map[string]string)
+
+ errZeroLengthKey = errors.New("zero length key")
+ errShortWrite = errors.New("i/o count too small")
)
func readenv(key string) (string, error) {
return err
}
defer Close(fd)
- _, err = Write(fd, []byte(value))
- return err
+ b := []byte(value)
+ n, err := Write(fd, b)
+ if err != nil {
+ return err
+ }
+ if n != len(b) {
+ return errShortWrite
+ }
+ return nil
}
func copyenv() {
- env = make(map[string]string)
fd, err := Open("/env", O_RDONLY)
if err != nil {
return
}
func Getenv(key string) (value string, found bool) {
- envOnce.Do(copyenv)
if len(key) == 0 {
return "", false
}
envLock.RLock()
defer envLock.RUnlock()
- v, ok := env[key]
- if !ok {
+ if v, ok := env[key]; ok {
+ return v, true
+ }
+ v, err := readenv(key)
+ if err != nil {
return "", false
}
+ env[key] = v
return v, true
}
func Setenv(key, value string) error {
- envOnce.Do(copyenv)
if len(key) == 0 {
- return errors.New("zero length key")
+ return errZeroLengthKey
}
envLock.Lock()
}
func Clearenv() {
- envOnce.Do(copyenv) // prevent copyenv in Getenv/Setenv
-
envLock.Lock()
defer envLock.Unlock()
}
func Environ() []string {
- envOnce.Do(copyenv)
envLock.RLock()
defer envLock.RUnlock()
+
+ envOnce.Do(copyenv)
a := make([]string, len(env))
i := 0
for k, v := range env {