OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [syscall/] [exec_linux.go] - Blame information for rev 801

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.