| // Copyright 2011 The Go Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style | 
 | // license that can be found in the LICENSE file. | 
 |  | 
 | // Plan 9 environment variables. | 
 |  | 
 | package syscall | 
 |  | 
 | import ( | 
 | 	"errors" | 
 | ) | 
 |  | 
 | var ( | 
 | 	errZeroLengthKey = errors.New("zero length key") | 
 | 	errShortWrite    = errors.New("i/o count too small") | 
 | ) | 
 |  | 
 | func readenv(key string) (string, error) { | 
 | 	fd, err := open("/env/"+key, O_RDONLY) | 
 | 	if err != nil { | 
 | 		return "", err | 
 | 	} | 
 | 	defer Close(fd) | 
 | 	l, _ := Seek(fd, 0, 2) | 
 | 	Seek(fd, 0, 0) | 
 | 	buf := make([]byte, l) | 
 | 	n, err := Read(fd, buf) | 
 | 	if err != nil { | 
 | 		return "", err | 
 | 	} | 
 | 	if n > 0 && buf[n-1] == 0 { | 
 | 		buf = buf[:n-1] | 
 | 	} | 
 | 	return string(buf), nil | 
 | } | 
 |  | 
 | func writeenv(key, value string) error { | 
 | 	fd, err := create("/env/"+key, O_RDWR, 0666) | 
 | 	if err != nil { | 
 | 		return err | 
 | 	} | 
 | 	defer Close(fd) | 
 | 	b := []byte(value) | 
 | 	n, err := Write(fd, b) | 
 | 	if err != nil { | 
 | 		return err | 
 | 	} | 
 | 	if n != len(b) { | 
 | 		return errShortWrite | 
 | 	} | 
 | 	return nil | 
 | } | 
 |  | 
 | func Getenv(key string) (value string, found bool) { | 
 | 	if len(key) == 0 { | 
 | 		return "", false | 
 | 	} | 
 | 	v, err := readenv(key) | 
 | 	if err != nil { | 
 | 		return "", false | 
 | 	} | 
 | 	return v, true | 
 | } | 
 |  | 
 | func Setenv(key, value string) error { | 
 | 	if len(key) == 0 { | 
 | 		return errZeroLengthKey | 
 | 	} | 
 | 	err := writeenv(key, value) | 
 | 	if err != nil { | 
 | 		return err | 
 | 	} | 
 | 	return nil | 
 | } | 
 |  | 
 | func Clearenv() { | 
 | 	RawSyscall(SYS_RFORK, RFCENVG, 0, 0) | 
 | } | 
 |  | 
 | func Unsetenv(key string) error { | 
 | 	if len(key) == 0 { | 
 | 		return errZeroLengthKey | 
 | 	} | 
 | 	Remove("/env/" + key) | 
 | 	return nil | 
 | } | 
 |  | 
 | func Environ() []string { | 
 | 	fd, err := open("/env", O_RDONLY) | 
 | 	if err != nil { | 
 | 		return nil | 
 | 	} | 
 | 	defer Close(fd) | 
 | 	files, err := readdirnames(fd) | 
 | 	if err != nil { | 
 | 		return nil | 
 | 	} | 
 | 	ret := make([]string, 0, len(files)) | 
 |  | 
 | 	for _, key := range files { | 
 | 		v, err := readenv(key) | 
 | 		if err != nil { | 
 | 			continue | 
 | 		} | 
 | 		ret = append(ret, key+"="+v) | 
 | 	} | 
 | 	return ret | 
 | } |