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

Subversion Repositories openrisc

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

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 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
        fd := append([]int(nil), attr.Files...)
43
 
44
        // About to call fork.
45
        // No more allocation or calls of non-assembly functions.
46
        r1, err1 = raw_fork()
47
        if err1 != 0 {
48
                return 0, err1
49
        }
50
 
51
        if r1 != 0 {
52
                // parent; return PID
53
                return int(r1), 0
54
        }
55
 
56
        // Fork succeeded, now in child.
57
 
58
        // Enable tracing if requested.
59
        if sys.Ptrace {
60
                err1 = raw_ptrace(_PTRACE_TRACEME, 0, nil, nil)
61
                if err1 != 0 {
62
                        goto childerror
63
                }
64
        }
65
 
66
        // Session ID
67
        if sys.Setsid {
68
                err1 = raw_setsid()
69
                if err1 != 0 {
70
                        goto childerror
71
                }
72
        }
73
 
74
        // Set process group
75
        if sys.Setpgid {
76
                err1 = raw_setpgid(0, 0)
77
                if err1 != 0 {
78
                        goto childerror
79
                }
80
        }
81
 
82
        // Chroot
83
        if chroot != nil {
84
                err1 = raw_chroot(chroot)
85
                if err1 != 0 {
86
                        goto childerror
87
                }
88
        }
89
 
90
        // User and groups
91
        if cred := sys.Credential; cred != nil {
92
                ngroups := len(cred.Groups)
93
                if ngroups == 0 {
94
                        err2 := setgroups(0, nil)
95
                        if err2 == nil {
96
                                err1 = 0
97
                        } else {
98
                                err1 = err2.(Errno)
99
                        }
100
                } else {
101
                        groups := make([]Gid_t, ngroups)
102
                        for i, v := range cred.Groups {
103
                                groups[i] = Gid_t(v)
104
                        }
105
                        err2 := setgroups(ngroups, &groups[0])
106
                        if err2 == nil {
107
                                err1 = 0
108
                        } else {
109
                                err1 = err2.(Errno)
110
                        }
111
                }
112
                if err1 != 0 {
113
                        goto childerror
114
                }
115
                err2 := Setgid(int(cred.Gid))
116
                if err2 != nil {
117
                        err1 = err2.(Errno)
118
                        goto childerror
119
                }
120
                err2 = Setuid(int(cred.Uid))
121
                if err2 != nil {
122
                        err1 = err2.(Errno)
123
                        goto childerror
124
                }
125
        }
126
 
127
        // Chdir
128
        if dir != nil {
129
                err1 = raw_chdir(dir)
130
                if err1 != 0 {
131
                        goto childerror
132
                }
133
        }
134
 
135
        // Pass 1: look for fd[i] < i and move those up above len(fd)
136
        // so that pass 2 won't stomp on an fd it needs later.
137
        nextfd = int(len(fd))
138
        if pipe < nextfd {
139
                err1 = raw_dup2(pipe, nextfd)
140
                if err1 != 0 {
141
                        goto childerror
142
                }
143
                raw_fcntl(nextfd, F_SETFD, FD_CLOEXEC)
144
                pipe = nextfd
145
                nextfd++
146
        }
147
        for i = 0; i < len(fd); i++ {
148
                if fd[i] >= 0 && fd[i] < int(i) {
149
                        err1 = raw_dup2(fd[i], nextfd)
150
                        if err1 != 0 {
151
                                goto childerror
152
                        }
153
                        raw_fcntl(nextfd, F_SETFD, FD_CLOEXEC)
154
                        fd[i] = nextfd
155
                        nextfd++
156
                        if nextfd == pipe { // don't stomp on pipe
157
                                nextfd++
158
                        }
159
                }
160
        }
161
 
162
        // Pass 2: dup fd[i] down onto i.
163
        for i = 0; i < len(fd); i++ {
164
                if fd[i] == -1 {
165
                        raw_close(i)
166
                        continue
167
                }
168
                if fd[i] == int(i) {
169
                        // dup2(i, i) won't clear close-on-exec flag on Linux,
170
                        // probably not elsewhere either.
171
                        _, err1 = raw_fcntl(fd[i], F_SETFD, 0)
172
                        if err1 != 0 {
173
                                goto childerror
174
                        }
175
                        continue
176
                }
177
                // The new fd is created NOT close-on-exec,
178
                // which is exactly what we want.
179
                err1 = raw_dup2(fd[i], i)
180
                if err1 != 0 {
181
                        goto childerror
182
                }
183
        }
184
 
185
        // By convention, we don't close-on-exec the fds we are
186
        // started with, so if len(fd) < 3, close 0, 1, 2 as needed.
187
        // Programs that know they inherit fds >= 3 will need
188
        // to set them close-on-exec.
189
        for i = len(fd); i < 3; i++ {
190
                raw_close(i)
191
        }
192
 
193
        // Detach fd 0 from tty
194
        if sys.Noctty {
195
                _, err1 = raw_ioctl(0, TIOCNOTTY, 0)
196
                if err1 != 0 {
197
                        goto childerror
198
                }
199
        }
200
 
201
        // Make fd 0 the tty
202
        if sys.Setctty {
203
                _, err1 = raw_ioctl(0, TIOCSCTTY, 0)
204
                if err1 != 0 {
205
                        goto childerror
206
                }
207
        }
208
 
209
        // Time to exec.
210
        err1 = raw_execve(argv0, &argv[0], &envv[0])
211
 
212
childerror:
213
        // send error code on pipe
214
        raw_write(pipe, (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1)))
215
        for {
216
                raw_exit(253)
217
        }
218
 
219
        // Calling panic is not actually safe,
220
        // but the for loop above won't break
221
        // and this shuts up the compiler.
222
        panic("unreached")
223
}

powered by: WebSVN 2.1.0

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