Imported Upstream version 4.8.1
[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 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 = make(map[string]string)
23
24         errZeroLengthKey = errors.New("zero length key")
25         errShortWrite    = errors.New("i/o count too small")
26 )
27
28 func readenv(key string) (string, error) {
29         fd, err := Open("/env/"+key, O_RDONLY)
30         if err != nil {
31                 return "", err
32         }
33         defer Close(fd)
34         l, _ := Seek(fd, 0, 2)
35         Seek(fd, 0, 0)
36         buf := make([]byte, l)
37         n, err := Read(fd, buf)
38         if err != nil {
39                 return "", err
40         }
41         if n > 0 && buf[n-1] == 0 {
42                 buf = buf[:n-1]
43         }
44         return string(buf), nil
45 }
46
47 func writeenv(key, value string) error {
48         fd, err := Create("/env/"+key, O_RDWR, 0666)
49         if err != nil {
50                 return err
51         }
52         defer Close(fd)
53         b := []byte(value)
54         n, err := Write(fd, b)
55         if err != nil {
56                 return err
57         }
58         if n != len(b) {
59                 return errShortWrite
60         }
61         return nil
62 }
63
64 func copyenv() {
65         fd, err := Open("/env", O_RDONLY)
66         if err != nil {
67                 return
68         }
69         defer Close(fd)
70         files, err := readdirnames(fd)
71         if err != nil {
72                 return
73         }
74         for _, key := range files {
75                 v, err := readenv(key)
76                 if err != nil {
77                         continue
78                 }
79                 env[key] = v
80         }
81 }
82
83 func Getenv(key string) (value string, found bool) {
84         if len(key) == 0 {
85                 return "", false
86         }
87
88         envLock.RLock()
89         defer envLock.RUnlock()
90
91         if v, ok := env[key]; ok {
92                 return v, true
93         }
94         v, err := readenv(key)
95         if err != nil {
96                 return "", false
97         }
98         env[key] = v
99         return v, true
100 }
101
102 func Setenv(key, value string) error {
103         if len(key) == 0 {
104                 return errZeroLengthKey
105         }
106
107         envLock.Lock()
108         defer envLock.Unlock()
109
110         err := writeenv(key, value)
111         if err != nil {
112                 return err
113         }
114         env[key] = value
115         return nil
116 }
117
118 func Clearenv() {
119         envLock.Lock()
120         defer envLock.Unlock()
121
122         env = make(map[string]string)
123         RawSyscall(SYS_RFORK, RFCENVG, 0, 0)
124 }
125
126 func Environ() []string {
127         envLock.RLock()
128         defer envLock.RUnlock()
129
130         envOnce.Do(copyenv)
131         a := make([]string, len(env))
132         i := 0
133         for k, v := range env {
134                 a[i] = k + "=" + v
135                 i++
136         }
137         return a
138 }