mirror of
https://github.com/golang/go
synced 2024-11-21 19:14:44 -07:00
os: make Setenv update C environment variables
Fixes #1569 R=rsc, bradfitzwork CC=golang-dev https://golang.org/cl/4456045
This commit is contained in:
parent
f985638b94
commit
623e7de187
@ -10,6 +10,7 @@ CGOFILES=\
|
|||||||
align.go\
|
align.go\
|
||||||
basic.go\
|
basic.go\
|
||||||
callback.go\
|
callback.go\
|
||||||
|
env.go\
|
||||||
issue1222.go\
|
issue1222.go\
|
||||||
issue1328.go\
|
issue1328.go\
|
||||||
issue1560.go\
|
issue1560.go\
|
||||||
|
@ -25,3 +25,4 @@ func TestZeroArgCallback(t *testing.T) { testZeroArgCallback(t) }
|
|||||||
func TestBlocking(t *testing.T) { testBlocking(t) }
|
func TestBlocking(t *testing.T) { testBlocking(t) }
|
||||||
func Test1328(t *testing.T) { test1328(t) }
|
func Test1328(t *testing.T) { test1328(t) }
|
||||||
func TestParallelSleep(t *testing.T) { testParallelSleep(t) }
|
func TestParallelSleep(t *testing.T) { testParallelSleep(t) }
|
||||||
|
func TestSetEnv(t *testing.T) { testSetEnv(t) }
|
||||||
|
34
misc/cgo/test/env.go
Normal file
34
misc/cgo/test/env.go
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
package cgotest
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <stdlib.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This is really an os package test but here for convenience.
|
||||||
|
func testSetEnv(t *testing.T) {
|
||||||
|
const key = "CGO_OS_TEST_KEY"
|
||||||
|
const val = "CGO_OS_TEST_VALUE"
|
||||||
|
os.Setenv(key, val)
|
||||||
|
keyc := C.CString(key)
|
||||||
|
defer C.free(unsafe.Pointer(keyc))
|
||||||
|
v := C.getenv(keyc)
|
||||||
|
if v == (*C.char)(unsafe.Pointer(uintptr(0))) {
|
||||||
|
t.Fatal("getenv returned NULL")
|
||||||
|
}
|
||||||
|
vs := C.GoString(v)
|
||||||
|
if vs != val {
|
||||||
|
t.Fatalf("getenv() = %q; want %q", vs, val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
package os
|
package os
|
||||||
|
|
||||||
|
func setenv_c(k, v string)
|
||||||
|
|
||||||
// Expand replaces ${var} or $var in the string based on the mapping function.
|
// Expand replaces ${var} or $var in the string based on the mapping function.
|
||||||
// Invocations of undefined variables are replaced with the empty string.
|
// Invocations of undefined variables are replaced with the empty string.
|
||||||
func Expand(s string, mapping func(string) string) string {
|
func Expand(s string, mapping func(string) string) string {
|
||||||
|
@ -29,6 +29,8 @@ func copyenv() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var envLock sync.RWMutex
|
||||||
|
|
||||||
// Getenverror retrieves the value of the environment variable named by the key.
|
// Getenverror retrieves the value of the environment variable named by the key.
|
||||||
// It returns the value and an error, if any.
|
// It returns the value and an error, if any.
|
||||||
func Getenverror(key string) (value string, err Error) {
|
func Getenverror(key string) (value string, err Error) {
|
||||||
@ -37,6 +39,10 @@ func Getenverror(key string) (value string, err Error) {
|
|||||||
if len(key) == 0 {
|
if len(key) == 0 {
|
||||||
return "", EINVAL
|
return "", EINVAL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
envLock.RLock()
|
||||||
|
defer envLock.RUnlock()
|
||||||
|
|
||||||
v, ok := env[key]
|
v, ok := env[key]
|
||||||
if !ok {
|
if !ok {
|
||||||
return "", ENOENV
|
return "", ENOENV
|
||||||
@ -55,24 +61,36 @@ func Getenv(key string) string {
|
|||||||
// It returns an Error, if any.
|
// It returns an Error, if any.
|
||||||
func Setenv(key, value string) Error {
|
func Setenv(key, value string) Error {
|
||||||
once.Do(copyenv)
|
once.Do(copyenv)
|
||||||
|
|
||||||
if len(key) == 0 {
|
if len(key) == 0 {
|
||||||
return EINVAL
|
return EINVAL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
envLock.Lock()
|
||||||
|
defer envLock.Unlock()
|
||||||
|
|
||||||
env[key] = value
|
env[key] = value
|
||||||
|
setenv_c(key, value) // is a no-op if cgo isn't loaded
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clearenv deletes all environment variables.
|
// Clearenv deletes all environment variables.
|
||||||
func Clearenv() {
|
func Clearenv() {
|
||||||
once.Do(copyenv) // prevent copyenv in Getenv/Setenv
|
once.Do(copyenv) // prevent copyenv in Getenv/Setenv
|
||||||
|
|
||||||
|
envLock.Lock()
|
||||||
|
defer envLock.Unlock()
|
||||||
|
|
||||||
env = make(map[string]string)
|
env = make(map[string]string)
|
||||||
|
|
||||||
|
// TODO(bradfitz): pass through to C
|
||||||
}
|
}
|
||||||
|
|
||||||
// Environ returns an array of strings representing the environment,
|
// Environ returns an array of strings representing the environment,
|
||||||
// in the form "key=value".
|
// in the form "key=value".
|
||||||
func Environ() []string {
|
func Environ() []string {
|
||||||
once.Do(copyenv)
|
once.Do(copyenv)
|
||||||
|
envLock.RLock()
|
||||||
|
defer envLock.RUnlock()
|
||||||
a := make([]string, len(env))
|
a := make([]string, len(env))
|
||||||
i := 0
|
i := 0
|
||||||
for k, v := range env {
|
for k, v := range env {
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#include "libcgo.h"
|
#include "libcgo.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
/* Stub for calling malloc from Go */
|
/* Stub for calling malloc from Go */
|
||||||
static void
|
static void
|
||||||
x_cgo_malloc(void *p)
|
x_cgo_malloc(void *p)
|
||||||
@ -49,3 +51,12 @@ xlibcgo_thread_start(ThreadStart *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void (*libcgo_thread_start)(ThreadStart*) = xlibcgo_thread_start;
|
void (*libcgo_thread_start)(ThreadStart*) = xlibcgo_thread_start;
|
||||||
|
|
||||||
|
/* Stub for calling setenv */
|
||||||
|
static void
|
||||||
|
xlibcgo_setenv(char **arg)
|
||||||
|
{
|
||||||
|
setenv(arg[0], arg[1], 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void (*libcgo_setenv)(char**) = xlibcgo_setenv;
|
||||||
|
@ -1343,3 +1343,26 @@ runtime·setcpuprofilerate(void (*fn)(uintptr*, int32), int32 hz)
|
|||||||
if(hz != 0)
|
if(hz != 0)
|
||||||
runtime·resetcpuprofiler(hz);
|
runtime·resetcpuprofiler(hz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void (*libcgo_setenv)(byte**);
|
||||||
|
|
||||||
|
void
|
||||||
|
os·setenv_c(String k, String v)
|
||||||
|
{
|
||||||
|
byte *arg[2];
|
||||||
|
|
||||||
|
if(libcgo_setenv == nil)
|
||||||
|
return;
|
||||||
|
|
||||||
|
arg[0] = runtime·malloc(k.len + 1);
|
||||||
|
runtime·mcpy(arg[0], k.str, k.len);
|
||||||
|
arg[0][k.len] = 0;
|
||||||
|
|
||||||
|
arg[1] = runtime·malloc(v.len + 1);
|
||||||
|
runtime·mcpy(arg[1], v.str, v.len);
|
||||||
|
arg[1][v.len] = 0;
|
||||||
|
|
||||||
|
runtime·asmcgocall(libcgo_setenv, arg);
|
||||||
|
runtime·free(arg[0]);
|
||||||
|
runtime·free(arg[1]);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user