change the sysroot and c++ include path to fix the bugs the application cannot find...
[platform/upstream/gcc48.git] / libgo / go / syscall / exec_bsd.go
1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // +build darwin freebsd netbsd openbsd
6
7 package syscall
8
9 import (
10         "unsafe"
11 )
12
13 type SysProcAttr struct {
14         Chroot     string      // Chroot.
15         Credential *Credential // Credential.
16         Ptrace     bool        // Enable tracing.
17         Setsid     bool        // Create session.
18         Setpgid    bool        // Set process group ID to new pid (SYSV setpgrp)
19         Setctty    bool        // Set controlling terminal to fd 0
20         Noctty     bool        // Detach fd 0 from controlling terminal
21 }
22
23 // Fork, dup fd onto 0..len(fd), and exec(argv0, argvv, envv) in child.
24 // If a dup or exec fails, write the errno error to pipe.
25 // (Pipe is close-on-exec so if exec succeeds, it will be closed.)
26 // In the child, this function must not acquire any locks, because
27 // they might have been locked at the time of the fork.  This means
28 // no rescheduling, no malloc calls, and no new stack segments.
29 // The calls to RawSyscall are okay because they are assembly
30 // functions that do not grow the stack.
31 func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) {
32         // Declare all variables at top in case any
33         // declarations require heap allocation (e.g., err1).
34         var (
35                 r1     Pid_t
36                 err1   Errno
37                 nextfd int
38                 i      int
39         )
40
41         // guard against side effects of shuffling fds below.
42         // Make sure that nextfd is beyond any currently open files so
43         // that we can't run the risk of overwriting any of them.
44         fd := make([]int, len(attr.Files))
45         nextfd = len(attr.Files)
46         for i, ufd := range attr.Files {
47                 if nextfd < int(ufd) {
48                         nextfd = int(ufd)
49                 }
50                 fd[i] = int(ufd)
51         }
52         nextfd++
53
54         // About to call fork.
55         // No more allocation or calls of non-assembly functions.
56         r1, err1 = raw_fork()
57         if err1 != 0 {
58                 return 0, err1
59         }
60
61         if r1 != 0 {
62                 // parent; return PID
63                 return int(r1), 0
64         }
65
66         // Fork succeeded, now in child.
67
68         // Enable tracing if requested.
69         if sys.Ptrace {
70                 err1 = raw_ptrace(_PTRACE_TRACEME, 0, nil, nil)
71                 if err1 != 0 {
72                         goto childerror
73                 }
74         }
75
76         // Session ID
77         if sys.Setsid {
78                 err1 = raw_setsid()
79                 if err1 != 0 {
80                         goto childerror
81                 }
82         }
83
84         // Set process group
85         if sys.Setpgid {
86                 err1 = raw_setpgid(0, 0)
87                 if err1 != 0 {
88                         goto childerror
89                 }
90         }
91
92         // Chroot
93         if chroot != nil {
94                 err1 = raw_chroot(chroot)
95                 if err1 != 0 {
96                         goto childerror
97                 }
98         }
99
100         // User and groups
101         if cred := sys.Credential; cred != nil {
102                 ngroups := len(cred.Groups)
103                 if ngroups == 0 {
104                         err2 := setgroups(0, nil)
105                         if err2 == nil {
106                                 err1 = 0
107                         } else {
108                                 err1 = err2.(Errno)
109                         }
110                 } else {
111                         groups := make([]Gid_t, ngroups)
112                         for i, v := range cred.Groups {
113                                 groups[i] = Gid_t(v)
114                         }
115                         err2 := setgroups(ngroups, &groups[0])
116                         if err2 == nil {
117                                 err1 = 0
118                         } else {
119                                 err1 = err2.(Errno)
120                         }
121                 }
122                 if err1 != 0 {
123                         goto childerror
124                 }
125                 err2 := Setgid(int(cred.Gid))
126                 if err2 != nil {
127                         err1 = err2.(Errno)
128                         goto childerror
129                 }
130                 err2 = Setuid(int(cred.Uid))
131                 if err2 != nil {
132                         err1 = err2.(Errno)
133                         goto childerror
134                 }
135         }
136
137         // Chdir
138         if dir != nil {
139                 err1 = raw_chdir(dir)
140                 if err1 != 0 {
141                         goto childerror
142                 }
143         }
144
145         // Pass 1: look for fd[i] < i and move those up above len(fd)
146         // so that pass 2 won't stomp on an fd it needs later.
147         if pipe < nextfd {
148                 err1 = raw_dup2(pipe, nextfd)
149                 if err1 != 0 {
150                         goto childerror
151                 }
152                 raw_fcntl(nextfd, F_SETFD, FD_CLOEXEC)
153                 pipe = nextfd
154                 nextfd++
155         }
156         for i = 0; i < len(fd); i++ {
157                 if fd[i] >= 0 && fd[i] < int(i) {
158                         err1 = raw_dup2(fd[i], nextfd)
159                         if err1 != 0 {
160                                 goto childerror
161                         }
162                         raw_fcntl(nextfd, F_SETFD, FD_CLOEXEC)
163                         fd[i] = nextfd
164                         nextfd++
165                         if nextfd == pipe { // don't stomp on pipe
166                                 nextfd++
167                         }
168                 }
169         }
170
171         // Pass 2: dup fd[i] down onto i.
172         for i = 0; i < len(fd); i++ {
173                 if fd[i] == -1 {
174                         raw_close(i)
175                         continue
176                 }
177                 if fd[i] == int(i) {
178                         // dup2(i, i) won't clear close-on-exec flag on Linux,
179                         // probably not elsewhere either.
180                         _, err1 = raw_fcntl(fd[i], F_SETFD, 0)
181                         if err1 != 0 {
182                                 goto childerror
183                         }
184                         continue
185                 }
186                 // The new fd is created NOT close-on-exec,
187                 // which is exactly what we want.
188                 err1 = raw_dup2(fd[i], i)
189                 if err1 != 0 {
190                         goto childerror
191                 }
192         }
193
194         // By convention, we don't close-on-exec the fds we are
195         // started with, so if len(fd) < 3, close 0, 1, 2 as needed.
196         // Programs that know they inherit fds >= 3 will need
197         // to set them close-on-exec.
198         for i = len(fd); i < 3; i++ {
199                 raw_close(i)
200         }
201
202         // Detach fd 0 from tty
203         if sys.Noctty {
204                 _, err1 = raw_ioctl(0, TIOCNOTTY, 0)
205                 if err1 != 0 {
206                         goto childerror
207                 }
208         }
209
210         // Make fd 0 the tty
211         if sys.Setctty {
212                 _, err1 = raw_ioctl(0, TIOCSCTTY, 0)
213                 if err1 != 0 {
214                         goto childerror
215                 }
216         }
217
218         // Time to exec.
219         err1 = raw_execve(argv0, &argv[0], &envv[0])
220
221 childerror:
222         // send error code on pipe
223         raw_write(pipe, (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1)))
224         for {
225                 raw_exit(253)
226         }
227 }
228
229 // Try to open a pipe with O_CLOEXEC set on both file descriptors.
230 func forkExecPipe(p []int) error {
231         err := Pipe(p)
232         if err != nil {
233                 return err
234         }
235         _, err = fcntl(p[0], F_SETFD, FD_CLOEXEC)
236         if err != nil {
237                 return err
238         }
239         _, err = fcntl(p[1], F_SETFD, FD_CLOEXEC)
240         return err
241 }