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