2014-04-11 Marc Glisse <marc.glisse@inria.fr>
[official-gcc.git] / libgo / go / syscall / env_unix.go
blobf64202ed1102c9ebbcc7a9daa249e500f1105e33
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.
5 // +build darwin dragonfly freebsd linux netbsd openbsd
7 // Unix environment variables.
9 package syscall
11 import "sync"
13 var (
14 // envOnce guards initialization by copyenv, which populates env.
15 envOnce sync.Once
17 // envLock guards env and envs.
18 envLock sync.RWMutex
20 // env maps from an environment variable to its first occurrence in envs.
21 env map[string]int
23 // envs is provided by the runtime. elements are expected to be
24 // of the form "key=value".
25 Envs []string
28 // setenv_c is provided by the runtime, but is a no-op if cgo isn't
29 // loaded.
30 func setenv_c(k, v string)
32 func copyenv() {
33 env = make(map[string]int)
34 for i, s := range Envs {
35 for j := 0; j < len(s); j++ {
36 if s[j] == '=' {
37 key := s[:j]
38 if _, ok := env[key]; !ok {
39 env[key] = i
41 break
47 func Getenv(key string) (value string, found bool) {
48 envOnce.Do(copyenv)
49 if len(key) == 0 {
50 return "", false
53 envLock.RLock()
54 defer envLock.RUnlock()
56 i, ok := env[key]
57 if !ok {
58 return "", false
60 s := Envs[i]
61 for i := 0; i < len(s); i++ {
62 if s[i] == '=' {
63 return s[i+1:], true
66 return "", false
69 func Setenv(key, value string) error {
70 envOnce.Do(copyenv)
71 if len(key) == 0 {
72 return EINVAL
74 for i := 0; i < len(key); i++ {
75 if key[i] == '=' || key[i] == 0 {
76 return EINVAL
79 for i := 0; i < len(value); i++ {
80 if value[i] == 0 {
81 return EINVAL
85 envLock.Lock()
86 defer envLock.Unlock()
88 i, ok := env[key]
89 kv := key + "=" + value
90 if ok {
91 Envs[i] = kv
92 } else {
93 i = len(Envs)
94 Envs = append(Envs, kv)
96 env[key] = i
97 setenv_c(key, value)
98 return nil
101 func Clearenv() {
102 envOnce.Do(copyenv) // prevent copyenv in Getenv/Setenv
104 envLock.Lock()
105 defer envLock.Unlock()
107 env = make(map[string]int)
108 Envs = []string{}
109 // TODO(bradfitz): pass through to C
112 func Environ() []string {
113 envOnce.Do(copyenv)
114 envLock.RLock()
115 defer envLock.RUnlock()
116 a := make([]string, len(Envs))
117 copy(a, Envs)
118 return a