Skip to content

Commit 43fcf8f

Browse files
committed
os rework
1 parent 2b0cd9e commit 43fcf8f

File tree

3 files changed

+64
-83
lines changed

3 files changed

+64
-83
lines changed

src/os/exec_linux.go

Lines changed: 5 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,6 @@ func (p *Process) release() error {
4646
// * No parent-child communication via pipes (TODO)
4747
// * No waiting for crashes child processes to prohibit zombie process accumulation / Wait status checking (TODO)
4848
func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error) {
49-
var (
50-
ret uintptr
51-
)
52-
5349
if len(argv) == 0 {
5450
return 0, errors.New("exec: no argv")
5551
}
@@ -58,40 +54,18 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
5854
attr = new(ProcAttr)
5955
}
6056

61-
argv0p, err := syscall.BytePtrFromString(argv0)
62-
if err != nil {
63-
return 0, err
64-
}
65-
argvp, err := syscall.SlicePtrFromStrings(argv)
66-
if err != nil {
67-
return 0, err
68-
}
69-
envp, err := syscall.SlicePtrFromStrings(attr.Env)
57+
pid, err = Fork()
7058
if err != nil {
7159
return 0, err
72-
}
73-
74-
if (runtime.GOOS == "freebsd" || runtime.GOOS == "dragonfly") && len(argv) > 0 && len(argv[0]) > len(argv0) {
75-
argvp[0] = argv0p
76-
}
77-
78-
ret = syscall.Fork()
79-
if int(ret) < 0 {
80-
return 0, errors.New("fork failed")
81-
}
82-
83-
if int(ret) != 0 {
84-
// if fd == 0 code runs in parent
85-
return int(ret), nil
8660
} else {
8761
// else code runs in child, which then should exec the new process
88-
ret = syscall.Execve(argv0, argv, envp)
89-
if int(ret) != 0 {
62+
err = Execve(argv0, argv, attr.Env)
63+
if err != nil {
9064
// exec failed
91-
return int(ret), errors.New("exec failed")
65+
return 0, err
9266
}
9367
// 3. TODO: use pipes to communicate back child status
94-
return int(ret), nil
68+
return pid, nil
9569
}
9670
}
9771

src/os/osexec.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
//go: build linux
2+
3+
package os
4+
5+
import (
6+
"errors"
7+
"syscall"
8+
"unsafe"
9+
)
10+
11+
func Fork() (pid int, err error) {
12+
// ret := libc_fork()
13+
// ret, _, _ := syscall.Syscall(syscall.SYS_FORK, 0, 0, 0)
14+
ret, _, _ := syscall.Syscall(57, 0, 0, 0)
15+
if ret < 0 {
16+
// TODO: parse the syscall return codes
17+
return 0, errors.New("fork failed")
18+
}
19+
return int(ret), nil
20+
}
21+
22+
// the golang standard library does not expose interfaces for execve and fork, so we define them here the same way via the libc wrapper
23+
func Execve(pathname string, argv []string, envv []string) (err error) {
24+
argv0 := cstring(pathname)
25+
26+
// transform argv and envv into the format expected by execve
27+
argv1 := make([]*byte, len(argv)+1)
28+
for i, arg := range argv {
29+
argv1[i] = &cstring(arg)[0]
30+
}
31+
argv1[len(argv)] = nil
32+
33+
env1 := make([]*byte, len(envv)+1)
34+
for i, env := range envv {
35+
env1[i] = &cstring(env)[0]
36+
}
37+
env1[len(envv)] = nil
38+
39+
// fail := libc_execve(&argv0[0], &argv1[0], &env1[0])
40+
// fail, _, _ := syscall.Syscall(syscall.SYS_EXECVE, uintptr(unsafe.Pointer(&argv0[0])), uintptr(unsafe.Pointer(&argv1[0])), uintptr(unsafe.Pointer(&env1[0])))
41+
fail, _, _ := syscall.Syscall(59, uintptr(unsafe.Pointer(&argv0[0])), uintptr(unsafe.Pointer(&argv1[0])), uintptr(unsafe.Pointer(&env1[0])))
42+
if fail < 0 {
43+
// TODO: parse the syscall return codes
44+
return errors.New("execve failed")
45+
}
46+
47+
return nil
48+
}
49+
50+
func cstring(s string) []byte {
51+
data := make([]byte, len(s)+1)
52+
copy(data, s)
53+
// final byte should be zero from the initial allocation
54+
return data
55+
}

src/syscall/syscall_unix.go

Lines changed: 4 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33

44
package syscall
55

6-
import "errors"
7-
86
func Exec(argv0 string, argv []string, envv []string) (err error)
97

108
// The two SockaddrInet* structs have been copied from the Go source tree.
@@ -22,53 +20,7 @@ type SockaddrInet6 struct {
2220
raw RawSockaddrInet6
2321
}
2422

25-
func Fork() (err error) {
26-
fail := int(libc_fork())
27-
if fail < 0 {
28-
// TODO: parse the syscall return codes
29-
return errors.New("fork failed")
30-
}
31-
return
32-
}
33-
34-
// the golang standard library does not expose interfaces for execve and fork, so we define them here the same way via the libc wrapper
35-
func Execve(pathname string, argv []string, envv []string) (err error) {
36-
argv0 := cstring(pathname)
37-
38-
// transform argv and envv into the format expected by execve
39-
argv1 := make([]*byte, len(argv)+1)
40-
for i, arg := range argv {
41-
argv1[i] = &cstring(arg)[0]
42-
}
43-
argv1[len(argv)] = nil
44-
45-
env1 := make([]*byte, len(envv)+1)
46-
for i, env := range envv {
47-
env1[i] = &cstring(env)[0]
48-
}
49-
env1[len(envv)] = nil
50-
51-
fail := int(libc_execve(&argv0[0], &argv1[0], &env1[0]))
52-
if fail < 0 {
53-
// TODO: parse the syscall return codes
54-
return errors.New("fork failed")
55-
}
56-
return
57-
}
58-
59-
func cstring(s string) []byte {
60-
data := make([]byte, len(s)+1)
61-
copy(data, s)
62-
// final byte should be zero from the initial allocation
63-
return data
64-
}
65-
66-
// pid_t fork(void);
67-
//
68-
//export fork
69-
func libc_fork() int32
70-
71-
// int execve(const char *filename, char *const argv[], char *const envp[]);
72-
//
73-
//export execve
74-
func libc_execve(filename *byte, argv **byte, envp **byte) int
23+
const (
24+
SYS_FORK = 57
25+
SYS_EXECVE = 59
26+
)

0 commit comments

Comments
 (0)