]> Cypherpunks repositories - gostls13.git/commitdiff
syscall: take over env implementation
authorRuss Cox <rsc@golang.org>
Mon, 14 Nov 2011 19:06:50 +0000 (14:06 -0500)
committerRuss Cox <rsc@golang.org>
Mon, 14 Nov 2011 19:06:50 +0000 (14:06 -0500)
The environment is needed by package time, which
we want not to depend on os (so that os can use
time.Time), so push down into syscall.

Delete syscall.Sleep, now unnecessary.

The package os environment API is preserved;
it is only the implementation that is moving to syscall.

Delete os.Envs, which was undocumented,
uninitialized on Windows and Plan 9, and
not maintained by Setenv and Clearenv.
Code can call os.Environ instead.

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/5370091

23 files changed:
src/pkg/os/Makefile
src/pkg/os/env.go
src/pkg/os/env_plan9.go [deleted file]
src/pkg/os/env_unix.go [deleted file]
src/pkg/os/env_windows.go [deleted file]
src/pkg/os/exec_windows.go
src/pkg/os/file_plan9.go
src/pkg/os/file_unix.go
src/pkg/os/file_windows.go
src/pkg/os/os_test.go
src/pkg/os/proc.go
src/pkg/runtime/proc.c
src/pkg/runtime/runtime.c
src/pkg/syscall/Makefile
src/pkg/syscall/env_plan9.go [new file with mode: 0644]
src/pkg/syscall/env_unix.go [new file with mode: 0644]
src/pkg/syscall/env_windows.go [new file with mode: 0644]
src/pkg/syscall/syscall_bsd.go
src/pkg/syscall/syscall_linux.go
src/pkg/syscall/syscall_plan9.go
src/pkg/syscall/syscall_windows.go
src/pkg/syscall/zsyscall_windows_386.go
src/pkg/syscall/zsyscall_windows_amd64.go

index 8923a8b480237c8ccfae794b1da40c8a8952fa1c..9bb2c0cbf157451bfd791a4787ed2197491a595b 100644 (file)
@@ -20,7 +20,6 @@ GOFILES=\
 GOFILES_freebsd=\
        dir_unix.go\
        error_posix.go\
-       env_unix.go\
        file_posix.go\
        file_unix.go\
        path_unix.go\
@@ -32,7 +31,6 @@ GOFILES_freebsd=\
 GOFILES_darwin=\
        dir_unix.go\
        error_posix.go\
-       env_unix.go\
        file_posix.go\
        file_unix.go\
        path_unix.go\
@@ -44,7 +42,6 @@ GOFILES_darwin=\
 GOFILES_linux=\
        dir_unix.go\
        error_posix.go\
-       env_unix.go\
        file_posix.go\
        file_unix.go\
        path_unix.go\
@@ -56,7 +53,6 @@ GOFILES_linux=\
 GOFILES_openbsd=\
        dir_unix.go\
        error_posix.go\
-       env_unix.go\
        file_posix.go\
        file_unix.go\
        path_unix.go\
@@ -68,7 +64,6 @@ GOFILES_openbsd=\
 GOFILES_windows=\
        dir_windows.go\
        error_posix.go\
-       env_windows.go\
        file_posix.go\
        file_windows.go\
        path_windows.go\
@@ -80,7 +75,6 @@ GOFILES_windows=\
 GOFILES_plan9=\
        dir_plan9.go\
        error_plan9.go\
-       env_plan9.go\
        file_plan9.go\
        path_plan9.go\
        sys_plan9.go\
index 4844fa3e26d61280b500c1deaa567f781016730e..7e3f52502e54ef93afec26e75991de666e19c17c 100644 (file)
@@ -6,7 +6,10 @@
 
 package os
 
-func setenv_c(k, v string)
+import (
+       "errors"
+       "syscall"
+)
 
 // Expand replaces ${var} or $var in the string based on the mapping function.
 // Invocations of undefined variables are replaced with the empty string.
@@ -73,3 +76,47 @@ func getShellName(s string) (string, int) {
        }
        return s[:i], i
 }
