Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 24 Mar 2008 18:30:04 GMT
From:      Ed Schouten <ed@80386.nl>
To:        freebsd-standards@FreeBSD.org
Subject:   Re: standards/122051: Add posix_spawn(3)
Message-ID:  <200803241830.m2OIU4dT033548@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR standards/122051; it has been noted by GNATS.

From: Ed Schouten <ed@80386.nl>
To: Kostik Belousov <kostikbel@gmail.com>
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 <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?200803241830.m2OIU4dT033548>