From owner-freebsd-standards@FreeBSD.ORG Mon Mar 24 18:30:05 2008 Return-Path: Delivered-To: freebsd-standards@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 1F0F2106569A for ; Mon, 24 Mar 2008 18:30:05 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id DDF858FC23 for ; Mon, 24 Mar 2008 18:30:04 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.14.2/8.14.2) with ESMTP id m2OIU46g033549 for ; Mon, 24 Mar 2008 18:30:04 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.2/8.14.1/Submit) id m2OIU4dT033548; Mon, 24 Mar 2008 18:30:04 GMT (envelope-from gnats) Date: Mon, 24 Mar 2008 18:30:04 GMT Message-Id: <200803241830.m2OIU4dT033548@freefall.freebsd.org> To: freebsd-standards@FreeBSD.org From: Ed Schouten Cc: Subject: Re: standards/122051: Add posix_spawn(3) X-BeenThere: freebsd-standards@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: Ed Schouten List-Id: Standards compliance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 24 Mar 2008 18:30:05 -0000 The following reply was made to PR standards/122051; it has been noted by GNATS. From: Ed Schouten To: Kostik Belousov Cc: Subject: Re: standards/122051: Add posix_spawn(3) Date: Mon, 24 Mar 2008 19:21:49 +0100 --mW9eGbZzDIYYWqGs Content-Type: multipart/mixed; boundary="uX7BrQs69PbBafpd" Content-Disposition: inline --uX7BrQs69PbBafpd Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Hello Kostik, Thanks a lot for your feedback! :-) * Kostik Belousov wrote: > > It isn't possible to make the structures opague, which is a pity with > > respect to binary compatibility. That's why I've decided to take the > > easy path by inlining most of the get/set routines. > Why ? >=20 > I do not remember any POSIX requirements that would force us to provide > the direct access to the the internals of the attrs. Am I wrong ? >=20 > If this is true, then it would be better to not inline the setters/getter= s, > and add the padding for the structures just in case. I forgot that we could typedef posix_spawnattr_t and posix_spawn_file_actions_t to a pointer type. That way we wouldn't need any padding. This also prevents a lot of namespace polution. > > This patch still misses a manual page. > FreeBSD has an permit to use the verbatim POSIX specification in its > manual pages, with proper attribution. > See the /usr/share/examples/mdoc/POSIX-copyright I'll take a look at it soon. I will probably store a final diff somewhere online, because the manual pages will make the diff too big to post it in the PR. > > --- lib/libc/gen/Symbol.map > > +++ lib/libc/gen/Symbol.map > > @@ -118,6 +118,7 @@ > > execlp; > > execv; > > execvp; > > + execvpe; > > execvP; > > fmtcheck; > > fmtmsg; > > @@ -220,9 +221,16 @@ > > nrand48; > > opendir; > > pause; > > - posix_madvise; > > - popen; > > pclose; > > + popen; > > + posix_madvise; > > + posix_spawn; > > + posix_spawn_file_actions_addclose; > > + posix_spawn_file_actions_adddup2; > > + posix_spawn_file_actions_addopen; > > + posix_spawn_file_actions_destroy; > > + posix_spawn_file_actions_init; > > + posix_spawnp; > > shm_open; > > shm_unlink; > > pselect; >=20 > These chunks are almost definitely wrong. You shall add new symbols to the > FBSD_1.1 namespace. Fixed. I've attached an updated version of my patch, which should already address all the issues you pointed out. > I have the unfulfilled obligation for the openat() and friends commit. > After I do that, unless somebody else shows the interest in your work, > feel free to ping me. I will. Thanks a lot! --=20 Ed Schouten WWW: http://g-rave.nl/ --uX7BrQs69PbBafpd Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="posix_spawn.diff" Content-Transfer-Encoding: quoted-printable --- include/Makefile +++ include/Makefile @@ -19,7 +19,7 @@ printf.h proc_service.h pthread.h \ pthread_np.h pwd.h ranlib.h readpassphrase.h regex.h regexp.h \ res_update.h resolv.h runetype.h search.h setjmp.h sgtty.h \ - signal.h stab.h \ + signal.h spawn.h stab.h \ stdbool.h stddef.h stdio.h stdlib.h string.h stringlist.h \ strings.h sysexits.h tar.h tgmath.h \ time.h timeconv.h timers.h ttyent.h \ --- include/spawn.h +++ include/spawn.h @@ -0,0 +1,114 @@ +/*- + * Copyright (c) 2008 Ed Schouten + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURP= OSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENT= IAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STR= ICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY W= AY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SPAWN_H_ +#define _SPAWN_H_ + +#include +#include +#include + +#ifndef _MODE_T_DECLARED +typedef __mode_t mode_t; +#define _MODE_T_DECLARED +#endif + +#ifndef _PID_T_DECLARED +typedef __pid_t pid_t; +#define _PID_T_DECLARED +#endif + +#ifndef _SIGSET_T_DECLARED +#define _SIGSET_T_DECLARED +typedef __sigset_t sigset_t; +#endif + +struct sched_param; + +typedef struct __posix_spawnattr *posix_spawnattr_t; +typedef struct __posix_spawn_file_actions *posix_spawn_file_actions_t; + +#define POSIX_SPAWN_RESETIDS 0x01 +#define POSIX_SPAWN_SETPGROUP 0x02 +#define POSIX_SPAWN_SETSCHEDPARAM 0x04 +#define POSIX_SPAWN_SETSCHEDULER 0x08 +#define POSIX_SPAWN_SETSIGDEF 0x10 +#define POSIX_SPAWN_SETSIGMASK 0x20 + +/* + * Spawn routines + */ +int posix_spawn(pid_t * __restrict, const char * __restrict, + const posix_spawn_file_actions_t *, const posix_spawnattr_t * __restri= ct, + char * const [__restrict], char * const [__restrict]); +int posix_spawnp(pid_t * __restrict, const char * __restrict, + const posix_spawn_file_actions_t *, const posix_spawnattr_t * __restri= ct, + char * const [__restrict], char * const [__restrict]); + +/* + * File descriptor actions + */ +int posix_spawn_file_actions_init(posix_spawn_file_actions_t *); +int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *); + +int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t * __restri= ct, + int, const char * __restrict, int, mode_t); +int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *, int, in= t); +int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *, int); + +/* + * Spawn attributes + */ + +int posix_spawnattr_init(posix_spawnattr_t *); +int posix_spawnattr_destroy(posix_spawnattr_t *); + +int posix_spawnattr_getflags(const posix_spawnattr_t * __restrict, + short * __restrict); +int posix_spawnattr_getpgroup(const posix_spawnattr_t * __restrict, + pid_t * __restrict); +int posix_spawnattr_getschedparam(const posix_spawnattr_t * __restrict, + struct sched_param * __restrict); +int posix_spawnattr_getschedpolicy(const posix_spawnattr_t * __restrict, + int * __restrict); +int posix_spawnattr_getsigdefault(const posix_spawnattr_t * __restrict, + sigset_t * __restrict); +int posix_spawnattr_getsigmask(const posix_spawnattr_t * __restrict, + sigset_t * __restrict sigmask); + +int posix_spawnattr_setflags(posix_spawnattr_t *, short); +int posix_spawnattr_setpgroup(posix_spawnattr_t *, pid_t); +int posix_spawnattr_setschedparam(posix_spawnattr_t * __restrict, + const struct sched_param * __restrict); +int posix_spawnattr_setschedpolicy(posix_spawnattr_t *, int); +int posix_spawnattr_setsigdefault(posix_spawnattr_t * __restrict, + const sigset_t * __restrict); +int posix_spawnattr_setsigmask(posix_spawnattr_t * __restrict, + const sigset_t * __restrict); + +#endif /* !_SPAWN_H_ */ --- include/unistd.h +++ include/unistd.h @@ -335,6 +335,7 @@ int execv(const char *, char * const *); int execve(const char *, char * const *, char * const *); int execvp(const char *, char * const *); +int execvpe(const char *, char * const *, char * const *); pid_t fork(void); long fpathconf(int, int); char *getcwd(char *, size_t); --- lib/libc/gen/Makefile.inc +++ lib/libc/gen/Makefile.inc @@ -21,7 +21,7 @@ initgroups.c isatty.c isinf.c isnan.c jrand48.c lcong48.c \ lockf.c lrand48.c mrand48.c nftw.c nice.c \ nlist.c nrand48.c opendir.c \ - pause.c pmadvise.c popen.c pselect.c \ + pause.c pmadvise.c popen.c posix_spawn.c pselect.c \ psignal.c pw_scan.c pwcache.c \ raise.c readdir.c readpassphrase.c rewinddir.c \ scandir.c seed48.c seekdir.c sem.c semctl.c \ @@ -80,7 +80,7 @@ err.3 verr.3 err.3 verrc.3 err.3 verrx.3 err.3 vwarn.3 err.3 vwarnc.3 \ err.3 vwarnx.3 err.3 warnc.3 err.3 warn.3 err.3 warnx.3 MLINKS+=3Dexec.3 execl.3 exec.3 execle.3 exec.3 execlp.3 exec.3 exect.3 \ - exec.3 execv.3 exec.3 execvp.3 exec.3 execvP.3 + exec.3 execv.3 exec.3 execvp.3 exec.3 execvpe.3 exec.3 execvP.3 MLINKS+=3Dfpclassify.3 finite.3 fpclassify.3 finitef.3 \ fpclassify.3 isfinite.3 fpclassify.3 isinf.3 fpclassify.3 isnan.3 \ fpclassify.3 isnormal.3 --- lib/libc/gen/Symbol.map +++ lib/libc/gen/Symbol.map @@ -329,6 +329,7 @@ }; =20 FBSD_1.1 { + execvpe; fts_open; fts_close; fts_read; @@ -337,6 +338,27 @@ fts_get_clientptr; fts_get_stream; fts_set_clientptr; + posix_spawn; + posix_spawn_file_actions_addclose; + posix_spawn_file_actions_adddup2; + posix_spawn_file_actions_addopen; + posix_spawn_file_actions_destroy; + posix_spawn_file_actions_init; + posix_spawnattr_destroy; + posix_spawnattr_getflags; + posix_spawnattr_getpgroup; + posix_spawnattr_getschedparam; + posix_spawnattr_getschedpolicy; + posix_spawnattr_getsigdefault; + posix_spawnattr_getsigmask; + posix_spawnattr_init; + posix_spawnattr_setflags; + posix_spawnattr_setpgroup; + posix_spawnattr_setschedparam; + posix_spawnattr_setschedpolicy; + posix_spawnattr_setsigdefault; + posix_spawnattr_setsigmask; + posix_spawnp; }; =20 FBSDprivate_1.0 { --- lib/libc/gen/exec.3 +++ lib/libc/gen/exec.3 @@ -38,6 +38,7 @@ .Nm exect , .Nm execv , .Nm execvp , +.Nm execvpe , .Nm execvP .Nd execute a file .Sh LIBRARY @@ -64,6 +65,8 @@ .Ft int .Fn execvp "const char *file" "char *const argv[]" .Ft int +.Fn execvpe "const char *file" "char *const argv[]" "char *const envp[]" +.Ft int .Fn execvP "const char *file" "const char *search_path" "char *const argv[= ]" .Sh DESCRIPTION The @@ -118,9 +121,10 @@ pointer. .Pp The -.Fn execle -and +.Fn execle , .Fn exect +and +.Fn execvpe functions also specify the environment of the executed process by following the .Dv NULL @@ -142,6 +146,7 @@ The functions .Fn execlp , .Fn execvp , +.Fn execvpe , and .Fn execvP will duplicate the actions of the shell in searching for an executable file @@ -152,6 +157,7 @@ .Fn execlp and .Fn execvp , +.Fn execvpe , search path is the path specified in the environment by .Dq Ev PATH variable. @@ -277,7 +283,8 @@ .Fn execl , .Fn execle , .Fn execlp , -.Fn execvp +.Fn execvp , +.Fn execvpe and .Fn execvP functions @@ -319,3 +326,7 @@ .Fn execvP function first appeared in .Fx 5.2 . +The +.Fn execvpe +function first appeared in +.Fx 8.0 . --- lib/libc/gen/exec.c +++ lib/libc/gen/exec.c @@ -140,20 +140,15 @@ int execvp(const char *name, char * const *argv) { - const char *path; - - /* Get the path we're searching. */ - if ((path =3D getenv("PATH")) =3D=3D NULL) - path =3D _PATH_DEFPATH; - - return (execvP(name, path, argv)); + return (execvpe(name, argv, environ)); } =20 -int -execvP(name, path, argv) +static int +execvPe(name, path, argv, envp) const char *name; const char *path; char * const *argv; + char * const *envp; { char **memp; int cnt, lp, ln; @@ -269,3 +264,21 @@ done: return (-1); } + +int +execvP(const char *name, const char *path, char * const argv[]) +{ + return execvPe(name, path, argv, environ); +} + +int +execvpe(const char *name, char * const argv[], char * const envp[]) +{ + const char *path; + + /* Get the path we're searching. */ + if ((path =3D getenv("PATH")) =3D=3D NULL) + path =3D _PATH_DEFPATH; + + return (execvPe(name, path, argv, envp)); +} --- lib/libc/gen/posix_spawn.c +++ lib/libc/gen/posix_spawn.c @@ -0,0 +1,441 @@ +/*- + * Copyright (c) 2008 Ed Schouten + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURP= OSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENT= IAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STR= ICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY W= AY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include "namespace.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include "un-namespace.h" + +extern char **environ; + +struct __posix_spawnattr { + short sa_flags; + pid_t sa_pgroup; + struct sched_param sa_schedparam; + int sa_schedpolicy; + sigset_t sa_sigdefault; + sigset_t sa_sigmask; +}; + +struct __posix_spawn_file_actions { + STAILQ_HEAD(, __posix_spawn_file_actions_entry) fa_list; +}; + +typedef struct __posix_spawn_file_actions_entry { + STAILQ_ENTRY(__posix_spawn_file_actions_entry) fae_list; + enum { FAE_OPEN, FAE_DUP2, FAE_CLOSE } fae_action; + + int fae_fildes; + union { + struct { + char *path; +#define fae_path fae_data.open.path + int oflag; +#define fae_oflag fae_data.open.oflag + mode_t mode; +#define fae_mode fae_data.open.mode + } open; + struct { + int newfildes; +#define fae_newfildes fae_data.dup2.newfildes + } dup2; + } fae_data; +} posix_spawn_file_actions_entry_t; + +/* + * Spawn routines + */ + +static void +process_file_entry(posix_spawn_file_actions_entry_t *fae) +{ + int fd; + + switch (fae->fae_action) { + case FAE_OPEN: + /* Perform an open(), make it use the right fd */ + fd =3D _open(fae->fae_path, fae->fae_oflag, fae->fae_mode); + if (fd < 0) + _exit(127); + if (fd !=3D fae->fae_fildes) { + if (_dup2(fd, fae->fae_fildes) =3D=3D -1) + _exit(127); + if (_close(fd) !=3D 0) + _exit(127); + } + if (_fcntl(fae->fae_fildes, F_SETFD, 0) =3D=3D -1) + _exit(127); + break; + case FAE_DUP2: + /* Perform a dup2() */ + if (_dup2(fae->fae_fildes, fae->fae_newfildes) =3D=3D -1) + _exit(127); + if (_fcntl(fae->fae_newfildes, F_SETFD, 0) =3D=3D -1) + _exit(127); + break; + case FAE_CLOSE: + /* Perform a close() */ + if (_close(fae->fae_fildes) !=3D 0) + _exit(127); + break; + } +} + +static pid_t +do_posix_spawn(const posix_spawn_file_actions_t *fa, const posix_spawnattr= _t sa) +{ + posix_spawn_file_actions_entry_t *fae; + struct sigaction sigact =3D { .sa_flags =3D 0, .sa_handler =3D SIG_DFL }; + pid_t p; + int i; + + /* Off we go */ + p =3D fork(); + if (p !=3D 0) + return (p); + + /* + * POSIX doesn't really describe in which order everything + * should be set. We'll just set them in the order in which they + * are mentioned. + */ + + /* Set signal masks/defaults */ + if (sa->sa_flags & POSIX_SPAWN_SETSIGMASK) { + _sigprocmask(SIG_SETMASK, &sa->sa_sigmask, NULL); + } + + if (sa->sa_flags & POSIX_SPAWN_SETSIGDEF) { + for (i =3D 1; i < NSIG; i++) { + if (sigismember(&sa->sa_sigdefault, i)) + if (_sigaction(i, &sigact, NULL) !=3D 0) + _exit(127); + } + } + + /* Reset user ID's */ + if (sa->sa_flags & POSIX_SPAWN_RESETIDS) { + if (setegid(getgid()) !=3D 0) + _exit(127); + if (seteuid(getuid()) !=3D 0) + _exit(127); + } + + /* Set process group */ + if (sa->sa_flags & POSIX_SPAWN_SETPGROUP) { + if (setpgid(0, sa->sa_pgroup) !=3D 0) + _exit(127); + } + + /* Set scheduler policy */ + if (sa->sa_flags & POSIX_SPAWN_SETSCHEDULER) { + if (sched_setscheduler(0, sa->sa_schedpolicy, + &sa->sa_schedparam) !=3D 0) + _exit(127); + } else if (sa->sa_flags & POSIX_SPAWN_SETSCHEDPARAM) { + if (sched_setparam(0, &sa->sa_schedparam) !=3D 0) + _exit(127); + } + + /* Replay all file descriptor modifications */ + if (fa !=3D NULL) { + STAILQ_FOREACH(fae, &(*fa)->fa_list, fae_list) + process_file_entry(fae); + } + + return (p); +} + +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], char * const envp[__restrict]) +{ + pid_t p; +=09 + p =3D do_posix_spawn(fa, *sa); + + switch (p) { + case -1: + return (-1); + case 0: + _execve(path, argv, envp !=3D NULL ? envp : environ); + _exit(127); + default: + *pid =3D p; + return (0); + } +} + +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], char * const envp[__restrict]) +{ + pid_t p; +=09 + p =3D do_posix_spawn(fa, *sa); + + switch (p) { + case -1: + return (-1); + case 0: + execvpe(path, argv, envp !=3D NULL ? envp : environ); + _exit(127); + default: + *pid =3D p; + return (0); + } +} + +/* + * File descriptor actions + */ + +int +posix_spawn_file_actions_init(posix_spawn_file_actions_t *ret) +{ + posix_spawn_file_actions_t fa; + + fa =3D malloc(sizeof(struct __posix_spawn_file_actions)); + if (fa =3D=3D NULL) + return (-1); + + STAILQ_INIT(&fa->fa_list); + *ret =3D fa; + return (0); +} + +int +posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *fa) +{ + posix_spawn_file_actions_entry_t *fae; + + while ((fae =3D STAILQ_FIRST(&(*fa)->fa_list)) !=3D NULL) { + /* Remove file action entry from the queue */ + STAILQ_REMOVE_HEAD(&(*fa)->fa_list, fae_list); + + /* Deallocate file action entry */ + if (fae->fae_action =3D=3D FAE_OPEN) + free(fae->fae_path); + free(fae); + } + + free(*fa); + return (0); +} + +int +posix_spawn_file_actions_addopen(posix_spawn_file_actions_t * __restrict f= a, + int fildes, const char * __restrict path, int oflag, mode_t mode) +{ + posix_spawn_file_actions_entry_t *fae; + + /* Allocate object */ + fae =3D malloc(sizeof(posix_spawn_file_actions_entry_t)); + if (fae =3D=3D NULL) + return (-1); + + /* Set values and store in queue */ + fae->fae_action =3D FAE_OPEN; + fae->fae_path =3D strdup(path); + if (fae->fae_path =3D=3D NULL) { + free(fae); + return (-1); + } + fae->fae_fildes =3D fildes; + fae->fae_oflag =3D oflag; + fae->fae_mode =3D mode; + + STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list); + return (0); +} + +int +posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *fa, + int fildes, int newfildes) +{ + posix_spawn_file_actions_entry_t *fae; + + /* Allocate object */ + fae =3D malloc(sizeof(posix_spawn_file_actions_entry_t)); + if (fae =3D=3D NULL) + return (-1); + + /* Set values and store in queue */ + fae->fae_action =3D FAE_DUP2; + fae->fae_fildes =3D fildes; + fae->fae_newfildes =3D newfildes; + + STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list); + return (0); +} + +int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *fa, + int fildes) +{ + posix_spawn_file_actions_entry_t *fae; + + /* Allocate object */ + fae =3D malloc(sizeof(posix_spawn_file_actions_entry_t)); + if (fae =3D=3D NULL) + return (-1); + + /* Set values and store in queue */ + fae->fae_action =3D FAE_CLOSE; + fae->fae_fildes =3D fildes; + + STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list); + return (0); +} + +/* + * Spawn attributes + */ + +int +posix_spawnattr_init(posix_spawnattr_t *ret) +{ + posix_spawnattr_t sa; + + sa =3D malloc(sizeof(struct __posix_spawnattr)); + if (sa =3D=3D NULL) + return (-1); +=09 + sa->sa_flags =3D 0; + *ret =3D sa; + return (0); +} + +int +posix_spawnattr_destroy(posix_spawnattr_t *sa) +{ + free(*sa); + return (0); +} + +int +posix_spawnattr_getflags(const posix_spawnattr_t * __restrict sa, + short * __restrict flags) +{ + *flags =3D (*sa)->sa_flags; + return (0); +} + +int +posix_spawnattr_getpgroup(const posix_spawnattr_t * __restrict sa, + pid_t * __restrict pgroup) +{ + *pgroup =3D (*sa)->sa_pgroup; + return (0); +} + +int +posix_spawnattr_getschedparam(const posix_spawnattr_t * __restrict sa, + struct sched_param * __restrict schedparam) +{ + *schedparam =3D (*sa)->sa_schedparam; + return (0); +} + +int +posix_spawnattr_getschedpolicy(const posix_spawnattr_t * __restrict sa, + int * __restrict schedpolicy) +{ + *schedpolicy =3D (*sa)->sa_schedpolicy; + return (0); +} + +int +posix_spawnattr_getsigdefault(const posix_spawnattr_t * __restrict sa, + sigset_t * __restrict sigdefault) +{ + *sigdefault =3D (*sa)->sa_sigdefault; + return (0); +} + +int +posix_spawnattr_getsigmask(const posix_spawnattr_t * __restrict sa, + sigset_t * __restrict sigmask) +{ + *sigmask =3D (*sa)->sa_sigmask; + return (0); +} + +int +posix_spawnattr_setflags(posix_spawnattr_t *sa, short flags) +{ + (*sa)->sa_flags =3D flags; + return (0); +} + +int +posix_spawnattr_setpgroup(posix_spawnattr_t *sa, pid_t pgroup) +{ + (*sa)->sa_pgroup =3D pgroup; + return (0); +} + +int +posix_spawnattr_setschedparam(posix_spawnattr_t *sa __restrict, + const struct sched_param * __restrict schedparam) +{ + (*sa)->sa_schedparam =3D *schedparam; + return (0); +} + +int +posix_spawnattr_setschedpolicy(posix_spawnattr_t *sa, int schedpolicy) +{ + (*sa)->sa_schedpolicy =3D schedpolicy; + return (0); +} + +int +posix_spawnattr_setsigdefault(posix_spawnattr_t * __restrict sa, + const sigset_t * __restrict sigdefault) +{ + (*sa)->sa_sigdefault =3D *sigdefault; + return (0); +} + +int +posix_spawnattr_setsigmask(posix_spawnattr_t * __restrict sa, + const sigset_t * __restrict sigmask) +{ + (*sa)->sa_sigmask =3D *sigmask; + return (0); +} --uX7BrQs69PbBafpd-- --mW9eGbZzDIYYWqGs Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.8 (FreeBSD) iEYEARECAAYFAkfn8T0ACgkQ52SDGA2eCwWhRQCff6TuuktlaPQ/aYrK2N7jauS9 8AIAn2WwYMrhqW2a18Ed+6Myb62eq05e =RrJz -----END PGP SIGNATURE----- --mW9eGbZzDIYYWqGs--