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