library patch: syscall, os environ
This commit is contained in:
@@ -215,6 +215,7 @@ The currently supported libraries include:
|
|||||||
* [c/clang](https://pkg.go.dev/github.com/goplus/llgo/c/clang)
|
* [c/clang](https://pkg.go.dev/github.com/goplus/llgo/c/clang)
|
||||||
* [c/llama2](https://pkg.go.dev/github.com/goplus/llgo/c/llama2)
|
* [c/llama2](https://pkg.go.dev/github.com/goplus/llgo/c/llama2)
|
||||||
* [c/lua](https://pkg.go.dev/github.com/goplus/llgo/c/lua)
|
* [c/lua](https://pkg.go.dev/github.com/goplus/llgo/c/lua)
|
||||||
|
* [c/neco](https://pkg.go.dev/github.com/goplus/llgo/c/neco)
|
||||||
* [c/raylib](https://pkg.go.dev/github.com/goplus/llgo/c/raylib)
|
* [c/raylib](https://pkg.go.dev/github.com/goplus/llgo/c/raylib)
|
||||||
* [c/sqlite](https://pkg.go.dev/github.com/goplus/llgo/c/sqlite)
|
* [c/sqlite](https://pkg.go.dev/github.com/goplus/llgo/c/sqlite)
|
||||||
* [c/zlib](https://pkg.go.dev/github.com/goplus/llgo/c/zlib)
|
* [c/zlib](https://pkg.go.dev/github.com/goplus/llgo/c/zlib)
|
||||||
|
|||||||
31
_demo/osproc/exec.go
Normal file
31
_demo/osproc/exec.go
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("os.Environ:", os.Environ())
|
||||||
|
|
||||||
|
ls := "ls"
|
||||||
|
args := []string{ls, "-l"}
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
ls = "dir"
|
||||||
|
args = []string{ls}
|
||||||
|
}
|
||||||
|
lspath, _ := exec.LookPath(ls)
|
||||||
|
if lspath != "" {
|
||||||
|
ls = lspath
|
||||||
|
}
|
||||||
|
proc, err := os.StartProcess(ls, args, &os.ProcAttr{
|
||||||
|
Files: []*os.File{nil, os.Stdout, os.Stderr},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("os.StartProcess error:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
proc.Wait()
|
||||||
|
}
|
||||||
161
internal/lib/os/env.go
Normal file
161
internal/lib/os/env.go
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
// General environment variables.
|
||||||
|
|
||||||
|
package os
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
/* TODO(xsw):
|
||||||
|
// Expand replaces ${var} or $var in the string based on the mapping function.
|
||||||
|
// For example, os.ExpandEnv(s) is equivalent to os.Expand(s, os.Getenv).
|
||||||
|
func Expand(s string, mapping func(string) string) string {
|
||||||
|
var buf []byte
|
||||||
|
// ${} is all ASCII, so bytes are fine for this operation.
|
||||||
|
i := 0
|
||||||
|
for j := 0; j < len(s); j++ {
|
||||||
|
if s[j] == '$' && j+1 < len(s) {
|
||||||
|
if buf == nil {
|
||||||
|
buf = make([]byte, 0, 2*len(s))
|
||||||
|
}
|
||||||
|
buf = append(buf, s[i:j]...)
|
||||||
|
name, w := getShellName(s[j+1:])
|
||||||
|
if name == "" && w > 0 {
|
||||||
|
// Encountered invalid syntax; eat the
|
||||||
|
// characters.
|
||||||
|
} else if name == "" {
|
||||||
|
// Valid syntax, but $ was not followed by a
|
||||||
|
// name. Leave the dollar character untouched.
|
||||||
|
buf = append(buf, s[j])
|
||||||
|
} else {
|
||||||
|
buf = append(buf, mapping(name)...)
|
||||||
|
}
|
||||||
|
j += w
|
||||||
|
i = j + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if buf == nil {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
return string(buf) + s[i:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExpandEnv replaces ${var} or $var in the string according to the values
|
||||||
|
// of the current environment variables. References to undefined
|
||||||
|
// variables are replaced by the empty string.
|
||||||
|
func ExpandEnv(s string) string {
|
||||||
|
return Expand(s, Getenv)
|
||||||
|
}
|
||||||
|
|
||||||
|
// isShellSpecialVar reports whether the character identifies a special
|
||||||
|
// shell variable such as $*.
|
||||||
|
func isShellSpecialVar(c uint8) bool {
|
||||||
|
switch c {
|
||||||
|
case '*', '#', '$', '@', '!', '?', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// isAlphaNum reports whether the byte is an ASCII letter, number, or underscore.
|
||||||
|
func isAlphaNum(c uint8) bool {
|
||||||
|
return c == '_' || '0' <= c && c <= '9' || 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z'
|
||||||
|
}
|
||||||
|
|
||||||
|
// getShellName returns the name that begins the string and the number of bytes
|
||||||
|
// consumed to extract it. If the name is enclosed in {}, it's part of a ${}
|
||||||
|
// expansion and two more bytes are needed than the length of the name.
|
||||||
|
func getShellName(s string) (string, int) {
|
||||||
|
switch {
|
||||||
|
case s[0] == '{':
|
||||||
|
if len(s) > 2 && isShellSpecialVar(s[1]) && s[2] == '}' {
|
||||||
|
return s[1:2], 3
|
||||||
|
}
|
||||||
|
// Scan to closing brace
|
||||||
|
for i := 1; i < len(s); i++ {
|
||||||
|
if s[i] == '}' {
|
||||||
|
if i == 1 {
|
||||||
|
return "", 2 // Bad syntax; eat "${}"
|
||||||
|
}
|
||||||
|
return s[1:i], i + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", 1 // Bad syntax; eat "${"
|
||||||
|
case isShellSpecialVar(s[0]):
|
||||||
|
return s[0:1], 1
|
||||||
|
}
|
||||||
|
// Scan alphanumerics.
|
||||||
|
var i int
|
||||||
|
for i = 0; i < len(s) && isAlphaNum(s[i]); i++ {
|
||||||
|
}
|
||||||
|
return s[:i], i
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Getenv retrieves the value of the environment variable named by the key.
|
||||||
|
// It returns the value, which will be empty if the variable is not present.
|
||||||
|
// To distinguish between an empty value and an unset value, use LookupEnv.
|
||||||
|
func Getenv(key string) string {
|
||||||
|
v, _ := syscall.Getenv(key)
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO(xsw):
|
||||||
|
func Getenv(key string) string {
|
||||||
|
return c.GoString(os.Getenv(c.AllocaCStr(key)))
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// LookupEnv retrieves the value of the environment variable named
|
||||||
|
// by the key. If the variable is present in the environment the
|
||||||
|
// value (which may be empty) is returned and the boolean is true.
|
||||||
|
// Otherwise the returned value will be empty and the boolean will
|
||||||
|
// be false.
|
||||||
|
func LookupEnv(key string) (string, bool) {
|
||||||
|
return syscall.Getenv(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setenv sets the value of the environment variable named by the key.
|
||||||
|
// It returns an error, if any.
|
||||||
|
func Setenv(key, value string) error {
|
||||||
|
err := syscall.Setenv(key, value)
|
||||||
|
if err != nil {
|
||||||
|
return NewSyscallError("setenv", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO(xsw):
|
||||||
|
func Setenv(key, value string) error {
|
||||||
|
ret := os.Setenv(c.AllocaCStr(key), c.AllocaCStr(value), 1)
|
||||||
|
if ret == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &SyscallError{"setenv", syscall.Errno(ret)}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Unsetenv unsets a single environment variable.
|
||||||
|
func Unsetenv(key string) error {
|
||||||
|
return syscall.Unsetenv(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO(xsw):
|
||||||
|
func Unsetenv(key string) error {
|
||||||
|
ret := os.Unsetenv(c.AllocaCStr(key))
|
||||||
|
if ret == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return syscall.Errno(ret)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Environ returns a copy of strings representing the environment,
|
||||||
|
// in the form "key=value".
|
||||||
|
func Environ() []string {
|
||||||
|
return syscall.Environ()
|
||||||
|
}
|
||||||
@@ -148,10 +148,6 @@ func Clearenv()
|
|||||||
// TODO(xsw):
|
// TODO(xsw):
|
||||||
// func DirFS(dir string) fs.FS
|
// func DirFS(dir string) fs.FS
|
||||||
|
|
||||||
func Environ() []string {
|
|
||||||
panic("todo: os.Environ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// func Executable() (string, error)
|
// func Executable() (string, error)
|
||||||
|
|
||||||
// TODO(xsw):
|
// TODO(xsw):
|
||||||
@@ -162,10 +158,6 @@ func Getegid() int {
|
|||||||
return int(os.Getegid())
|
return int(os.Getegid())
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getenv(key string) string {
|
|
||||||
return c.GoString(os.Getenv(c.AllocaCStr(key)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func Geteuid() int {
|
func Geteuid() int {
|
||||||
return int(os.Geteuid())
|
return int(os.Geteuid())
|
||||||
}
|
}
|
||||||
@@ -330,14 +322,6 @@ func Rename(oldpath, newpath string) error {
|
|||||||
// TODO(xsw):
|
// TODO(xsw):
|
||||||
// func SameFile(fi1, fi2 FileInfo) bool
|
// func SameFile(fi1, fi2 FileInfo) bool
|
||||||
|
|
||||||
func Setenv(key, value string) error {
|
|
||||||
ret := os.Setenv(c.AllocaCStr(key), c.AllocaCStr(value), 1)
|
|
||||||
if ret == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return &SyscallError{"setenv", syscall.Errno(ret)}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Symlink(oldname, newname string) error {
|
func Symlink(oldname, newname string) error {
|
||||||
ret := os.Symlink(c.AllocaCStr(oldname), c.AllocaCStr(newname))
|
ret := os.Symlink(c.AllocaCStr(oldname), c.AllocaCStr(newname))
|
||||||
if ret == 0 {
|
if ret == 0 {
|
||||||
@@ -357,14 +341,6 @@ func Truncate(name string, size int64) error {
|
|||||||
return toPathErr("truncate", name, ret)
|
return toPathErr("truncate", name, ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Unsetenv(key string) error {
|
|
||||||
ret := os.Unsetenv(c.AllocaCStr(key))
|
|
||||||
if ret == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return syscall.Errno(ret)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UserCacheDir returns the default root directory to use for user-specific
|
// UserCacheDir returns the default root directory to use for user-specific
|
||||||
// cached data. Users should create their own application-specific subdirectory
|
// cached data. Users should create their own application-specific subdirectory
|
||||||
// within this one and use that.
|
// within this one and use that.
|
||||||
|
|||||||
173
internal/lib/syscall/env_unix.go
Normal file
173
internal/lib/syscall/env_unix.go
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
//go:build unix || (js && wasm) || plan9 || wasip1
|
||||||
|
|
||||||
|
// Unix environment variables.
|
||||||
|
|
||||||
|
package syscall
|
||||||
|
|
||||||
|
import (
|
||||||
|
"runtime"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/os"
|
||||||
|
)
|
||||||
|
|
||||||
|
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 = runtimeEnvs()
|
||||||
|
)
|
||||||
|
|
||||||
|
func runtimeEnvs() []string {
|
||||||
|
ret := make([]string, 0, 8)
|
||||||
|
cenvs := os.Environ
|
||||||
|
i := 0
|
||||||
|
for {
|
||||||
|
ce := *c.Advance(cenvs, i)
|
||||||
|
if ce == nil {
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
ret = append(ret, c.GoString(ce))
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
os.Unsetenv(c.AllocaCStr(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
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO(xsw):
|
||||||
|
func Getenv(key string) (value string, found bool) {
|
||||||
|
ret := os.Getenv(c.AllocaCStr(key))
|
||||||
|
if ret != nil {
|
||||||
|
return c.GoString(ret), 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// On Plan 9, null is used as a separator, eg in $path.
|
||||||
|
if runtime.GOOS != "plan9" {
|
||||||
|
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
|
||||||
|
os.Setenv(c.AllocaCStr(key), c.AllocaCStr(value), 1)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Clearenv() {
|
||||||
|
envOnce.Do(copyenv) // prevent copyenv in Getenv/Setenv
|
||||||
|
|
||||||
|
envLock.Lock()
|
||||||
|
defer envLock.Unlock()
|
||||||
|
|
||||||
|
os.Clearenv()
|
||||||
|
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
|
||||||
|
}
|
||||||
96
internal/lib/syscall/env_windows.go
Normal file
96
internal/lib/syscall/env_windows.go
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
// Windows environment variables.
|
||||||
|
|
||||||
|
package syscall
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Getenv(key string) (value string, found bool) {
|
||||||
|
keyp, err := UTF16PtrFromString(key)
|
||||||
|
if err != nil {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
n := uint32(100)
|
||||||
|
for {
|
||||||
|
b := make([]uint16, n)
|
||||||
|
n, err = GetEnvironmentVariable(keyp, &b[0], uint32(len(b)))
|
||||||
|
if n == 0 && err == ERROR_ENVVAR_NOT_FOUND {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
if n <= uint32(len(b)) {
|
||||||
|
return UTF16ToString(b[:n]), true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Setenv(key, value string) error {
|
||||||
|
v, err := UTF16PtrFromString(value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
keyp, err := UTF16PtrFromString(key)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
e := SetEnvironmentVariable(keyp, v)
|
||||||
|
if e != nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
runtimeSetenv(key, value)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Unsetenv(key string) error {
|
||||||
|
keyp, err := UTF16PtrFromString(key)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
e := SetEnvironmentVariable(keyp, nil)
|
||||||
|
if e != nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
runtimeUnsetenv(key)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Clearenv() {
|
||||||
|
for _, s := range Environ() {
|
||||||
|
// Environment variables can begin with =
|
||||||
|
// so start looking for the separator = at j=1.
|
||||||
|
// https://devblogs.microsoft.com/oldnewthing/20100506-00/?p=14133
|
||||||
|
for j := 1; j < len(s); j++ {
|
||||||
|
if s[j] == '=' {
|
||||||
|
Unsetenv(s[0:j])
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Environ() []string {
|
||||||
|
envp, e := GetEnvironmentStrings()
|
||||||
|
if e != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer FreeEnvironmentStrings(envp)
|
||||||
|
|
||||||
|
r := make([]string, 0, 50) // Empty with room to grow.
|
||||||
|
const size = unsafe.Sizeof(*envp)
|
||||||
|
for *envp != 0 { // environment block ends with empty string
|
||||||
|
// find NUL terminator
|
||||||
|
end := unsafe.Pointer(envp)
|
||||||
|
for *(*uint16)(end) != 0 {
|
||||||
|
end = unsafe.Add(end, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
entry := unsafe.Slice(envp, (uintptr(end)-uintptr(unsafe.Pointer(envp)))/size)
|
||||||
|
r = append(r, UTF16ToString(entry))
|
||||||
|
envp = (*uint16)(unsafe.Add(end, size))
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
@@ -73,14 +73,6 @@ func Getwd() (string, error) {
|
|||||||
return "", Errno(os.Errno)
|
return "", Errno(os.Errno)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getenv(key string) (value string, found bool) {
|
|
||||||
ret := os.Getenv(c.AllocaCStr(key))
|
|
||||||
if ret != nil {
|
|
||||||
return c.GoString(ret), true
|
|
||||||
}
|
|
||||||
return "", false
|
|
||||||
}
|
|
||||||
|
|
||||||
func Getpid() (pid int) {
|
func Getpid() (pid int) {
|
||||||
return int(os.Getpid())
|
return int(os.Getpid())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user