osexec.mx raw
1 //go:build linux && !baremetal && !moxie.wasm && !nintendoswitch
2
3 package os
4
5 import (
6 "syscall"
7 "unsafe"
8 )
9
10 func fork() (pid int32, err error) {
11 pid = libc_fork()
12 if pid != 0 {
13 if errno := *libc_errno(); errno != 0 {
14 err = syscall.Errno(*libc_errno())
15 }
16 }
17 return
18 }
19
20 // the golang standard library does not expose interfaces for execve and fork, so we define them here the same way via the libc wrapper
21 func execve(pathname string, argv []string, envv []string) error {
22 argv0 := cstring(pathname)
23
24 // transform argv and envv into the format expected by execve
25 argv1 := make([]*byte, len(argv)+1)
26 for i, arg := range argv {
27 argv1[i] = &cstring(arg)[0]
28 }
29 argv1[len(argv)] = nil
30
31 env1 := make([]*byte, len(envv)+1)
32 for i, env := range envv {
33 env1[i] = &cstring(env)[0]
34 }
35 env1[len(envv)] = nil
36
37 ret, _, err := syscall.Syscall(syscall.SYS_EXECVE, uintptr(unsafe.Pointer(&argv0[0])), uintptr(unsafe.Pointer(&argv1[0])), uintptr(unsafe.Pointer(&env1[0])))
38 if int(ret) != 0 {
39 return err
40 }
41
42 return nil
43 }
44
45 func cstring(s string) []byte {
46 data := make([]byte, len(s)+1)
47 copy(data, s)
48 // final byte should be zero from the initial allocation
49 return data
50 }
51
52 //export fork
53 func libc_fork() int32
54
55 //export _exit
56 func libc_exit(code int32)
57
58 // Internal musl function to get the C errno pointer.
59 //
60 //export __errno_location
61 func libc_errno() *int32
62