env_plan9.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  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. func Getenv(key string) (value string, found bool) {
  79. if len(key) == 0 {
  80. return "", false
  81. }
  82. envLock.RLock()
  83. defer envLock.RUnlock()
  84. if v, ok := env[key]; ok {
  85. return v, true
  86. }
  87. v, err := readenv(key)
  88. if err != nil {
  89. return "", false
  90. }
  91. env[key] = v
  92. envs = append(envs, key+"="+v)
  93. return v, true
  94. }
  95. func Setenv(key, value string) error {
  96. if len(key) == 0 {
  97. return errZeroLengthKey
  98. }
  99. envLock.Lock()
  100. defer envLock.Unlock()
  101. err := writeenv(key, value)
  102. if err != nil {
  103. return err
  104. }
  105. env[key] = value
  106. envs = append(envs, key+"="+value)
  107. return nil
  108. }
  109. func Clearenv() {
  110. envLock.Lock()
  111. defer envLock.Unlock()
  112. env = make(map[string]string)
  113. envs = []string{}
  114. RawSyscall(SYS_RFORK, RFCENVG, 0, 0)
  115. }
  116. func Environ() []string {
  117. envLock.RLock()
  118. defer envLock.RUnlock()
  119. envOnce.Do(copyenv)
  120. return append([]string(nil), envs...)
  121. }