Merge pull request #533 from xushiwei/q
library os: StartProcess/Wait/Sysctl/environ; syscall.Wait4; c/syscall: zerrors; c/os: Setrlimit/Getrlimit;
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/llama2](https://pkg.go.dev/github.com/goplus/llgo/c/llama2)
|
||||
* [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/sqlite](https://pkg.go.dev/github.com/goplus/llgo/c/sqlite)
|
||||
* [c/zlib](https://pkg.go.dev/github.com/goplus/llgo/c/zlib)
|
||||
|
||||
30
_cmptest/osproc/exec.go
Normal file
30
_cmptest/osproc/exec.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
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()
|
||||
fmt.Println("proc.Wait done")
|
||||
}
|
||||
85
c/os/os.go
85
c/os/os.go
@@ -263,21 +263,50 @@ func Execve(path *c.Char, argv **c.Char, envp **c.Char) c.Int
|
||||
//go:linkname Execvp C.execvp
|
||||
func Execvp(file *c.Char, argv **c.Char) c.Int
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
type PidT c.Int
|
||||
|
||||
//go:linkname Fork C.fork
|
||||
func Fork() c.Int
|
||||
func Fork() PidT
|
||||
|
||||
//go:linkname Getpid C.getpid
|
||||
func Getpid() PidT
|
||||
|
||||
//go:linkname Getppid C.getppid
|
||||
func Getppid() PidT
|
||||
|
||||
//go:linkname Kill C.kill
|
||||
func Kill(pid c.Int, sig c.Int) c.Int
|
||||
func Kill(pid PidT, sig c.Int) c.Int
|
||||
|
||||
// If wait() returns due to a stopped or terminated child process, the process ID
|
||||
// of the child is returned to the calling process. Otherwise, a value of -1 is
|
||||
// returned and errno is set to indicate the error.
|
||||
//
|
||||
//go:linkname Wait C.wait
|
||||
func Wait(statLoc *c.Int) PidT
|
||||
|
||||
// If wait3(), wait4(), or waitpid() returns due to a stopped or terminated child
|
||||
// process, the process ID of the child is returned to the calling process. If
|
||||
// there are no children not previously awaited, -1 is returned with errno set to
|
||||
// [ECHILD]. Otherwise, if WNOHANG is specified and there are no stopped or exited
|
||||
// children, 0 is returned. If an error is detected or a caught signal aborts the
|
||||
// call, a value of -1 is returned and errno is set to indicate the error.
|
||||
//
|
||||
//go:linkname Wait3 C.wait3
|
||||
func Wait3(statLoc *c.Int, options c.Int, rusage *syscall.Rusage) PidT
|
||||
|
||||
//go:linkname Wait4 C.wait4
|
||||
func Wait4(pid PidT, statLoc *c.Int, options c.Int, rusage *syscall.Rusage) PidT
|
||||
|
||||
//go:linkname Waitpid C.waitpid
|
||||
func Waitpid(pid PidT, statLoc *c.Int, options c.Int) PidT
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
//go:linkname Exit C.exit
|
||||
func Exit(c.Int)
|
||||
|
||||
//go:linkname Getpid C.getpid
|
||||
func Getpid() c.Int
|
||||
|
||||
//go:linkname Getppid C.getppid
|
||||
func Getppid() c.Int
|
||||
|
||||
//go:linkname Getuid C.getuid
|
||||
func Getuid() UidT
|
||||
|
||||
@@ -291,3 +320,43 @@ func Getgid() GidT
|
||||
func Getegid() GidT
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
//go:linkname Getrlimit C.getrlimit
|
||||
func Getrlimit(resource c.Int, rlp *syscall.Rlimit) c.Int
|
||||
|
||||
//go:linkname Setrlimit C.setrlimit
|
||||
func Setrlimit(resource c.Int, rlp *syscall.Rlimit) c.Int
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Upon successful completion, the value 0 is returned; otherwise the value -1
|
||||
// is returned and the global variable errno is set to indicate the error.
|
||||
//
|
||||
//go:linkname Sysctl C.sysctl
|
||||
func Sysctl(
|
||||
name *c.Int, namelen c.Uint,
|
||||
oldp c.Pointer, oldlenp *uintptr,
|
||||
newp c.Pointer, newlen uintptr) c.Int
|
||||
|
||||
//go:linkname Sysctlbyname C.sysctlbyname
|
||||
func Sysctlbyname(
|
||||
name *c.Char, oldp c.Pointer, oldlenp *uintptr,
|
||||
newp c.Pointer, newlen uintptr) c.Int
|
||||
|
||||
// The sysctlnametomib() function accepts an ASCII representation of the
|
||||
// name, looks up the integer name vector, and returns the numeric repre-
|
||||
// sentation in the mib array pointed to by mibp. The number of elements
|
||||
// in the mib array is given by the location specified by sizep before the
|
||||
// call, and that location gives the number of entries copied after a suc-
|
||||
// cessful call. The resulting mib and size may be used in subsequent
|
||||
// sysctl() calls to get the data associated with the requested ASCII
|
||||
// name. This interface is intended for use by applications that want to
|
||||
// repeatedly request the same variable (the sysctl() function runs in
|
||||
// about a third the time as the same request made via the sysctlbyname()
|
||||
// function). The sysctlnametomib() function is also useful for fetching
|
||||
// mib prefixes and then adding a final component.
|
||||
//
|
||||
//go:linkname Sysctlnametomib C.sysctlnametomib
|
||||
func Sysctlnametomib(name *c.Char, mibp *c.Int, sizep *uintptr) c.Int
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -19,3 +19,9 @@ package syscall
|
||||
const (
|
||||
LLGoPackage = "decl"
|
||||
)
|
||||
|
||||
type Errno = uintptr
|
||||
|
||||
// A Signal is a number describing a process signal.
|
||||
// It implements the os.Signal interface.
|
||||
type Signal = int
|
||||
|
||||
1153
c/syscall/zerrors_aix_ppc64.go
Normal file
1153
c/syscall/zerrors_aix_ppc64.go
Normal file
File diff suppressed because it is too large
Load Diff
1279
c/syscall/zerrors_darwin_amd64.go
Normal file
1279
c/syscall/zerrors_darwin_amd64.go
Normal file
File diff suppressed because it is too large
Load Diff
1291
c/syscall/zerrors_darwin_arm64.go
Normal file
1291
c/syscall/zerrors_darwin_arm64.go
Normal file
File diff suppressed because it is too large
Load Diff
1392
c/syscall/zerrors_dragonfly_amd64.go
Normal file
1392
c/syscall/zerrors_dragonfly_amd64.go
Normal file
File diff suppressed because it is too large
Load Diff
1580
c/syscall/zerrors_freebsd_386.go
Normal file
1580
c/syscall/zerrors_freebsd_386.go
Normal file
File diff suppressed because it is too large
Load Diff
1581
c/syscall/zerrors_freebsd_amd64.go
Normal file
1581
c/syscall/zerrors_freebsd_amd64.go
Normal file
File diff suppressed because it is too large
Load Diff
1580
c/syscall/zerrors_freebsd_arm.go
Normal file
1580
c/syscall/zerrors_freebsd_arm.go
Normal file
File diff suppressed because it is too large
Load Diff
1581
c/syscall/zerrors_freebsd_arm64.go
Normal file
1581
c/syscall/zerrors_freebsd_arm64.go
Normal file
File diff suppressed because it is too large
Load Diff
1581
c/syscall/zerrors_freebsd_riscv64.go
Normal file
1581
c/syscall/zerrors_freebsd_riscv64.go
Normal file
File diff suppressed because it is too large
Load Diff
1355
c/syscall/zerrors_linux_386.go
Normal file
1355
c/syscall/zerrors_linux_386.go
Normal file
File diff suppressed because it is too large
Load Diff
1356
c/syscall/zerrors_linux_amd64.go
Normal file
1356
c/syscall/zerrors_linux_amd64.go
Normal file
File diff suppressed because it is too large
Load Diff
1368
c/syscall/zerrors_linux_arm.go
Normal file
1368
c/syscall/zerrors_linux_arm.go
Normal file
File diff suppressed because it is too large
Load Diff
1632
c/syscall/zerrors_linux_arm64.go
Normal file
1632
c/syscall/zerrors_linux_arm64.go
Normal file
File diff suppressed because it is too large
Load Diff
1931
c/syscall/zerrors_linux_loong64.go
Normal file
1931
c/syscall/zerrors_linux_loong64.go
Normal file
File diff suppressed because it is too large
Load Diff
1639
c/syscall/zerrors_linux_mips.go
Normal file
1639
c/syscall/zerrors_linux_mips.go
Normal file
File diff suppressed because it is too large
Load Diff
1622
c/syscall/zerrors_linux_mips64.go
Normal file
1622
c/syscall/zerrors_linux_mips64.go
Normal file
File diff suppressed because it is too large
Load Diff
1622
c/syscall/zerrors_linux_mips64le.go
Normal file
1622
c/syscall/zerrors_linux_mips64le.go
Normal file
File diff suppressed because it is too large
Load Diff
1639
c/syscall/zerrors_linux_mipsle.go
Normal file
1639
c/syscall/zerrors_linux_mipsle.go
Normal file
File diff suppressed because it is too large
Load Diff
1687
c/syscall/zerrors_linux_ppc64.go
Normal file
1687
c/syscall/zerrors_linux_ppc64.go
Normal file
File diff suppressed because it is too large
Load Diff
1711
c/syscall/zerrors_linux_ppc64le.go
Normal file
1711
c/syscall/zerrors_linux_ppc64le.go
Normal file
File diff suppressed because it is too large
Load Diff
1686
c/syscall/zerrors_linux_riscv64.go
Normal file
1686
c/syscall/zerrors_linux_riscv64.go
Normal file
File diff suppressed because it is too large
Load Diff
1747
c/syscall/zerrors_linux_s390x.go
Normal file
1747
c/syscall/zerrors_linux_s390x.go
Normal file
File diff suppressed because it is too large
Load Diff
1575
c/syscall/zerrors_netbsd_386.go
Normal file
1575
c/syscall/zerrors_netbsd_386.go
Normal file
File diff suppressed because it is too large
Load Diff
1565
c/syscall/zerrors_netbsd_amd64.go
Normal file
1565
c/syscall/zerrors_netbsd_amd64.go
Normal file
File diff suppressed because it is too large
Load Diff
1551
c/syscall/zerrors_netbsd_arm.go
Normal file
1551
c/syscall/zerrors_netbsd_arm.go
Normal file
File diff suppressed because it is too large
Load Diff
1565
c/syscall/zerrors_netbsd_arm64.go
Normal file
1565
c/syscall/zerrors_netbsd_arm64.go
Normal file
File diff suppressed because it is too large
Load Diff
1454
c/syscall/zerrors_openbsd_386.go
Normal file
1454
c/syscall/zerrors_openbsd_386.go
Normal file
File diff suppressed because it is too large
Load Diff
1453
c/syscall/zerrors_openbsd_amd64.go
Normal file
1453
c/syscall/zerrors_openbsd_amd64.go
Normal file
File diff suppressed because it is too large
Load Diff
1453
c/syscall/zerrors_openbsd_arm.go
Normal file
1453
c/syscall/zerrors_openbsd_arm.go
Normal file
File diff suppressed because it is too large
Load Diff
1540
c/syscall/zerrors_openbsd_arm64.go
Normal file
1540
c/syscall/zerrors_openbsd_arm64.go
Normal file
File diff suppressed because it is too large
Load Diff
1547
c/syscall/zerrors_openbsd_mips64.go
Normal file
1547
c/syscall/zerrors_openbsd_mips64.go
Normal file
File diff suppressed because it is too large
Load Diff
1247
c/syscall/zerrors_solaris_amd64.go
Normal file
1247
c/syscall/zerrors_solaris_amd64.go
Normal file
File diff suppressed because it is too large
Load Diff
148
c/syscall/zerrors_windows.go
Normal file
148
c/syscall/zerrors_windows.go
Normal file
@@ -0,0 +1,148 @@
|
||||
// mkerrors_windows.sh -m32
|
||||
// Code generated by the command above; DO NOT EDIT.
|
||||
|
||||
package syscall
|
||||
|
||||
// Go names for Windows errors.
|
||||
const (
|
||||
ENOENT Errno = ERROR_FILE_NOT_FOUND
|
||||
ENOTDIR Errno = ERROR_PATH_NOT_FOUND
|
||||
)
|
||||
|
||||
// Windows reserves errors >= 1<<29 for application use.
|
||||
const APPLICATION_ERROR = 1 << 29
|
||||
|
||||
// Invented values to support what package os and others expects.
|
||||
const (
|
||||
E2BIG Errno = APPLICATION_ERROR + iota
|
||||
EACCES
|
||||
EADDRINUSE
|
||||
EADDRNOTAVAIL
|
||||
EADV
|
||||
EAFNOSUPPORT
|
||||
EAGAIN
|
||||
EALREADY
|
||||
EBADE
|
||||
EBADF
|
||||
EBADFD
|
||||
EBADMSG
|
||||
EBADR
|
||||
EBADRQC
|
||||
EBADSLT
|
||||
EBFONT
|
||||
EBUSY
|
||||
ECANCELED
|
||||
ECHILD
|
||||
ECHRNG
|
||||
ECOMM
|
||||
ECONNABORTED
|
||||
ECONNREFUSED
|
||||
ECONNRESET
|
||||
EDEADLK
|
||||
EDEADLOCK
|
||||
EDESTADDRREQ
|
||||
EDOM
|
||||
EDOTDOT
|
||||
EDQUOT
|
||||
EEXIST
|
||||
EFAULT
|
||||
EFBIG
|
||||
EHOSTDOWN
|
||||
EHOSTUNREACH
|
||||
EIDRM
|
||||
EILSEQ
|
||||
EINPROGRESS
|
||||
EINTR
|
||||
EINVAL
|
||||
EIO
|
||||
EISCONN
|
||||
EISDIR
|
||||
EISNAM
|
||||
EKEYEXPIRED
|
||||
EKEYREJECTED
|
||||
EKEYREVOKED
|
||||
EL2HLT
|
||||
EL2NSYNC
|
||||
EL3HLT
|
||||
EL3RST
|
||||
ELIBACC
|
||||
ELIBBAD
|
||||
ELIBEXEC
|
||||
ELIBMAX
|
||||
ELIBSCN
|
||||
ELNRNG
|
||||
ELOOP
|
||||
EMEDIUMTYPE
|
||||
EMFILE
|
||||
EMLINK
|
||||
EMSGSIZE
|
||||
EMULTIHOP
|
||||
ENAMETOOLONG
|
||||
ENAVAIL
|
||||
ENETDOWN
|
||||
ENETRESET
|
||||
ENETUNREACH
|
||||
ENFILE
|
||||
ENOANO
|
||||
ENOBUFS
|
||||
ENOCSI
|
||||
ENODATA
|
||||
ENODEV
|
||||
ENOEXEC
|
||||
ENOKEY
|
||||
ENOLCK
|
||||
ENOLINK
|
||||
ENOMEDIUM
|
||||
ENOMEM
|
||||
ENOMSG
|
||||
ENONET
|
||||
ENOPKG
|
||||
ENOPROTOOPT
|
||||
ENOSPC
|
||||
ENOSR
|
||||
ENOSTR
|
||||
ENOSYS
|
||||
ENOTBLK
|
||||
ENOTCONN
|
||||
ENOTEMPTY
|
||||
ENOTNAM
|
||||
ENOTRECOVERABLE
|
||||
ENOTSOCK
|
||||
ENOTSUP
|
||||
ENOTTY
|
||||
ENOTUNIQ
|
||||
ENXIO
|
||||
EOPNOTSUPP
|
||||
EOVERFLOW
|
||||
EOWNERDEAD
|
||||
EPERM
|
||||
EPFNOSUPPORT
|
||||
EPIPE
|
||||
EPROTO
|
||||
EPROTONOSUPPORT
|
||||
EPROTOTYPE
|
||||
ERANGE
|
||||
EREMCHG
|
||||
EREMOTE
|
||||
EREMOTEIO
|
||||
ERESTART
|
||||
EROFS
|
||||
ESHUTDOWN
|
||||
ESOCKTNOSUPPORT
|
||||
ESPIPE
|
||||
ESRCH
|
||||
ESRMNT
|
||||
ESTALE
|
||||
ESTRPIPE
|
||||
ETIME
|
||||
ETIMEDOUT
|
||||
ETOOMANYREFS
|
||||
ETXTBSY
|
||||
EUCLEAN
|
||||
EUNATCH
|
||||
EUSERS
|
||||
EWOULDBLOCK
|
||||
EXDEV
|
||||
EXFULL
|
||||
EWINDOWS
|
||||
)
|
||||
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()
|
||||
}
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
)
|
||||
|
||||
func (p *Process) wait() (ps *ProcessState, err error) {
|
||||
/* TODO(xsw):
|
||||
if p.Pid == -1 {
|
||||
return nil, syscall.EINVAL
|
||||
}
|
||||
@@ -58,8 +57,6 @@ func (p *Process) wait() (ps *ProcessState, err error) {
|
||||
rusage: &rusage,
|
||||
}
|
||||
return ps, nil
|
||||
*/
|
||||
panic("todo: os.Process.wait")
|
||||
}
|
||||
|
||||
func (p *Process) signal(sig Signal) error {
|
||||
|
||||
@@ -148,10 +148,6 @@ func Clearenv()
|
||||
// TODO(xsw):
|
||||
// func DirFS(dir string) fs.FS
|
||||
|
||||
func Environ() []string {
|
||||
panic("todo: os.Environ")
|
||||
}
|
||||
|
||||
// func Executable() (string, error)
|
||||
|
||||
// TODO(xsw):
|
||||
@@ -162,10 +158,6 @@ func Getegid() int {
|
||||
return int(os.Getegid())
|
||||
}
|
||||
|
||||
func Getenv(key string) string {
|
||||
return c.GoString(os.Getenv(c.AllocaCStr(key)))
|
||||
}
|
||||
|
||||
func Geteuid() int {
|
||||
return int(os.Geteuid())
|
||||
}
|
||||
@@ -330,14 +322,6 @@ func Rename(oldpath, newpath string) error {
|
||||
// TODO(xsw):
|
||||
// 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 {
|
||||
ret := os.Symlink(c.AllocaCStr(oldname), c.AllocaCStr(newname))
|
||||
if ret == 0 {
|
||||
@@ -357,14 +341,6 @@ func Truncate(name string, size int64) error {
|
||||
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
|
||||
// cached data. Users should create their own application-specific subdirectory
|
||||
// within this one and use that.
|
||||
|
||||
21
internal/lib/os/wait_unimp.go
Normal file
21
internal/lib/os/wait_unimp.go
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
// aix, darwin, js/wasm, openbsd, solaris and wasip1/wasm don't implement
|
||||
// waitid/wait6.
|
||||
|
||||
//go:build aix || darwin || (js && wasm) || openbsd || solaris || wasip1
|
||||
|
||||
package os
|
||||
|
||||
// blockUntilWaitable attempts to block until a call to p.Wait will
|
||||
// succeed immediately, and reports whether it has done so.
|
||||
// It does not actually call p.Wait.
|
||||
// This version is used on systems that do not implement waitid,
|
||||
// or where we have not implemented it yet. Note that this is racy:
|
||||
// a call to Process.Signal can in an extremely unlikely case send a
|
||||
// signal to the wrong process, see issue #13987.
|
||||
func (p *Process) blockUntilWaitable() (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
@@ -7,5 +7,6 @@
|
||||
package runtime
|
||||
|
||||
func SetFinalizer(obj any, finalizer any) {
|
||||
panic("todo: runtime.SetFinalizer")
|
||||
// TODO(xsw):
|
||||
// panic("todo: runtime.SetFinalizer")
|
||||
}
|
||||
|
||||
174
internal/lib/syscall/env_unix.go
Normal file
174
internal/lib/syscall/env_unix.go
Normal file
@@ -0,0 +1,174 @@
|
||||
// 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"
|
||||
"github.com/goplus/llgo/c/syscall"
|
||||
)
|
||||
|
||||
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 Errno(syscall.EINVAL)
|
||||
}
|
||||
for i := 0; i < len(key); i++ {
|
||||
if key[i] == '=' || key[i] == 0 {
|
||||
return Errno(syscall.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 Errno(syscall.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
|
||||
}
|
||||
@@ -6,6 +6,12 @@
|
||||
|
||||
package syscall
|
||||
|
||||
import (
|
||||
"github.com/goplus/llgo/c"
|
||||
"github.com/goplus/llgo/c/os"
|
||||
"github.com/goplus/llgo/c/syscall"
|
||||
)
|
||||
|
||||
type SysProcAttr struct {
|
||||
Chroot string // Chroot.
|
||||
Credential *Credential // Credential.
|
||||
@@ -48,146 +54,191 @@ func runtime_AfterForkInChild()
|
||||
// functions that do not grow the stack.
|
||||
//
|
||||
//go:norace
|
||||
func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err1 Errno) {
|
||||
/* TODO(xsw):
|
||||
// Declare all variables at top in case any
|
||||
// declarations require heap allocation (e.g., err1).
|
||||
var (
|
||||
r1 uintptr
|
||||
nextfd int
|
||||
i int
|
||||
err error
|
||||
pgrp _C_int
|
||||
cred *Credential
|
||||
ngroups, groups uintptr
|
||||
)
|
||||
func forkAndExecInChild(argv0 *c.Char, argv, envv **c.Char, chroot, dir *c.Char, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err1 Errno) {
|
||||
// Declare all variables at top in case any
|
||||
// declarations require heap allocation (e.g., err1).
|
||||
var (
|
||||
r1 uintptr
|
||||
nextfd int
|
||||
i int
|
||||
cred *Credential
|
||||
// err error
|
||||
// pgrp c.Int
|
||||
// ngroups, groups uintptr
|
||||
)
|
||||
|
||||
rlim, rlimOK := origRlimitNofile.Load().(Rlimit)
|
||||
rlim, rlimOK := origRlimitNofile.Load().(Rlimit)
|
||||
|
||||
// guard against side effects of shuffling fds below.
|
||||
// Make sure that nextfd is beyond any currently open files so
|
||||
// that we can't run the risk of overwriting any of them.
|
||||
fd := make([]int, len(attr.Files))
|
||||
nextfd = len(attr.Files)
|
||||
for i, ufd := range attr.Files {
|
||||
if nextfd < int(ufd) {
|
||||
nextfd = int(ufd)
|
||||
}
|
||||
fd[i] = int(ufd)
|
||||
// guard against side effects of shuffling fds below.
|
||||
// Make sure that nextfd is beyond any currently open files so
|
||||
// that we can't run the risk of overwriting any of them.
|
||||
fd := make([]int, len(attr.Files))
|
||||
nextfd = len(attr.Files)
|
||||
for i, ufd := range attr.Files {
|
||||
if nextfd < int(ufd) {
|
||||
nextfd = int(ufd)
|
||||
}
|
||||
nextfd++
|
||||
fd[i] = int(ufd)
|
||||
}
|
||||
nextfd++
|
||||
|
||||
// About to call fork.
|
||||
// No more allocation or calls of non-assembly functions.
|
||||
runtime_BeforeFork()
|
||||
r1, _, err1 = rawSyscall(abi.FuncPCABI0(libc_fork_trampoline), 0, 0, 0)
|
||||
// About to call fork.
|
||||
// No more allocation or calls of non-assembly functions.
|
||||
// runtime_BeforeFork()
|
||||
r1, err1 = fork()
|
||||
if err1 != 0 {
|
||||
// runtime_AfterFork()
|
||||
return 0, err1
|
||||
}
|
||||
|
||||
if r1 != 0 {
|
||||
// parent; return PID
|
||||
// runtime_AfterFork()
|
||||
return int(r1), 0
|
||||
}
|
||||
|
||||
// Fork succeeded, now in child.
|
||||
|
||||
// TODO(xsw): check this
|
||||
// Enable tracing if requested.
|
||||
if sys.Ptrace {
|
||||
/* TODO(xsw):
|
||||
if err = ptrace(PTRACE_TRACEME, 0, 0, 0); err != nil {
|
||||
err1 = err.(Errno)
|
||||
goto childerror
|
||||
}
|
||||
*/
|
||||
panic("todo: syscall.forkAndExecInChild - sys.Ptrace")
|
||||
}
|
||||
|
||||
// Session ID
|
||||
if sys.Setsid {
|
||||
/* TODO(xsw):
|
||||
_, _, err1 = rawSyscall(abi.FuncPCABI0(libc_setsid_trampoline), 0, 0, 0)
|
||||
if err1 != 0 {
|
||||
runtime_AfterFork()
|
||||
return 0, err1
|
||||
goto childerror
|
||||
}
|
||||
*/
|
||||
panic("todo: syscall.forkAndExecInChild - sys.Setsid")
|
||||
}
|
||||
|
||||
if r1 != 0 {
|
||||
// parent; return PID
|
||||
runtime_AfterFork()
|
||||
return int(r1), 0
|
||||
// Set process group
|
||||
if sys.Setpgid || sys.Foreground {
|
||||
/* TODO(xsw):
|
||||
// Place child in process group.
|
||||
_, _, err1 = rawSyscall(abi.FuncPCABI0(libc_setpgid_trampoline), 0, uintptr(sys.Pgid), 0)
|
||||
if err1 != 0 {
|
||||
goto childerror
|
||||
}
|
||||
*/
|
||||
panic("todo: syscall.forkAndExecInChild - sys.Setpgid")
|
||||
}
|
||||
|
||||
// Fork succeeded, now in child.
|
||||
|
||||
// Enable tracing if requested.
|
||||
if sys.Ptrace {
|
||||
if err = ptrace(PTRACE_TRACEME, 0, 0, 0); err != nil {
|
||||
err1 = err.(Errno)
|
||||
if sys.Foreground {
|
||||
/* TODO(xsw):
|
||||
// This should really be pid_t, however _C_int (aka int32) is
|
||||
// generally equivalent.
|
||||
pgrp = _C_int(sys.Pgid)
|
||||
if pgrp == 0 {
|
||||
r1, _, err1 = rawSyscall(abi.FuncPCABI0(libc_getpid_trampoline), 0, 0, 0)
|
||||
if err1 != 0 {
|
||||
goto childerror
|
||||
}
|
||||
pgrp = _C_int(r1)
|
||||
}
|
||||
|
||||
// Session ID
|
||||
if sys.Setsid {
|
||||
_, _, err1 = rawSyscall(abi.FuncPCABI0(libc_setsid_trampoline), 0, 0, 0)
|
||||
// Place process group in foreground.
|
||||
_, _, err1 = rawSyscall(abi.FuncPCABI0(libc_ioctl_trampoline), uintptr(sys.Ctty), uintptr(TIOCSPGRP), uintptr(unsafe.Pointer(&pgrp)))
|
||||
if err1 != 0 {
|
||||
goto childerror
|
||||
}
|
||||
*/
|
||||
panic("todo: syscall.forkAndExecInChild - sys.Foreground")
|
||||
}
|
||||
|
||||
// Restore the signal mask. We do this after TIOCSPGRP to avoid
|
||||
// having the kernel send a SIGTTOU signal to the process group.
|
||||
// runtime_AfterForkInChild()
|
||||
|
||||
// Chroot
|
||||
if chroot != nil {
|
||||
/* TODO(xsw):
|
||||
_, _, err1 = rawSyscall(abi.FuncPCABI0(libc_chroot_trampoline), uintptr(unsafe.Pointer(chroot)), 0, 0)
|
||||
if err1 != 0 {
|
||||
goto childerror
|
||||
}
|
||||
*/
|
||||
panic("todo: syscall.forkAndExecInChild - chroot")
|
||||
}
|
||||
|
||||
// User and groups
|
||||
if cred = sys.Credential; cred != nil {
|
||||
/* TODO(xsw):
|
||||
ngroups = uintptr(len(cred.Groups))
|
||||
groups = uintptr(0)
|
||||
if ngroups > 0 {
|
||||
groups = uintptr(unsafe.Pointer(&cred.Groups[0]))
|
||||
}
|
||||
if !cred.NoSetGroups {
|
||||
_, _, err1 = rawSyscall(abi.FuncPCABI0(libc_setgroups_trampoline), ngroups, groups, 0)
|
||||
if err1 != 0 {
|
||||
goto childerror
|
||||
}
|
||||
}
|
||||
|
||||
// Set process group
|
||||
if sys.Setpgid || sys.Foreground {
|
||||
// Place child in process group.
|
||||
_, _, err1 = rawSyscall(abi.FuncPCABI0(libc_setpgid_trampoline), 0, uintptr(sys.Pgid), 0)
|
||||
if err1 != 0 {
|
||||
goto childerror
|
||||
}
|
||||
_, _, err1 = rawSyscall(abi.FuncPCABI0(libc_setgid_trampoline), uintptr(cred.Gid), 0, 0)
|
||||
if err1 != 0 {
|
||||
goto childerror
|
||||
}
|
||||
|
||||
if sys.Foreground {
|
||||
// This should really be pid_t, however _C_int (aka int32) is
|
||||
// generally equivalent.
|
||||
pgrp = _C_int(sys.Pgid)
|
||||
if pgrp == 0 {
|
||||
r1, _, err1 = rawSyscall(abi.FuncPCABI0(libc_getpid_trampoline), 0, 0, 0)
|
||||
if err1 != 0 {
|
||||
goto childerror
|
||||
}
|
||||
pgrp = _C_int(r1)
|
||||
}
|
||||
|
||||
// Place process group in foreground.
|
||||
_, _, err1 = rawSyscall(abi.FuncPCABI0(libc_ioctl_trampoline), uintptr(sys.Ctty), uintptr(TIOCSPGRP), uintptr(unsafe.Pointer(&pgrp)))
|
||||
if err1 != 0 {
|
||||
goto childerror
|
||||
}
|
||||
_, _, err1 = rawSyscall(abi.FuncPCABI0(libc_setuid_trampoline), uintptr(cred.Uid), 0, 0)
|
||||
if err1 != 0 {
|
||||
goto childerror
|
||||
}
|
||||
*/
|
||||
panic("todo: syscall.forkAndExecInChild - sys.Credential")
|
||||
}
|
||||
|
||||
// Restore the signal mask. We do this after TIOCSPGRP to avoid
|
||||
// having the kernel send a SIGTTOU signal to the process group.
|
||||
runtime_AfterForkInChild()
|
||||
|
||||
// Chroot
|
||||
if chroot != nil {
|
||||
_, _, err1 = rawSyscall(abi.FuncPCABI0(libc_chroot_trampoline), uintptr(unsafe.Pointer(chroot)), 0, 0)
|
||||
if err1 != 0 {
|
||||
goto childerror
|
||||
}
|
||||
// Chdir
|
||||
if dir != nil {
|
||||
/* TODO(xsw):
|
||||
_, _, err1 = rawSyscall(abi.FuncPCABI0(libc_chdir_trampoline), uintptr(unsafe.Pointer(dir)), 0, 0)
|
||||
if err1 != 0 {
|
||||
goto childerror
|
||||
}
|
||||
*/
|
||||
panic("todo: syscall.forkAndExecInChild - dir")
|
||||
}
|
||||
|
||||
// User and groups
|
||||
if cred = sys.Credential; cred != nil {
|
||||
ngroups = uintptr(len(cred.Groups))
|
||||
groups = uintptr(0)
|
||||
if ngroups > 0 {
|
||||
groups = uintptr(unsafe.Pointer(&cred.Groups[0]))
|
||||
}
|
||||
if !cred.NoSetGroups {
|
||||
_, _, err1 = rawSyscall(abi.FuncPCABI0(libc_setgroups_trampoline), ngroups, groups, 0)
|
||||
if err1 != 0 {
|
||||
goto childerror
|
||||
}
|
||||
}
|
||||
_, _, err1 = rawSyscall(abi.FuncPCABI0(libc_setgid_trampoline), uintptr(cred.Gid), 0, 0)
|
||||
if err1 != 0 {
|
||||
goto childerror
|
||||
}
|
||||
_, _, err1 = rawSyscall(abi.FuncPCABI0(libc_setuid_trampoline), uintptr(cred.Uid), 0, 0)
|
||||
// Pass 1: look for fd[i] < i and move those up above len(fd)
|
||||
// so that pass 2 won't stomp on an fd it needs later.
|
||||
if pipe < nextfd {
|
||||
/* TODO(xsw):
|
||||
if runtime.GOOS == "openbsd" {
|
||||
_, _, err1 = rawSyscall(dupTrampoline, uintptr(pipe), uintptr(nextfd), O_CLOEXEC)
|
||||
} else {
|
||||
_, _, err1 = rawSyscall(dupTrampoline, uintptr(pipe), uintptr(nextfd), 0)
|
||||
if err1 != 0 {
|
||||
goto childerror
|
||||
}
|
||||
_, _, err1 = rawSyscall(abi.FuncPCABI0(libc_fcntl_trampoline), uintptr(nextfd), F_SETFD, FD_CLOEXEC)
|
||||
}
|
||||
|
||||
// Chdir
|
||||
if dir != nil {
|
||||
_, _, err1 = rawSyscall(abi.FuncPCABI0(libc_chdir_trampoline), uintptr(unsafe.Pointer(dir)), 0, 0)
|
||||
if err1 != 0 {
|
||||
goto childerror
|
||||
}
|
||||
if err1 != 0 {
|
||||
goto childerror
|
||||
}
|
||||
|
||||
// Pass 1: look for fd[i] < i and move those up above len(fd)
|
||||
// so that pass 2 won't stomp on an fd it needs later.
|
||||
if pipe < nextfd {
|
||||
pipe = nextfd
|
||||
nextfd++
|
||||
*/
|
||||
panic("todo: syscall.forkAndExecInChild - pipe < nextfd")
|
||||
}
|
||||
for i = 0; i < len(fd); i++ {
|
||||
if fd[i] >= 0 && fd[i] < i {
|
||||
/* TODO(xsw):
|
||||
if nextfd == pipe { // don't stomp on pipe
|
||||
nextfd++
|
||||
}
|
||||
if runtime.GOOS == "openbsd" {
|
||||
_, _, err1 = rawSyscall(dupTrampoline, uintptr(pipe), uintptr(nextfd), O_CLOEXEC)
|
||||
_, _, err1 = rawSyscall(dupTrampoline, uintptr(fd[i]), uintptr(nextfd), O_CLOEXEC)
|
||||
} else {
|
||||
_, _, err1 = rawSyscall(dupTrampoline, uintptr(pipe), uintptr(nextfd), 0)
|
||||
_, _, err1 = rawSyscall(dupTrampoline, uintptr(fd[i]), uintptr(nextfd), 0)
|
||||
if err1 != 0 {
|
||||
goto childerror
|
||||
}
|
||||
@@ -196,95 +247,94 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
|
||||
if err1 != 0 {
|
||||
goto childerror
|
||||
}
|
||||
pipe = nextfd
|
||||
fd[i] = nextfd
|
||||
nextfd++
|
||||
*/
|
||||
panic("todo: syscall.forkAndExecInChild - for fd")
|
||||
}
|
||||
for i = 0; i < len(fd); i++ {
|
||||
if fd[i] >= 0 && fd[i] < i {
|
||||
if nextfd == pipe { // don't stomp on pipe
|
||||
nextfd++
|
||||
}
|
||||
if runtime.GOOS == "openbsd" {
|
||||
_, _, err1 = rawSyscall(dupTrampoline, uintptr(fd[i]), uintptr(nextfd), O_CLOEXEC)
|
||||
} else {
|
||||
_, _, err1 = rawSyscall(dupTrampoline, uintptr(fd[i]), uintptr(nextfd), 0)
|
||||
if err1 != 0 {
|
||||
goto childerror
|
||||
}
|
||||
_, _, err1 = rawSyscall(abi.FuncPCABI0(libc_fcntl_trampoline), uintptr(nextfd), F_SETFD, FD_CLOEXEC)
|
||||
}
|
||||
if err1 != 0 {
|
||||
goto childerror
|
||||
}
|
||||
fd[i] = nextfd
|
||||
nextfd++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pass 2: dup fd[i] down onto i.
|
||||
for i = 0; i < len(fd); i++ {
|
||||
if fd[i] == -1 {
|
||||
rawSyscall(abi.FuncPCABI0(libc_close_trampoline), uintptr(i), 0, 0)
|
||||
continue
|
||||
}
|
||||
if fd[i] == i {
|
||||
// dup2(i, i) won't clear close-on-exec flag on Linux,
|
||||
// probably not elsewhere either.
|
||||
_, _, err1 = rawSyscall(abi.FuncPCABI0(libc_fcntl_trampoline), uintptr(fd[i]), F_SETFD, 0)
|
||||
if err1 != 0 {
|
||||
goto childerror
|
||||
}
|
||||
continue
|
||||
}
|
||||
// The new fd is created NOT close-on-exec,
|
||||
// which is exactly what we want.
|
||||
_, _, err1 = rawSyscall(abi.FuncPCABI0(libc_dup2_trampoline), uintptr(fd[i]), uintptr(i), 0)
|
||||
if err1 != 0 {
|
||||
// Pass 2: dup fd[i] down onto i.
|
||||
for i = 0; i < len(fd); i++ {
|
||||
if fd[i] == -1 {
|
||||
os.Close(c.Int(i))
|
||||
continue
|
||||
}
|
||||
if fd[i] == i {
|
||||
// dup2(i, i) won't clear close-on-exec flag on Linux,
|
||||
// probably not elsewhere either.
|
||||
ret := os.Fcntl(c.Int(fd[i]), syscall.F_SETFD, 0)
|
||||
if ret != 0 {
|
||||
err1 = Errno(ret)
|
||||
goto childerror
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// By convention, we don't close-on-exec the fds we are
|
||||
// started with, so if len(fd) < 3, close 0, 1, 2 as needed.
|
||||
// Programs that know they inherit fds >= 3 will need
|
||||
// to set them close-on-exec.
|
||||
for i = len(fd); i < 3; i++ {
|
||||
rawSyscall(abi.FuncPCABI0(libc_close_trampoline), uintptr(i), 0, 0)
|
||||
/* TODO(xsw):
|
||||
// The new fd is created NOT close-on-exec,
|
||||
// which is exactly what we want.
|
||||
_, _, err1 = rawSyscall(abi.FuncPCABI0(libc_dup2_trampoline), uintptr(fd[i]), uintptr(i), 0)
|
||||
if err1 != 0 {
|
||||
goto childerror
|
||||
}
|
||||
*/
|
||||
panic("todo: syscall.forkAndExecInChild - dup2")
|
||||
}
|
||||
|
||||
// Detach fd 0 from tty
|
||||
if sys.Noctty {
|
||||
_, _, err1 = rawSyscall(abi.FuncPCABI0(libc_ioctl_trampoline), 0, uintptr(TIOCNOTTY), 0)
|
||||
if err1 != 0 {
|
||||
goto childerror
|
||||
}
|
||||
// By convention, we don't close-on-exec the fds we are
|
||||
// started with, so if len(fd) < 3, close 0, 1, 2 as needed.
|
||||
// Programs that know they inherit fds >= 3 will need
|
||||
// to set them close-on-exec.
|
||||
for i = len(fd); i < 3; i++ {
|
||||
/* TODO(xsw):
|
||||
rawSyscall(abi.FuncPCABI0(libc_close_trampoline), uintptr(i), 0, 0)
|
||||
*/
|
||||
panic("todo: syscall.forkAndExecInChild - for i")
|
||||
}
|
||||
|
||||
// Detach fd 0 from tty
|
||||
if sys.Noctty {
|
||||
/* TODO(xsw):
|
||||
_, _, err1 = rawSyscall(abi.FuncPCABI0(libc_ioctl_trampoline), 0, uintptr(TIOCNOTTY), 0)
|
||||
if err1 != 0 {
|
||||
goto childerror
|
||||
}
|
||||
*/
|
||||
panic("todo: syscall.forkAndExecInChild - sys.Noctty")
|
||||
}
|
||||
|
||||
// Set the controlling TTY to Ctty
|
||||
if sys.Setctty {
|
||||
_, _, err1 = rawSyscall(abi.FuncPCABI0(libc_ioctl_trampoline), uintptr(sys.Ctty), uintptr(TIOCSCTTY), 0)
|
||||
if err1 != 0 {
|
||||
goto childerror
|
||||
}
|
||||
// Set the controlling TTY to Ctty
|
||||
if sys.Setctty {
|
||||
/* TODO(xsw):
|
||||
_, _, err1 = rawSyscall(abi.FuncPCABI0(libc_ioctl_trampoline), uintptr(sys.Ctty), uintptr(TIOCSCTTY), 0)
|
||||
if err1 != 0 {
|
||||
goto childerror
|
||||
}
|
||||
*/
|
||||
panic("todo: syscall.forkAndExecInChild - sys.Setctty")
|
||||
}
|
||||
|
||||
// Restore original rlimit.
|
||||
if rlimOK && rlim.Cur != 0 {
|
||||
rawSyscall(abi.FuncPCABI0(libc_setrlimit_trampoline), uintptr(RLIMIT_NOFILE), uintptr(unsafe.Pointer(&rlim)), 0)
|
||||
}
|
||||
// Restore original rlimit.
|
||||
if rlimOK && rlim.Cur != 0 {
|
||||
os.Setrlimit(syscall.RLIMIT_NOFILE, (*syscall.Rlimit)(&rlim))
|
||||
}
|
||||
|
||||
// Time to exec.
|
||||
_, _, err1 = rawSyscall(abi.FuncPCABI0(libc_execve_trampoline),
|
||||
uintptr(unsafe.Pointer(argv0)),
|
||||
uintptr(unsafe.Pointer(&argv[0])),
|
||||
uintptr(unsafe.Pointer(&envv[0])))
|
||||
|
||||
childerror:
|
||||
// send error code on pipe
|
||||
rawSyscall(abi.FuncPCABI0(libc_write_trampoline), uintptr(pipe), uintptr(unsafe.Pointer(&err1)), unsafe.Sizeof(err1))
|
||||
for {
|
||||
rawSyscall(abi.FuncPCABI0(libc_exit_trampoline), 253, 0, 0)
|
||||
}
|
||||
// Time to exec.
|
||||
os.Execve(argv0, argv, envv)
|
||||
/* TODO(xsw):
|
||||
ret := os.Execve(argv0, argv, envv)
|
||||
if ret != 0 {
|
||||
err1 = Errno(ret)
|
||||
}
|
||||
*/
|
||||
panic("todo: syscall.forkAndExecInChild")
|
||||
|
||||
childerror:
|
||||
/* TODO(xsw):
|
||||
// send error code on pipe
|
||||
rawSyscall(abi.FuncPCABI0(libc_write_trampoline), uintptr(pipe), uintptr(unsafe.Pointer(&err1)), unsafe.Sizeof(err1))
|
||||
for {
|
||||
rawSyscall(abi.FuncPCABI0(libc_exit_trampoline), 253, 0, 0)
|
||||
}
|
||||
*/
|
||||
panic("todo: syscall.forkAndExecInChild - childerror")
|
||||
}
|
||||
|
||||
@@ -9,11 +9,14 @@
|
||||
package syscall
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"runtime"
|
||||
"sync"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goplus/llgo/c"
|
||||
"github.com/goplus/llgo/c/os"
|
||||
"github.com/goplus/llgo/c/syscall"
|
||||
)
|
||||
|
||||
// ForkLock is used to synchronize creation of new file descriptors
|
||||
@@ -106,13 +109,10 @@ type ProcAttr struct {
|
||||
Sys *SysProcAttr
|
||||
}
|
||||
|
||||
/* TODO(xsw):
|
||||
var zeroProcAttr ProcAttr
|
||||
var zeroSysProcAttr SysProcAttr
|
||||
*/
|
||||
|
||||
func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error) {
|
||||
/* TODO(xsw):
|
||||
var p [2]int
|
||||
var n int
|
||||
var err1 Errno
|
||||
@@ -127,45 +127,30 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
|
||||
}
|
||||
|
||||
// Convert args to C form.
|
||||
argv0p, err := BytePtrFromString(argv0)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
argvp, err := SlicePtrFromStrings(argv)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
envvp, err := SlicePtrFromStrings(attr.Env)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
argv0p := c.AllocaCStr(argv0)
|
||||
argvp := c.AllocaCStrs(argv, true)
|
||||
envvp := c.AllocaCStrs(attr.Env, true)
|
||||
|
||||
if (runtime.GOOS == "freebsd" || runtime.GOOS == "dragonfly") && len(argv) > 0 && len(argv[0]) > len(argv0) {
|
||||
argvp[0] = argv0p
|
||||
*argvp = argv0p
|
||||
}
|
||||
|
||||
var chroot *byte
|
||||
var chroot *c.Char
|
||||
if sys.Chroot != "" {
|
||||
chroot, err = BytePtrFromString(sys.Chroot)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
chroot = c.AllocaCStr(sys.Chroot)
|
||||
}
|
||||
var dir *byte
|
||||
var dir *c.Char
|
||||
if attr.Dir != "" {
|
||||
dir, err = BytePtrFromString(attr.Dir)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
dir = c.AllocaCStr(attr.Dir)
|
||||
}
|
||||
|
||||
// Both Setctty and Foreground use the Ctty field,
|
||||
// but they give it slightly different meanings.
|
||||
if sys.Setctty && sys.Foreground {
|
||||
return 0, errorspkg.New("both Setctty and Foreground set in SysProcAttr")
|
||||
return 0, errors.New("both Setctty and Foreground set in SysProcAttr")
|
||||
}
|
||||
if sys.Setctty && sys.Ctty >= len(attr.Files) {
|
||||
return 0, errorspkg.New("Setctty set but Ctty not valid in child")
|
||||
return 0, errors.New("Setctty set but Ctty not valid in child")
|
||||
}
|
||||
|
||||
acquireForkLock()
|
||||
@@ -190,7 +175,7 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
|
||||
Close(p[1])
|
||||
for {
|
||||
n, err = readlen(p[0], (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1)))
|
||||
if err != EINTR {
|
||||
if err != Errno(syscall.EINTR) {
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -200,13 +185,13 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
|
||||
err = Errno(err1)
|
||||
}
|
||||
if err == nil {
|
||||
err = EPIPE
|
||||
err = Errno(syscall.EPIPE)
|
||||
}
|
||||
|
||||
// Child failed; wait for it to exit, to make sure
|
||||
// the zombies don't accumulate.
|
||||
_, err1 := Wait4(pid, &wstatus, 0, nil)
|
||||
for err1 == EINTR {
|
||||
for err1 == Errno(syscall.EINTR) {
|
||||
_, err1 = Wait4(pid, &wstatus, 0, nil)
|
||||
}
|
||||
return 0, err
|
||||
@@ -214,8 +199,6 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
|
||||
|
||||
// Read got EOF, so pipe closed on exec, so exec succeeded.
|
||||
return pid, nil
|
||||
*/
|
||||
panic("todo: syscall.forkExec")
|
||||
}
|
||||
|
||||
// Combination of fork and exec, careful to be thread safe.
|
||||
@@ -247,5 +230,5 @@ func Exec(argv0 string, argv []string, envv []string) (err error) {
|
||||
if ret == 0 {
|
||||
return nil
|
||||
}
|
||||
return syscall.Errno(ret)
|
||||
return Errno(ret)
|
||||
}
|
||||
|
||||
39
internal/lib/syscall/forkpipe.go
Normal file
39
internal/lib/syscall/forkpipe.go
Normal file
@@ -0,0 +1,39 @@
|
||||
// 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.
|
||||
|
||||
//go:build aix || darwin
|
||||
|
||||
package syscall
|
||||
|
||||
import (
|
||||
"github.com/goplus/llgo/c"
|
||||
"github.com/goplus/llgo/c/os"
|
||||
"github.com/goplus/llgo/c/syscall"
|
||||
)
|
||||
|
||||
// forkExecPipe opens a pipe and non-atomically sets O_CLOEXEC on both file
|
||||
// descriptors.
|
||||
func forkExecPipe(p []int) error {
|
||||
err := Pipe(p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ret := os.Fcntl(c.Int(p[0]), syscall.F_SETFD, syscall.FD_CLOEXEC)
|
||||
if ret != 0 {
|
||||
return Errno(ret)
|
||||
}
|
||||
ret = os.Fcntl(c.Int(p[1]), syscall.F_SETFD, syscall.FD_CLOEXEC)
|
||||
if ret != 0 {
|
||||
return Errno(ret)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func acquireForkLock() {
|
||||
ForkLock.Lock()
|
||||
}
|
||||
|
||||
func releaseForkLock() {
|
||||
ForkLock.Unlock()
|
||||
}
|
||||
52
internal/lib/syscall/rlimit.go
Normal file
52
internal/lib/syscall/rlimit.go
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright 2022 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
|
||||
|
||||
package syscall
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/goplus/llgo/c/syscall"
|
||||
)
|
||||
|
||||
// origRlimitNofile, if not {0, 0}, is the original soft RLIMIT_NOFILE.
|
||||
// When we can assume that we are bootstrapping with Go 1.19,
|
||||
// this can be atomic.Pointer[Rlimit].
|
||||
var origRlimitNofile atomic.Value // of Rlimit
|
||||
|
||||
// Some systems set an artificially low soft limit on open file count, for compatibility
|
||||
// with code that uses select and its hard-coded maximum file descriptor
|
||||
// (limited by the size of fd_set).
|
||||
//
|
||||
// Go does not use select, so it should not be subject to these limits.
|
||||
// On some systems the limit is 256, which is very easy to run into,
|
||||
// even in simple programs like gofmt when they parallelize walking
|
||||
// a file tree.
|
||||
//
|
||||
// After a long discussion on go.dev/issue/46279, we decided the
|
||||
// best approach was for Go to raise the limit unconditionally for itself,
|
||||
// and then leave old software to set the limit back as needed.
|
||||
// Code that really wants Go to leave the limit alone can set the hard limit,
|
||||
// which Go of course has no choice but to respect.
|
||||
func init() {
|
||||
var lim Rlimit
|
||||
if err := Getrlimit(syscall.RLIMIT_NOFILE, &lim); err == nil && lim.Cur != lim.Max {
|
||||
origRlimitNofile.Store(lim)
|
||||
lim.Cur = lim.Max
|
||||
adjustFileLimit(&lim)
|
||||
setrlimit(syscall.RLIMIT_NOFILE, &lim)
|
||||
}
|
||||
}
|
||||
|
||||
func Setrlimit(resource int, rlim *Rlimit) error {
|
||||
err := setrlimit(resource, rlim)
|
||||
if err == nil && resource == syscall.RLIMIT_NOFILE {
|
||||
// Store zeroes in origRlimitNofile to tell StartProcess
|
||||
// to not adjust the rlimit in the child process.
|
||||
origRlimitNofile.Store(Rlimit{0, 0})
|
||||
}
|
||||
return err
|
||||
}
|
||||
20
internal/lib/syscall/rlimit_darwin.go
Normal file
20
internal/lib/syscall/rlimit_darwin.go
Normal file
@@ -0,0 +1,20 @@
|
||||
// Copyright 2022 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 darwin
|
||||
|
||||
package syscall
|
||||
|
||||
// adjustFileLimit adds per-OS limitations on the Rlimit used for RLIMIT_NOFILE. See rlimit.go.
|
||||
func adjustFileLimit(lim *Rlimit) {
|
||||
// On older macOS, setrlimit(RLIMIT_NOFILE, lim) with lim.Cur = infinity fails.
|
||||
// Set to the value of kern.maxfilesperproc instead.
|
||||
n, err := SysctlUint32("kern.maxfilesperproc")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if lim.Cur > uint64(n) {
|
||||
lim.Cur = uint64(n)
|
||||
}
|
||||
}
|
||||
10
internal/lib/syscall/rlimit_stub.go
Normal file
10
internal/lib/syscall/rlimit_stub.go
Normal file
@@ -0,0 +1,10 @@
|
||||
// Copyright 2022 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 aix || dragonfly || freebsd || linux || netbsd || openbsd || solaris
|
||||
|
||||
package syscall
|
||||
|
||||
// adjustFileLimit adds per-OS limitations on the Rlimit used for RLIMIT_NOFILE. See rlimit.go.
|
||||
func adjustFileLimit(lim *Rlimit) {}
|
||||
@@ -73,24 +73,32 @@ func Getwd() (string, error) {
|
||||
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) {
|
||||
return int(os.Getpid())
|
||||
}
|
||||
|
||||
func Kill(pid int, signum Signal) (err error) {
|
||||
ret := os.Kill(c.Int(pid), c.Int(signum))
|
||||
ret := os.Kill(os.PidT(pid), c.Int(signum))
|
||||
if ret == 0 {
|
||||
return nil
|
||||
}
|
||||
return Errno(os.Errno)
|
||||
return Errno(ret)
|
||||
}
|
||||
|
||||
func fork() (uintptr, Errno) {
|
||||
ret := os.Fork()
|
||||
if ret >= 0 {
|
||||
return uintptr(ret), Errno(0)
|
||||
}
|
||||
return 0, Errno(os.Errno)
|
||||
}
|
||||
|
||||
func wait4(pid int, wstatus *c.Int, options int, rusage *syscall.Rusage) (wpid int, err error) {
|
||||
ret := os.Wait4(os.PidT(pid), wstatus, c.Int(options), rusage)
|
||||
if ret >= 0 {
|
||||
return int(ret), nil
|
||||
}
|
||||
return 0, Errno(os.Errno)
|
||||
}
|
||||
|
||||
func Open(path string, mode int, perm uint32) (fd int, err error) {
|
||||
@@ -117,12 +125,20 @@ func Read(fd int, p []byte) (n int, err error) {
|
||||
return 0, Errno(os.Errno)
|
||||
}
|
||||
|
||||
func readlen(fd int, buf *byte, nbuf int) (n int, err error) {
|
||||
ret := os.Read(c.Int(fd), unsafe.Pointer(buf), uintptr(nbuf))
|
||||
if ret >= 0 {
|
||||
return ret, nil // TODO(xsw): confirm err == nil (not io.EOF) when ret == 0
|
||||
}
|
||||
return 0, Errno(os.Errno)
|
||||
}
|
||||
|
||||
func Close(fd int) (err error) {
|
||||
ret := os.Close(c.Int(fd))
|
||||
if ret == 0 {
|
||||
return nil
|
||||
}
|
||||
return Errno(os.Errno)
|
||||
return Errno(ret)
|
||||
}
|
||||
|
||||
type Stat_t = syscall.Stat_t
|
||||
@@ -132,7 +148,7 @@ func Lstat(path string, stat *Stat_t) (err error) {
|
||||
if ret == 0 {
|
||||
return nil
|
||||
}
|
||||
return Errno(os.Errno)
|
||||
return Errno(ret)
|
||||
}
|
||||
|
||||
func Stat(path string, stat *Stat_t) (err error) {
|
||||
@@ -140,5 +156,37 @@ func Stat(path string, stat *Stat_t) (err error) {
|
||||
if ret == 0 {
|
||||
return nil
|
||||
}
|
||||
return Errno(os.Errno)
|
||||
return Errno(ret)
|
||||
}
|
||||
|
||||
func Pipe(p []int) (err error) {
|
||||
if len(p) != 2 {
|
||||
return Errno(syscall.EINVAL)
|
||||
}
|
||||
var q [2]c.Int
|
||||
ret := os.Pipe(&q)
|
||||
if ret == 0 {
|
||||
p[0] = int(q[0])
|
||||
p[1] = int(q[1])
|
||||
return nil
|
||||
}
|
||||
return Errno(ret)
|
||||
}
|
||||
|
||||
type Rlimit syscall.Rlimit
|
||||
|
||||
func Getrlimit(which int, lim *Rlimit) (err error) {
|
||||
ret := os.Getrlimit(c.Int(which), (*syscall.Rlimit)(lim))
|
||||
if ret == 0 {
|
||||
return nil
|
||||
}
|
||||
return Errno(ret)
|
||||
}
|
||||
|
||||
func setrlimit(which int, lim *Rlimit) (err error) {
|
||||
ret := os.Setrlimit(c.Int(which), (*syscall.Rlimit)(lim))
|
||||
if ret == 0 {
|
||||
return nil
|
||||
}
|
||||
return Errno(ret)
|
||||
}
|
||||
|
||||
@@ -12,6 +12,14 @@
|
||||
|
||||
package syscall
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/goplus/llgo/c"
|
||||
"github.com/goplus/llgo/c/os"
|
||||
"github.com/goplus/llgo/c/syscall"
|
||||
)
|
||||
|
||||
func Getgroups() (gids []int, err error) {
|
||||
/* TODO(xsw):
|
||||
n, err := getgroups(0, nil)
|
||||
@@ -106,9 +114,13 @@ func (w WaitStatus) Signal() Signal {
|
||||
|
||||
func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 }
|
||||
|
||||
func (w WaitStatus) Stopped() bool { return w&mask == stopped && Signal(w>>shift) != SIGSTOP }
|
||||
func (w WaitStatus) Stopped() bool {
|
||||
return w&mask == stopped && Signal(w>>shift) != Signal(syscall.SIGSTOP)
|
||||
}
|
||||
|
||||
func (w WaitStatus) Continued() bool { return w&mask == stopped && Signal(w>>shift) == SIGSTOP }
|
||||
func (w WaitStatus) Continued() bool {
|
||||
return w&mask == stopped && Signal(w>>shift) == Signal(syscall.SIGSTOP)
|
||||
}
|
||||
|
||||
func (w WaitStatus) StopSignal() Signal {
|
||||
if !w.Stopped() {
|
||||
@@ -119,9 +131,8 @@ func (w WaitStatus) StopSignal() Signal {
|
||||
|
||||
func (w WaitStatus) TrapCause() int { return -1 }
|
||||
|
||||
/* TODO(xsw):
|
||||
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
|
||||
var status _C_int
|
||||
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *syscall.Rusage) (wpid int, err error) {
|
||||
var status c.Int
|
||||
wpid, err = wait4(pid, &status, options, rusage)
|
||||
if wstatus != nil {
|
||||
*wstatus = WaitStatus(status)
|
||||
@@ -129,6 +140,7 @@ func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int,
|
||||
return
|
||||
}
|
||||
|
||||
/* TODO(xsw):
|
||||
func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||
if sa.Port < 0 || sa.Port > 0xFFFF {
|
||||
return nil, 0, EINVAL
|
||||
@@ -430,8 +442,10 @@ func Sysctl(name string) (value string, err error) {
|
||||
}
|
||||
return string(buf[0:n]), nil
|
||||
}
|
||||
*/
|
||||
|
||||
func SysctlUint32(name string) (value uint32, err error) {
|
||||
/* TODO(xsw):
|
||||
// Translate name to mib number.
|
||||
mib, err := nametomib(name)
|
||||
if err != nil {
|
||||
@@ -445,11 +459,19 @@ func SysctlUint32(name string) (value uint32, err error) {
|
||||
return 0, err
|
||||
}
|
||||
if n != 4 {
|
||||
return 0, EIO
|
||||
return 0, Errno(syscall.EIO)
|
||||
}
|
||||
return *(*uint32)(unsafe.Pointer(&buf[0])), nil
|
||||
*/
|
||||
n := uintptr(4)
|
||||
ret := os.Sysctlbyname(c.AllocaCStr(name), unsafe.Pointer(&value), &n, nil, 0)
|
||||
if ret != 0 {
|
||||
err = Errno(os.Errno)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
//sys utimes(path string, timeval *[2]Timeval) (err error)
|
||||
|
||||
func Utimes(path string, tv []Timeval) (err error) {
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/goplus/llgo/c"
|
||||
"github.com/goplus/llgo/c/syscall"
|
||||
"github.com/goplus/llgo/internal/lib/internal/oserror"
|
||||
)
|
||||
|
||||
@@ -29,11 +30,11 @@ func (e Errno) Error() string {
|
||||
func (e Errno) Is(target error) bool {
|
||||
switch target {
|
||||
case oserror.ErrPermission:
|
||||
return e == EACCES || e == EPERM
|
||||
return e == Errno(syscall.EACCES) || e == Errno(syscall.EPERM)
|
||||
case oserror.ErrExist:
|
||||
return e == EEXIST || e == ENOTEMPTY
|
||||
return e == Errno(syscall.EEXIST) || e == Errno(syscall.ENOTEMPTY)
|
||||
case oserror.ErrNotExist:
|
||||
return e == ENOENT
|
||||
return e == Errno(syscall.ENOENT)
|
||||
// TODO(xsw): go1.21
|
||||
// case errors.ErrUnsupported:
|
||||
// return e == ENOSYS || e == ENOTSUP || e == EOPNOTSUPP
|
||||
@@ -42,11 +43,12 @@ func (e Errno) Is(target error) bool {
|
||||
}
|
||||
|
||||
func (e Errno) Temporary() bool {
|
||||
return e == EINTR || e == EMFILE || e == ENFILE || e.Timeout()
|
||||
return e == Errno(syscall.EINTR) || e == Errno(syscall.EMFILE) ||
|
||||
e == Errno(syscall.ENFILE) || e.Timeout()
|
||||
}
|
||||
|
||||
func (e Errno) Timeout() bool {
|
||||
return e == EAGAIN || e == EWOULDBLOCK || e == ETIMEDOUT
|
||||
return e == Errno(syscall.EAGAIN) || e == Errno(syscall.EWOULDBLOCK) || e == Errno(syscall.ETIMEDOUT)
|
||||
}
|
||||
|
||||
// A Signal is a number describing a process signal.
|
||||
|
||||
@@ -1,165 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package syscall
|
||||
|
||||
// Errors
|
||||
const (
|
||||
E2BIG = Errno(0x7)
|
||||
EACCES = Errno(0xd)
|
||||
EADDRINUSE = Errno(0x30)
|
||||
EADDRNOTAVAIL = Errno(0x31)
|
||||
EAFNOSUPPORT = Errno(0x2f)
|
||||
EAGAIN = Errno(0x23)
|
||||
EALREADY = Errno(0x25)
|
||||
EAUTH = Errno(0x50)
|
||||
EBADARCH = Errno(0x56)
|
||||
EBADEXEC = Errno(0x55)
|
||||
EBADF = Errno(0x9)
|
||||
EBADMACHO = Errno(0x58)
|
||||
EBADMSG = Errno(0x5e)
|
||||
EBADRPC = Errno(0x48)
|
||||
EBUSY = Errno(0x10)
|
||||
ECANCELED = Errno(0x59)
|
||||
ECHILD = Errno(0xa)
|
||||
ECONNABORTED = Errno(0x35)
|
||||
ECONNREFUSED = Errno(0x3d)
|
||||
ECONNRESET = Errno(0x36)
|
||||
EDEADLK = Errno(0xb)
|
||||
EDESTADDRREQ = Errno(0x27)
|
||||
EDEVERR = Errno(0x53)
|
||||
EDOM = Errno(0x21)
|
||||
EDQUOT = Errno(0x45)
|
||||
EEXIST = Errno(0x11)
|
||||
EFAULT = Errno(0xe)
|
||||
EFBIG = Errno(0x1b)
|
||||
EFTYPE = Errno(0x4f)
|
||||
EHOSTDOWN = Errno(0x40)
|
||||
EHOSTUNREACH = Errno(0x41)
|
||||
EIDRM = Errno(0x5a)
|
||||
EILSEQ = Errno(0x5c)
|
||||
EINPROGRESS = Errno(0x24)
|
||||
EINTR = Errno(0x4)
|
||||
EINVAL = Errno(0x16)
|
||||
EIO = Errno(0x5)
|
||||
EISCONN = Errno(0x38)
|
||||
EISDIR = Errno(0x15)
|
||||
ELAST = Errno(0x6a)
|
||||
ELOOP = Errno(0x3e)
|
||||
EMFILE = Errno(0x18)
|
||||
EMLINK = Errno(0x1f)
|
||||
EMSGSIZE = Errno(0x28)
|
||||
EMULTIHOP = Errno(0x5f)
|
||||
ENAMETOOLONG = Errno(0x3f)
|
||||
ENEEDAUTH = Errno(0x51)
|
||||
ENETDOWN = Errno(0x32)
|
||||
ENETRESET = Errno(0x34)
|
||||
ENETUNREACH = Errno(0x33)
|
||||
ENFILE = Errno(0x17)
|
||||
ENOATTR = Errno(0x5d)
|
||||
ENOBUFS = Errno(0x37)
|
||||
ENODATA = Errno(0x60)
|
||||
ENODEV = Errno(0x13)
|
||||
ENOENT = Errno(0x2)
|
||||
ENOEXEC = Errno(0x8)
|
||||
ENOLCK = Errno(0x4d)
|
||||
ENOLINK = Errno(0x61)
|
||||
ENOMEM = Errno(0xc)
|
||||
ENOMSG = Errno(0x5b)
|
||||
ENOPOLICY = Errno(0x67)
|
||||
ENOPROTOOPT = Errno(0x2a)
|
||||
ENOSPC = Errno(0x1c)
|
||||
ENOSR = Errno(0x62)
|
||||
ENOSTR = Errno(0x63)
|
||||
ENOSYS = Errno(0x4e)
|
||||
ENOTBLK = Errno(0xf)
|
||||
ENOTCONN = Errno(0x39)
|
||||
ENOTDIR = Errno(0x14)
|
||||
ENOTEMPTY = Errno(0x42)
|
||||
ENOTRECOVERABLE = Errno(0x68)
|
||||
ENOTSOCK = Errno(0x26)
|
||||
ENOTSUP = Errno(0x2d)
|
||||
ENOTTY = Errno(0x19)
|
||||
ENXIO = Errno(0x6)
|
||||
EOPNOTSUPP = Errno(0x66)
|
||||
EOVERFLOW = Errno(0x54)
|
||||
EOWNERDEAD = Errno(0x69)
|
||||
EPERM = Errno(0x1)
|
||||
EPFNOSUPPORT = Errno(0x2e)
|
||||
EPIPE = Errno(0x20)
|
||||
EPROCLIM = Errno(0x43)
|
||||
EPROCUNAVAIL = Errno(0x4c)
|
||||
EPROGMISMATCH = Errno(0x4b)
|
||||
EPROGUNAVAIL = Errno(0x4a)
|
||||
EPROTO = Errno(0x64)
|
||||
EPROTONOSUPPORT = Errno(0x2b)
|
||||
EPROTOTYPE = Errno(0x29)
|
||||
EPWROFF = Errno(0x52)
|
||||
EQFULL = Errno(0x6a)
|
||||
ERANGE = Errno(0x22)
|
||||
EREMOTE = Errno(0x47)
|
||||
EROFS = Errno(0x1e)
|
||||
ERPCMISMATCH = Errno(0x49)
|
||||
ESHLIBVERS = Errno(0x57)
|
||||
ESHUTDOWN = Errno(0x3a)
|
||||
ESOCKTNOSUPPORT = Errno(0x2c)
|
||||
ESPIPE = Errno(0x1d)
|
||||
ESRCH = Errno(0x3)
|
||||
ESTALE = Errno(0x46)
|
||||
ETIME = Errno(0x65)
|
||||
ETIMEDOUT = Errno(0x3c)
|
||||
ETOOMANYREFS = Errno(0x3b)
|
||||
ETXTBSY = Errno(0x1a)
|
||||
EUSERS = Errno(0x44)
|
||||
EWOULDBLOCK = Errno(0x23)
|
||||
EXDEV = Errno(0x12)
|
||||
)
|
||||
|
||||
// Signals
|
||||
const (
|
||||
SIGABRT = Signal(0x6)
|
||||
SIGALRM = Signal(0xe)
|
||||
SIGBUS = Signal(0xa)
|
||||
SIGCHLD = Signal(0x14)
|
||||
SIGCONT = Signal(0x13)
|
||||
SIGEMT = Signal(0x7)
|
||||
SIGFPE = Signal(0x8)
|
||||
SIGHUP = Signal(0x1)
|
||||
SIGILL = Signal(0x4)
|
||||
SIGINFO = Signal(0x1d)
|
||||
SIGINT = Signal(0x2)
|
||||
SIGIO = Signal(0x17)
|
||||
SIGIOT = Signal(0x6)
|
||||
SIGKILL = Signal(0x9)
|
||||
SIGPIPE = Signal(0xd)
|
||||
SIGPROF = Signal(0x1b)
|
||||
SIGQUIT = Signal(0x3)
|
||||
SIGSEGV = Signal(0xb)
|
||||
SIGSTOP = Signal(0x11)
|
||||
SIGSYS = Signal(0xc)
|
||||
SIGTERM = Signal(0xf)
|
||||
SIGTRAP = Signal(0x5)
|
||||
SIGTSTP = Signal(0x12)
|
||||
SIGTTIN = Signal(0x15)
|
||||
SIGTTOU = Signal(0x16)
|
||||
SIGURG = Signal(0x10)
|
||||
SIGUSR1 = Signal(0x1e)
|
||||
SIGUSR2 = Signal(0x1f)
|
||||
SIGVTALRM = Signal(0x1a)
|
||||
SIGWINCH = Signal(0x1c)
|
||||
SIGXCPU = Signal(0x18)
|
||||
SIGXFSZ = Signal(0x19)
|
||||
)
|
||||
@@ -1,193 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package syscall
|
||||
|
||||
// Errors
|
||||
const (
|
||||
E2BIG = Errno(0x7)
|
||||
EACCES = Errno(0xd)
|
||||
EADDRINUSE = Errno(0x62)
|
||||
EADDRNOTAVAIL = Errno(0x63)
|
||||
EADV = Errno(0x44)
|
||||
EAFNOSUPPORT = Errno(0x61)
|
||||
EAGAIN = Errno(0xb)
|
||||
EALREADY = Errno(0x72)
|
||||
EBADE = Errno(0x34)
|
||||
EBADF = Errno(0x9)
|
||||
EBADFD = Errno(0x4d)
|
||||
EBADMSG = Errno(0x4a)
|
||||
EBADR = Errno(0x35)
|
||||
EBADRQC = Errno(0x38)
|
||||
EBADSLT = Errno(0x39)
|
||||
EBFONT = Errno(0x3b)
|
||||
EBUSY = Errno(0x10)
|
||||
ECANCELED = Errno(0x7d)
|
||||
ECHILD = Errno(0xa)
|
||||
ECHRNG = Errno(0x2c)
|
||||
ECOMM = Errno(0x46)
|
||||
ECONNABORTED = Errno(0x67)
|
||||
ECONNREFUSED = Errno(0x6f)
|
||||
ECONNRESET = Errno(0x68)
|
||||
EDEADLK = Errno(0x23)
|
||||
EDEADLOCK = Errno(0x23)
|
||||
EDESTADDRREQ = Errno(0x59)
|
||||
EDOM = Errno(0x21)
|
||||
EDOTDOT = Errno(0x49)
|
||||
EDQUOT = Errno(0x7a)
|
||||
EEXIST = Errno(0x11)
|
||||
EFAULT = Errno(0xe)
|
||||
EFBIG = Errno(0x1b)
|
||||
EHOSTDOWN = Errno(0x70)
|
||||
EHOSTUNREACH = Errno(0x71)
|
||||
EIDRM = Errno(0x2b)
|
||||
EILSEQ = Errno(0x54)
|
||||
EINPROGRESS = Errno(0x73)
|
||||
EINTR = Errno(0x4)
|
||||
EINVAL = Errno(0x16)
|
||||
EIO = Errno(0x5)
|
||||
EISCONN = Errno(0x6a)
|
||||
EISDIR = Errno(0x15)
|
||||
EISNAM = Errno(0x78)
|
||||
EKEYEXPIRED = Errno(0x7f)
|
||||
EKEYREJECTED = Errno(0x81)
|
||||
EKEYREVOKED = Errno(0x80)
|
||||
EL2HLT = Errno(0x33)
|
||||
EL2NSYNC = Errno(0x2d)
|
||||
EL3HLT = Errno(0x2e)
|
||||
EL3RST = Errno(0x2f)
|
||||
ELIBACC = Errno(0x4f)
|
||||
ELIBBAD = Errno(0x50)
|
||||
ELIBEXEC = Errno(0x53)
|
||||
ELIBMAX = Errno(0x52)
|
||||
ELIBSCN = Errno(0x51)
|
||||
ELNRNG = Errno(0x30)
|
||||
ELOOP = Errno(0x28)
|
||||
EMEDIUMTYPE = Errno(0x7c)
|
||||
EMFILE = Errno(0x18)
|
||||
EMLINK = Errno(0x1f)
|
||||
EMSGSIZE = Errno(0x5a)
|
||||
EMULTIHOP = Errno(0x48)
|
||||
ENAMETOOLONG = Errno(0x24)
|
||||
ENAVAIL = Errno(0x77)
|
||||
ENETDOWN = Errno(0x64)
|
||||
ENETRESET = Errno(0x66)
|
||||
ENETUNREACH = Errno(0x65)
|
||||
ENFILE = Errno(0x17)
|
||||
ENOANO = Errno(0x37)
|
||||
ENOBUFS = Errno(0x69)
|
||||
ENOCSI = Errno(0x32)
|
||||
ENODATA = Errno(0x3d)
|
||||
ENODEV = Errno(0x13)
|
||||
ENOENT = Errno(0x2)
|
||||
ENOEXEC = Errno(0x8)
|
||||
ENOKEY = Errno(0x7e)
|
||||
ENOLCK = Errno(0x25)
|
||||
ENOLINK = Errno(0x43)
|
||||
ENOMEDIUM = Errno(0x7b)
|
||||
ENOMEM = Errno(0xc)
|
||||
ENOMSG = Errno(0x2a)
|
||||
ENONET = Errno(0x40)
|
||||
ENOPKG = Errno(0x41)
|
||||
ENOPROTOOPT = Errno(0x5c)
|
||||
ENOSPC = Errno(0x1c)
|
||||
ENOSR = Errno(0x3f)
|
||||
ENOSTR = Errno(0x3c)
|
||||
ENOSYS = Errno(0x26)
|
||||
ENOTBLK = Errno(0xf)
|
||||
ENOTCONN = Errno(0x6b)
|
||||
ENOTDIR = Errno(0x14)
|
||||
ENOTEMPTY = Errno(0x27)
|
||||
ENOTNAM = Errno(0x76)
|
||||
ENOTRECOVERABLE = Errno(0x83)
|
||||
ENOTSOCK = Errno(0x58)
|
||||
ENOTSUP = Errno(0x5f)
|
||||
ENOTTY = Errno(0x19)
|
||||
ENOTUNIQ = Errno(0x4c)
|
||||
ENXIO = Errno(0x6)
|
||||
EOPNOTSUPP = Errno(0x5f)
|
||||
EOVERFLOW = Errno(0x4b)
|
||||
EOWNERDEAD = Errno(0x82)
|
||||
EPERM = Errno(0x1)
|
||||
EPFNOSUPPORT = Errno(0x60)
|
||||
EPIPE = Errno(0x20)
|
||||
EPROTO = Errno(0x47)
|
||||
EPROTONOSUPPORT = Errno(0x5d)
|
||||
EPROTOTYPE = Errno(0x5b)
|
||||
ERANGE = Errno(0x22)
|
||||
EREMCHG = Errno(0x4e)
|
||||
EREMOTE = Errno(0x42)
|
||||
EREMOTEIO = Errno(0x79)
|
||||
ERESTART = Errno(0x55)
|
||||
ERFKILL = Errno(0x84)
|
||||
EROFS = Errno(0x1e)
|
||||
ESHUTDOWN = Errno(0x6c)
|
||||
ESOCKTNOSUPPORT = Errno(0x5e)
|
||||
ESPIPE = Errno(0x1d)
|
||||
ESRCH = Errno(0x3)
|
||||
ESRMNT = Errno(0x45)
|
||||
ESTALE = Errno(0x74)
|
||||
ESTRPIPE = Errno(0x56)
|
||||
ETIME = Errno(0x3e)
|
||||
ETIMEDOUT = Errno(0x6e)
|
||||
ETOOMANYREFS = Errno(0x6d)
|
||||
ETXTBSY = Errno(0x1a)
|
||||
EUCLEAN = Errno(0x75)
|
||||
EUNATCH = Errno(0x31)
|
||||
EUSERS = Errno(0x57)
|
||||
EWOULDBLOCK = Errno(0xb)
|
||||
EXDEV = Errno(0x12)
|
||||
EXFULL = Errno(0x36)
|
||||
)
|
||||
|
||||
// Signals
|
||||
const (
|
||||
SIGABRT = Signal(0x6)
|
||||
SIGALRM = Signal(0xe)
|
||||
SIGBUS = Signal(0x7)
|
||||
SIGCHLD = Signal(0x11)
|
||||
SIGCLD = Signal(0x11)
|
||||
SIGCONT = Signal(0x12)
|
||||
SIGFPE = Signal(0x8)
|
||||
SIGHUP = Signal(0x1)
|
||||
SIGILL = Signal(0x4)
|
||||
SIGINT = Signal(0x2)
|
||||
SIGIO = Signal(0x1d)
|
||||
SIGIOT = Signal(0x6)
|
||||
SIGKILL = Signal(0x9)
|
||||
SIGPIPE = Signal(0xd)
|
||||
SIGPOLL = Signal(0x1d)
|
||||
SIGPROF = Signal(0x1b)
|
||||
SIGPWR = Signal(0x1e)
|
||||
SIGQUIT = Signal(0x3)
|
||||
SIGSEGV = Signal(0xb)
|
||||
SIGSTKFLT = Signal(0x10)
|
||||
SIGSTOP = Signal(0x13)
|
||||
SIGSYS = Signal(0x1f)
|
||||
SIGTERM = Signal(0xf)
|
||||
SIGTRAP = Signal(0x5)
|
||||
SIGTSTP = Signal(0x14)
|
||||
SIGTTIN = Signal(0x15)
|
||||
SIGTTOU = Signal(0x16)
|
||||
SIGUNUSED = Signal(0x1f)
|
||||
SIGURG = Signal(0x17)
|
||||
SIGUSR1 = Signal(0xa)
|
||||
SIGUSR2 = Signal(0xc)
|
||||
SIGVTALRM = Signal(0x1a)
|
||||
SIGWINCH = Signal(0x1c)
|
||||
SIGXCPU = Signal(0x18)
|
||||
SIGXFSZ = Signal(0x19)
|
||||
)
|
||||
Reference in New Issue
Block a user