1179838Sdavidxu/*- 2179840Sed * Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org> 3179838Sdavidxu * All rights reserved. 4179838Sdavidxu * 5179838Sdavidxu * Redistribution and use in source and binary forms, with or without 6179838Sdavidxu * modification, are permitted provided that the following conditions 7179838Sdavidxu * are met: 8179838Sdavidxu * 1. Redistributions of source code must retain the above copyright 9179838Sdavidxu * notice, this list of conditions and the following disclaimer. 10179838Sdavidxu * 2. Redistributions in binary form must reproduce the above copyright 11179838Sdavidxu * notice, this list of conditions and the following disclaimer in the 12179838Sdavidxu * documentation and/or other materials provided with the distribution. 13179838Sdavidxu * 14179838Sdavidxu * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15179838Sdavidxu * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16179838Sdavidxu * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17179838Sdavidxu * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18179838Sdavidxu * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19179838Sdavidxu * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20179838Sdavidxu * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21179838Sdavidxu * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22179838Sdavidxu * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23179838Sdavidxu * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24179838Sdavidxu * SUCH DAMAGE. 25179838Sdavidxu */ 26179838Sdavidxu 27179838Sdavidxu#include <sys/cdefs.h> 28179838Sdavidxu__FBSDID("$FreeBSD: stable/11/lib/libc/gen/posix_spawn.c 362281 2020-06-17 16:22:08Z kevans $"); 29179838Sdavidxu 30179838Sdavidxu#include "namespace.h" 31362281Skevans#include <sys/param.h> 32179838Sdavidxu#include <sys/queue.h> 33223907Sjilles#include <sys/wait.h> 34179838Sdavidxu 35179838Sdavidxu#include <errno.h> 36179838Sdavidxu#include <fcntl.h> 37179838Sdavidxu#include <sched.h> 38179838Sdavidxu#include <spawn.h> 39179838Sdavidxu#include <signal.h> 40179838Sdavidxu#include <stdlib.h> 41179838Sdavidxu#include <string.h> 42179838Sdavidxu#include <unistd.h> 43179838Sdavidxu#include "un-namespace.h" 44179947Sed#include "libc_private.h" 45179838Sdavidxu 46179838Sdavidxuextern char **environ; 47179838Sdavidxu 48179838Sdavidxustruct __posix_spawnattr { 49179838Sdavidxu short sa_flags; 50179838Sdavidxu pid_t sa_pgroup; 51179838Sdavidxu struct sched_param sa_schedparam; 52179838Sdavidxu int sa_schedpolicy; 53179838Sdavidxu sigset_t sa_sigdefault; 54179838Sdavidxu sigset_t sa_sigmask; 55179838Sdavidxu}; 56179838Sdavidxu 57179838Sdavidxustruct __posix_spawn_file_actions { 58179838Sdavidxu STAILQ_HEAD(, __posix_spawn_file_actions_entry) fa_list; 59179838Sdavidxu}; 60179838Sdavidxu 61179838Sdavidxutypedef struct __posix_spawn_file_actions_entry { 62179838Sdavidxu STAILQ_ENTRY(__posix_spawn_file_actions_entry) fae_list; 63179838Sdavidxu enum { FAE_OPEN, FAE_DUP2, FAE_CLOSE } fae_action; 64179838Sdavidxu 65179838Sdavidxu int fae_fildes; 66179838Sdavidxu union { 67179838Sdavidxu struct { 68179838Sdavidxu char *path; 69179838Sdavidxu#define fae_path fae_data.open.path 70179838Sdavidxu int oflag; 71179838Sdavidxu#define fae_oflag fae_data.open.oflag 72179838Sdavidxu mode_t mode; 73179838Sdavidxu#define fae_mode fae_data.open.mode 74179838Sdavidxu } open; 75179838Sdavidxu struct { 76179838Sdavidxu int newfildes; 77179838Sdavidxu#define fae_newfildes fae_data.dup2.newfildes 78179838Sdavidxu } dup2; 79179838Sdavidxu } fae_data; 80179838Sdavidxu} posix_spawn_file_actions_entry_t; 81179838Sdavidxu 82179838Sdavidxu/* 83179838Sdavidxu * Spawn routines 84179838Sdavidxu */ 85179838Sdavidxu 86179838Sdavidxustatic int 87179838Sdavidxuprocess_spawnattr(const posix_spawnattr_t sa) 88179838Sdavidxu{ 89179838Sdavidxu struct sigaction sigact = { .sa_flags = 0, .sa_handler = SIG_DFL }; 90179838Sdavidxu int i; 91179838Sdavidxu 92179838Sdavidxu /* 93179838Sdavidxu * POSIX doesn't really describe in which order everything 94179838Sdavidxu * should be set. We'll just set them in the order in which they 95179838Sdavidxu * are mentioned. 96179838Sdavidxu */ 97179838Sdavidxu 98179838Sdavidxu /* Set process group */ 99179838Sdavidxu if (sa->sa_flags & POSIX_SPAWN_SETPGROUP) { 100179838Sdavidxu if (setpgid(0, sa->sa_pgroup) != 0) 101179838Sdavidxu return (errno); 102179838Sdavidxu } 103179838Sdavidxu 104179838Sdavidxu /* Set scheduler policy */ 105179838Sdavidxu if (sa->sa_flags & POSIX_SPAWN_SETSCHEDULER) { 106179838Sdavidxu if (sched_setscheduler(0, sa->sa_schedpolicy, 107179838Sdavidxu &sa->sa_schedparam) != 0) 108179838Sdavidxu return (errno); 109179838Sdavidxu } else if (sa->sa_flags & POSIX_SPAWN_SETSCHEDPARAM) { 110179838Sdavidxu if (sched_setparam(0, &sa->sa_schedparam) != 0) 111179838Sdavidxu return (errno); 112179838Sdavidxu } 113179866Sdavidxu 114179866Sdavidxu /* Reset user ID's */ 115179866Sdavidxu if (sa->sa_flags & POSIX_SPAWN_RESETIDS) { 116179866Sdavidxu if (setegid(getgid()) != 0) 117179866Sdavidxu return (errno); 118179866Sdavidxu if (seteuid(getuid()) != 0) 119179866Sdavidxu return (errno); 120179866Sdavidxu } 121179866Sdavidxu 122287292Skib /* 123287292Skib * Set signal masks/defaults. 124287292Skib * Use unwrapped syscall, libthr is in undefined state after vfork(). 125287292Skib */ 126179866Sdavidxu if (sa->sa_flags & POSIX_SPAWN_SETSIGMASK) { 127287300Skib __sys_sigprocmask(SIG_SETMASK, &sa->sa_sigmask, NULL); 128179866Sdavidxu } 129179866Sdavidxu 130179866Sdavidxu if (sa->sa_flags & POSIX_SPAWN_SETSIGDEF) { 131179866Sdavidxu for (i = 1; i <= _SIG_MAXSIG; i++) { 132179866Sdavidxu if (sigismember(&sa->sa_sigdefault, i)) 133287300Skib if (__sys_sigaction(i, &sigact, NULL) != 0) 134179866Sdavidxu return (errno); 135179866Sdavidxu } 136179866Sdavidxu } 137179866Sdavidxu 138179838Sdavidxu return (0); 139179838Sdavidxu} 140179838Sdavidxu 141179838Sdavidxustatic int 142179838Sdavidxuprocess_file_actions_entry(posix_spawn_file_actions_entry_t *fae) 143179838Sdavidxu{ 144300662Struckman int fd, saved_errno; 145179838Sdavidxu 146179838Sdavidxu switch (fae->fae_action) { 147179838Sdavidxu case FAE_OPEN: 148179838Sdavidxu /* Perform an open(), make it use the right fd */ 149179838Sdavidxu fd = _open(fae->fae_path, fae->fae_oflag, fae->fae_mode); 150179838Sdavidxu if (fd < 0) 151179838Sdavidxu return (errno); 152179838Sdavidxu if (fd != fae->fae_fildes) { 153300662Struckman if (_dup2(fd, fae->fae_fildes) == -1) { 154300662Struckman saved_errno = errno; 155300662Struckman (void)_close(fd); 156300662Struckman return (saved_errno); 157300662Struckman } 158179838Sdavidxu if (_close(fd) != 0) { 159179838Sdavidxu if (errno == EBADF) 160179838Sdavidxu return (EBADF); 161179838Sdavidxu } 162179838Sdavidxu } 163179838Sdavidxu if (_fcntl(fae->fae_fildes, F_SETFD, 0) == -1) 164179838Sdavidxu return (errno); 165179838Sdavidxu break; 166179838Sdavidxu case FAE_DUP2: 167179838Sdavidxu /* Perform a dup2() */ 168179838Sdavidxu if (_dup2(fae->fae_fildes, fae->fae_newfildes) == -1) 169179838Sdavidxu return (errno); 170179838Sdavidxu if (_fcntl(fae->fae_newfildes, F_SETFD, 0) == -1) 171179838Sdavidxu return (errno); 172179838Sdavidxu break; 173179838Sdavidxu case FAE_CLOSE: 174222511Sjilles /* Perform a close(), do not fail if already closed */ 175222511Sjilles (void)_close(fae->fae_fildes); 176179838Sdavidxu break; 177179838Sdavidxu } 178179838Sdavidxu return (0); 179179838Sdavidxu} 180179838Sdavidxu 181179838Sdavidxustatic int 182179838Sdavidxuprocess_file_actions(const posix_spawn_file_actions_t fa) 183179838Sdavidxu{ 184179838Sdavidxu posix_spawn_file_actions_entry_t *fae; 185179838Sdavidxu int error; 186179838Sdavidxu 187179838Sdavidxu /* Replay all file descriptor modifications */ 188179838Sdavidxu STAILQ_FOREACH(fae, &fa->fa_list, fae_list) { 189179838Sdavidxu error = process_file_actions_entry(fae); 190179838Sdavidxu if (error) 191179838Sdavidxu return (error); 192179838Sdavidxu } 193223576Sed return (0); 194179838Sdavidxu} 195179838Sdavidxu 196353789Skevansstruct posix_spawn_args { 197353789Skevans const char *path; 198353789Skevans const posix_spawn_file_actions_t *fa; 199353789Skevans const posix_spawnattr_t *sa; 200353789Skevans char * const * argv; 201353789Skevans char * const * envp; 202353789Skevans int use_env_path; 203357089Skevans volatile int error; 204353789Skevans}; 205353789Skevans 206362281Skevans#define PSPAWN_STACK_ALIGNMENT 16 207362281Skevans#define PSPAWN_STACK_ALIGNBYTES (PSPAWN_STACK_ALIGNMENT - 1) 208362281Skevans#define PSPAWN_STACK_ALIGN(sz) \ 209362281Skevans (((sz) + PSPAWN_STACK_ALIGNBYTES) & ~PSPAWN_STACK_ALIGNBYTES) 210362281Skevans 211353789Skevans#if defined(__i386__) || defined(__amd64__) 212362281Skevans/* 213362281Skevans * Below we'll assume that _RFORK_THREAD_STACK_SIZE is appropriately aligned for 214362281Skevans * the posix_spawn() case where we do not end up calling _execvpe and won't ever 215362281Skevans * try to allocate space on the stack for argv[]. 216362281Skevans */ 217353789Skevans#define _RFORK_THREAD_STACK_SIZE 4096 218362281Skevans_Static_assert((_RFORK_THREAD_STACK_SIZE % PSPAWN_STACK_ALIGNMENT) == 0, 219362281Skevans "Inappropriate stack size alignment"); 220353789Skevans#endif 221353789Skevans 222179838Sdavidxustatic int 223353789Skevans_posix_spawn_thr(void *data) 224353789Skevans{ 225353789Skevans struct posix_spawn_args *psa; 226353789Skevans char * const *envp; 227353789Skevans 228353789Skevans psa = data; 229353789Skevans if (psa->sa != NULL) { 230353789Skevans psa->error = process_spawnattr(*psa->sa); 231353789Skevans if (psa->error) 232353789Skevans _exit(127); 233353789Skevans } 234353789Skevans if (psa->fa != NULL) { 235353789Skevans psa->error = process_file_actions(*psa->fa); 236353789Skevans if (psa->error) 237353789Skevans _exit(127); 238353789Skevans } 239353789Skevans envp = psa->envp != NULL ? psa->envp : environ; 240353789Skevans if (psa->use_env_path) 241353789Skevans _execvpe(psa->path, psa->argv, envp); 242353789Skevans else 243353789Skevans _execve(psa->path, psa->argv, envp); 244353789Skevans psa->error = errno; 245353789Skevans 246353789Skevans /* This is called in such a way that it must not exit. */ 247353789Skevans _exit(127); 248353789Skevans} 249353789Skevans 250353789Skevansstatic int 251179838Sdavidxudo_posix_spawn(pid_t *pid, const char *path, 252179838Sdavidxu const posix_spawn_file_actions_t *fa, 253179838Sdavidxu const posix_spawnattr_t *sa, 254179838Sdavidxu char * const argv[], char * const envp[], int use_env_path) 255179838Sdavidxu{ 256353789Skevans struct posix_spawn_args psa; 257179838Sdavidxu pid_t p; 258353789Skevans#ifdef _RFORK_THREAD_STACK_SIZE 259353789Skevans char *stack; 260362281Skevans size_t cnt, stacksz; 261223576Sed 262362281Skevans stacksz = _RFORK_THREAD_STACK_SIZE; 263362281Skevans if (use_env_path) { 264362281Skevans /* 265362281Skevans * We need to make sure we have enough room on the stack for the 266362281Skevans * potential alloca() in execvPe if it gets kicked back an 267362281Skevans * ENOEXEC from execve(2), plus the original buffer we gave 268362281Skevans * ourselves; this protects us in the event that the caller 269362281Skevans * intentionally or inadvertently supplies enough arguments to 270362281Skevans * make us blow past the stack we've allocated from it. 271362281Skevans */ 272362281Skevans for (cnt = 0; argv[cnt] != NULL; ++cnt) 273362281Skevans ; 274362281Skevans stacksz += MAX(3, cnt + 2) * sizeof(char *); 275362281Skevans stacksz = PSPAWN_STACK_ALIGN(stacksz); 276362281Skevans } 277362281Skevans 278362281Skevans /* 279362281Skevans * aligned_alloc is not safe to use here, because we can't guarantee 280362281Skevans * that aligned_alloc and free will be provided by the same 281362281Skevans * implementation. We've actively hit at least one application that 282362281Skevans * will provide its own malloc/free but not aligned_alloc leading to 283362281Skevans * a free by the wrong allocator. 284362281Skevans */ 285362281Skevans stack = malloc(stacksz); 286353789Skevans if (stack == NULL) 287353789Skevans return (ENOMEM); 288362281Skevans stacksz = (((uintptr_t)stack + stacksz) & ~PSPAWN_STACK_ALIGNBYTES) - 289362281Skevans (uintptr_t)stack; 290353789Skevans#endif 291353789Skevans psa.path = path; 292353789Skevans psa.fa = fa; 293353789Skevans psa.sa = sa; 294353789Skevans psa.argv = argv; 295353789Skevans psa.envp = envp; 296353789Skevans psa.use_env_path = use_env_path; 297353789Skevans psa.error = 0; 298353789Skevans 299353789Skevans /* 300353789Skevans * Passing RFSPAWN to rfork(2) gives us effectively a vfork that drops 301353789Skevans * non-ignored signal handlers. We'll fall back to the slightly less 302353789Skevans * ideal vfork(2) if we get an EINVAL from rfork -- this should only 303353789Skevans * happen with newer libc on older kernel that doesn't accept 304353789Skevans * RFSPAWN. 305353789Skevans */ 306353789Skevans#ifdef _RFORK_THREAD_STACK_SIZE 307353789Skevans /* 308353789Skevans * x86 stores the return address on the stack, so rfork(2) cannot work 309353789Skevans * as-is because the child would clobber the return address om the 310353789Skevans * parent. Because of this, we must use rfork_thread instead while 311353789Skevans * almost every other arch stores the return address in a register. 312353789Skevans */ 313362281Skevans p = rfork_thread(RFSPAWN, stack + stacksz, _posix_spawn_thr, &psa); 314353789Skevans free(stack); 315353789Skevans#else 316353789Skevans p = rfork(RFSPAWN); 317353789Skevans if (p == 0) 318353789Skevans /* _posix_spawn_thr does not return */ 319353789Skevans _posix_spawn_thr(&psa); 320353789Skevans#endif 321353789Skevans /* 322353789Skevans * The above block should leave us in a state where we've either 323353789Skevans * succeeded and we're ready to process the results, or we need to 324353789Skevans * fallback to vfork() if the kernel didn't like RFSPAWN. 325353789Skevans */ 326353789Skevans 327353789Skevans if (p == -1 && errno == EINVAL) { 328353789Skevans p = vfork(); 329353789Skevans if (p == 0) 330353789Skevans /* _posix_spawn_thr does not return */ 331353789Skevans _posix_spawn_thr(&psa); 332353789Skevans } 333353789Skevans if (p == -1) 334179838Sdavidxu return (errno); 335353789Skevans if (psa.error != 0) 336353789Skevans /* Failed; ready to reap */ 337353789Skevans _waitpid(p, NULL, WNOHANG); 338353789Skevans else if (pid != NULL) 339353789Skevans /* exec succeeded */ 340353789Skevans *pid = p; 341353789Skevans return (psa.error); 342179838Sdavidxu} 343179838Sdavidxu 344179838Sdavidxuint 345179838Sdavidxuposix_spawn(pid_t *pid, const char *path, 346179838Sdavidxu const posix_spawn_file_actions_t *fa, 347179838Sdavidxu const posix_spawnattr_t *sa, 348179838Sdavidxu char * const argv[], char * const envp[]) 349179838Sdavidxu{ 350179838Sdavidxu return do_posix_spawn(pid, path, fa, sa, argv, envp, 0); 351179838Sdavidxu} 352179838Sdavidxu 353179838Sdavidxuint 354179838Sdavidxuposix_spawnp(pid_t *pid, const char *path, 355179838Sdavidxu const posix_spawn_file_actions_t *fa, 356179838Sdavidxu const posix_spawnattr_t *sa, 357179838Sdavidxu char * const argv[], char * const envp[]) 358179838Sdavidxu{ 359179838Sdavidxu return do_posix_spawn(pid, path, fa, sa, argv, envp, 1); 360179838Sdavidxu} 361179838Sdavidxu 362179838Sdavidxu/* 363179838Sdavidxu * File descriptor actions 364179838Sdavidxu */ 365179838Sdavidxu 366179838Sdavidxuint 367179838Sdavidxuposix_spawn_file_actions_init(posix_spawn_file_actions_t *ret) 368179838Sdavidxu{ 369179838Sdavidxu posix_spawn_file_actions_t fa; 370179838Sdavidxu 371179838Sdavidxu fa = malloc(sizeof(struct __posix_spawn_file_actions)); 372179838Sdavidxu if (fa == NULL) 373179838Sdavidxu return (-1); 374179838Sdavidxu 375179838Sdavidxu STAILQ_INIT(&fa->fa_list); 376179838Sdavidxu *ret = fa; 377179838Sdavidxu return (0); 378179838Sdavidxu} 379179838Sdavidxu 380179838Sdavidxuint 381179838Sdavidxuposix_spawn_file_actions_destroy(posix_spawn_file_actions_t *fa) 382179838Sdavidxu{ 383179838Sdavidxu posix_spawn_file_actions_entry_t *fae; 384179838Sdavidxu 385179838Sdavidxu while ((fae = STAILQ_FIRST(&(*fa)->fa_list)) != NULL) { 386179838Sdavidxu /* Remove file action entry from the queue */ 387179838Sdavidxu STAILQ_REMOVE_HEAD(&(*fa)->fa_list, fae_list); 388179838Sdavidxu 389179838Sdavidxu /* Deallocate file action entry */ 390179838Sdavidxu if (fae->fae_action == FAE_OPEN) 391179838Sdavidxu free(fae->fae_path); 392179838Sdavidxu free(fae); 393179838Sdavidxu } 394179838Sdavidxu 395179838Sdavidxu free(*fa); 396179838Sdavidxu return (0); 397179838Sdavidxu} 398179838Sdavidxu 399179838Sdavidxuint 400179838Sdavidxuposix_spawn_file_actions_addopen(posix_spawn_file_actions_t * __restrict fa, 401179838Sdavidxu int fildes, const char * __restrict path, int oflag, mode_t mode) 402179838Sdavidxu{ 403179838Sdavidxu posix_spawn_file_actions_entry_t *fae; 404179838Sdavidxu int error; 405179838Sdavidxu 406179838Sdavidxu if (fildes < 0) 407179838Sdavidxu return (EBADF); 408179838Sdavidxu 409179838Sdavidxu /* Allocate object */ 410179838Sdavidxu fae = malloc(sizeof(posix_spawn_file_actions_entry_t)); 411179838Sdavidxu if (fae == NULL) 412179838Sdavidxu return (errno); 413179838Sdavidxu 414179838Sdavidxu /* Set values and store in queue */ 415179838Sdavidxu fae->fae_action = FAE_OPEN; 416179838Sdavidxu fae->fae_path = strdup(path); 417179838Sdavidxu if (fae->fae_path == NULL) { 418179838Sdavidxu error = errno; 419179838Sdavidxu free(fae); 420179838Sdavidxu return (error); 421179838Sdavidxu } 422179838Sdavidxu fae->fae_fildes = fildes; 423179838Sdavidxu fae->fae_oflag = oflag; 424179838Sdavidxu fae->fae_mode = mode; 425179838Sdavidxu 426179838Sdavidxu STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list); 427179838Sdavidxu return (0); 428179838Sdavidxu} 429179838Sdavidxu 430179838Sdavidxuint 431179838Sdavidxuposix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *fa, 432179838Sdavidxu int fildes, int newfildes) 433179838Sdavidxu{ 434179838Sdavidxu posix_spawn_file_actions_entry_t *fae; 435179838Sdavidxu 436179838Sdavidxu if (fildes < 0 || newfildes < 0) 437179838Sdavidxu return (EBADF); 438179838Sdavidxu 439179838Sdavidxu /* Allocate object */ 440179838Sdavidxu fae = malloc(sizeof(posix_spawn_file_actions_entry_t)); 441179838Sdavidxu if (fae == NULL) 442179838Sdavidxu return (errno); 443179838Sdavidxu 444179838Sdavidxu /* Set values and store in queue */ 445179838Sdavidxu fae->fae_action = FAE_DUP2; 446179838Sdavidxu fae->fae_fildes = fildes; 447179838Sdavidxu fae->fae_newfildes = newfildes; 448179838Sdavidxu 449179838Sdavidxu STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list); 450179838Sdavidxu return (0); 451179838Sdavidxu} 452179838Sdavidxu 453179841Sdavidxuint 454179841Sdavidxuposix_spawn_file_actions_addclose(posix_spawn_file_actions_t *fa, 455179838Sdavidxu int fildes) 456179838Sdavidxu{ 457179838Sdavidxu posix_spawn_file_actions_entry_t *fae; 458179838Sdavidxu 459179838Sdavidxu if (fildes < 0) 460179838Sdavidxu return (EBADF); 461179838Sdavidxu 462179838Sdavidxu /* Allocate object */ 463179838Sdavidxu fae = malloc(sizeof(posix_spawn_file_actions_entry_t)); 464179838Sdavidxu if (fae == NULL) 465179838Sdavidxu return (errno); 466179838Sdavidxu 467179838Sdavidxu /* Set values and store in queue */ 468179838Sdavidxu fae->fae_action = FAE_CLOSE; 469179838Sdavidxu fae->fae_fildes = fildes; 470179838Sdavidxu 471179838Sdavidxu STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list); 472179838Sdavidxu return (0); 473179838Sdavidxu} 474179838Sdavidxu 475179838Sdavidxu/* 476179838Sdavidxu * Spawn attributes 477179838Sdavidxu */ 478179838Sdavidxu 479179838Sdavidxuint 480179838Sdavidxuposix_spawnattr_init(posix_spawnattr_t *ret) 481179838Sdavidxu{ 482179838Sdavidxu posix_spawnattr_t sa; 483179838Sdavidxu 484179838Sdavidxu sa = calloc(1, sizeof(struct __posix_spawnattr)); 485179838Sdavidxu if (sa == NULL) 486179838Sdavidxu return (errno); 487179838Sdavidxu 488179838Sdavidxu /* Set defaults as specified by POSIX, cleared above */ 489179838Sdavidxu *ret = sa; 490179838Sdavidxu return (0); 491179838Sdavidxu} 492179838Sdavidxu 493179838Sdavidxuint 494179838Sdavidxuposix_spawnattr_destroy(posix_spawnattr_t *sa) 495179838Sdavidxu{ 496179838Sdavidxu free(*sa); 497179838Sdavidxu return (0); 498179838Sdavidxu} 499179838Sdavidxu 500179838Sdavidxuint 501179838Sdavidxuposix_spawnattr_getflags(const posix_spawnattr_t * __restrict sa, 502179838Sdavidxu short * __restrict flags) 503179838Sdavidxu{ 504179838Sdavidxu *flags = (*sa)->sa_flags; 505179838Sdavidxu return (0); 506179838Sdavidxu} 507179838Sdavidxu 508179838Sdavidxuint 509179838Sdavidxuposix_spawnattr_getpgroup(const posix_spawnattr_t * __restrict sa, 510179838Sdavidxu pid_t * __restrict pgroup) 511179838Sdavidxu{ 512179838Sdavidxu *pgroup = (*sa)->sa_pgroup; 513179838Sdavidxu return (0); 514179838Sdavidxu} 515179838Sdavidxu 516179838Sdavidxuint 517179838Sdavidxuposix_spawnattr_getschedparam(const posix_spawnattr_t * __restrict sa, 518179838Sdavidxu struct sched_param * __restrict schedparam) 519179838Sdavidxu{ 520179838Sdavidxu *schedparam = (*sa)->sa_schedparam; 521179838Sdavidxu return (0); 522179838Sdavidxu} 523179838Sdavidxu 524179838Sdavidxuint 525179838Sdavidxuposix_spawnattr_getschedpolicy(const posix_spawnattr_t * __restrict sa, 526179838Sdavidxu int * __restrict schedpolicy) 527179838Sdavidxu{ 528179838Sdavidxu *schedpolicy = (*sa)->sa_schedpolicy; 529179838Sdavidxu return (0); 530179838Sdavidxu} 531179838Sdavidxu 532179838Sdavidxuint 533179838Sdavidxuposix_spawnattr_getsigdefault(const posix_spawnattr_t * __restrict sa, 534179838Sdavidxu sigset_t * __restrict sigdefault) 535179838Sdavidxu{ 536179838Sdavidxu *sigdefault = (*sa)->sa_sigdefault; 537179838Sdavidxu return (0); 538179838Sdavidxu} 539179838Sdavidxu 540179838Sdavidxuint 541179838Sdavidxuposix_spawnattr_getsigmask(const posix_spawnattr_t * __restrict sa, 542179838Sdavidxu sigset_t * __restrict sigmask) 543179838Sdavidxu{ 544179838Sdavidxu *sigmask = (*sa)->sa_sigmask; 545179838Sdavidxu return (0); 546179838Sdavidxu} 547179838Sdavidxu 548179838Sdavidxuint 549179838Sdavidxuposix_spawnattr_setflags(posix_spawnattr_t *sa, short flags) 550179838Sdavidxu{ 551179838Sdavidxu (*sa)->sa_flags = flags; 552179838Sdavidxu return (0); 553179838Sdavidxu} 554179838Sdavidxu 555179838Sdavidxuint 556179838Sdavidxuposix_spawnattr_setpgroup(posix_spawnattr_t *sa, pid_t pgroup) 557179838Sdavidxu{ 558179838Sdavidxu (*sa)->sa_pgroup = pgroup; 559179838Sdavidxu return (0); 560179838Sdavidxu} 561179838Sdavidxu 562179838Sdavidxuint 563184203Srdivackyposix_spawnattr_setschedparam(posix_spawnattr_t * __restrict sa, 564179838Sdavidxu const struct sched_param * __restrict schedparam) 565179838Sdavidxu{ 566179838Sdavidxu (*sa)->sa_schedparam = *schedparam; 567179838Sdavidxu return (0); 568179838Sdavidxu} 569179838Sdavidxu 570179838Sdavidxuint 571179838Sdavidxuposix_spawnattr_setschedpolicy(posix_spawnattr_t *sa, int schedpolicy) 572179838Sdavidxu{ 573179838Sdavidxu (*sa)->sa_schedpolicy = schedpolicy; 574179838Sdavidxu return (0); 575179838Sdavidxu} 576179838Sdavidxu 577179838Sdavidxuint 578179838Sdavidxuposix_spawnattr_setsigdefault(posix_spawnattr_t * __restrict sa, 579179838Sdavidxu const sigset_t * __restrict sigdefault) 580179838Sdavidxu{ 581179838Sdavidxu (*sa)->sa_sigdefault = *sigdefault; 582179838Sdavidxu return (0); 583179838Sdavidxu} 584179838Sdavidxu 585179838Sdavidxuint 586179838Sdavidxuposix_spawnattr_setsigmask(posix_spawnattr_t * __restrict sa, 587179838Sdavidxu const sigset_t * __restrict sigmask) 588179838Sdavidxu{ 589179838Sdavidxu (*sa)->sa_sigmask = *sigmask; 590179838Sdavidxu return (0); 591179838Sdavidxu} 592