1+ //go: build !darwin && !nintendoswitch && !wasip1 && !wasip2
2+
13package syscall
24
3- func Exec ( argv0 string , argv [] string , envv [] string ) ( err error )
5+ import "errors"
46
57// The two SockaddrInet* structs have been copied from the Go source tree.
6-
78type SockaddrInet4 struct {
89 Port int
910 Addr [4 ]byte
@@ -16,3 +17,54 @@ type SockaddrInet6 struct {
1617 Addr [16 ]byte
1718 raw RawSockaddrInet6
1819}
20+
21+ func Fork () (err error ) {
22+ fail := int (libc_fork ())
23+ if fail < 0 {
24+ // TODO: parse the syscall return codes
25+ return errors .New ("fork failed" )
26+ }
27+ return
28+ }
29+
30+ // the golang standard library does not expose interfaces for execve and fork, so we define them here the same way via the libc wrapper
31+ func Execve (pathname string , argv []string , envv []string ) (err error ) {
32+ argv0 := cstring (pathname )
33+
34+ // transform argv and envv into the format expected by execve
35+ argv1 := make ([]* byte , len (argv )+ 1 )
36+ for i , arg := range argv {
37+ argv1 [i ] = & cstring (arg )[0 ]
38+ }
39+ argv1 [len (argv )] = nil
40+
41+ env1 := make ([]* byte , len (envv )+ 1 )
42+ for i , env := range envv {
43+ env1 [i ] = & cstring (env )[0 ]
44+ }
45+ env1 [len (envv )] = nil
46+
47+ fail := int (libc_execve (& argv0 [0 ], & argv1 [0 ], & env1 [0 ]))
48+ if fail < 0 {
49+ // TODO: parse the syscall return codes
50+ return errors .New ("fork failed" )
51+ }
52+ return
53+ }
54+
55+ func cstring (s string ) []byte {
56+ data := make ([]byte , len (s )+ 1 )
57+ copy (data , s )
58+ // final byte should be zero from the initial allocation
59+ return data
60+ }
61+
62+ // pid_t fork(void);
63+ //
64+ //export fork
65+ func libc_fork () int32
66+
67+ // int execve(const char *filename, char *const argv[], char *const envp[]);
68+ //
69+ //export execve
70+ func libc_execve (filename * byte , argv * * byte , envp * * byte ) int
0 commit comments