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