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 hurd js,wasm linux nacl netbsd openbsd solaris 6 7// Unix environment variables. 8 9package syscall 10 11import "sync" 12 13var ( 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 29func 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. 33func setenv_c(k, v string) 34func unsetenv_c(k string) 35 36func 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 57func 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 71func 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 93func 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 125func 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 138func 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