1
0
mirror of https://github.com/golang/go synced 2024-11-19 21:54:40 -07:00

runtime: translate env*.c to Go

In an earlier CL I wrote a separate Go-only version, but that broke Plan 9,
because the Go-only version assumed a non-Plan 9 system.

Translate the real ones instead.

LGTM=r
R=golang-codereviews, r
CC=0intro, golang-codereviews, iant, khr
https://golang.org/cl/140050044
This commit is contained in:
Russ Cox 2014-08-30 14:53:47 -04:00
parent 2fd62a42b4
commit 50199d7b35
9 changed files with 121 additions and 124 deletions

View File

@ -7,4 +7,4 @@
#pragma cgo_import_static x_cgo_setenv #pragma cgo_import_static x_cgo_setenv
void x_cgo_setenv(char**); void x_cgo_setenv(char**);
void (*_cgo_setenv)(char**) = x_cgo_setenv; void (*runtime·_cgo_setenv)(char**) = x_cgo_setenv;

View File

@ -1,42 +0,0 @@
// Copyright 2012 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.
#include "runtime.h"
#include "os_GOOS.h"
byte*
runtime·getenv(int8 *s)
{
int32 fd, n, r;
intgo len;
byte file[128];
byte *p;
static byte b[128];
len = runtime·findnull((byte*)s);
if(len > sizeof file-6)
return nil;
runtime·memclr(file, sizeof file);
runtime·memmove((void*)file, (void*)"/env/", 5);
runtime·memmove((void*)(file+5), (void*)s, len);
fd = runtime·open((int8*)file, OREAD, 0);
if(fd < 0)
return nil;
n = runtime·seek(fd, 0, 2);
if(runtime·strcmp((byte*)s, (byte*)"GOTRACEBACK") == 0){
// should not call malloc
if(n >= sizeof b)
return nil;
runtime·memclr(b, sizeof b);
p = b;
}else
p = runtime·mallocgc(n+1, nil, 0);
r = runtime·pread(fd, p, n, 0);
runtime·close(fd);
if(r < 0)
return nil;
return p;
}

View File

@ -0,0 +1,58 @@
// Copyright 2012 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 runtime
import "unsafe"
func getenv(s *byte) *byte {
val := gogetenv(gostringnocopy(s))
if val == "" {
return nil
}
// Strings found in environment are NUL-terminated.
return &bytes(val)[0]
}
var tracebackbuf [128]byte
func gogetenv(key string) string {
var file [128]byte
if len(key) > len(file)-6 {
return ""
}
copy(file[:], "/env/")
copy(file[5:], key)
fd := open(&file[0], _OREAD, 0)
if fd < 0 {
return ""
}
n := seek(fd, 0, 2)
var p unsafe.Pointer
// Be sure not to allocate for $GOTRACEBACK.
if key == "GOTRACEBACK" {
if n >= 128 {
return ""
}
p = unsafe.Pointer(&tracebackbuf[0])
} else {
p = gomallocgc(uintptr(n+1), nil, 0)
}
r := pread(fd, p, int32(n), 0)
close(fd)
if r < 0 {
return ""
}
var s string
sp := (*_string)(unsafe.Pointer(&s))
sp.str = (*byte)(p)
sp.len = int(r)
return s
}

View File

@ -1,64 +0,0 @@
// Copyright 2012 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 windows
#include "runtime.h"
#include "arch_GOARCH.h"
#include "malloc.h"
Slice syscall·envs;
byte*
runtime·getenv(int8 *s)
{
int32 i, j;
intgo len;
byte *v, *bs;
String* envv;
int32 envc;
bs = (byte*)s;
len = runtime·findnull(bs);
envv = (String*)syscall·envs.array;
if(envv == nil)
runtime·throw("getenv before env init");
envc = syscall·envs.len;
for(i=0; i<envc; i++){
if(envv[i].len <= len)
continue;
v = envv[i].str;
for(j=0; j<len; j++)
if(bs[j] != v[j])
goto nomatch;
if(v[len] != '=')
goto nomatch;
return v+len+1;
nomatch:;
}
return nil;
}
void (*_cgo_setenv)(byte**);
// Update the C environment if cgo is loaded.
// Called from syscall.Setenv.
void
syscall·setenv_c(String k, String v)
{
byte *arg[2];
if(_cgo_setenv == nil)
return;
arg[0] = runtime·mallocgc(k.len + 1, nil, 0);
runtime·memmove(arg[0], k.str, k.len);
arg[0][k.len] = 0;
arg[1] = runtime·mallocgc(v.len + 1, nil, 0);
runtime·memmove(arg[1], v.str, v.len);
arg[1][v.len] = 0;
runtime·asmcgocall((void*)_cgo_setenv, arg);
}

View File

