Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 24 Mar 2008 19:21:49 +0100
From:      Ed Schouten <ed@80386.nl>
To:        Kostik Belousov <kostikbel@gmail.com>
Subject:   Re: standards/122051: Add posix_spawn(3)
Message-ID:  <20080324182149.GQ51074@hoeg.nl>
Resent-Message-ID: <20080324182227.GS51074@hoeg.nl>
In-Reply-To: <20080324160522.GL7965@deviant.kiev.zoral.com.ua>
References:  <20080324153823.E02241CC50@palm.hoeg.nl> <20080324160522.GL7965@deviant.kiev.zoral.com.ua>

next in thread | previous in thread | raw e-mail | index | archive | help

--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 <kostikbel@gmail.com> 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 <ed@80386.nl>
 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 <ed@80386.nl>
+ * 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 <sys/cdefs.h>
+#include <sys/_types.h>
+#include <sys/_sigset.h>
+
+#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 <ed@80386.nl>
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/queue.h>
+
+#include <fcntl.h>
+#include <sched.h>
+#include <spawn.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#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--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20080324182149.GQ51074>