github.com/golang-haiku/go-1.4.3@v0.0.0-20190609233734-1f5ae41cc308/src/syscall/exec_haiku.go (about) 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 package syscall 6 7 import ( 8 "unsafe" 9 ) 10 11 type SysProcAttr struct { 12 Chroot string // Chroot. 13 Credential *Credential // Credential. 14 Setsid bool // Create session. 15 Setpgid bool // Set process group ID to new pid (SYSV setpgrp) 16 Setctty bool // Set controlling terminal to fd 0 17 Noctty bool // Detach fd 0 from controlling terminal 18 } 19 20 // Implemented in runtime package. 21 func runtime_BeforeFork() 22 func runtime_AfterFork() 23 24 func chdir(path uintptr) (err Errno) 25 func chroot1(path uintptr) (err Errno) 26 func close(fd uintptr) (err Errno) 27 func dup2(fd1 uintptr, fd2 uintptr) (val uintptr, err Errno) 28 func execve(path uintptr, argv uintptr, envp uintptr) (err Errno) 29 func exit(code uintptr) 30 func fcntl1(fd uintptr, cmd uintptr, arg uintptr) (val uintptr, err Errno) 31 func forkx(flags uintptr) (pid uintptr, err Errno) 32 func ioctl(fd uintptr, req uintptr, arg uintptr) (err Errno) 33 func setgid(gid uintptr) (err Errno) 34 func setgroups1(ngid uintptr, gid uintptr) (err Errno) 35 func setsid() (pid uintptr, err Errno) 36 func setuid(uid uintptr) (err Errno) 37 func setpgid(pid uintptr, pgid uintptr) (err Errno) 38 func write1(fd uintptr, buf uintptr, nbyte uintptr) (n uintptr, err Errno) 39 40 // Fork, dup fd onto 0..len(fd), and exec(argv0, argvv, envv) in child. 41 // If a dup or exec fails, write the errno error to pipe. 42 // (Pipe is close-on-exec so if exec succeeds, it will be closed.) 43 // In the child, this function must not acquire any locks, because 44 // they might have been locked at the time of the fork. This means 45 // no rescheduling, no malloc calls, and no new stack segments. 46 // 47 // We call hand-crafted syscalls, implemented in 48 // ../runtime/syscall_solaris.goc, rather than generated libc wrappers 49 // because we need to avoid lazy-loading the functions (might malloc, 50 // split the stack, or acquire mutexes). We can't call RawSyscall 51 // because it's not safe even for BSD-subsystem calls. 52 func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) { 53 // Declare all variables at top in case any 54 // declarations require heap allocation (e.g., err1). 55 var ( 56 r1 uintptr 57 err1 Errno 58 nextfd int 59 i int 60 ) 61 62 // guard against side effects of shuffling fds below. 63 // Make sure that nextfd is beyond any currently open files so 64 // that we can't run the risk of overwriting any of them. 65 fd := make([]int, len(attr.Files)) 66 nextfd = len(attr.Files) 67 for i, ufd := range attr.Files { 68 if nextfd < int(ufd) { 69 nextfd = int(ufd) 70 } 71 fd[i] = int(ufd) 72 } 73 nextfd++ 74 75 // About to call fork. 76 // No more allocation or calls of non-assembly functions. 77 runtime_BeforeFork() 78 r1, err1 = forkx(0x1) // FORK_NOSIGCHLD 79 if err1 != 0 { 80 runtime_AfterFork() 81 return 0, err1 82 } 83 84 if r1 != 0 { 85 // parent; return PID 86 runtime_AfterFork() 87 return int(r1), 0 88 } 89 90 // Fork succeeded, now in child. 91 92 /* 93 // Session ID 94 if sys.Setsid { 95 _, err1 = setsid() 96 if err1 != 0 { 97 goto childerror 98 } 99 } 100 101 // Set process group 102 if sys.Setpgid { 103 err1 = setpgid(0, 0) 104 if err1 != 0 { 105 goto childerror 106 } 107 } 108 109 // Chroot 110 if chroot != nil { 111 err1 = chroot1(uintptr(unsafe.Pointer(chroot))) 112 if err1 != 0 { 113 goto childerror 114 } 115 } 116 117 // User and groups 118 if cred := sys.Credential; cred != nil { 119 ngroups := uintptr(len(cred.Groups)) 120 groups := uintptr(0) 121 if ngroups > 0 { 122 groups = uintptr(unsafe.Pointer(&cred.Groups[0])) 123 } 124 err1 = setgroups1(ngroups, groups) 125 if err1 != 0 { 126 goto childerror 127 } 128 err1 = setgid(uintptr(cred.Gid)) 129 if err1 != 0 { 130 goto childerror 131 } 132 err1 = setuid(uintptr(cred.Uid)) 133 if err1 != 0 { 134 goto childerror 135 } 136 } 137 138 // Chdir 139 if dir != nil { 140 err1 = chdir(uintptr(unsafe.Pointer(dir))) 141 if err1 != 0 { 142 goto childerror 143 } 144 } 145 */ 146 147 // Pass 1: look for fd[i] < i and move those up above len(fd) 148 // so that pass 2 won't stomp on an fd it needs later. 149 if pipe < nextfd { 150 _, err1 = dup2(uintptr(pipe), uintptr(nextfd)) 151 if err1 != 0 { 152 goto childerror 153 } 154 fcntl1(uintptr(nextfd), F_SETFD, FD_CLOEXEC) 155 pipe = nextfd 156 nextfd++ 157 } 158 for i = 0; i < len(fd); i++ { 159 if fd[i] >= 0 && fd[i] < int(i) { 160 _, err1 = dup2(uintptr(pipe), uintptr(nextfd)) 161 if err1 != 0 { 162 goto childerror 163 } 164 fcntl1(uintptr(nextfd), F_SETFD, FD_CLOEXEC) 165 fd[i] = nextfd 166 nextfd++ 167 if nextfd == pipe { // don't stomp on pipe 168 nextfd++ 169 } 170 } 171 } 172 173 // Pass 2: dup fd[i] down onto i. 174 for i = 0; i < len(fd); i++ { 175 if fd[i] == -1 { 176 close(uintptr(i)) 177 continue 178 } 179 if fd[i] == int(i) { 180 // dup2(i, i) won't clear close-on-exec flag on Linux, 181 // probably not elsewhere either. 182 _, err1 = fcntl1(uintptr(fd[i]), F_SETFD, 0) 183 if err1 != 0 { 184 goto childerror 185 } 186 continue 187 } 188 // The new fd is created NOT close-on-exec, 189 // which is exactly what we want. 190 _, err1 = dup2(uintptr(fd[i]), uintptr(i)) 191 if err1 != 0 { 192 goto childerror 193 } 194 } 195 196 // By convention, we don't close-on-exec the fds we are 197 // started with, so if len(fd) < 3, close 0, 1, 2 as needed. 198 // Programs that know they inherit fds >= 3 will need 199 // to set them close-on-exec. 200 for i = len(fd); i < 3; i++ { 201 close(uintptr(i)) 202 } 203 204 /*// Detach fd 0 from tty 205 if sys.Noctty { 206 err1 = ioctl(0, uintptr(TIOCNOTTY), 0) 207 if err1 != 0 { 208 goto childerror 209 } 210 } 211 212 // Make fd 0 the tty 213 if sys.Setctty { 214 err1 = ioctl(0, uintptr(TIOCSCTTY), 0) 215 if err1 != 0 { 216 goto childerror 217 } 218 }*/ 219 220 // Time to exec. 221 err1 = execve( 222 uintptr(unsafe.Pointer(argv0)), 223 uintptr(unsafe.Pointer(&argv[0])), 224 uintptr(unsafe.Pointer(&envv[0]))) 225 226 childerror: 227 // send error code on pipe 228 write1(uintptr(pipe), uintptr(unsafe.Pointer(&err1)), unsafe.Sizeof(err1)) 229 for { 230 exit(253) 231 } 232 } 233 234 // Try to open a pipe with O_CLOEXEC set on both file descriptors. 235 func forkExecPipe(p []int) error { 236 err := Pipe(p) 237 if err != nil { 238 return err 239 } 240 _, err = fcntl(p[0], F_SETFD, FD_CLOEXEC) 241 if err != nil { 242 return err 243 } 244 _, err = fcntl(p[1], F_SETFD, FD_CLOEXEC) 245 return err 246 }