2013-12-05 Richard Biener <rguenther@suse.de>
[official-gcc.git] / libgo / go / syscall / env_plan9.go
blob9587ab5af9d21796cb7d73dba70bce3eebdd9b01
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.
5 // Plan 9 environment variables.
7 package syscall
9 import (
10 "errors"
11 "sync"
14 var (
15 // envOnce guards copyenv, which populates env.
16 envOnce sync.Once
18 // envLock guards env and envs.
19 envLock sync.RWMutex
21 // env maps from an environment variable to its value.
22 env = make(map[string]string)
24 // envs contains elements of env in the form "key=value".
25 envs []string
27 errZeroLengthKey = errors.New("zero length key")
28 errShortWrite = errors.New("i/o count too small")
31 func readenv(key string) (string, error) {
32 fd, err := Open("/env/"+key, O_RDONLY)
33 if err != nil {
34 return "", err
36 defer Close(fd)
37 l, _ := Seek(fd, 0, 2)
38 Seek(fd, 0, 0)
39 buf := make([]byte, l)
40 n, err := Read(fd, buf)
41 if err != nil {
42 return "", err
44 if n > 0 && buf[n-1] == 0 {
45 buf = buf[:n-1]
47 return string(buf), nil
50 func writeenv(key, value string) error {
51 fd, err := Create("/env/"+key, O_RDWR, 0666)
52 if err != nil {
53 return err
55 defer Close(fd)
56 b := []byte(value)
57 n, err := Write(fd, b)
58 if err != nil {
59 return err
61 if n != len(b) {
62 return errShortWrite
64 return nil
67 func copyenv() {
68 fd, err := Open("/env", O_RDONLY)
69 if err != nil {
70 return
72 defer Close(fd)
73 files, err := readdirnames(fd)
74 if err != nil {
75 return
77 envs = make([]string, len(files))
78 i := 0
79 for _, key := range files {
80 v, err := readenv(key)
81 if err != nil {
82 continue
84 env[key] = v
85 envs[i] = key + "=" + v
86 i++
90 func Getenv(key string) (value string, found bool) {
91 if len(key) == 0 {
92 return "", false
95 envLock.RLock()
96 defer envLock.RUnlock()
98 if v, ok := env[key]; ok {
99 return v, true
101 v, err := readenv(key)
102 if err != nil {
103 return "", false
105 env[key] = v
106 envs = append(envs, key+"="+v)
107 return v, true
110 func Setenv(key, value string) error {
111 if len(key) == 0 {
112 return errZeroLengthKey
115 envLock.Lock()
116 defer envLock.Unlock()
118 err := writeenv(key, value)
119 if err != nil {
120 return err
122 env[key] = value
123 envs = append(envs, key+"="+value)
124 return nil
127 func Clearenv() {
128 envLock.Lock()
129 defer envLock.Unlock()
131 env = make(map[string]string)
132 envs = []string{}
133 RawSyscall(SYS_RFORK, RFCENVG, 0, 0)
136 func Environ() []string {
137 envLock.RLock()
138 defer envLock.RUnlock()
140 envOnce.Do(copyenv)
141 return append([]string(nil), envs...)