...

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

View as plain text