...
Run Format

Source file src/syscall/env_unix.go

  // 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 syscall
  
  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". An empty string means deleted
  	// (or a duplicate to be ignored).
  	envs []string = runtime_envs()
  )
  
  func runtime_envs() []string // in package runtime
  
  // 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)
  	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 // 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
  			}
  		}
  	}
  }
  
  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 {
  		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()
  
  	for k := range env {
  		unsetenv_c(k)
  	}
  	env = make(map[string]int)
  	envs = []string{}
  }
  
  func Environ() []string {
  	envOnce.Do(copyenv)
  	envLock.RLock()
  	defer envLock.RUnlock()
  	a := make([]string, 0, len(envs))
  	for _, env := range envs {
  		if env != "" {
  			a = append(a, env)
  		}
  	}
  	return a
  }
  

View as plain text