...

Source file src/syscall/env_unix.go

Documentation: syscall

		 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  //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris || plan9
		 6  // +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris plan9
		 7  
		 8  // Unix environment variables.
		 9  
		10  package syscall
		11  
		12  import (
		13  	"runtime"
		14  	"sync"
		15  )
		16  
		17  var (
		18  	// envOnce guards initialization by copyenv, which populates env.
		19  	envOnce sync.Once
		20  
		21  	// envLock guards env and envs.
		22  	envLock sync.RWMutex
		23  
		24  	// env maps from an environment variable to its first occurrence in envs.
		25  	env map[string]int
		26  
		27  	// envs is provided by the runtime. elements are expected to
		28  	// be of the form "key=value". An empty string means deleted
		29  	// (or a duplicate to be ignored).
		30  	envs []string = runtime_envs()
		31  )
		32  
		33  func runtime_envs() []string // in package runtime
		34  
		35  // setenv_c and unsetenv_c are provided by the runtime but are no-ops
		36  // if cgo isn't loaded.
		37  func setenv_c(k, v string)
		38  func unsetenv_c(k string)
		39  
		40  func copyenv() {
		41  	env = make(map[string]int)
		42  	for i, s := range envs {
		43  		for j := 0; j < len(s); j++ {
		44  			if s[j] == '=' {
		45  				key := s[:j]
		46  				if _, ok := env[key]; !ok {
		47  					env[key] = i // first mention of key
		48  				} else {
		49  					// Clear duplicate keys. This permits Unsetenv to
		50  					// safely delete only the first item without
		51  					// worrying about unshadowing a later one,
		52  					// which might be a security problem.
		53  					envs[i] = ""
		54  				}
		55  				break
		56  			}
		57  		}
		58  	}
		59  }
		60  
		61  func Unsetenv(key string) error {
		62  	envOnce.Do(copyenv)
		63  
		64  	envLock.Lock()
		65  	defer envLock.Unlock()
		66  
		67  	if i, ok := env[key]; ok {
		68  		envs[i] = ""
		69  		delete(env, key)
		70  	}
		71  	unsetenv_c(key)
		72  	return nil
		73  }
		74  
		75  func Getenv(key string) (value string, found bool) {
		76  	envOnce.Do(copyenv)
		77  	if len(key) == 0 {
		78  		return "", false
		79  	}
		80  
		81  	envLock.RLock()
		82  	defer envLock.RUnlock()
		83  
		84  	i, ok := env[key]
		85  	if !ok {
		86  		return "", false
		87  	}
		88  	s := envs[i]
		89  	for i := 0; i < len(s); i++ {
		90  		if s[i] == '=' {
		91  			return s[i+1:], true
		92  		}
		93  	}
		94  	return "", false
		95  }
		96  
		97  func Setenv(key, value string) error {
		98  	envOnce.Do(copyenv)
		99  	if len(key) == 0 {
	 100  		return EINVAL
	 101  	}
	 102  	for i := 0; i < len(key); i++ {
	 103  		if key[i] == '=' || key[i] == 0 {
	 104  			return EINVAL
	 105  		}
	 106  	}
	 107  	// On Plan 9, null is used as a separator, eg in $path.
	 108  	if runtime.GOOS != "plan9" {
	 109  		for i := 0; i < len(value); i++ {
	 110  			if value[i] == 0 {
	 111  				return EINVAL
	 112  			}
	 113  		}
	 114  	}
	 115  
	 116  	envLock.Lock()
	 117  	defer envLock.Unlock()
	 118  
	 119  	i, ok := env[key]
	 120  	kv := key + "=" + value
	 121  	if ok {
	 122  		envs[i] = kv
	 123  	} else {
	 124  		i = len(envs)
	 125  		envs = append(envs, kv)
	 126  	}
	 127  	env[key] = i
	 128  	setenv_c(key, value)
	 129  	return nil
	 130  }
	 131  
	 132  func Clearenv() {
	 133  	envOnce.Do(copyenv) // prevent copyenv in Getenv/Setenv
	 134  
	 135  	envLock.Lock()
	 136  	defer envLock.Unlock()
	 137  
	 138  	for k := range env {
	 139  		unsetenv_c(k)
	 140  	}
	 141  	env = make(map[string]int)
	 142  	envs = []string{}
	 143  }
	 144  
	 145  func Environ() []string {
	 146  	envOnce.Do(copyenv)
	 147  	envLock.RLock()
	 148  	defer envLock.RUnlock()
	 149  	a := make([]string, 0, len(envs))
	 150  	for _, env := range envs {
	 151  		if env != "" {
	 152  			a = append(a, env)
	 153  		}
	 154  	}
	 155  	return a
	 156  }
	 157  

View as plain text