2 * process related system call shims and definitions
4 * Copyright (c) 2013-14 Stacey D. Son
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #ifndef BSD_USER_FREEBSD_OS_PROC_H
21 #define BSD_USER_FREEBSD_OS_PROC_H
23 #include <sys/param.h>
24 #include <sys/procctl.h>
25 #include <sys/signal.h>
26 #include <sys/types.h>
27 #include <sys/procdesc.h>
31 #include "target_arch_cpu.h"
33 pid_t
safe_wait4(pid_t wpid
, int *status
, int options
, struct rusage
*rusage
);
34 pid_t
safe_wait6(idtype_t idtype
, id_t id
, int *status
, int options
,
35 struct __wrusage
*wrusage
, siginfo_t
*infop
);
37 extern int __setugid(int flag
);
40 static inline abi_long
do_freebsd_execve(abi_ulong path_or_fd
, abi_ulong argp
,
44 return freebsd_exec_common(path_or_fd
, argp
, envp
, 0);
48 static inline abi_long
do_freebsd_fexecve(abi_ulong path_or_fd
, abi_ulong argp
,
52 return freebsd_exec_common(path_or_fd
, argp
, envp
, 1);
56 static inline abi_long
do_freebsd_wait4(abi_long arg1
, abi_ulong target_status
,
57 abi_long arg3
, abi_ulong target_rusage
)
61 struct rusage rusage
, *rusage_ptr
= NULL
;
66 ret
= get_errno(safe_wait4(arg1
, &status
, arg3
, rusage_ptr
));
71 if (target_status
!= 0) {
72 status
= host_to_target_waitstatus(status
);
73 if (put_user_s32(status
, target_status
) != 0) {
74 return -TARGET_EFAULT
;
77 if (target_rusage
!= 0) {
78 host_to_target_rusage(target_rusage
, &rusage
);
84 static inline abi_long
do_freebsd_wait6(void *cpu_env
, abi_long idtype
,
85 abi_long id1
, abi_long id2
,
86 abi_ulong target_status
, abi_long options
, abi_ulong target_wrusage
,
87 abi_ulong target_infop
, abi_ulong pad1
)
91 struct __wrusage wrusage
, *wrusage_ptr
= NULL
;
95 if (regpairs_aligned(cpu_env
) != 0) {
96 /* printf("shifting args\n"); */
97 /* 64-bit id is aligned, so shift all the arguments over by one */
100 target_status
= options
;
101 options
= target_wrusage
;
102 target_wrusage
= target_infop
;
106 if (target_wrusage
) {
107 wrusage_ptr
= &wrusage
;
109 ret
= get_errno(safe_wait6(idtype
, target_arg64(id1
, id2
),
110 &status
, options
, wrusage_ptr
, &info
));
115 if (target_status
!= 0) {
116 status
= host_to_target_waitstatus(status
);
117 if (put_user_s32(status
, target_status
) != 0) {
118 return -TARGET_EFAULT
;
121 if (target_wrusage
!= 0) {
122 host_to_target_wrusage(target_wrusage
, &wrusage
);
124 if (target_infop
!= 0) {
125 p
= lock_user(VERIFY_WRITE
, target_infop
, sizeof(target_siginfo_t
), 0);
127 return -TARGET_EFAULT
;
129 host_to_target_siginfo(p
, &info
);
130 unlock_user(p
, target_infop
, sizeof(target_siginfo_t
));
135 /* setloginclass(2) */
136 static inline abi_long
do_freebsd_setloginclass(abi_ulong arg1
)
141 p
= lock_user_string(arg1
);
143 return -TARGET_EFAULT
;
145 ret
= get_errno(setloginclass(p
));
146 unlock_user(p
, arg1
, 0);
151 /* getloginclass(2) */
152 static inline abi_long
do_freebsd_getloginclass(abi_ulong arg1
, abi_ulong arg2
)
157 p
= lock_user(VERIFY_WRITE
, arg1
, arg2
, 0);
159 return -TARGET_EFAULT
;
161 ret
= get_errno(getloginclass(p
, arg2
));
162 unlock_user(p
, arg1
, arg2
);
168 static inline abi_long
do_freebsd_pdgetpid(abi_long fd
, abi_ulong target_pidp
)
173 ret
= get_errno(pdgetpid(fd
, &pid
));
174 if (!is_error(ret
)) {
175 if (put_user_u32(pid
, target_pidp
)) {
176 return -TARGET_EFAULT
;
182 /* undocumented __setugid */
183 static inline abi_long
do_freebsd___setugid(abi_long arg1
)
185 return -TARGET_ENOSYS
;
189 static inline abi_long
do_freebsd_fork(void *cpu_env
)
192 abi_ulong child_flag
;
199 target_cpu_clone_regs(cpu_env
, 0);
206 * The fork system call sets a child flag in the second return
207 * value: 0 for parent process, 1 for child process.
209 set_second_rval(cpu_env
, child_flag
);
217 static inline abi_long
do_freebsd_vfork(void *cpu_env
)
219 return do_freebsd_fork(cpu_env
);
223 static inline abi_long
do_freebsd_rfork(void *cpu_env
, abi_long flags
)
226 abi_ulong child_flag
;
229 * XXX We need to handle RFMEM here, as well. Neither are safe to execute
230 * as-is on x86 hosts because they'll split memory but not the stack,
231 * wreaking havoc on host architectures that use the stack to store the
232 * return address as both threads try to pop it off. Rejecting RFSPAWN
233 * entirely for now is ok, the only consumer at the moment is posix_spawn
234 * and it will fall back to classic vfork(2) if we return EINVAL.
236 if ((flags
& TARGET_RFSPAWN
) != 0) {
237 return -TARGET_EINVAL
;
244 target_cpu_clone_regs(cpu_env
, 0);
251 * The fork system call sets a child flag in the second return
252 * value: 0 for parent process, 1 for child process.
254 set_second_rval(cpu_env
, child_flag
);
262 static inline abi_long
do_freebsd_pdfork(void *cpu_env
, abi_ulong target_fdp
,
266 abi_ulong child_flag
;
270 ret
= pdfork(&fd
, flags
);
274 target_cpu_clone_regs(cpu_env
, 0);
278 if (put_user_s32(fd
, target_fdp
)) {
279 return -TARGET_EFAULT
;
284 * The fork system call sets a child flag in the second return
285 * value: 0 for parent process, 1 for child process.
287 set_second_rval(cpu_env
, child_flag
);
293 #endif /* BSD_USER_FREEBSD_OS_PROC_H */