xref: /dflybsd-src/lib/libc/gen/posix_spawn.c (revision d33005aaee6af52c80428b59b52aee522c002492)
1c4dd129bSPeter Avalos /*-
2c4dd129bSPeter Avalos  * Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org>
3c4dd129bSPeter Avalos  * All rights reserved.
4c4dd129bSPeter Avalos  *
5c4dd129bSPeter Avalos  * Redistribution and use in source and binary forms, with or without
6c4dd129bSPeter Avalos  * modification, are permitted provided that the following conditions
7c4dd129bSPeter Avalos  * are met:
8c4dd129bSPeter Avalos  * 1. Redistributions of source code must retain the above copyright
9c4dd129bSPeter Avalos  *    notice, this list of conditions and the following disclaimer.
10c4dd129bSPeter Avalos  * 2. Redistributions in binary form must reproduce the above copyright
11c4dd129bSPeter Avalos  *    notice, this list of conditions and the following disclaimer in the
12c4dd129bSPeter Avalos  *    documentation and/or other materials provided with the distribution.
13c4dd129bSPeter Avalos  *
14c4dd129bSPeter Avalos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15c4dd129bSPeter Avalos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16c4dd129bSPeter Avalos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17c4dd129bSPeter Avalos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18c4dd129bSPeter Avalos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19c4dd129bSPeter Avalos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20c4dd129bSPeter Avalos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21c4dd129bSPeter Avalos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22c4dd129bSPeter Avalos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23c4dd129bSPeter Avalos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24c4dd129bSPeter Avalos  * SUCH DAMAGE.
25c4dd129bSPeter Avalos  *
26c4dd129bSPeter Avalos  * $FreeBSD: src/lib/libc/gen/posix_spawn.c,v 1.6 2008/10/23 15:32:06 rdivacky Exp $
27c4dd129bSPeter Avalos  */
28c4dd129bSPeter Avalos 
29c4dd129bSPeter Avalos #include "namespace.h"
30c4dd129bSPeter Avalos #include <sys/queue.h>
31c4dd129bSPeter Avalos 
32c4dd129bSPeter Avalos #include <errno.h>
33c4dd129bSPeter Avalos #include <fcntl.h>
34c4dd129bSPeter Avalos #include <sched.h>
35c4dd129bSPeter Avalos #include <spawn.h>
36c4dd129bSPeter Avalos #include <signal.h>
37c4dd129bSPeter Avalos #include <stdlib.h>
38c4dd129bSPeter Avalos #include <string.h>
39c4dd129bSPeter Avalos #include <unistd.h>
40c4dd129bSPeter Avalos #include "un-namespace.h"
41c4dd129bSPeter Avalos #include "libc_private.h"
42c4dd129bSPeter Avalos 
43c4dd129bSPeter Avalos extern char **environ;
44c4dd129bSPeter Avalos 
45c4dd129bSPeter Avalos struct __posix_spawnattr {
46c4dd129bSPeter Avalos 	short			sa_flags;
47c4dd129bSPeter Avalos 	pid_t			sa_pgroup;
48c4dd129bSPeter Avalos 	struct sched_param	sa_schedparam;
49c4dd129bSPeter Avalos 	int			sa_schedpolicy;
50c4dd129bSPeter Avalos 	sigset_t		sa_sigdefault;
51c4dd129bSPeter Avalos 	sigset_t		sa_sigmask;
52c4dd129bSPeter Avalos };
53c4dd129bSPeter Avalos 
54c4dd129bSPeter Avalos struct __posix_spawn_file_actions {
55c4dd129bSPeter Avalos 	STAILQ_HEAD(, __posix_spawn_file_actions_entry) fa_list;
56c4dd129bSPeter Avalos };
57c4dd129bSPeter Avalos 
58c4dd129bSPeter Avalos typedef struct __posix_spawn_file_actions_entry {
59c4dd129bSPeter Avalos 	STAILQ_ENTRY(__posix_spawn_file_actions_entry) fae_list;
60c4dd129bSPeter Avalos 	enum { FAE_OPEN, FAE_DUP2, FAE_CLOSE } fae_action;
61c4dd129bSPeter Avalos 
62c4dd129bSPeter Avalos 	int fae_fildes;
63c4dd129bSPeter Avalos 	union {
64c4dd129bSPeter Avalos 		struct {
65c4dd129bSPeter Avalos 			char *path;
66c4dd129bSPeter Avalos #define fae_path	fae_data.open.path
67c4dd129bSPeter Avalos 			int oflag;
68c4dd129bSPeter Avalos #define fae_oflag	fae_data.open.oflag
69c4dd129bSPeter Avalos 			mode_t mode;
70c4dd129bSPeter Avalos #define fae_mode	fae_data.open.mode
71c4dd129bSPeter Avalos 		} open;
72c4dd129bSPeter Avalos 		struct {
73c4dd129bSPeter Avalos 			int newfildes;
74c4dd129bSPeter Avalos #define fae_newfildes	fae_data.dup2.newfildes
75c4dd129bSPeter Avalos 		} dup2;
76c4dd129bSPeter Avalos 	} fae_data;
77c4dd129bSPeter Avalos } posix_spawn_file_actions_entry_t;
78c4dd129bSPeter Avalos 
79c4dd129bSPeter Avalos /*
80c4dd129bSPeter Avalos  * Spawn routines
81c4dd129bSPeter Avalos  */
82c4dd129bSPeter Avalos 
83c4dd129bSPeter Avalos static int
process_spawnattr(const posix_spawnattr_t sa)84c4dd129bSPeter Avalos process_spawnattr(const posix_spawnattr_t sa)
85c4dd129bSPeter Avalos {
86c4dd129bSPeter Avalos 	struct sigaction sigact = { .sa_flags = 0, .sa_handler = SIG_DFL };
87c4dd129bSPeter Avalos 	int i;
88c4dd129bSPeter Avalos 
89c4dd129bSPeter Avalos 	/*
90c4dd129bSPeter Avalos 	 * POSIX doesn't really describe in which order everything
91c4dd129bSPeter Avalos 	 * should be set. We'll just set them in the order in which they
92c4dd129bSPeter Avalos 	 * are mentioned.
93c4dd129bSPeter Avalos 	 */
94c4dd129bSPeter Avalos 
95c4dd129bSPeter Avalos 	/* Set process group */
96c4dd129bSPeter Avalos 	if (sa->sa_flags & POSIX_SPAWN_SETPGROUP) {
97c4dd129bSPeter Avalos 		if (setpgid(0, sa->sa_pgroup) != 0)
98c4dd129bSPeter Avalos 			return (errno);
99c4dd129bSPeter Avalos 	}
100c4dd129bSPeter Avalos 
101c4dd129bSPeter Avalos 	/* Set scheduler policy */
102c4dd129bSPeter Avalos 	if (sa->sa_flags & POSIX_SPAWN_SETSCHEDULER) {
103c4dd129bSPeter Avalos 		if (sched_setscheduler(0, sa->sa_schedpolicy,
104c4dd129bSPeter Avalos 		    &sa->sa_schedparam) != 0)
105c4dd129bSPeter Avalos 			return (errno);
106c4dd129bSPeter Avalos 	} else if (sa->sa_flags & POSIX_SPAWN_SETSCHEDPARAM) {
107c4dd129bSPeter Avalos 		if (sched_setparam(0, &sa->sa_schedparam) != 0)
108c4dd129bSPeter Avalos 			return (errno);
109c4dd129bSPeter Avalos 	}
110c4dd129bSPeter Avalos 
111c4dd129bSPeter Avalos 	/* Reset user ID's */
112c4dd129bSPeter Avalos 	if (sa->sa_flags & POSIX_SPAWN_RESETIDS) {
113c4dd129bSPeter Avalos 		if (setegid(getgid()) != 0)
114c4dd129bSPeter Avalos 			return (errno);
115c4dd129bSPeter Avalos 		if (seteuid(getuid()) != 0)
116c4dd129bSPeter Avalos 			return (errno);
117c4dd129bSPeter Avalos 	}
118c4dd129bSPeter Avalos 
119c4dd129bSPeter Avalos 	/* Set signal masks/defaults */
120c4dd129bSPeter Avalos 	if (sa->sa_flags & POSIX_SPAWN_SETSIGMASK) {
121c4dd129bSPeter Avalos 		_sigprocmask(SIG_SETMASK, &sa->sa_sigmask, NULL);
122c4dd129bSPeter Avalos 	}
123c4dd129bSPeter Avalos 
124c4dd129bSPeter Avalos 	if (sa->sa_flags & POSIX_SPAWN_SETSIGDEF) {
125c4dd129bSPeter Avalos 		for (i = 1; i <= _SIG_MAXSIG; i++) {
126c4dd129bSPeter Avalos 			if (sigismember(&sa->sa_sigdefault, i))
127c4dd129bSPeter Avalos 				if (_sigaction(i, &sigact, NULL) != 0)
128c4dd129bSPeter Avalos 					return (errno);
129c4dd129bSPeter Avalos 		}
130c4dd129bSPeter Avalos 	}
131c4dd129bSPeter Avalos 
132c4dd129bSPeter Avalos 	return (0);
133c4dd129bSPeter Avalos }
134c4dd129bSPeter Avalos 
135c4dd129bSPeter Avalos static int
process_file_actions_entry(posix_spawn_file_actions_entry_t * fae)136c4dd129bSPeter Avalos process_file_actions_entry(posix_spawn_file_actions_entry_t *fae)
137c4dd129bSPeter Avalos {
138c4dd129bSPeter Avalos 	int fd;
139c4dd129bSPeter Avalos 
140c4dd129bSPeter Avalos 	switch (fae->fae_action) {
141c4dd129bSPeter Avalos 	case FAE_OPEN:
142c4dd129bSPeter Avalos 		/* Perform an open(), make it use the right fd */
143c4dd129bSPeter Avalos 		fd = _open(fae->fae_path, fae->fae_oflag, fae->fae_mode);
144c4dd129bSPeter Avalos 		if (fd < 0)
145c4dd129bSPeter Avalos 			return (errno);
146c4dd129bSPeter Avalos 		if (fd != fae->fae_fildes) {
147c4dd129bSPeter Avalos 			if (_dup2(fd, fae->fae_fildes) == -1)
148c4dd129bSPeter Avalos 				return (errno);
149c4dd129bSPeter Avalos 			if (_close(fd) != 0) {
150c4dd129bSPeter Avalos 				if (errno == EBADF)
151c4dd129bSPeter Avalos 					return (EBADF);
152c4dd129bSPeter Avalos 			}
153c4dd129bSPeter Avalos 		}
154c4dd129bSPeter Avalos 		if (_fcntl(fae->fae_fildes, F_SETFD, 0) == -1)
155c4dd129bSPeter Avalos 			return (errno);
156c4dd129bSPeter Avalos 		break;
157c4dd129bSPeter Avalos 	case FAE_DUP2:
158c4dd129bSPeter Avalos 		/* Perform a dup2() */
159c4dd129bSPeter Avalos 		if (_dup2(fae->fae_fildes, fae->fae_newfildes) == -1)
160c4dd129bSPeter Avalos 			return (errno);
161c4dd129bSPeter Avalos 		if (_fcntl(fae->fae_newfildes, F_SETFD, 0) == -1)
162c4dd129bSPeter Avalos 			return (errno);
163c4dd129bSPeter Avalos 		break;
164c4dd129bSPeter Avalos 	case FAE_CLOSE:
165c4dd129bSPeter Avalos 		/* Perform a close() */
166c4dd129bSPeter Avalos 		if (_close(fae->fae_fildes) != 0) {
167c4dd129bSPeter Avalos 			if (errno == EBADF)
168c4dd129bSPeter Avalos 				return (EBADF);
169c4dd129bSPeter Avalos 		}
170c4dd129bSPeter Avalos 		break;
171c4dd129bSPeter Avalos 	}
172c4dd129bSPeter Avalos 	return (0);
173c4dd129bSPeter Avalos }
174c4dd129bSPeter Avalos 
175c4dd129bSPeter Avalos static int
process_file_actions(const posix_spawn_file_actions_t fa)176c4dd129bSPeter Avalos process_file_actions(const posix_spawn_file_actions_t fa)
177c4dd129bSPeter Avalos {
178c4dd129bSPeter Avalos 	posix_spawn_file_actions_entry_t *fae;
179c4dd129bSPeter Avalos 	int error;
180c4dd129bSPeter Avalos 
181c4dd129bSPeter Avalos 	/* Replay all file descriptor modifications */
182c4dd129bSPeter Avalos 	STAILQ_FOREACH(fae, &fa->fa_list, fae_list) {
183c4dd129bSPeter Avalos 		error = process_file_actions_entry(fae);
184c4dd129bSPeter Avalos 		if (error)
185c4dd129bSPeter Avalos 			return (error);
186c4dd129bSPeter Avalos 	}
187c4dd129bSPeter Avalos 	return (0);
188c4dd129bSPeter Avalos }
189c4dd129bSPeter Avalos 
190c4dd129bSPeter Avalos 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)191c4dd129bSPeter Avalos do_posix_spawn(pid_t *pid, const char *path,
192c4dd129bSPeter Avalos 	       const posix_spawn_file_actions_t *fa,
193c4dd129bSPeter Avalos 	       const posix_spawnattr_t *sa, char * const argv[],
194c4dd129bSPeter Avalos 	       char * const envp[], int use_env_path)
195c4dd129bSPeter Avalos {
196c4dd129bSPeter Avalos 	pid_t p;
197c4dd129bSPeter Avalos 	volatile int error = 0;
198c4dd129bSPeter Avalos 
199c4dd129bSPeter Avalos 	p = vfork();
200c4dd129bSPeter Avalos 	switch (p) {
201c4dd129bSPeter Avalos 	case -1:
202c4dd129bSPeter Avalos 		return (errno);
203c4dd129bSPeter Avalos 	case 0:
204c4dd129bSPeter Avalos 		if (sa != NULL) {
205c4dd129bSPeter Avalos 			error = process_spawnattr(*sa);
206c4dd129bSPeter Avalos 			if (error)
207c4dd129bSPeter Avalos 				_exit(127);
208c4dd129bSPeter Avalos 		}
209c4dd129bSPeter Avalos 		if (fa != NULL) {
210c4dd129bSPeter Avalos 			error = process_file_actions(*fa);
211c4dd129bSPeter Avalos 			if (error)
212c4dd129bSPeter Avalos 				_exit(127);
213c4dd129bSPeter Avalos 		}
214c4dd129bSPeter Avalos 		if (use_env_path)
215c4dd129bSPeter Avalos 			_execvpe(path, argv, envp != NULL ? envp : environ);
216c4dd129bSPeter Avalos 		else
217c4dd129bSPeter Avalos 			_execve(path, argv, envp != NULL ? envp : environ);
218c4dd129bSPeter Avalos 		error = errno;
219c4dd129bSPeter Avalos 		_exit(127);
220c4dd129bSPeter Avalos 	default:
221c4dd129bSPeter Avalos 		if (pid != NULL)
222c4dd129bSPeter Avalos 			*pid = p;
223c4dd129bSPeter Avalos 		return (error);
224c4dd129bSPeter Avalos 	}
225c4dd129bSPeter Avalos }
226c4dd129bSPeter Avalos 
227c4dd129bSPeter Avalos int
posix_spawn(pid_t * __restrict pid,const char * __restrict path,const posix_spawn_file_actions_t * fa,const posix_spawnattr_t * __restrict sa,char * const argv[__restrict_arr],char * const envp[__restrict_arr])228*d33005aaSSascha Wildner posix_spawn(pid_t * __restrict pid, const char * __restrict path,
229*d33005aaSSascha Wildner     const posix_spawn_file_actions_t *fa,
230*d33005aaSSascha Wildner     const posix_spawnattr_t * __restrict sa, char * const argv[__restrict_arr],
231*d33005aaSSascha Wildner     char * const envp[__restrict_arr])
232c4dd129bSPeter Avalos {
233c4dd129bSPeter Avalos 	return do_posix_spawn(pid, path, fa, sa, argv, envp, 0);
234c4dd129bSPeter Avalos }
235c4dd129bSPeter Avalos 
236c4dd129bSPeter Avalos int
posix_spawnp(pid_t * __restrict pid,const char * __restrict path,const posix_spawn_file_actions_t * fa,const posix_spawnattr_t * __restrict sa,char * const argv[__restrict_arr],char * const envp[__restrict_arr])237*d33005aaSSascha Wildner posix_spawnp(pid_t * __restrict pid, const char * __restrict path,
238*d33005aaSSascha Wildner     const posix_spawn_file_actions_t *fa,
239*d33005aaSSascha Wildner     const posix_spawnattr_t * __restrict sa, char * const argv[__restrict_arr],
240*d33005aaSSascha Wildner     char * const envp[__restrict_arr])
241c4dd129bSPeter Avalos {
242c4dd129bSPeter Avalos 	return do_posix_spawn(pid, path, fa, sa, argv, envp, 1);
243c4dd129bSPeter Avalos }
244c4dd129bSPeter Avalos 
245c4dd129bSPeter Avalos /*
246c4dd129bSPeter Avalos  * File descriptor actions
247c4dd129bSPeter Avalos  */
248c4dd129bSPeter Avalos 
249c4dd129bSPeter Avalos int
posix_spawn_file_actions_init(posix_spawn_file_actions_t * ret)250c4dd129bSPeter Avalos posix_spawn_file_actions_init(posix_spawn_file_actions_t *ret)
251c4dd129bSPeter Avalos {
252c4dd129bSPeter Avalos 	posix_spawn_file_actions_t fa;
253c4dd129bSPeter Avalos 
254c4dd129bSPeter Avalos 	fa = malloc(sizeof(struct __posix_spawn_file_actions));
255c4dd129bSPeter Avalos 	if (fa == NULL)
256c4dd129bSPeter Avalos 		return (-1);
257c4dd129bSPeter Avalos 
258c4dd129bSPeter Avalos 	STAILQ_INIT(&fa->fa_list);
259c4dd129bSPeter Avalos 	*ret = fa;
260c4dd129bSPeter Avalos 	return (0);
261c4dd129bSPeter Avalos }
262c4dd129bSPeter Avalos 
263c4dd129bSPeter Avalos int
posix_spawn_file_actions_destroy(posix_spawn_file_actions_t * fa)264c4dd129bSPeter Avalos posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *fa)
265c4dd129bSPeter Avalos {
266c4dd129bSPeter Avalos 	posix_spawn_file_actions_entry_t *fae;
267c4dd129bSPeter Avalos 
268c4dd129bSPeter Avalos 	while ((fae = STAILQ_FIRST(&(*fa)->fa_list)) != NULL) {
269c4dd129bSPeter Avalos 		/* Remove file action entry from the queue */
270c4dd129bSPeter Avalos 		STAILQ_REMOVE_HEAD(&(*fa)->fa_list, fae_list);
271c4dd129bSPeter Avalos 
272c4dd129bSPeter Avalos 		/* Deallocate file action entry */
273c4dd129bSPeter Avalos 		if (fae->fae_action == FAE_OPEN)
274c4dd129bSPeter Avalos 			free(fae->fae_path);
275c4dd129bSPeter Avalos 		free(fae);
276c4dd129bSPeter Avalos 	}
277c4dd129bSPeter Avalos 
278c4dd129bSPeter Avalos 	free(*fa);
279c4dd129bSPeter Avalos 	return (0);
280c4dd129bSPeter Avalos }
281c4dd129bSPeter Avalos 
282c4dd129bSPeter Avalos int
posix_spawn_file_actions_addopen(posix_spawn_file_actions_t * __restrict fa,int fildes,const char * __restrict path,int oflag,mode_t mode)283c4dd129bSPeter Avalos posix_spawn_file_actions_addopen(posix_spawn_file_actions_t * __restrict fa,
284c4dd129bSPeter Avalos 				 int fildes, const char * __restrict path,
285c4dd129bSPeter Avalos 				 int oflag, mode_t mode)
286c4dd129bSPeter Avalos {
287c4dd129bSPeter Avalos 	posix_spawn_file_actions_entry_t *fae;
288c4dd129bSPeter Avalos 	int error;
289c4dd129bSPeter Avalos 
290c4dd129bSPeter Avalos 	if (fildes < 0)
291c4dd129bSPeter Avalos 		return (EBADF);
292c4dd129bSPeter Avalos 
293c4dd129bSPeter Avalos 	/* Allocate object */
294c4dd129bSPeter Avalos 	fae = malloc(sizeof(posix_spawn_file_actions_entry_t));
295c4dd129bSPeter Avalos 	if (fae == NULL)
296c4dd129bSPeter Avalos 		return (errno);
297c4dd129bSPeter Avalos 
298c4dd129bSPeter Avalos 	/* Set values and store in queue */
299c4dd129bSPeter Avalos 	fae->fae_action = FAE_OPEN;
300c4dd129bSPeter Avalos 	fae->fae_path = strdup(path);
301c4dd129bSPeter Avalos 	if (fae->fae_path == NULL) {
302c4dd129bSPeter Avalos 		error = errno;
303c4dd129bSPeter Avalos 		free(fae);
304c4dd129bSPeter Avalos 		return (error);
305c4dd129bSPeter Avalos 	}
306c4dd129bSPeter Avalos 	fae->fae_fildes = fildes;
307c4dd129bSPeter Avalos 	fae->fae_oflag = oflag;
308c4dd129bSPeter Avalos 	fae->fae_mode = mode;
309c4dd129bSPeter Avalos 
310c4dd129bSPeter Avalos 	STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list);
311c4dd129bSPeter Avalos 	return (0);
312c4dd129bSPeter Avalos }
313c4dd129bSPeter Avalos 
314c4dd129bSPeter Avalos int
posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t * fa,int fildes,int newfildes)315c4dd129bSPeter Avalos posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *fa,
316c4dd129bSPeter Avalos 				 int fildes, int newfildes)
317c4dd129bSPeter Avalos {
318c4dd129bSPeter Avalos 	posix_spawn_file_actions_entry_t *fae;
319c4dd129bSPeter Avalos 
320c4dd129bSPeter Avalos 	if (fildes < 0 || newfildes < 0)
321c4dd129bSPeter Avalos 		return (EBADF);
322c4dd129bSPeter Avalos 
323c4dd129bSPeter Avalos 	/* Allocate object */
324c4dd129bSPeter Avalos 	fae = malloc(sizeof(posix_spawn_file_actions_entry_t));
325c4dd129bSPeter Avalos 	if (fae == NULL)
326c4dd129bSPeter Avalos 		return (errno);
327c4dd129bSPeter Avalos 
328c4dd129bSPeter Avalos 	/* Set values and store in queue */
329c4dd129bSPeter Avalos 	fae->fae_action = FAE_DUP2;
330c4dd129bSPeter Avalos 	fae->fae_fildes = fildes;
331c4dd129bSPeter Avalos 	fae->fae_newfildes = newfildes;
332c4dd129bSPeter Avalos 
333c4dd129bSPeter Avalos 	STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list);
334c4dd129bSPeter Avalos 	return (0);
335c4dd129bSPeter Avalos }
336c4dd129bSPeter Avalos 
337c4dd129bSPeter Avalos int
posix_spawn_file_actions_addclose(posix_spawn_file_actions_t * fa,int fildes)338c4dd129bSPeter Avalos posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *fa,
339c4dd129bSPeter Avalos 				  int fildes)
340c4dd129bSPeter Avalos {
341c4dd129bSPeter Avalos 	posix_spawn_file_actions_entry_t *fae;
342c4dd129bSPeter Avalos 
343c4dd129bSPeter Avalos 	if (fildes < 0)
344c4dd129bSPeter Avalos 		return (EBADF);
345c4dd129bSPeter Avalos 
346c4dd129bSPeter Avalos 	/* Allocate object */
347c4dd129bSPeter Avalos 	fae = malloc(sizeof(posix_spawn_file_actions_entry_t));
348c4dd129bSPeter Avalos 	if (fae == NULL)
349c4dd129bSPeter Avalos 		return (errno);
350c4dd129bSPeter Avalos 
351c4dd129bSPeter Avalos 	/* Set values and store in queue */
352c4dd129bSPeter Avalos 	fae->fae_action = FAE_CLOSE;
353c4dd129bSPeter Avalos 	fae->fae_fildes = fildes;
354c4dd129bSPeter Avalos 
355c4dd129bSPeter Avalos 	STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list);
356c4dd129bSPeter Avalos 	return (0);
357c4dd129bSPeter Avalos }
358c4dd129bSPeter Avalos 
359c4dd129bSPeter Avalos /*
360c4dd129bSPeter Avalos  * Spawn attributes
361c4dd129bSPeter Avalos  */
362c4dd129bSPeter Avalos 
363c4dd129bSPeter Avalos int
posix_spawnattr_init(posix_spawnattr_t * ret)364c4dd129bSPeter Avalos posix_spawnattr_init(posix_spawnattr_t *ret)
365c4dd129bSPeter Avalos {
366c4dd129bSPeter Avalos 	posix_spawnattr_t sa;
367c4dd129bSPeter Avalos 
368c4dd129bSPeter Avalos 	sa = calloc(1, sizeof(struct __posix_spawnattr));
369c4dd129bSPeter Avalos 	if (sa == NULL)
370c4dd129bSPeter Avalos 		return (errno);
371c4dd129bSPeter Avalos 
372c4dd129bSPeter Avalos 	/* Set defaults as specified by POSIX, cleared above */
373c4dd129bSPeter Avalos 	*ret = sa;
374c4dd129bSPeter Avalos 	return (0);
375c4dd129bSPeter Avalos }
376c4dd129bSPeter Avalos 
377c4dd129bSPeter Avalos int
posix_spawnattr_destroy(posix_spawnattr_t * sa)378c4dd129bSPeter Avalos posix_spawnattr_destroy(posix_spawnattr_t *sa)
379c4dd129bSPeter Avalos {
380c4dd129bSPeter Avalos 	free(*sa);
381c4dd129bSPeter Avalos 	return (0);
382c4dd129bSPeter Avalos }
383c4dd129bSPeter Avalos 
384c4dd129bSPeter Avalos int
posix_spawnattr_getflags(const posix_spawnattr_t * __restrict sa,short * __restrict flags)385c4dd129bSPeter Avalos posix_spawnattr_getflags(const posix_spawnattr_t * __restrict sa,
386c4dd129bSPeter Avalos 			 short * __restrict flags)
387c4dd129bSPeter Avalos {
388c4dd129bSPeter Avalos 	*flags = (*sa)->sa_flags;
389c4dd129bSPeter Avalos 	return (0);
390c4dd129bSPeter Avalos }
391c4dd129bSPeter Avalos 
392c4dd129bSPeter Avalos int
posix_spawnattr_getpgroup(const posix_spawnattr_t * __restrict sa,pid_t * __restrict pgroup)393c4dd129bSPeter Avalos posix_spawnattr_getpgroup(const posix_spawnattr_t * __restrict sa,
394c4dd129bSPeter Avalos 			  pid_t * __restrict pgroup)
395c4dd129bSPeter Avalos {
396c4dd129bSPeter Avalos 	*pgroup = (*sa)->sa_pgroup;
397c4dd129bSPeter Avalos 	return (0);
398c4dd129bSPeter Avalos }
399c4dd129bSPeter Avalos 
400c4dd129bSPeter Avalos int
posix_spawnattr_getschedparam(const posix_spawnattr_t * __restrict sa,struct sched_param * __restrict schedparam)401c4dd129bSPeter Avalos posix_spawnattr_getschedparam(const posix_spawnattr_t * __restrict sa,
402c4dd129bSPeter Avalos 			      struct sched_param * __restrict schedparam)
403c4dd129bSPeter Avalos {
404c4dd129bSPeter Avalos 	*schedparam = (*sa)->sa_schedparam;
405c4dd129bSPeter Avalos 	return (0);
406c4dd129bSPeter Avalos }
407c4dd129bSPeter Avalos 
408c4dd129bSPeter Avalos int
posix_spawnattr_getschedpolicy(const posix_spawnattr_t * __restrict sa,int * __restrict schedpolicy)409c4dd129bSPeter Avalos posix_spawnattr_getschedpolicy(const posix_spawnattr_t * __restrict sa,
410c4dd129bSPeter Avalos 			       int * __restrict schedpolicy)
411c4dd129bSPeter Avalos {
412c4dd129bSPeter Avalos 	*schedpolicy = (*sa)->sa_schedpolicy;
413c4dd129bSPeter Avalos 	return (0);
414c4dd129bSPeter Avalos }
415c4dd129bSPeter Avalos 
416c4dd129bSPeter Avalos int
posix_spawnattr_getsigdefault(const posix_spawnattr_t * __restrict sa,sigset_t * __restrict sigdefault)417c4dd129bSPeter Avalos posix_spawnattr_getsigdefault(const posix_spawnattr_t * __restrict sa,
418c4dd129bSPeter Avalos 			      sigset_t * __restrict sigdefault)
419c4dd129bSPeter Avalos {
420c4dd129bSPeter Avalos 	*sigdefault = (*sa)->sa_sigdefault;
421c4dd129bSPeter Avalos 	return (0);
422c4dd129bSPeter Avalos }
423c4dd129bSPeter Avalos 
424c4dd129bSPeter Avalos int
posix_spawnattr_getsigmask(const posix_spawnattr_t * __restrict sa,sigset_t * __restrict sigmask)425c4dd129bSPeter Avalos posix_spawnattr_getsigmask(const posix_spawnattr_t * __restrict sa,
426c4dd129bSPeter Avalos 			   sigset_t * __restrict sigmask)
427c4dd129bSPeter Avalos {
428c4dd129bSPeter Avalos 	*sigmask = (*sa)->sa_sigmask;
429c4dd129bSPeter Avalos 	return (0);
430c4dd129bSPeter Avalos }
431c4dd129bSPeter Avalos 
432c4dd129bSPeter Avalos int
posix_spawnattr_setflags(posix_spawnattr_t * sa,short flags)433c4dd129bSPeter Avalos posix_spawnattr_setflags(posix_spawnattr_t *sa, short flags)
434c4dd129bSPeter Avalos {
435c4dd129bSPeter Avalos 	(*sa)->sa_flags = flags;
436c4dd129bSPeter Avalos 	return (0);
437c4dd129bSPeter Avalos }
438c4dd129bSPeter Avalos 
439c4dd129bSPeter Avalos int
posix_spawnattr_setpgroup(posix_spawnattr_t * sa,pid_t pgroup)440c4dd129bSPeter Avalos posix_spawnattr_setpgroup(posix_spawnattr_t *sa, pid_t pgroup)
441c4dd129bSPeter Avalos {
442c4dd129bSPeter Avalos 	(*sa)->sa_pgroup = pgroup;
443c4dd129bSPeter Avalos 	return (0);
444c4dd129bSPeter Avalos }
445c4dd129bSPeter Avalos 
446c4dd129bSPeter Avalos int
posix_spawnattr_setschedparam(posix_spawnattr_t * __restrict sa,const struct sched_param * __restrict schedparam)447c4dd129bSPeter Avalos posix_spawnattr_setschedparam(posix_spawnattr_t * __restrict sa,
448c4dd129bSPeter Avalos 			      const struct sched_param * __restrict schedparam)
449c4dd129bSPeter Avalos {
450c4dd129bSPeter Avalos 	(*sa)->sa_schedparam = *schedparam;
451c4dd129bSPeter Avalos 	return (0);
452c4dd129bSPeter Avalos }
453c4dd129bSPeter Avalos 
454c4dd129bSPeter Avalos int
posix_spawnattr_setschedpolicy(posix_spawnattr_t * sa,int schedpolicy)455c4dd129bSPeter Avalos posix_spawnattr_setschedpolicy(posix_spawnattr_t *sa, int schedpolicy)
456c4dd129bSPeter Avalos {
457c4dd129bSPeter Avalos 	(*sa)->sa_schedpolicy = schedpolicy;
458c4dd129bSPeter Avalos 	return (0);
459c4dd129bSPeter Avalos }
460c4dd129bSPeter Avalos 
461c4dd129bSPeter Avalos int
posix_spawnattr_setsigdefault(posix_spawnattr_t * __restrict sa,const sigset_t * __restrict sigdefault)462c4dd129bSPeter Avalos posix_spawnattr_setsigdefault(posix_spawnattr_t * __restrict sa,
463c4dd129bSPeter Avalos 			      const sigset_t * __restrict sigdefault)
464c4dd129bSPeter Avalos {
465c4dd129bSPeter Avalos 	(*sa)->sa_sigdefault = *sigdefault;
466c4dd129bSPeter Avalos 	return (0);
467c4dd129bSPeter Avalos }
468c4dd129bSPeter Avalos 
469c4dd129bSPeter Avalos int
posix_spawnattr_setsigmask(posix_spawnattr_t * __restrict sa,const sigset_t * __restrict sigmask)470c4dd129bSPeter Avalos posix_spawnattr_setsigmask(posix_spawnattr_t * __restrict sa,
471c4dd129bSPeter Avalos 			   const sigset_t * __restrict sigmask)
472c4dd129bSPeter Avalos {
473c4dd129bSPeter Avalos 	(*sa)->sa_sigmask = *sigmask;
474c4dd129bSPeter Avalos 	return (0);
475c4dd129bSPeter Avalos }
476