xref: /openbsd-src/lib/libc/gen/posix_spawn.c (revision df69c215c7c66baf660f3f65414fd34796c96152)
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