Initial contribution
diff --git a/src/syscall/env_unix.go b/src/syscall/env_unix.go
new file mode 100644
index 0000000..b5ded9c
--- /dev/null
+++ b/src/syscall/env_unix.go
@@ -0,0 +1,149 @@
+// 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 dragonfly freebsd linux nacl netbsd openbsd solaris
+
+// Unix environment variables.
+
+package syscall
+
+import "sync"
+
+var (
+	// envOnce guards initialization by copyenv, which populates env.
+	envOnce sync.Once
+
+	// envLock guards env and envs.
+	envLock sync.RWMutex
+
+	// env maps from an environment variable to its first occurrence in envs.
+	env map[string]int
+
+	// envs is provided by the runtime. elements are expected to
+	// be of the form "key=value". An empty string means deleted
+	// (or a duplicate to be ignored).
+	envs []string = runtime_envs()
+)
+
+func runtime_envs() []string // in package runtime
+
+// setenv_c and unsetenv_c are provided by the runtime but are no-ops
+// if cgo isn't loaded.
+func setenv_c(k, v string)
+func unsetenv_c(k string)
+
+func copyenv() {
+	env = make(map[string]int)
+	for i, s := range envs {
+		for j := 0; j < len(s); j++ {
+			if s[j] == '=' {
+				key := s[:j]
+				if _, ok := env[key]; !ok {
+					env[key] = i // first mention of key
+				} else {
+					// Clear duplicate keys. This permits Unsetenv to
+					// safely delete only the first item without
+					// worrying about unshadowing a later one,
+					// which might be a security problem.
+					envs[i] = ""
+				}
+				break
+			}
+		}
+	}
+}
+
+func Unsetenv(key string) error {
+	envOnce.Do(copyenv)
+
+	envLock.Lock()
+	defer envLock.Unlock()
+
+	if i, ok := env[key]; ok {
+		envs[i] = ""
+		delete(env, key)
+	}
+	unsetenv_c(key)
+	return nil
+}
+
+func Getenv(key string) (value string, found bool) {
+	envOnce.Do(copyenv)
+	if len(key) == 0 {
+		return "", false
+	}
+
+	envLock.RLock()
+	defer envLock.RUnlock()
+
+	i, ok := env[key]
+	if !ok {
+		return "", false
+	}
+	s := envs[i]
+	for i := 0; i < len(s); i++ {
+		if s[i] == '=' {
+			return s[i+1:], true
+		}
+	}
+	return "", false
+}
+
+func Setenv(key, value string) error {
+	envOnce.Do(copyenv)
+	if len(key) == 0 {
+		return EINVAL
+	}
+	for i := 0; i < len(key); i++ {
+		if key[i] == '=' || key[i] == 0 {
+			return EINVAL
+		}
+	}
+	for i := 0; i < len(value); i++ {
+		if value[i] == 0 {
+			return EINVAL
+		}
+	}
+
+	envLock.Lock()
+	defer envLock.Unlock()
+
+	i, ok := env[key]
+	kv := key + "=" + value
+	if ok {
+		envs[i] = kv
+	} else {
+		i = len(envs)
+		envs = append(envs, kv)
+	}
+	env[key] = i
+	setenv_c(key, value)
+	return nil
+}
+
+func Clearenv() {
+	envOnce.Do(copyenv) // prevent copyenv in Getenv/Setenv
+
+	envLock.Lock()
+	defer envLock.Unlock()
+
+	for k := range env {
+		unsetenv_c(k)
+	}
+	env = make(map[string]int)
+	envs = []string{}
+}
+
+func Environ() []string {
+	envOnce.Do(copyenv)
+	envLock.RLock()
+	defer envLock.RUnlock()
+	a := make([]string, 0, len(envs))
+	for _, env := range envs {
+		if env != "" {
+			a = append(a, env)
+		}
+	}
+	return a
+}