1*df69c215Sderaadt /* $OpenBSD: posix_spawn.c,v 1.10 2019/06/28 13:32:41 deraadt Exp $ */
25365c52eSmatthew /*-
35365c52eSmatthew * Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org>
45365c52eSmatthew * All rights reserved.
55365c52eSmatthew *
65365c52eSmatthew * Redistribution and use in source and binary forms, with or without
75365c52eSmatthew * modification, are permitted provided that the following conditions
85365c52eSmatthew * are met:
95365c52eSmatthew * 1. Redistributions of source code must retain the above copyright
105365c52eSmatthew * notice, this list of conditions and the following disclaimer.
115365c52eSmatthew * 2. Redistributions in binary form must reproduce the above copyright
125365c52eSmatthew * notice, this list of conditions and the following disclaimer in the
135365c52eSmatthew * documentation and/or other materials provided with the distribution.
145365c52eSmatthew *
155365c52eSmatthew * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
165365c52eSmatthew * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
175365c52eSmatthew * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
185365c52eSmatthew * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
195365c52eSmatthew * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
205365c52eSmatthew * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
215365c52eSmatthew * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
225365c52eSmatthew * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
235365c52eSmatthew * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
245365c52eSmatthew * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
255365c52eSmatthew * SUCH DAMAGE.
265365c52eSmatthew */
275365c52eSmatthew
285365c52eSmatthew #include <sys/queue.h>
295365c52eSmatthew
305365c52eSmatthew #include <errno.h>
315365c52eSmatthew #include <fcntl.h>
325365c52eSmatthew #include <sched.h>
335365c52eSmatthew #include <spawn.h>
345365c52eSmatthew #include <signal.h>
355365c52eSmatthew #include <stdlib.h>
365365c52eSmatthew #include <string.h>
375365c52eSmatthew #include <unistd.h>
385365c52eSmatthew
395365c52eSmatthew struct __posix_spawnattr {
405365c52eSmatthew short sa_flags;
415365c52eSmatthew pid_t sa_pgroup;
425365c52eSmatthew struct sched_param sa_schedparam;
435365c52eSmatthew int sa_schedpolicy;
445365c52eSmatthew sigset_t sa_sigdefault;
455365c52eSmatthew sigset_t sa_sigmask;
465365c52eSmatthew };
475365c52eSmatthew
485365c52eSmatthew struct __posix_spawn_file_actions {
495365c52eSmatthew SIMPLEQ_HEAD(, __posix_spawn_file_actions_entry) fa_list;
505365c52eSmatthew };
515365c52eSmatthew
525365c52eSmatthew typedef struct __posix_spawn_file_actions_entry {
535365c52eSmatthew SIMPLEQ_ENTRY(__posix_spawn_file_actions_entry) fae_list;
545365c52eSmatthew enum { FAE_OPEN, FAE_DUP2, FAE_CLOSE } fae_action;
555365c52eSmatthew
565365c52eSmatthew int fae_fildes;
575365c52eSmatthew union {
585365c52eSmatthew struct {
595365c52eSmatthew char *path;
605365c52eSmatthew #define fae_path fae_data.open.path
615365c52eSmatthew int oflag;
625365c52eSmatthew #define fae_oflag fae_data.open.oflag
635365c52eSmatthew mode_t mode;
645365c52eSmatthew #define fae_mode fae_data.open.mode
655365c52eSmatthew } open;
665365c52eSmatthew struct {
675365c52eSmatthew int newfildes;
685365c52eSmatthew #define fae_newfildes fae_data.dup2.newfildes
695365c52eSmatthew } dup2;
705365c52eSmatthew } fae_data;
715365c52eSmatthew } posix_spawn_file_actions_entry_t;
725365c52eSmatthew
735365c52eSmatthew /*
745365c52eSmatthew * Spawn routines
755365c52eSmatthew */
765365c52eSmatthew
775365c52eSmatthew static int
process_spawnattr(const posix_spawnattr_t sa)785365c52eSmatthew process_spawnattr(const posix_spawnattr_t sa)
795365c52eSmatthew {
809e9b8682Sderaadt struct sigaction sigact;
815365c52eSmatthew int i;
825365c52eSmatthew
839e9b8682Sderaadt memset(&sigact, 0, sizeof(sigact));
849e9b8682Sderaadt sigact.sa_handler = SIG_DFL;
859e9b8682Sderaadt
865365c52eSmatthew /*
875365c52eSmatthew * POSIX doesn't really describe in which order everything
885365c52eSmatthew * should be set. We'll just set them in the order in which they
895365c52eSmatthew * are mentioned.
905365c52eSmatthew */
915365c52eSmatthew
925365c52eSmatthew /* Set process group */
935365c52eSmatthew if (sa->sa_flags & POSIX_SPAWN_SETPGROUP) {
945365c52eSmatthew if (setpgid(0, sa->sa_pgroup) != 0)
955365c52eSmatthew return (errno);
965365c52eSmatthew }
975365c52eSmatthew
985365c52eSmatthew #if 0 /* NOT IMPLEMENTED */
995365c52eSmatthew /* Set scheduler policy */
1005365c52eSmatthew if (sa->sa_flags & POSIX_SPAWN_SETSCHEDULER) {
1015365c52eSmatthew if (sched_setscheduler(0, sa->sa_schedpolicy,
1025365c52eSmatthew &sa->sa_schedparam) != 0)
1035365c52eSmatthew return (errno);
1045365c52eSmatthew } else if (sa->sa_flags & POSIX_SPAWN_SETSCHEDPARAM) {
1055365c52eSmatthew if (sched_setparam(0, &sa->sa_schedparam) != 0)
1065365c52eSmatthew return (errno);
1075365c52eSmatthew }
1085365c52eSmatthew #endif
1095365c52eSmatthew
1105365c52eSmatthew /* Reset user ID's */
1115365c52eSmatthew if (sa->sa_flags & POSIX_SPAWN_RESETIDS) {
1125365c52eSmatthew if (setegid(getgid()) != 0)
1135365c52eSmatthew return (errno);
1145365c52eSmatthew if (seteuid(getuid()) != 0)
1155365c52eSmatthew return (errno);
1165365c52eSmatthew }
1175365c52eSmatthew
1185365c52eSmatthew /* Set signal masks/defaults */
1195365c52eSmatthew if (sa->sa_flags & POSIX_SPAWN_SETSIGMASK) {
1205aed4d28Sguenther WRAP(sigprocmask)(SIG_SETMASK, &sa->sa_sigmask, NULL);
1215365c52eSmatthew }
1225365c52eSmatthew
1235365c52eSmatthew if (sa->sa_flags & POSIX_SPAWN_SETSIGDEF) {
12410f1a6deSjmatthew for (i = 1; i < _NSIG; i++) {
1255aed4d28Sguenther /* silently ignore attempts to alter SIGTHR */
1265aed4d28Sguenther if (sigismember(&sa->sa_sigdefault, i) && i != SIGTHR)
1275365c52eSmatthew if (sigaction(i, &sigact, NULL) != 0)
1285365c52eSmatthew return (errno);
1295365c52eSmatthew }
1305365c52eSmatthew }
1315365c52eSmatthew
1325365c52eSmatthew return (0);
1335365c52eSmatthew }
1345365c52eSmatthew
1355365c52eSmatthew static int
process_file_actions_entry(posix_spawn_file_actions_entry_t * fae)1365365c52eSmatthew process_file_actions_entry(posix_spawn_file_actions_entry_t *fae)
1375365c52eSmatthew {
1385365c52eSmatthew int fd;
1395365c52eSmatthew
1405365c52eSmatthew switch (fae->fae_action) {
1415365c52eSmatthew case FAE_OPEN:
1425365c52eSmatthew /* Perform an open(), make it use the right fd */
1435365c52eSmatthew fd = open(fae->fae_path, fae->fae_oflag, fae->fae_mode);
144*df69c215Sderaadt if (fd == -1)
1455365c52eSmatthew return (errno);
1465365c52eSmatthew if (fd != fae->fae_fildes) {
1475365c52eSmatthew if (dup2(fd, fae->fae_fildes) == -1)
1485365c52eSmatthew return (errno);
1495365c52eSmatthew if (close(fd) != 0) {
1505365c52eSmatthew if (errno == EBADF)
1515365c52eSmatthew return (EBADF);
1525365c52eSmatthew }
1535365c52eSmatthew }
1545365c52eSmatthew break;
1555365c52eSmatthew case FAE_DUP2:
156ed42a740Sguenther /*
157ed42a740Sguenther * Perform a dup2(), making sure the FD_CLOEXEC flag is clear
158ed42a740Sguenther */
159f34865dfSguenther fd = fae->fae_fildes;
160f34865dfSguenther if (fd == fae->fae_newfildes) {
161ed42a740Sguenther int flags = fcntl(fd, F_GETFD);
162ed42a740Sguenther
163ed42a740Sguenther if (flags == -1 ||
164ed42a740Sguenther ((flags & FD_CLOEXEC) &&
165ed42a740Sguenther fcntl(fd, F_SETFD, flags & ~FD_CLOEXEC) == -1))
166ed42a740Sguenther return (errno);
167f34865dfSguenther } else if (dup2(fd, fae->fae_newfildes) == -1)
1685365c52eSmatthew return (errno);
1695365c52eSmatthew break;
1705365c52eSmatthew case FAE_CLOSE:
1715365c52eSmatthew /* Perform a close(), do not fail if already closed */
1725365c52eSmatthew (void)close(fae->fae_fildes);
1735365c52eSmatthew break;
1745365c52eSmatthew }
1755365c52eSmatthew return (0);
1765365c52eSmatthew }
1775365c52eSmatthew
1785365c52eSmatthew static int
process_file_actions(const posix_spawn_file_actions_t fa)1795365c52eSmatthew process_file_actions(const posix_spawn_file_actions_t fa)
1805365c52eSmatthew {
1815365c52eSmatthew posix_spawn_file_actions_entry_t *fae;
1825365c52eSmatthew int error;
1835365c52eSmatthew
1845365c52eSmatthew /* Replay all file descriptor modifications */
1855365c52eSmatthew SIMPLEQ_FOREACH(fae, &fa->fa_list, fae_list) {
1865365c52eSmatthew error = process_file_actions_entry(fae);
1875365c52eSmatthew if (error)
1885365c52eSmatthew return (error);
1895365c52eSmatthew }
1905365c52eSmatthew return (0);
1915365c52eSmatthew }
1925365c52eSmatthew
1935365c52eSmatthew static int
do_posix_spawn(pid_t * pid,const char * path,const posix_spawn_file_actions_t * fa,const posix_spawnattr_t * sa,char * const argv[],char * const envp[],int use_env_path)1945365c52eSmatthew do_posix_spawn(pid_t *pid, const char *path,
1955365c52eSmatthew const posix_spawn_file_actions_t *fa,
1965365c52eSmatthew const posix_spawnattr_t *sa,
1975365c52eSmatthew char *const argv[], char *const envp[], int use_env_path)
1985365c52eSmatthew {
1995365c52eSmatthew pid_t p;
2005365c52eSmatthew
2015365c52eSmatthew p = fork();
2025365c52eSmatthew switch (p) {
2035365c52eSmatthew case -1:
2045365c52eSmatthew return (errno);
2055365c52eSmatthew case 0: {
2065365c52eSmatthew int error;
2075365c52eSmatthew if (sa != NULL) {
2085365c52eSmatthew error = process_spawnattr(*sa);
2095365c52eSmatthew if (error)
2105365c52eSmatthew _exit(127);
2115365c52eSmatthew }
2125365c52eSmatthew if (fa != NULL) {
2135365c52eSmatthew error = process_file_actions(*fa);
2145365c52eSmatthew if (error)
2155365c52eSmatthew _exit(127);
2165365c52eSmatthew }
2175365c52eSmatthew if (use_env_path)
2185365c52eSmatthew execvpe(path, argv, envp != NULL ? envp : environ);
2195365c52eSmatthew else
2205365c52eSmatthew execve(path, argv, envp != NULL ? envp : environ);
2215365c52eSmatthew _exit(127);
2225365c52eSmatthew }
2235365c52eSmatthew default:
2245365c52eSmatthew if (pid != NULL)
2255365c52eSmatthew *pid = p;
2265365c52eSmatthew return (0);
2275365c52eSmatthew }
2285365c52eSmatthew }
2295365c52eSmatthew
2305365c52eSmatthew int
posix_spawn(pid_t * pid,const char * path,const posix_spawn_file_actions_t * fa,const posix_spawnattr_t * sa,char * const argv[],char * const envp[])2315365c52eSmatthew posix_spawn(pid_t *pid, const char *path,
2325365c52eSmatthew const posix_spawn_file_actions_t *fa,
2335365c52eSmatthew const posix_spawnattr_t *sa,
2345365c52eSmatthew char *const argv[], char *const envp[])
2355365c52eSmatthew {
2365365c52eSmatthew return do_posix_spawn(pid, path, fa, sa, argv, envp, 0);
2375365c52eSmatthew }
2385365c52eSmatthew
2395365c52eSmatthew int
posix_spawnp(pid_t * pid,const char * path,const posix_spawn_file_actions_t * fa,const posix_spawnattr_t * sa,char * const argv[],char * const envp[])2405365c52eSmatthew posix_spawnp(pid_t *pid, const char *path,
2415365c52eSmatthew const posix_spawn_file_actions_t *fa,
2425365c52eSmatthew const posix_spawnattr_t *sa,
2435365c52eSmatthew char *const argv[], char *const envp[])
2445365c52eSmatthew {
2455365c52eSmatthew return do_posix_spawn(pid, path, fa, sa, argv, envp, 1);
2465365c52eSmatthew }
2475365c52eSmatthew
2485365c52eSmatthew /*
2495365c52eSmatthew * File descriptor actions
2505365c52eSmatthew */
2515365c52eSmatthew
2525365c52eSmatthew int
posix_spawn_file_actions_init(posix_spawn_file_actions_t * ret)2535365c52eSmatthew posix_spawn_file_actions_init(posix_spawn_file_actions_t *ret)
2545365c52eSmatthew {
2555365c52eSmatthew posix_spawn_file_actions_t fa;
2565365c52eSmatthew
2575365c52eSmatthew fa = malloc(sizeof(struct __posix_spawn_file_actions));
2585365c52eSmatthew if (fa == NULL)
2595365c52eSmatthew return (errno);
2605365c52eSmatthew
2615365c52eSmatthew SIMPLEQ_INIT(&fa->fa_list);
2625365c52eSmatthew *ret = fa;
2635365c52eSmatthew return (0);
2645365c52eSmatthew }
2655365c52eSmatthew
2665365c52eSmatthew int
posix_spawn_file_actions_destroy(posix_spawn_file_actions_t * fa)2675365c52eSmatthew posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *fa)
2685365c52eSmatthew {
2695365c52eSmatthew posix_spawn_file_actions_entry_t *fae;
2705365c52eSmatthew
2715365c52eSmatthew while ((fae = SIMPLEQ_FIRST(&(*fa)->fa_list)) != NULL) {
2725365c52eSmatthew /* Remove file action entry from the queue */
2735365c52eSmatthew SIMPLEQ_REMOVE_HEAD(&(*fa)->fa_list, fae_list);
2745365c52eSmatthew
2755365c52eSmatthew /* Deallocate file action entry */
2765365c52eSmatthew if (fae->fae_action == FAE_OPEN)
2775365c52eSmatthew free(fae->fae_path);
2785365c52eSmatthew free(fae);
2795365c52eSmatthew }
2805365c52eSmatthew
2815365c52eSmatthew free(*fa);
2825365c52eSmatthew return (0);
2835365c52eSmatthew }
2845365c52eSmatthew
2855365c52eSmatthew int
posix_spawn_file_actions_addopen(posix_spawn_file_actions_t * __restrict fa,int fildes,const char * __restrict path,int oflag,mode_t mode)2865365c52eSmatthew posix_spawn_file_actions_addopen(posix_spawn_file_actions_t *__restrict fa,
2875365c52eSmatthew int fildes, const char *__restrict path, int oflag, mode_t mode)
2885365c52eSmatthew {
2895365c52eSmatthew posix_spawn_file_actions_entry_t *fae;
2905365c52eSmatthew int error;
2915365c52eSmatthew
2925365c52eSmatthew if (fildes < 0)
2935365c52eSmatthew return (EBADF);
2945365c52eSmatthew
2955365c52eSmatthew /* Allocate object */
2965365c52eSmatthew fae = malloc(sizeof(posix_spawn_file_actions_entry_t));
2975365c52eSmatthew if (fae == NULL)
2985365c52eSmatthew return (errno);
2995365c52eSmatthew
3005365c52eSmatthew /* Set values and store in queue */
3015365c52eSmatthew fae->fae_action = FAE_OPEN;
3025365c52eSmatthew fae->fae_path = strdup(path);
3035365c52eSmatthew if (fae->fae_path == NULL) {
3045365c52eSmatthew error = errno;
3055365c52eSmatthew free(fae);
3065365c52eSmatthew return (error);
3075365c52eSmatthew }
3085365c52eSmatthew fae->fae_fildes = fildes;
3095365c52eSmatthew fae->fae_oflag = oflag;
3105365c52eSmatthew fae->fae_mode = mode;
3115365c52eSmatthew
3125365c52eSmatthew SIMPLEQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list);
3135365c52eSmatthew return (0);
3145365c52eSmatthew }
3155365c52eSmatthew
3165365c52eSmatthew int
posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t * fa,int fildes,int newfildes)3175365c52eSmatthew posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *fa,
3185365c52eSmatthew int fildes, int newfildes)
3195365c52eSmatthew {
3205365c52eSmatthew posix_spawn_file_actions_entry_t *fae;
3215365c52eSmatthew
3225365c52eSmatthew if (fildes < 0 || newfildes < 0)
3235365c52eSmatthew return (EBADF);
3245365c52eSmatthew
3255365c52eSmatthew /* Allocate object */
3265365c52eSmatthew fae = malloc(sizeof(posix_spawn_file_actions_entry_t));
3275365c52eSmatthew if (fae == NULL)
3285365c52eSmatthew return (errno);
3295365c52eSmatthew
3305365c52eSmatthew /* Set values and store in queue */
3315365c52eSmatthew fae->fae_action = FAE_DUP2;
3325365c52eSmatthew fae->fae_fildes = fildes;
3335365c52eSmatthew fae->fae_newfildes = newfildes;
3345365c52eSmatthew
3355365c52eSmatthew SIMPLEQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list);
3365365c52eSmatthew return (0);
3375365c52eSmatthew }
3385365c52eSmatthew
3395365c52eSmatthew int
posix_spawn_file_actions_addclose(posix_spawn_file_actions_t * fa,int fildes)3405365c52eSmatthew posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *fa,
3415365c52eSmatthew int fildes)
3425365c52eSmatthew {
3435365c52eSmatthew posix_spawn_file_actions_entry_t *fae;
3445365c52eSmatthew
3455365c52eSmatthew if (fildes < 0)
3465365c52eSmatthew return (EBADF);
3475365c52eSmatthew
3485365c52eSmatthew /* Allocate object */
3495365c52eSmatthew fae = malloc(sizeof(posix_spawn_file_actions_entry_t));
3505365c52eSmatthew if (fae == NULL)
3515365c52eSmatthew return (errno);
3525365c52eSmatthew
3535365c52eSmatthew /* Set values and store in queue */
3545365c52eSmatthew fae->fae_action = FAE_CLOSE;
3555365c52eSmatthew fae->fae_fildes = fildes;
3565365c52eSmatthew
3575365c52eSmatthew SIMPLEQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list);
3585365c52eSmatthew return (0);
3595365c52eSmatthew }
3605365c52eSmatthew
3615365c52eSmatthew /*
3625365c52eSmatthew * Spawn attributes
3635365c52eSmatthew */
3645365c52eSmatthew
3655365c52eSmatthew int
posix_spawnattr_init(posix_spawnattr_t * ret)3665365c52eSmatthew posix_spawnattr_init(posix_spawnattr_t *ret)
3675365c52eSmatthew {
3685365c52eSmatthew posix_spawnattr_t sa;
3695365c52eSmatthew
3705365c52eSmatthew sa = calloc(1, sizeof(struct __posix_spawnattr));
3715365c52eSmatthew if (sa == NULL)
3725365c52eSmatthew return (errno);
3735365c52eSmatthew
3745365c52eSmatthew /* Set defaults as specified by POSIX, cleared above */
3755365c52eSmatthew *ret = sa;
3765365c52eSmatthew return (0);
3775365c52eSmatthew }
3785365c52eSmatthew
3795365c52eSmatthew int
posix_spawnattr_destroy(posix_spawnattr_t * sa)3805365c52eSmatthew posix_spawnattr_destroy(posix_spawnattr_t *sa)
3815365c52eSmatthew {
3825365c52eSmatthew free(*sa);
3835365c52eSmatthew return (0);
3845365c52eSmatthew }
3855365c52eSmatthew
3865365c52eSmatthew int
posix_spawnattr_getflags(const posix_spawnattr_t * __restrict sa,short * __restrict flags)3875365c52eSmatthew posix_spawnattr_getflags(const posix_spawnattr_t *__restrict sa,
3885365c52eSmatthew short *__restrict flags)
3895365c52eSmatthew {
3905365c52eSmatthew *flags = (*sa)->sa_flags;
3915365c52eSmatthew return (0);
3925365c52eSmatthew }
3935365c52eSmatthew
3945365c52eSmatthew int
posix_spawnattr_getpgroup(const posix_spawnattr_t * __restrict sa,pid_t * __restrict pgroup)3955365c52eSmatthew posix_spawnattr_getpgroup(const posix_spawnattr_t *__restrict sa,
3965365c52eSmatthew pid_t *__restrict pgroup)
3975365c52eSmatthew {
3985365c52eSmatthew *pgroup = (*sa)->sa_pgroup;
3995365c52eSmatthew return (0);
4005365c52eSmatthew }
4015365c52eSmatthew
4025365c52eSmatthew int
posix_spawnattr_getschedparam(const posix_spawnattr_t * __restrict sa,struct sched_param * __restrict schedparam)4035365c52eSmatthew posix_spawnattr_getschedparam(const posix_spawnattr_t *__restrict sa,
4045365c52eSmatthew struct sched_param *__restrict schedparam)
4055365c52eSmatthew {
4065365c52eSmatthew *schedparam = (*sa)->sa_schedparam;
4075365c52eSmatthew return (0);
4085365c52eSmatthew }
4095365c52eSmatthew
4105365c52eSmatthew int
posix_spawnattr_getschedpolicy(const posix_spawnattr_t * __restrict sa,int * __restrict schedpolicy)4115365c52eSmatthew posix_spawnattr_getschedpolicy(const posix_spawnattr_t *__restrict sa,
4125365c52eSmatthew int *__restrict schedpolicy)
4135365c52eSmatthew {
4145365c52eSmatthew *schedpolicy = (*sa)->sa_schedpolicy;
4155365c52eSmatthew return (0);
4165365c52eSmatthew }
4175365c52eSmatthew
4185365c52eSmatthew int
posix_spawnattr_getsigdefault(const posix_spawnattr_t * __restrict sa,sigset_t * __restrict sigdefault)4195365c52eSmatthew posix_spawnattr_getsigdefault(const posix_spawnattr_t *__restrict sa,
4205365c52eSmatthew sigset_t *__restrict sigdefault)
4215365c52eSmatthew {
4225365c52eSmatthew *sigdefault = (*sa)->sa_sigdefault;
4235365c52eSmatthew return (0);
4245365c52eSmatthew }
4255365c52eSmatthew
4265365c52eSmatthew int
posix_spawnattr_getsigmask(const posix_spawnattr_t * __restrict sa,sigset_t * __restrict sigmask)4275365c52eSmatthew posix_spawnattr_getsigmask(const posix_spawnattr_t *__restrict sa,
4285365c52eSmatthew sigset_t *__restrict sigmask)
4295365c52eSmatthew {
4305365c52eSmatthew *sigmask = (*sa)->sa_sigmask;
4315365c52eSmatthew return (0);
4325365c52eSmatthew }
4335365c52eSmatthew
4345365c52eSmatthew int
posix_spawnattr_setflags(posix_spawnattr_t * sa,short flags)4355365c52eSmatthew posix_spawnattr_setflags(posix_spawnattr_t *sa, short flags)
4365365c52eSmatthew {
4375365c52eSmatthew (*sa)->sa_flags = flags;
4385365c52eSmatthew return (0);
4395365c52eSmatthew }
4405365c52eSmatthew
4415365c52eSmatthew int
posix_spawnattr_setpgroup(posix_spawnattr_t * sa,pid_t pgroup)4425365c52eSmatthew posix_spawnattr_setpgroup(posix_spawnattr_t *sa, pid_t pgroup)
4435365c52eSmatthew {
4445365c52eSmatthew (*sa)->sa_pgroup = pgroup;
4455365c52eSmatthew return (0);
4465365c52eSmatthew }
4475365c52eSmatthew
4485365c52eSmatthew int
posix_spawnattr_setschedparam(posix_spawnattr_t * __restrict sa,const struct sched_param * __restrict schedparam)4495365c52eSmatthew posix_spawnattr_setschedparam(posix_spawnattr_t *__restrict sa,
4505365c52eSmatthew const struct sched_param *__restrict schedparam)
4515365c52eSmatthew {
4525365c52eSmatthew (*sa)->sa_schedparam = *schedparam;
4535365c52eSmatthew return (0);
4545365c52eSmatthew }
4555365c52eSmatthew
4565365c52eSmatthew int
posix_spawnattr_setschedpolicy(posix_spawnattr_t * sa,int schedpolicy)4575365c52eSmatthew posix_spawnattr_setschedpolicy(posix_spawnattr_t *sa, int schedpolicy)
4585365c52eSmatthew {
4595365c52eSmatthew (*sa)->sa_schedpolicy = schedpolicy;
4605365c52eSmatthew return (0);
4615365c52eSmatthew }
4625365c52eSmatthew
4635365c52eSmatthew int
posix_spawnattr_setsigdefault(posix_spawnattr_t * __restrict sa,const sigset_t * __restrict sigdefault)4645365c52eSmatthew posix_spawnattr_setsigdefault(posix_spawnattr_t *__restrict sa,
4655365c52eSmatthew const sigset_t *__restrict sigdefault)
4665365c52eSmatthew {
4675365c52eSmatthew (*sa)->sa_sigdefault = *sigdefault;
4685365c52eSmatthew return (0);
4695365c52eSmatthew }
4705365c52eSmatthew
4715365c52eSmatthew int
posix_spawnattr_setsigmask(posix_spawnattr_t * __restrict sa,const sigset_t * __restrict sigmask)4725365c52eSmatthew posix_spawnattr_setsigmask(posix_spawnattr_t *__restrict sa,
4735365c52eSmatthew const sigset_t *__restrict sigmask)
4745365c52eSmatthew {
4755365c52eSmatthew (*sa)->sa_sigmask = *sigmask;
4765365c52eSmatthew return (0);
4775365c52eSmatthew }
478