Commit 50199d7b authored by Russ Cox's avatar Russ Cox

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
parent 2fd62a42
......@@ -7,4 +7,4 @@
#pragma cgo_import_static x_cgo_setenv
void x_cgo_setenv(char**);
void (*_cgo_setenv)(char**) = x_cgo_setenv;
void (*runtime·_cgo_setenv)(char**) = x_cgo_setenv;
// 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;
}
// 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
}
// 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);
}
// 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])
}
......@@ -149,20 +149,6 @@ func Callers(skip int, pc []uintptr) int {
func callers(int32, *uintptr, int32) int32
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.
// It uses the GOROOT environment variable, if set,
......
......@@ -152,7 +152,6 @@ func tracebackothers(gp *g)
func cgocallback(fn, frame unsafe.Pointer, framesize uintptr)
func gogo(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 close(fd int32) int32
func mincore(addr unsafe.Pointer, n uintptr, dst *byte) int32
......@@ -162,7 +161,6 @@ func asminit()
func setg(gg *g)
func exit(code int32)
func breakpoint()
func asmcgocall(fn, arg unsafe.Pointer)
func nanotime() int64
func usleep(usec uint32)
func cputicks() int64
......@@ -247,3 +245,9 @@ func getcallerpc(argp unsafe.Pointer) uintptr
//go:noescape
func getcallersp(argp unsafe.Pointer) uintptr
//go:noescape
func asmcgocall(fn, arg unsafe.Pointer)
//go:noescape
func open(name *byte, mode, perm int32) int32
......@@ -36,7 +36,7 @@ TEXT _seek<>(SB),NOSPLIT,$0
// int64 seek(int32, int64, int32)
// Convenience wrapper around _seek, the actual system call.
TEXT runtime·seek(SB),NOSPLIT,$32
LEAQ $ret+24(FP), AX
LEAQ ret+24(FP), AX
MOVL fd+0(FP), BX
MOVQ offset+8(FP), CX
MOVL whence+16(FP), DX
......
......@@ -70,3 +70,6 @@ TEXT reflect·chanrecv(SB), NOSPLIT, $0-0
TEXT runtimedebug·freeOSMemory(SB), NOSPLIT, $0-0
JMP runtime·freeOSMemory(SB)
TEXT syscall·setenv_c(SB), NOSPLIT, $0-0
JMP runtime·syscall_setenv_c(SB)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment