Imported Upstream version 4.7.2
[platform/upstream/gcc48.git] / libgo / go / syscall / env_plan9.go
1 // Copyright 2011 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 // Plan 9 environment variables.
6
7 package syscall
8
9 import (
10         "errors"
11         "sync"
12 )
13
14 var (
15         // envOnce guards initialization by copyenv, which populates env.
16         envOnce sync.Once
17
18         // envLock guards env.
19         envLock sync.RWMutex
20
21         // env maps from an environment variable to its value.
22         env map[string]string
23 )
24
25 func readenv(key string) (string, error) {
26         fd, err := Open("/env/"+key, O_RDONLY)
27         if err != nil {
28                 return "", err
29         }
30         defer Close(fd)
31         l, _ := Seek(fd, 0, 2)
32         Seek(fd, 0, 0)
33         buf := make([]byte, l)
34         n, err := Read(fd, buf)
35         if err != nil {
36                 return "", err
37         }
38         if n > 0 && buf[n-1] == 0 {
39                 buf = buf[:n-1]
40         }
41         return string(buf), nil
42 }
43
44 func writeenv(key, value string) error {
45         fd, err := Create("/env/"+key, O_RDWR, 0666)
46         if err != nil {
47                 return err
48         }
49         defer Close(fd)
50         _, err = Write(fd, []byte(value))
51         return err
52 }
53
54 func copyenv() {
55         env = make(map[string]string)
56         fd, err := Open("/env", O_RDONLY)
57         if err != nil {
58                 return
59         }
60         defer Close(fd)
61         files, err := readdirnames(fd)
62         if err != nil {
63                 return
64         }
65         for _, key := range files {
66                 v, err := readenv(key)
67                 if err != nil {
68                         continue
69                 }
70                 env[key] = v
71         }
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         v, ok := env[key]
84         if !ok {
85                 return "", false
86         }
87         return v, true
88 }
89
90 func Setenv(key, value string) error {
91         envOnce.Do(copyenv)
92         if len(key) == 0 {
93                 return errors.New("zero length key")
94         }
95
96         envLock.Lock()
97         defer envLock.Unlock()
98
99         err := writeenv(key, value)
100         if err != nil {
101                 return err
102         }
103         env[key] = value
104         return nil
105 }
106
107 func Clearenv() {
108         envOnce.Do(copyenv) // prevent copyenv in Getenv/Setenv
109
110         envLock.Lock()
111         defer envLock.Unlock()
112
113         env = make(map[string]string)
114         RawSyscall(SYS_RFORK, RFCENVG, 0, 0)
115 }
116
117 func Environ() []string {
118         envOnce.Do(copyenv)
119         envLock.RLock()
120         defer envLock.RUnlock()
121         a := make([]string, len(env))
122         i := 0
123         for k, v := range env {
124                 a[i] = k + "=" + v
125                 i++
126         }
127         return a
128 }