env_plan9.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  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. // Plan 9 environment variables.
  5. package plan9
  6. import (
  7. "errors"
  8. "sync"
  9. )
  10. var (
  11. // envOnce guards copyenv, which populates env.
  12. envOnce sync.Once
  13. // envLock guards env and envs.
  14. envLock sync.RWMutex
  15. // env maps from an environment variable to its value.
  16. env = make(map[string]string)
  17. // envs contains elements of env in the form "key=value".
  18. envs []string
  19. errZeroLengthKey = errors.New("zero length key")
  20. errShortWrite = errors.New("i/o count too small")
  21. )
  22. func readenv(key string) (string, error) {
  23. fd, err := open("/env/"+key, O_RDONLY)
  24. if err != nil {
  25. return "", err
  26. }
  27. defer Close(fd)
  28. l, _ := Seek(fd, 0, 2)
  29. Seek(fd, 0, 0)
  30. buf := make([]byte, l)
  31. n, err := Read(fd, buf)
  32. if err != nil {
  33. return "", err
  34. }
  35. if n > 0 && buf[n-1] == 0 {
  36. buf = buf[:n-1]
  37. }
  38. return string(buf), nil
  39. }
  40. func writeenv(key, value string) error {
  41. fd, err := create("/env/"+key, O_RDWR, 0666)
  42. if err != nil {
  43. return err
  44. }
  45. defer Close(fd)
  46. b := []byte(value)
  47. n, err := Write(fd, b)
  48. if err != nil {
  49. return err
  50. }
  51. if n != len(b) {
  52. return errShortWrite
  53. }
  54. return nil
  55. }
  56. func copyenv() {
  57. fd, err := open("/env", O_RDONLY)
  58. if err != nil {
  59. return
  60. }
  61. defer Close(fd)
  62. files, err := readdirnames(fd)
  63. if err != nil {
  64. return
  65. }
  66. envs = make([]string, len(files))
  67. i := 0
  68. for _, key := range files {
  69. v, err := readenv(key)
  70. if err != nil {
  71. continue
  72. }
  73. env[key] = v
  74. envs[i] = key + "=" + v
  75. i++
  76. }
  77. }
  78. // readdirnames returns the names of files inside the directory represented by dirfd.
  79. func readdirnames(dirfd int) (names []string, err error) {
  80. names = make([]string, 0, 100)
  81. var buf [STATMAX]byte
  82. for {
  83. n, e := Read(dirfd, buf[:])
  84. if e != nil {
  85. return nil, e
  86. }
  87. if n == 0 {
  88. break
  89. }
  90. for i := 0; i < n; {
  91. m, _ := gbit16(buf[i:])
  92. m += 2
  93. if m < STATFIXLEN {
  94. return nil, ErrBadStat
  95. }
  96. s, _, ok := gstring(buf[i+41:])
  97. if !ok {
  98. return nil, ErrBadStat
  99. }
  100. names = append(names, s)
  101. i += int(m)
  102. }
  103. }
  104. return
  105. }
  106. func Getenv(key string) (value string, found bool) {
  107. if len(key) == 0 {
  108. return "", false
  109. }
  110. envLock.RLock()
  111. defer envLock.RUnlock()
  112. if v, ok := env[key]; ok {
  113. return v, true
  114. }
  115. v, err := readenv(key)
  116. if err != nil {
  117. return "", false
  118. }
  119. env[key] = v
  120. envs = append(envs, key+"="+v)
  121. return v, true
  122. }
  123. func Setenv(key, value string) error {
  124. if len(key) == 0 {
  125. return errZeroLengthKey
  126. }
  127. envLock.Lock()
  128. defer envLock.Unlock()
  129. err := writeenv(key, value)
  130. if err != nil {
  131. return err
  132. }
  133. env[key] = value
  134. envs = append(envs, key+"="+value)
  135. return nil
  136. }
  137. func Clearenv() {
  138. envLock.Lock()
  139. defer envLock.Unlock()
  140. env = make(map[string]string)
  141. envs = []string{}
  142. RawSyscall(SYS_RFORK, RFCENVG, 0, 0)
  143. }
  144. func Environ() []string {
  145. envLock.RLock()
  146. defer envLock.RUnlock()
  147. envOnce.Do(copyenv)
  148. return append([]string(nil), envs...)
  149. }