mirror of
https://github.com/golang/go
synced 2024-11-21 15:04: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\
|
||||
basic.go\
|
||||
callback.go\
|
||||
env.go\
|
||||
issue1222.go\
|
||||
issue1328.go\
|
||||
issue1560.go\
|
||||
|
@ -25,3 +25,4 @@ func TestZeroArgCallback(t *testing.T) { testZeroArgCallback(t) }
|
||||
func TestBlocking(t *testing.T) { testBlocking(t) }
|
||||
func Test1328(t *testing.T) { test1328(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
|
||||
|
||||
func setenv_c(k, v string)
|
||||
|
||||
// Expand replaces ${var} or $var in the string based on the mapping function.
|
||||
// Invocations of undefined variables are replaced with the empty 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.
|
||||
// It returns the value and an error, if any.
|
||||
func Getenverror(key string) (value string, err Error) {
|
||||
@ -37,6 +39,10 @@ func Getenverror(key string) (value string, err Error) {
|
||||
if len(key) == 0 {
|
||||
return "", EINVAL
|
||||
}
|
||||
|
||||
envLock.RLock()
|
||||
defer envLock.RUnlock()
|
||||
|
||||
v, ok := env[key]
|
||||
if !ok {
|
||||
return "", ENOENV
|
||||
@ -55,24 +61,36 @@ func Getenv(key string) string {
|
||||
// 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 {
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
#include "libcgo.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Stub for calling malloc from Go */
|
||||
static void
|
||||
x_cgo_malloc(void *p)
|
||||
@ -49,3 +51,12 @@ xlibcgo_thread_start(ThreadStart *arg)
|
||||
}
|
||||
|
||||
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)
|
||||
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