+
+// ENOENV is the error indicating that an environment variable does not exist.
+var ENOENV = errors.New("no such environment variable")
+
+// Getenverror retrieves the value of the environment variable named by the key.
+// It returns the value and an error, if any.
+func Getenverror(key string) (value string, err error) {
+       if len(key) == 0 {
+               return "", EINVAL
+       }
+       val, found := syscall.Getenv(key)
+       if !found {
+               return "", ENOENV
+       }
+       return val, nil
+}
+
+// Getenv retrieves the value of the environment variable named by the key.
+// It returns the value, which will be empty if the variable is not present.
+func Getenv(key string) string {
+       v, _ := Getenverror(key)
+       return v
+}
+
+// Setenv sets the value of the environment variable named by the key.
+// It returns an error, if any.
+func Setenv(key, value string) error {
+       err := syscall.Setenv(key, value)
+       if err != nil {
+               return NewSyscallError("setenv", err)
+       }
+       return nil
+}
+
+// Clearenv deletes all environment variables.
+func Clearenv() {
+       syscall.Clearenv()
+}
+
+// Environ returns an array of strings representing the environment,
+// in the form "key=value".
+func Environ() []string {
+       return syscall.Environ()
+}
diff --git a/src/pkg/os/env_plan9.go b/src/pkg/os/env_plan9.go
deleted file mode 100644 (file)
index 286a5fe..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-// 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 os
-
-import (
-       "errors"
-       "syscall"
-)
-
-// ENOENV is the error indicating that an environment variable does not exist.
-var ENOENV = errors.New("no such environment variable")
-
-// Getenverror retrieves the value of the environment variable named by the key.
-// It returns the value and an error, if any.
-func Getenverror(key string) (value string, err error) {
-       if len(key) == 0 {
-               return "", EINVAL
-       }
-       f, e := Open("/env/" + key)
-       if e != nil {
-               return "", ENOENV
-       }
-       defer f.Close()
-
-       l, _ := f.Seek(0, 2)
-       f.Seek(0, 0)
-       buf := make([]byte, l)
-       n, e := f.Read(buf)
-       if e != nil {
-               return "", ENOENV
-       }
-
-       if n > 0 && buf[n-1] == 0 {
-               buf = buf[:n-1]
-       }
-       return string(buf), nil
-}
-
-// Getenv retrieves the value of the environment variable named by the key.
-// It returns the value, which will be empty if the variable is not present.
-func Getenv(key string) string {
-       v, _ := Getenverror(key)
-       return v
-}
-
-// Setenv sets the value of the environment variable named by the key.
-// It returns an error, if any.
-func Setenv(key, value string) error {
-       if len(key) == 0 {
-               return EINVAL
-       }
-
-       f, e := Create("/env/" + key)
-       if e != nil {
-               return e
-       }
-       defer f.Close()
-
-       _, e = f.Write([]byte(value))
-       return nil
-}
-
-// Clearenv deletes all environment variables.
-func Clearenv() {
-       syscall.RawSyscall(syscall.SYS_RFORK, syscall.RFCENVG, 0, 0)
-}
-
-// Environ returns an array of strings representing the environment,
-// in the form "key=value".
-func Environ() []string {
-       env := make([]string, 0, 100)
-
-       f, e := Open("/env")
-       if e != nil {
-               panic(e)
-       }
-       defer f.Close()
-
-       names, e := f.Readdirnames(-1)
-       if e != nil {
-               panic(e)
-       }
-
-       for _, k := range names {
-               if v, e := Getenverror(k); e == nil {
-                       env = append(env, k+"="+v)
-               }
-       }
-       return env[0:len(env)]
-}
-
-// TempDir returns the default directory to use for temporary files.
-func TempDir() string {
-       return "/tmp"
-}
diff --git a/src/pkg/os/env_unix.go b/src/pkg/os/env_unix.go
deleted file mode 100644 (file)
index 01fd9d4..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright 2010 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.
-
-// +build darwin freebsd linux openbsd
-
-// Unix environment variables.
-
-package os
-
-import (
-       "errors"
-       "sync"
-)
-
-// ENOENV is the error indicating that an environment variable does not exist.
-var ENOENV = errors.New("no such environment variable")
-
-var env map[string]string
-var once sync.Once
-
-func copyenv() {
-       env = make(map[string]string)
-       for _, s := range Envs {
-               for j := 0; j < len(s); j++ {
-                       if s[j] == '=' {
-                               env[s[0:j]] = s[j+1:]
-                               break
-                       }
-               }
-       }
-}
-
-var envLock sync.RWMutex
-
-// Getenverror retrieves the value of the environment variable named by the key.
-// It returns the value and an error, if any.
-func Getenverror(key string) (value string, err error) {
-       once.Do(copyenv)
-
-       if len(key) == 0 {
-               return "", EINVAL
-       }
-
-       envLock.RLock()
-       defer envLock.RUnlock()
-
-       v, ok := env[key]
-       if !ok {
-               return "", ENOENV
-       }
-       return v, nil
-}
-
-// Getenv retrieves the value of the environment variable named by the key.
-// It returns the value, which will be empty if the variable is not present.
-func Getenv(key string) string {
-       v, _ := Getenverror(key)
-       return v
-}
-
-// Setenv sets the value of the environment variable named by the key.
-// It returns an error, if any.
-func Setenv(key, value string) error {
-       once.Do(copyenv)
-       if len(key) == 0 {
-               return EINVAL
-       }
-
-       envLock.Lock()
-       defer envLock.Unlock()
-
-       env[key] = value
-       setenv_c(key, value) // is a no-op if cgo isn't loaded
-       return nil
-}
-
-// Clearenv deletes all environment variables.
-func Clearenv() {
-       once.Do(copyenv) // prevent copyenv in Getenv/Setenv
-
-       envLock.Lock()
-       defer envLock.Unlock()
-
-       env = make(map[string]string)
-
-       // TODO(bradfitz): pass through to C
-}
-
-// Environ returns an array of strings representing the environment,
-// in the form "key=value".
-func Environ() []string {
-       once.Do(copyenv)
-       envLock.RLock()
-       defer envLock.RUnlock()
-       a := make([]string, len(env))
-       i := 0
-       for k, v := range env {
-               a[i] = k + "=" + v
-               i++
-       }
-       return a
-}
-
-// TempDir returns the default directory to use for temporary files.
-func TempDir() string {
-       dir := Getenv("TMPDIR")
-       if dir == "" {
-               dir = "/tmp"
-       }
-       return dir
-}
diff --git a/src/pkg/os/env_windows.go b/src/pkg/os/env_windows.go
deleted file mode 100644 (file)
index 88d6697..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright 2010 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.
-
-// Windows environment variables.
-
-package os
-
-import (
-       "errors"
-       "syscall"
-       "unicode/utf16"
-       "unsafe"
-)
-
-// ENOENV is the error indicating that an environment variable does not exist.
-var ENOENV = errors.New("no such environment variable")
-
-// Getenverror retrieves the value of the environment variable named by the key.
-// It returns the value and an error, if any.
-func Getenverror(key string) (value string, err error) {
-       b := make([]uint16, 100)
-       n, e := syscall.GetEnvironmentVariable(syscall.StringToUTF16Ptr(key), &b[0], uint32(len(b)))
-       if n == 0 && e == syscall.ERROR_ENVVAR_NOT_FOUND {
-               return "", ENOENV
-       }
-       if n > uint32(len(b)) {
-               b = make([]uint16, n)
-               n, e = syscall.GetEnvironmentVariable(syscall.StringToUTF16Ptr(key), &b[0], uint32(len(b)))
-               if n > uint32(len(b)) {
-                       n = 0
-               }
-       }
-       if n == 0 {
-               return "", NewSyscallError("GetEnvironmentVariable", e)
-       }
-       return string(utf16.Decode(b[0:n])), nil
-}
-
-// Getenv retrieves the value of the environment variable named by the key.
-// It returns the value, which will be empty if the variable is not present.
-func Getenv(key string) string {
-       v, _ := Getenverror(key)
-       return v
-}
-
-// Setenv sets the value of the environment variable named by the key.
-// It returns an error, if any.
-func Setenv(key, value string) error {
-       var v *uint16
-       if len(value) > 0 {
-               v = syscall.StringToUTF16Ptr(value)
-       }
-       e := syscall.SetEnvironmentVariable(syscall.StringToUTF16Ptr(key), v)
-       if e != nil {
-               return NewSyscallError("SetEnvironmentVariable", e)
-       }
-       return nil
-}
-
-// Clearenv deletes all environment variables.
-func Clearenv() {
-       for _, s := range Environ() {
-               // Environment variables can begin with =
-               // so start looking for the separator = at j=1.
-               // http://blogs.msdn.com/b/oldnewthing/archive/2010/05/06/10008132.aspx
-               for j := 1; j < len(s); j++ {
-                       if s[j] == '=' {
-                               Setenv(s[0:j], "")
-                               break
-                       }
-               }
-       }
-}
-
-// Environ returns an array of strings representing the environment,
-// in the form "key=value".
-func Environ() []string {
-       s, e := syscall.GetEnvironmentStrings()
-       if e != nil {
-               return nil
-       }
-       defer syscall.FreeEnvironmentStrings(s)
-       r := make([]string, 0, 50) // Empty with room to grow.
-       for from, i, p := 0, 0, (*[1 << 24]uint16)(unsafe.Pointer(s)); true; i++ {
-               if p[i] == 0 {
-                       // empty string marks the end
-                       if i <= from {
-                               break
-                       }
-                       r = append(r, string(utf16.Decode(p[from:i])))
-                       from = i + 1
-               }
-       }
-       return r
-}
-
-// TempDir returns the default directory to use for temporary files.
-func TempDir() string {
-       const pathSep = '\\'
-       dirw := make([]uint16, syscall.MAX_PATH)
-       n, _ := syscall.GetTempPath(uint32(len(dirw)), &dirw[0])
-       if n > uint32(len(dirw)) {
-               dirw = make([]uint16, n)
-               n, _ = syscall.GetTempPath(uint32(len(dirw)), &dirw[0])
-               if n > uint32(len(dirw)) {
-                       n = 0
-               }
-       }
-       if n > 0 && dirw[n-1] == pathSep {
-               n--
-       }
-       return string(utf16.Decode(dirw[0:n]))
-}
-
-func init() {
-       var argc int32
-       cmd := syscall.GetCommandLine()
-       argv, e := syscall.CommandLineToArgv(cmd, &argc)
-       if e != nil {
-               return
-       }
-       defer syscall.LocalFree(syscall.Handle(uintptr(unsafe.Pointer(argv))))
-       Args = make([]string, argc)
-       for i, v := range (*argv)[:argc] {
-               Args[i] = string(syscall.UTF16ToString((*v)[:]))
-       }
-}
index f24580d15c9df29cec9c1b64ff899e08b253f516..46adb050d8b272b62c7cde3c2509bb300074c5de 100644 (file)
@@ -65,3 +65,17 @@ func FindProcess(pid int) (p *Process, err error) {
        }
        return newProcess(pid, int(h)), nil
 }
