Skip to content

Commit 8cce6c2

Browse files
committed
os rework
1 parent 2b0cd9e commit 8cce6c2

File tree

3 files changed

+65
-83
lines changed

3 files changed

+65
-83
lines changed

src/os/exec_linux.go

+5-31
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

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

src/syscall/syscall_unix.go

+4-52
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)