Source file
src/syscall/exec_plan9.go
1
2
3
4
5
6
7 package syscall
8
9 import (
10 "internal/itoa"
11 "runtime"
12 "sync"
13 "unsafe"
14 )
15
16
17 var ForkLock sync.RWMutex
18
19
20
21
22
23
24 func gstringb(b []byte) []byte {
25 if len(b) < 2 {
26 return nil
27 }
28 n, b := gbit16(b)
29 if int(n) > len(b) {
30 return nil
31 }
32 return b[:n]
33 }
34
35
36 const nameOffset = 39
37
38
39
40
41
42
43 func gdirname(buf []byte) (name []byte, rest []byte) {
44 if len(buf) < 2 {
45 return
46 }
47 size, buf := gbit16(buf)
48 if size < STATFIXLEN || int(size) > len(buf) {
49 return
50 }
51 name = gstringb(buf[nameOffset:size])
52 rest = buf[size:]
53 return
54 }
55
56
57
58
59
60
61 func StringSlicePtr(ss []string) []*byte {
62 bb := make([]*byte, len(ss)+1)
63 for i := 0; i < len(ss); i++ {
64 bb[i] = StringBytePtr(ss[i])
65 }
66 bb[len(ss)] = nil
67 return bb
68 }
69
70
71
72
73 func SlicePtrFromStrings(ss []string) ([]*byte, error) {
74 var err error
75 bb := make([]*byte, len(ss)+1)
76 for i := 0; i < len(ss); i++ {
77 bb[i], err = BytePtrFromString(ss[i])
78 if err != nil {
79 return nil, err
80 }
81 }
82 bb[len(ss)] = nil
83 return bb, nil
84 }
85
86
87 func readdirnames(dirfd int) (names []string, err error) {
88 names = make([]string, 0, 100)
89 var buf [STATMAX]byte
90
91 for {
92 n, e := Read(dirfd, buf[:])
93 if e != nil {
94 return nil, e
95 }
96 if n == 0 {
97 break
98 }
99 for b := buf[:n]; len(b) > 0; {
100 var s []byte
101 s, b = gdirname(b)
102 if s == nil {
103 return nil, ErrBadStat
104 }
105 names = append(names, string(s))
106 }
107 }
108 return
109 }
110
111
112 var dupdev, _ = BytePtrFromString("#d")
113
114
115
116
117
118
119
120
121
122
123
124
125
126 func forkAndExecInChild(argv0 *byte, argv []*byte, envv []envItem, dir *byte, attr *ProcAttr, pipe int, rflag int) (pid int, err error) {
127
128
129 var (
130 r1 uintptr
131 nextfd int
132 i int
133 clearenv int
134 envfd int
135 errbuf [ERRMAX]byte
136 statbuf [STATMAX]byte
137 dupdevfd int
138 n int
139 b []byte
140 )
141
142
143
144
145 fd := make([]int, len(attr.Files))
146 nextfd = len(attr.Files)
147 for i, ufd := range attr.Files {
148 if nextfd < int(ufd) {
149 nextfd = int(ufd)
150 }
151 fd[i] = int(ufd)
152 }
153 nextfd++
154
155 if envv != nil {
156 clearenv = RFCENVG
157 }
158
159
160
161 r1, _, _ = RawSyscall(SYS_RFORK, uintptr(RFPROC|RFFDG|RFREND|clearenv|rflag), 0, 0)
162
163 if r1 != 0 {
164 if int32(r1) == -1 {
165 return 0, NewError(errstr())
166 }
167
168 return int(r1), nil
169 }
170
171
172
173
174 r1, _, _ = RawSyscall(SYS_OPEN, uintptr(unsafe.Pointer(dupdev)), uintptr(O_RDONLY), 0)
175 dupdevfd = int(r1)
176 if dupdevfd == -1 {
177 goto childerror
178 }
179 dirloop:
180 for {
181 r1, _, _ = RawSyscall6(SYS_PREAD, uintptr(dupdevfd), uintptr(unsafe.Pointer(&statbuf[0])), uintptr(len(statbuf)), ^uintptr(0), ^uintptr(0), 0)
182 n = int(r1)
183 switch n {
184 case -1:
185 goto childerror
186 case 0:
187 break dirloop
188 }
189 for b = statbuf[:n]; len(b) > 0; {
190 var s []byte
191 s, b = gdirname(b)
192 if s == nil {
193 copy(errbuf[:], ErrBadStat.Error())
194 goto childerror1
195 }
196 if s[len(s)-1] == 'l' {
197
198 continue
199 }
200 closeFdExcept(int(atoi(s)), pipe, dupdevfd, fd)
201 }
202 }
203 RawSyscall(SYS_CLOSE, uintptr(dupdevfd), 0, 0)
204
205
206 if envv != nil {
207 for i = 0; i < len(envv); i++ {
208 r1, _, _ = RawSyscall(SYS_CREATE, uintptr(unsafe.Pointer(envv[i].name)), uintptr(O_WRONLY), uintptr(0666))
209
210 if int32(r1) == -1 {
211 goto childerror
212 }
213
214 envfd = int(r1)
215
216 r1, _, _ = RawSyscall6(SYS_PWRITE, uintptr(envfd), uintptr(unsafe.Pointer(envv[i].value)), uintptr(envv[i].nvalue),
217 ^uintptr(0), ^uintptr(0), 0)
218
219 if int32(r1) == -1 || int(r1) != envv[i].nvalue {
220 goto childerror
221 }
222
223 r1, _, _ = RawSyscall(SYS_CLOSE, uintptr(envfd), 0, 0)
224
225 if int32(r1) == -1 {
226 goto childerror
227 }
228 }
229 }
230
231
232 if dir != nil {
233 r1, _, _ = RawSyscall(SYS_CHDIR, uintptr(unsafe.Pointer(dir)), 0, 0)
234 if int32(r1) == -1 {
235 goto childerror
236 }
237 }
238
239
240
241 if pipe < nextfd {
242 r1, _, _ = RawSyscall(SYS_DUP, uintptr(pipe), uintptr(nextfd), 0)
243 if int32(r1) == -1 {
244 goto childerror
245 }
246 pipe = nextfd
247 nextfd++
248 }
249 for i = 0; i < len(fd); i++ {
250 if fd[i] >= 0 && fd[i] < i {
251 if nextfd == pipe {
252 nextfd++
253 }
254 r1, _, _ = RawSyscall(SYS_DUP, uintptr(fd[i]), uintptr(nextfd), 0)
255 if int32(r1) == -1 {
256 goto childerror
257 }
258
259 fd[i] = nextfd
260 nextfd++
261 }
262 }
263
264
265 for i = 0; i < len(fd); i++ {
266 if fd[i] == -1 {
267 RawSyscall(SYS_CLOSE, uintptr(i), 0, 0)
268 continue
269 }
270 if fd[i] == i {
271 continue
272 }
273 r1, _, _ = RawSyscall(SYS_DUP, uintptr(fd[i]), uintptr(i), 0)
274 if int32(r1) == -1 {
275 goto childerror
276 }
277 }
278
279
280 for i = 0; i < len(fd); i++ {
281 if fd[i] >= len(fd) {
282 RawSyscall(SYS_CLOSE, uintptr(fd[i]), 0, 0)
283 }
284 }
285
286
287 r1, _, _ = RawSyscall(SYS_EXEC,
288 uintptr(unsafe.Pointer(argv0)),
289 uintptr(unsafe.Pointer(&argv[0])), 0)
290
291 childerror:
292
293 RawSyscall(SYS_ERRSTR, uintptr(unsafe.Pointer(&errbuf[0])), uintptr(len(errbuf)), 0)
294 childerror1:
295 errbuf[len(errbuf)-1] = 0
296 i = 0
297 for i < len(errbuf) && errbuf[i] != 0 {
298 i++
299 }
300
301 RawSyscall6(SYS_PWRITE, uintptr(pipe), uintptr(unsafe.Pointer(&errbuf[0])), uintptr(i),
302 ^uintptr(0), ^uintptr(0), 0)
303
304 for {
305 RawSyscall(SYS_EXITS, 0, 0, 0)
306 }
307 }
308
309
310
311
312 func closeFdExcept(n int, fd1 int, fd2 int, fds []int) {
313 if n == fd1 || n == fd2 {
314 return
315 }
316 for _, fd := range fds {
317 if n == fd {
318 return
319 }
320 }
321 RawSyscall(SYS_CLOSE, uintptr(n), 0, 0)
322 }
323
324 func cexecPipe(p []int) error {
325 e := Pipe(p)
326 if e != nil {
327 return e
328 }
329
330 fd, e := Open("#d/"+itoa.Itoa(p[1]), O_RDWR|O_CLOEXEC)
331 if e != nil {
332 Close(p[0])
333 Close(p[1])
334 return e
335 }
336
337 Close(p[1])
338 p[1] = fd
339 return nil
340 }
341
342 type envItem struct {
343 name *byte
344 value *byte
345 nvalue int
346 }
347
348 type ProcAttr struct {
349 Dir string
350 Env []string
351 Files []uintptr
352 Sys *SysProcAttr
353 }
354
355 type SysProcAttr struct {
356 Rfork int
357 }
358
359 var zeroProcAttr ProcAttr
360 var zeroSysProcAttr SysProcAttr
361
362 func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error) {
363 var (
364 p [2]int
365 n int
366 errbuf [ERRMAX]byte
367 wmsg Waitmsg
368 )
369
370 if attr == nil {
371 attr = &zeroProcAttr
372 }
373 sys := attr.Sys
374 if sys == nil {
375 sys = &zeroSysProcAttr
376 }
377
378 p[0] = -1
379 p[1] = -1
380
381
382 argv0p, err := BytePtrFromString(argv0)
383 if err != nil {
384 return 0, err
385 }
386 argvp, err := SlicePtrFromStrings(argv)
387 if err != nil {
388 return 0, err
389 }
390
391 destDir := attr.Dir
392 if destDir == "" {
393 wdmu.Lock()
394 destDir = wdStr
395 wdmu.Unlock()
396 }
397 var dir *byte
398 if destDir != "" {
399 dir, err = BytePtrFromString(destDir)
400 if err != nil {
401 return 0, err
402 }
403 }
404 var envvParsed []envItem
405 if attr.Env != nil {
406 envvParsed = make([]envItem, 0, len(attr.Env))
407 for _, v := range attr.Env {
408 i := 0
409 for i < len(v) && v[i] != '=' {
410 i++
411 }
412
413 envname, err := BytePtrFromString("/env/" + v[:i])
414 if err != nil {
415 return 0, err
416 }
417 envvalue := make([]byte, len(v)-i)
418 copy(envvalue, v[i+1:])
419 envvParsed = append(envvParsed, envItem{envname, &envvalue[0], len(v) - i})
420 }
421 }
422
423
424 e := cexecPipe(p[:])
425
426 if e != nil {
427 return 0, e
428 }
429
430
431 pid, err = forkAndExecInChild(argv0p, argvp, envvParsed, dir, attr, p[1], sys.Rfork)
432
433 if err != nil {
434 if p[0] >= 0 {
435 Close(p[0])
436 Close(p[1])
437 }
438 return 0, err
439 }
440
441
442 Close(p[1])
443 n, err = Read(p[0], errbuf[:])
444 Close(p[0])
445
446 if err != nil || n != 0 {
447 if n > 0 {
448 err = NewError(string(errbuf[:n]))
449 } else if err == nil {
450 err = NewError("failed to read exec status")
451 }
452
453
454
455 for wmsg.Pid != pid {
456 Await(&wmsg)
457 }
458 return 0, err
459 }
460
461
462 return pid, nil
463 }
464
465 type waitErr struct {
466 Waitmsg
467 err error
468 }
469
470 var procs struct {
471 sync.Mutex
472 waits map[int]chan *waitErr
473 }
474
475
476
477
478
479
480
481
482
483
484
485 func startProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, err error) {
486 type forkRet struct {
487 pid int
488 err error
489 }
490
491 forkc := make(chan forkRet, 1)
492 go func() {
493 runtime.LockOSThread()
494 var ret forkRet
495
496 ret.pid, ret.err = forkExec(argv0, argv, attr)
497
498 if ret.err != nil || ret.pid == 0 {
499 forkc <- ret
500 return
501 }
502
503 waitc := make(chan *waitErr, 1)
504
505
506 procs.Lock()
507 if procs.waits == nil {
508 procs.waits = make(map[int]chan *waitErr)
509 }
510 procs.waits[ret.pid] = waitc
511 procs.Unlock()
512
513 forkc <- ret
514
515 var w waitErr
516 for w.err == nil && w.Pid != ret.pid {
517 w.err = Await(&w.Waitmsg)
518 }
519 waitc <- &w
520 close(waitc)
521 }()
522 ret := <-forkc
523 return ret.pid, ret.err
524 }
525
526
527 func ForkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error) {
528 return startProcess(argv0, argv, attr)
529 }
530
531
532 func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle uintptr, err error) {
533 pid, err = startProcess(argv0, argv, attr)
534 return pid, 0, err
535 }
536
537
538 func Exec(argv0 string, argv []string, envv []string) (err error) {
539 if envv != nil {
540 r1, _, _ := RawSyscall(SYS_RFORK, RFCENVG, 0, 0)
541 if int32(r1) == -1 {
542 return NewError(errstr())
543 }
544
545 for _, v := range envv {
546 i := 0
547 for i < len(v) && v[i] != '=' {
548 i++
549 }
550
551 fd, e := Create("/env/"+v[:i], O_WRONLY, 0666)
552 if e != nil {
553 return e
554 }
555
556 _, e = Write(fd, []byte(v[i+1:]))
557 if e != nil {
558 Close(fd)
559 return e
560 }
561 Close(fd)
562 }
563 }
564
565 argv0p, err := BytePtrFromString(argv0)
566 if err != nil {
567 return err
568 }
569 argvp, err := SlicePtrFromStrings(argv)
570 if err != nil {
571 return err
572 }
573 _, _, e1 := Syscall(SYS_EXEC,
574 uintptr(unsafe.Pointer(argv0p)),
575 uintptr(unsafe.Pointer(&argvp[0])),
576 0)
577
578 return e1
579 }
580
581
582
583
584
585
586 func WaitProcess(pid int, w *Waitmsg) (err error) {
587 procs.Lock()
588 ch := procs.waits[pid]
589 procs.Unlock()
590
591 var wmsg *waitErr
592 if ch != nil {
593 wmsg = <-ch
594 procs.Lock()
595 if procs.waits[pid] == ch {
596 delete(procs.waits, pid)
597 }
598 procs.Unlock()
599 }
600 if wmsg == nil {
601
602 return NewError("process not found")
603 }
604 if wmsg.err != nil {
605 return wmsg.err
606 }
607 if w != nil {
608 *w = wmsg.Waitmsg
609 }
610 return nil
611 }
612
View as plain text