+
+func init() {
+       var argc int32
+       cmd := GetCommandLine()
+       argv, e := CommandLineToArgv(cmd, &argc)
+       if e != nil {
+               return
+       }
+       defer LocalFree(Handle(uintptr(unsafe.Pointer(argv))))
+       Args = make([]string, argc)
+       for i, v := range (*argv)[:argc] {
+               Args[i] = string(UTF16ToString((*v)[:]))
+       }
+}
index ecdd5d51efa342da437afa206de87a6932257506..15d66813a207ceb10a9fccaba52acabf5c167b90 100644 (file)
@@ -329,3 +329,8 @@ func Lchown(name string, uid, gid int) error {
 func (f *File) Chown(uid, gid int) error {
        return EPLAN9
 }
+
+// TempDir returns the default directory to use for temporary files.
+func TempDir() string {
+       return "/tmp"
+}
index 140c93d8f24038357bb715fccd6b945d82891e71..d8fcb22ae1be955ef4af6abdd4e8f888faf85193 100644 (file)
@@ -241,3 +241,12 @@ func Pipe() (r *File, w *File, err error) {
 
        return NewFile(p[0], "|0"), NewFile(p[1], "|1"), nil
 }
+
+// TempDir returns the default directory to use for temporary files.
+func TempDir() string {
+       dir := Getenv("TMPDIR")
+       if dir == "" {
+               dir = "/tmp"
+       }
+       return dir
+}
index 7dae46b212249273971541b6f044c6dd2e1a1935..fef868c68e62361ebae392cf5670019f7ff44dd3 100644 (file)
@@ -283,3 +283,21 @@ func Pipe() (r *File, w *File, err error) {
 
        return NewFile(p[0], "|0"), NewFile(p[1], "|1"), nil
 }
+
+// TempDir returns the default directory to use for temporary files.
+func TempDir() string {
+       const pathSep = '\\'
+       dirw := make([]uint16, MAX_PATH)
+       n, _ := syscall.GetTempPath(uint32(len(dirw)), &dirw[0])
+       if n > uint32(len(dirw)) {
+               dirw = make([]uint16, n)
+               n, _ = syscall.GetTempPath(uint32(len(dirw)), &dirw[0])
+               if n > uint32(len(dirw)) {
+                       n = 0
+               }
+       }
+       if n > 0 && dirw[n-1] == pathSep {
+               n--
+       }
+       return string(utf16.Decode(dirw[0:n]))
+}
index 16b41f7b6659c97912cd025e99477a053c4edbca..1b6cb8028c2532e3ecf0597b8db6ef9f76abaf75 100644 (file)
@@ -18,7 +18,7 @@ import (
 
 var dot = []string{
        "dir_unix.go",
-       "env_unix.go",
+       "env.go",
        "error.go",
        "file.go",
        "os_test.go",
index d21f849f21085d12106f0278507f739be2faf6e2..0ef6e411c314e48e9d87f6dfc3290a447e52a798 100644 (file)
@@ -8,8 +8,8 @@ package os
 
 import "syscall"
 
-var Args []string // provided by runtime
-var Envs []string // provided by runtime
+// Args is the command-line arguments, starting with the program name.
+var Args []string
 
 // Getuid returns the numeric user id of the caller.
 func Getuid() int { return syscall.Getuid() }
index 0b925fd52527683bd7be55a26799ff4d1e22ea75..8f4d1ffb4c6f94786094a2346072420dd1ebec4c 100644 (file)
@@ -1723,9 +1723,9 @@ runtime·setcpuprofilerate(void (*fn)(uintptr*, int32), int32 hz)
 void (*libcgo_setenv)(byte**);
 
 // Update the C environment if cgo is loaded.
-// Called from os.Setenv.
+// Called from syscall.Setenv.
 void
-os·setenv_c(String k, String v)
+syscall·setenv_c(String k, String v)
 {
        byte *arg[2];
 
index a82e8b6b4908685939c103b4c889a3c93b6dbecc..a609a26f80f4ec4a0097780aeca40c08012bcb51 100644 (file)
@@ -172,7 +172,7 @@ static int32        argc;
 static uint8** argv;
 
 Slice os·Args;
-Slice os·Envs;
+Slice syscall·envs;
 
 void
 runtime·args(int32 c, uint8 **v)
@@ -214,9 +214,9 @@ runtime·goenvs_unix(void)
        s = runtime·malloc(n*sizeof s[0]);
        for(i=0; i<n; i++)
                s[i] = runtime·gostringnocopy(argv[argc+1+i]);
-       os·Envs.array = (byte*)s;
-       os·Envs.len = n;
-       os·Envs.cap = n;
+       syscall·envs.array = (byte*)s;
+       syscall·envs.len = n;
+       syscall·envs.cap = n;
 }
 
 byte*
@@ -229,8 +229,8 @@ runtime·getenv(int8 *s)
 
        bs = (byte*)s;
        len = runtime·findnull(bs);
-       envv = (String*)os·Envs.array;
-       envc = os·Envs.len;
+       envv = (String*)syscall·envs.array;
+       envc = syscall·envs.len;
        for(i=0; i<envc; i++){
                if(envv[i].len <= len)
                        continue;
index 2c4579ff082adb77bf5abb1d58680a9754186554..3b4bbedf131b366e7e1ff57852bf9db408b9b547 100644 (file)
@@ -18,6 +18,7 @@ GOFILES=\
 
 GOFILES_freebsd=\
        bpf_bsd.go\
+       env_unix.go\
        exec_unix.go\
        route_bsd.go\
        route_freebsd.go\
@@ -27,6 +28,7 @@ GOFILES_freebsd=\
 
 GOFILES_darwin=\
        bpf_bsd.go\
+       env_unix.go\
        exec_unix.go\
        route_bsd.go\
        route_darwin.go\
@@ -35,6 +37,7 @@ GOFILES_darwin=\
        syscall_unix.go\
 
 GOFILES_linux=\
+       env_unix.go\
        exec_unix.go\
        lsf_linux.go\
        netlink_linux.go\
@@ -44,6 +47,7 @@ GOFILES_linux=\
 
 GOFILES_openbsd=\
        bpf_bsd.go\
+       env_unix.go\
        exec_unix.go\
        route_bsd.go\
        route_openbsd.go\
@@ -52,12 +56,14 @@ GOFILES_openbsd=\
        syscall_unix.go\
 
 GOFILES_windows=\
+       env_windows.go\
        exec_windows.go\
        dll_windows.go\
        zerrors_windows.go\
        ztypes_windows.go\
 
 GOFILES_plan9=\
+       env_plan9.go\
        exec_plan9.go\
 
 OFILES=\
diff --git a/src/pkg/syscall/env_plan9.go b/src/pkg/syscall/env_plan9.go
new file mode 100644 (file)
index 0000000..7a6ea90
--- /dev/null
@@ -0,0 +1,74 @@
+// 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"
+
+func Getenv(key string) (value string, found bool) {
+       if len(key) == 0 {
+               return "", EINVAL
+       }
+       f, e := Open("/env/" + key)
+       if e != nil {
+               return "", ENOENV
+       }
+       defer f.Close()
+
+       l, _ := f.Seek(0, 2)
+       f.Seek(0, 0)
+       buf := make([]byte, l)
+       n, e := f.Read(buf)
+       if e != nil {
+               return "", ENOENV
+       }
+
+       if n > 0 && buf[n-1] == 0 {
+               buf = buf[:n-1]
+       }
+       return string(buf), nil
+}
+
+func Setenv(key, value string) error {
+       if len(key) == 0 {
+               return EINVAL
+       }
+
+       f, e := Create("/env/" + key)
+       if e != nil {
+               return e
+       }
+       defer f.Close()
+
+       _, e = f.Write([]byte(value))
+       return nil
+}
+
+func Clearenv() {
+       RawSyscall(SYS_RFORK, RFCENVG, 0, 0)
+}
+
+func Environ() []string {
+       env := make([]string, 0, 100)
+
+       f, e := Open("/env")
+       if e != nil {
+               panic(e)
+       }
+       defer f.Close()
+
+       names, e := f.Readdirnames(-1)
+       if e != nil {
+               panic(e)
+       }
+
+       for _, k := range names {
+               if v, ok := Getenv(k); ok {
+                       env = append(env, k+"="+v)
+               }
+       }
+       return env[0:len(env)]
+}
diff --git a/src/pkg/syscall/env_unix.go b/src/pkg/syscall/env_unix.go
new file mode 100644 (file)
index 0000000..94a6471
--- /dev/null
@@ -0,0 +1,85 @@
+// Copyright 2010 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.
+
+// +build darwin freebsd linux openbsd
+
+// Unix environment variables.
+
+package syscall
+
+import "sync"
+
+var env map[string]string
+var envOnce sync.Once
+var envs []string // provided by runtime
+
+func setenv_c(k, v string)
+
+func copyenv() {
+       env = make(map[string]string)
+       for _, s := range envs {
+               for j := 0; j < len(s); j++ {
+                       if s[j] == '=' {
+                               env[s[0:j]] = s[j+1:]
+                               break
+                       }
+               }
+       }
+}
+
+var envLock sync.RWMutex
+
+func Getenv(key string) (value string, found bool) {
+       envOnce.Do(copyenv)
+       if len(key) == 0 {
+               return "", false
+       }
+
+       envLock.RLock()
+       defer envLock.RUnlock()
+
+       v, ok := env[key]
+       if !ok {
+               return "", false
+       }
+       return v, true
+}
+
+func Setenv(key, value string) error {
+       envOnce.Do(copyenv)
+       if len(key) == 0 {
+               return EINVAL
+       }
+
+       envLock.Lock()
+       defer envLock.Unlock()
+
+       env[key] = value
+       setenv_c(key, value) // is a no-op if cgo isn't loaded
+       return nil
+}
+
+func Clearenv() {
+       envOnce.Do(copyenv) // prevent copyenv in Getenv/Setenv
+
+       envLock.Lock()
+       defer envLock.Unlock()
+
+       env = make(map[string]string)
+
+       // TODO(bradfitz): pass through to C
+}
+
+func Environ() []string {
+       envOnce.Do(copyenv)
+       envLock.RLock()
+       defer envLock.RUnlock()
+       a := make([]string, len(env))
+       i := 0
+       for k, v := range env {
+               a[i] = k + "=" + v
+               i++
+       }
+       return a
+}
diff --git a/src/pkg/syscall/env_windows.go b/src/pkg/syscall/env_windows.go
new file mode 100644 (file)
index 0000000..8c1c427
--- /dev/null
@@ -0,0 +1,78 @@
+// Copyright 2010 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.
+
+// Windows environment variables.
+
+package syscall
+
+import (
+       "errors"
+       "unicode/utf16"
+       "unsafe"
+)
+
+func Getenv(key string) (value string, found bool) {
+       b := make([]uint16, 100)
+       n, e := GetEnvironmentVariable(StringToUTF16Ptr(key), &b[0], uint32(len(b)))
+       if n == 0 && e == ERROR_ENVVAR_NOT_FOUND {
+               return "", false
+       }
+       if n > uint32(len(b)) {
+               b = make([]uint16, n)
+               n, e = GetEnvironmentVariable(StringToUTF16Ptr(key), &b[0], uint32(len(b)))
+               if n > uint32(len(b)) {
+                       n = 0
+               }
+       }
+       if n == 0 {
+               return "", false
+       }
+       return string(utf16.Decode(b[0:n])), true
+}
+
+func Setenv(key, value string) error {
+       var v *uint16
+       if len(value) > 0 {
+               v = StringToUTF16Ptr(value)
+       }
+       e := SetEnvironmentVariable(StringToUTF16Ptr(key), v)
+       if e != nil {
+               return e
+       }
+       return nil
+}
+
+func Clearenv() {
+       for _, s := range Environ() {
+               // Environment variables can begin with =
+               // so start looking for the separator = at j=1.
+               // http://blogs.msdn.com/b/oldnewthing/archive/2010/05/06/10008132.aspx
+               for j := 1; j < len(s); j++ {
+                       if s[j] == '=' {
+                               Setenv(s[0:j], "")
+                               break
+                       }
+               }
+       }
+}
+
+func Environ() []string {
+       s, e := GetEnvironmentStrings()
+       if e != nil {
+               return nil
+       }
+       defer FreeEnvironmentStrings(s)
+       r := make([]string, 0, 50) // Empty with room to grow.
+       for from, i, p := 0, 0, (*[1 << 24]uint16)(unsafe.Pointer(s)); true; i++ {
+               if p[i] == 0 {
+                       // empty string marks the end
+                       if i <= from {
+                               break
+                       }
+                       r = append(r, string(utf16.Decode(p[from:i])))
+                       from = i + 1
+               }
+       }
+       return r
+}
index 9d02d127f21e046435011b40e7b1fe01e10a4fe0..c8ffd09d588b5a96b8be73d75bc23b1e1a413187 100644 (file)
@@ -137,11 +137,6 @@ func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int,
        return
 }
 
-func Sleep(ns int64) (err error) {
-       tv := NsecToTimeval(ns)
-       return Select(0, nil, nil, nil, &tv)
-}
-
 //sys  accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error)
 //sys  bind(s int, addr uintptr, addrlen _Socklen) (err error)
 //sys  connect(s int, addr uintptr, addrlen _Socklen) (err error)
index 52a7dc26bfb50268ec03463c108c2fbd6e3aa1b1..bae7f20e1ccabff532e75b71128c635945ae30ba 100644 (file)
@@ -184,12 +184,6 @@ func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int,
        return
 }
 
-func Sleep(nsec int64) (err error) {
-       tv := NsecToTimeval(nsec)
-       _, err = Select(0, nil, nil, nil, &tv)
-       return err
-}
-
 func Mkfifo(path string, mode uint32) (err error) {
        return Mknod(path, mode|S_IFIFO, 0)
 }
index 0409a040d936e56587c0f8956af54ba48d79163d..2005d812a5262b0741d908e1c6525202a55ec369 100644 (file)
@@ -163,11 +163,6 @@ func Pipe(p []int) (err Error) {
        return
 }
 
-//sys  sleep(millisecs int32) (err Error)
-func Sleep(nsec int64) (err Error) {
-       return sleep(int32((nsec + 999) / 1e6)) // round up to microsecond
-}
-
 // Underlying system call writes to newoffset via pointer.
 // Implemented in assembly to avoid allocation.
 func seek(placeholder uintptr, fd int, offset int64, whence int) (newoffset int64, err string)
index db8d3bc21efcc1c389ac5deac1236d978314e839..2c0cc5401f69f1ca9691a206d28410b6a027dd1f 100644 (file)
@@ -110,7 +110,6 @@ func NewCallback(fn interface{}) uintptr
 //sys  GetComputerName(buf *uint16, n *uint32) (err error) = GetComputerNameW
 //sys  SetEndOfFile(handle Handle) (err error)
 //sys  GetSystemTimeAsFileTime(time *Filetime)
-//sys  sleep(msec uint32) = Sleep
 //sys  GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, err error) [failretval==0xffffffff]
 //sys  CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (handle Handle, err error)
 //sys  GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (err error)
index 57010243e7445276972f4cd2db2e953db39fffd8..7970d3e050d4030f8d2d870df36afce6f5b7ddc2 100644 (file)
@@ -41,7 +41,6 @@ var (
        procGetComputerNameW            = modkernel32.NewProc("GetComputerNameW")
        procSetEndOfFile                = modkernel32.NewProc("SetEndOfFile")
        procGetSystemTimeAsFileTime     = modkernel32.NewProc("GetSystemTimeAsFileTime")
-       procSleep                       = modkernel32.NewProc("Sleep")
        procGetTimeZoneInformation      = modkernel32.NewProc("GetTimeZoneInformation")
        procCreateIoCompletionPort      = modkernel32.NewProc("CreateIoCompletionPort")
        procGetQueuedCompletionStatus   = modkernel32.NewProc("GetQueuedCompletionStatus")
@@ -427,11 +426,6 @@ func GetSystemTimeAsFileTime(time *Filetime) {
        return
 }
 
-func sleep(msec uint32) {
-       Syscall(procSleep.Addr(), 1, uintptr(msec), 0, 0)
-       return
-}
-
 func GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, err error) {
        r0, _, e1 := Syscall(procGetTimeZoneInformation.Addr(), 1, uintptr(unsafe.Pointer(tzi)), 0, 0)
        rc = uint32(r0)
index 56d4399158a03c5cd3f3cf3c1ab263d3afb04c1d..49c5fb0fe95347bf511a547253b251f6bd675ec1 100644 (file)
@@ -41,7 +41,6 @@ var (
        procGetComputerNameW            = modkernel32.NewProc("GetComputerNameW")
        procSetEndOfFile                = modkernel32.NewProc("SetEndOfFile")
        procGetSystemTimeAsFileTime     = modkernel32.NewProc("GetSystemTimeAsFileTime")
-       procSleep                       = modkernel32.NewProc("Sleep")
        procGetTimeZoneInformation      = modkernel32.NewProc("GetTimeZoneInformation")
        procCreateIoCompletionPort      = modkernel32.NewProc("CreateIoCompletionPort")
        procGetQueuedCompletionStatus   = modkernel32.NewProc("GetQueuedCompletionStatus")
@@ -427,11 +426,6 @@ func GetSystemTimeAsFileTime(time *Filetime) {
        return
 }
 
-func sleep(msec uint32) {
-       Syscall(procSleep.Addr(), 1, uintptr(msec), 0, 0)
-       return
-}
-
 func GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, err error) {
        r0, _, e1 := Syscall(procGetTimeZoneInformation.Addr(), 1, uintptr(unsafe.Pointer(tzi)), 0, 0)
        rc = uint32(r0)