mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			150 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			150 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			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
 | 
						|
}
 |