@ -0,0 +1,52 @@
// Copyright 2012 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 windows
package runtime
import "unsafe"
func environ() []string
func getenv(s *byte) *byte {
val := gogetenv(gostringnocopy(s))
if val == "" {
return nil
}
// Strings found in environment are NUL-terminated.
return &bytes(val)[0]
}
func gogetenv(key string) string {
env := environ()
if env == nil {
gothrow("getenv before env init")
}
for _, s := range environ() {
if len(s) > len(key) && s[len(key)] == '=' && s[:len(key)] == key {
return s[len(key)+1:]
}
}
return ""
}
var _cgo_setenv uintptr // pointer to C function
// Update the C environment if cgo is loaded.
// Called from syscall.Setenv.
func syscall_setenv_c(k string, v string) {
if _cgo_setenv == 0 {
return
}
arg := [2]unsafe.Pointer{cstring(k), cstring(v)}
asmcgocall(unsafe.Pointer(_cgo_setenv), unsafe.Pointer(&arg))
}
func cstring(s string) unsafe.Pointer {
p := make([]byte, len(s)+1)
sp := (*_string)(unsafe.Pointer(&s))
memmove(unsafe.Pointer(&p[0]), unsafe.Pointer(sp.str), uintptr(len(s)))
return unsafe.Pointer(&p[0])
}

View File

@ -149,20 +149,6 @@ func Callers(skip int, pc []uintptr) int {
func callers(int32, *uintptr, int32) int32 func callers(int32, *uintptr, int32) int32
func getgoroot() string func getgoroot() string
func environ() []string
func gogetenv(key string) string {
env := environ()
if env == nil {
gothrow("getenv before env init")
}
for _, s := range env {
if len(s) > len(key) && s[len(key)] == '=' && s[:len(key)] == key {
return s[len(key)+1:]
}
}
return ""
}
// GOROOT returns the root of the Go tree. // GOROOT returns the root of the Go tree.
// It uses the GOROOT environment variable, if set, // It uses the GOROOT environment variable, if set,

View File

@ -152,7 +152,6 @@ func tracebackothers(gp *g)
func cgocallback(fn, frame unsafe.Pointer, framesize uintptr) func cgocallback(fn, frame unsafe.Pointer, framesize uintptr)
func gogo(buf *gobuf) func gogo(buf *gobuf)
func gosave(buf *gobuf) func gosave(buf *gobuf)
func open(name *byte, mode, perm int32) int32
func read(fd int32, p unsafe.Pointer, n int32) int32 func read(fd int32, p unsafe.Pointer, n int32) int32
func close(fd int32) int32 func close(fd int32) int32
func mincore(addr unsafe.Pointer, n uintptr, dst *byte) int32 func mincore(addr unsafe.Pointer, n uintptr, dst *byte) int32
@ -162,7 +161,6 @@ func asminit()
func setg(gg *g) func setg(gg *g)
func exit(code int32) func exit(code int32)
func breakpoint() func breakpoint()
func asmcgocall(fn, arg unsafe.Pointer)
func nanotime() int64 func nanotime() int64
func usleep(usec uint32) func usleep(usec uint32)
func cputicks() int64 func cputicks() int64
@ -247,3 +245,9 @@ func getcallerpc(argp unsafe.Pointer) uintptr
//go:noescape //go:noescape
func getcallersp(argp unsafe.Pointer) uintptr func getcallersp(argp unsafe.Pointer) uintptr
//go:noescape
func asmcgocall(fn, arg unsafe.Pointer)
//go:noescape
func open(name *byte, mode, perm int32) int32

View File

@ -36,7 +36,7 @@ TEXT _seek<>(SB),NOSPLIT,$0
// int64 seek(int32, int64, int32) // int64 seek(int32, int64, int32)
// Convenience wrapper around _seek, the actual system call. // Convenience wrapper around _seek, the actual system call.
TEXT runtime·seek(SB),NOSPLIT,$32 TEXT runtime·seek(SB),NOSPLIT,$32
LEAQ $ret+24(FP), AX LEAQ ret+24(FP), AX
MOVL fd+0(FP), BX MOVL fd+0(FP), BX
MOVQ offset+8(FP), CX MOVQ offset+8(FP), CX
MOVL whence+16(FP), DX MOVL whence+16(FP), DX

View File

@ -70,3 +70,6 @@ TEXT reflect·chanrecv(SB), NOSPLIT, $0-0
TEXT runtimedebug·freeOSMemory(SB), NOSPLIT, $0-0 TEXT runtimedebug·freeOSMemory(SB), NOSPLIT, $0-0
JMP runtime·freeOSMemory(SB) JMP runtime·freeOSMemory(SB)
TEXT syscall·setenv_c(SB), NOSPLIT, $0-0
JMP runtime·syscall_setenv_c(SB)