Source file src/pkg/syscall/exec_unix.go
1
2
3
4
5
6
7
8
9 package syscall
10
11 import (
12 "internal/bytealg"
13 "runtime"
14 "sync"
15 "unsafe"
16 )
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 var ForkLock sync.RWMutex
66
67
68
69
70
71
72 func StringSlicePtr(ss []string) []*byte {
73 bb := make([]*byte, len(ss)+1)
74 for i := 0; i < len(ss); i++ {
75 bb[i] = StringBytePtr(ss[i])
76 }
77 bb[len(ss)] = nil
78 return bb
79 }
80
81
82
83
84 func SlicePtrFromStrings(ss []string) ([]*byte, error) {
85 n := 0
86 for _, s := range ss {
87 if bytealg.IndexByteString(s, 0) != -1 {
88 return nil, EINVAL
89 }
90 n += len(s) + 1
91 }
92 bb := make([]*byte, len(ss)+1)
93 b := make([]byte, n)
94 n = 0
95 for i, s := range ss {
96 bb[i] = &b[n]
97 copy(b[n:], s)
98 n += len(s) + 1
99 }
100 return bb, nil
101 }
102
103 func CloseOnExec(fd int) { fcntl(fd, F_SETFD, FD_CLOEXEC) }
104
105 func SetNonblock(fd int, nonblocking bool) (err error) {
106 flag, err := fcntl(fd, F_GETFL, 0)
107 if err != nil {
108 return err
109 }
110 if nonblocking {
111 flag |= O_NONBLOCK
112 } else {
113 flag &^= O_NONBLOCK
114 }
115 _, err = fcntl(fd, F_SETFL, flag)
116 return err
117 }
118
119
120
121 type Credential struct {
122 Uid uint32
123 Gid uint32
124 Groups []uint32
125 NoSetGroups bool
126 }
127
128
129
130 type ProcAttr struct {
131 Dir string
132 Env []string
133 Files []uintptr
134 Sys *SysProcAttr
135 }
136
137 var zeroProcAttr ProcAttr
138 var zeroSysProcAttr SysProcAttr
139
140 func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error) {
141 var p [2]int
142 var n int
143 var err1 Errno
144 var wstatus WaitStatus
145
146 if attr == nil {
147 attr = &zeroProcAttr
148 }
149 sys := attr.Sys
150 if sys == nil {
151 sys = &zeroSysProcAttr
152 }
153
154 p[0] = -1
155 p[1] = -1
156
157
158 argv0p, err := BytePtrFromString(argv0)
159 if err != nil {
160 return 0, err
161 }
162 argvp, err := SlicePtrFromStrings(argv)
163 if err != nil {
164 return 0, err
165 }
166 envvp, err := SlicePtrFromStrings(attr.Env)
167 if err != nil {
168 return 0, err
169 }
170
171 if (runtime.GOOS == "freebsd" || runtime.GOOS == "dragonfly") && len(argv[0]) > len(argv0) {
172 argvp[0] = argv0p
173 }
174
175 var chroot *byte
176 if sys.Chroot != "" {
177 chroot, err = BytePtrFromString(sys.Chroot)
178 if err != nil {
179 return 0, err
180 }
181 }
182 var dir *byte
183 if attr.Dir != "" {
184 dir, err = BytePtrFromString(attr.Dir)
185 if err != nil {
186 return 0, err
187 }
188 }
189
190
191
192
193 ForkLock.Lock()
194
195
196 if err = forkExecPipe(p[:]); err != nil {
197 goto error
198 }
199
200
201 pid, err1 = forkAndExecInChild(argv0p, argvp, envvp, chroot, dir, attr, sys, p[1])
202 if err1 != 0 {
203 err = Errno(err1)
204 goto error
205 }
206 ForkLock.Unlock()
207
208
209 Close(p[1])
210 n, err = readlen(p[0], (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1)))
211 Close(p[0])
212 if err != nil || n != 0 {
213 if n == int(unsafe.Sizeof(err1)) {
214 err = Errno(err1)
215 }
216 if err == nil {
217 err = EPIPE
218 }
219
220
221
222 _, err1 := Wait4(pid, &wstatus, 0, nil)
223 for err1 == EINTR {
224 _, err1 = Wait4(pid, &wstatus, 0, nil)
225 }
226 return 0, err
227 }
228
229
230 return pid, nil
231
232 error:
233 if p[0] >= 0 {
234 Close(p[0])
235 Close(p[1])
236 }
237 ForkLock.Unlock()
238 return 0, err
239 }
240
241
242 func ForkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error) {
243 return forkExec(argv0, argv, attr)
244 }
245
246
247 func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle uintptr, err error) {
248 pid, err = forkExec(argv0, argv, attr)
249 return pid, 0, err
250 }
251
252
253 func runtime_BeforeExec()
254 func runtime_AfterExec()
255
256
257
258 var execveLibc func(path uintptr, argv uintptr, envp uintptr) Errno
259 var execveDarwin func(path *byte, argv **byte, envp **byte) error
260
261
262 func Exec(argv0 string, argv []string, envv []string) (err error) {
263 argv0p, err := BytePtrFromString(argv0)
264 if err != nil {
265 return err
266 }
267 argvp, err := SlicePtrFromStrings(argv)
268 if err != nil {
269 return err
270 }
271 envvp, err := SlicePtrFromStrings(envv)
272 if err != nil {
273 return err
274 }
275 runtime_BeforeExec()
276
277 var err1 error
278 if runtime.GOOS == "solaris" || runtime.GOOS == "illumos" || runtime.GOOS == "aix" {
279
280 err1 = execveLibc(
281 uintptr(unsafe.Pointer(argv0p)),
282 uintptr(unsafe.Pointer(&argvp[0])),
283 uintptr(unsafe.Pointer(&envvp[0])))
284 } else if runtime.GOOS == "darwin" {
285
286 err1 = execveDarwin(argv0p, &argvp[0], &envvp[0])
287 } else {
288 _, _, err1 = RawSyscall(SYS_EXECVE,
289 uintptr(unsafe.Pointer(argv0p)),
290 uintptr(unsafe.Pointer(&argvp[0])),
291 uintptr(unsafe.Pointer(&envvp[0])))
292 }
293 runtime_AfterExec()
294 return err1
295 }
296
View as plain text