From owner-freebsd-standards@FreeBSD.ORG Mon Mar 24 11:07:15 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 2F8411065670 for ; Mon, 24 Mar 2008 11:07:15 +0000 (UTC) (envelope-from owner-bugmaster@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 2D7B78FC28 for ; Mon, 24 Mar 2008 11:07:15 +0000 (UTC) (envelope-from owner-bugmaster@FreeBSD.org) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.2/8.14.2) with ESMTP id m2OB7FXQ087946 for ; Mon, 24 Mar 2008 11:07:15 GMT (envelope-from owner-bugmaster@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.2/8.14.1/Submit) id m2OB7EjN087942 for freebsd-standards@FreeBSD.org; Mon, 24 Mar 2008 11:07:14 GMT (envelope-from owner-bugmaster@FreeBSD.org) Date: Mon, 24 Mar 2008 11:07:14 GMT Message-Id: <200803241107.m2OB7EjN087942@freefall.freebsd.org> X-Authentication-Warning: freefall.freebsd.org: gnats set sender to owner-bugmaster@FreeBSD.org using -f From: FreeBSD bugmaster To: freebsd-standards@FreeBSD.org Cc: Subject: Current problem reports assigned to freebsd-standards@FreeBSD.org X-BeenThere: freebsd-standards@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Standards compliance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 24 Mar 2008 11:07:15 -0000 Current FreeBSD problem reports Critical problems Serious problems S Tracker Resp. Description -------------------------------------------------------------------------------- o bin/25542 standards /bin/sh: null char in quoted string o stand/54410 standards one-true-awk not POSIX compliant (no extended REs) o stand/82654 standards C99 long double math functions are missing o stand/94729 standards [libc] fcntl() throws undocumented ENOTTY 4 problems total. Non-critical problems S Tracker Resp. Description -------------------------------------------------------------------------------- s bin/14925 standards getsubopt isn't poisonous enough o stand/21519 standards sys/dir.h should be deprecated some more o bin/24390 standards Replacing old dir-symlinks when using /bin/ln s stand/24590 standards timezone function not compatible witn Single Unix Spec f stand/25777 standards [kernel] [patch] atime not updated on exec a docs/26003 standards getgroups(2) lists NGROUPS_MAX but not syslimits.h o kern/27835 standards [libc] execve() doesn't conform to execve(2) spec in s s stand/36076 standards Implementation of POSIX fuser command o stand/39256 standards snprintf/vsnprintf aren't POSIX-conformant for strings p stand/41576 standards POSIX compliance of ln(1) o stand/44425 standards getcwd() succeeds even if current dir has perm 000. o stand/46119 standards Priority problems for SCHED_OTHER using pthreads o stand/54833 standards [pcvt] more pcvt deficits o stand/54839 standards [pcvt] pcvt deficits p stand/55112 standards glob.h, glob_t's gl_pathc should be "size_t", not "int o stand/56476 standards cd9660 unicode support simple hack o stand/58676 standards grantpt(3) alters storage used by ptsname(3) s stand/62858 standards malloc(0) not C99 compliant s kern/64875 standards [libc] [patch] [request] add a system call: fdatasync( o stand/66357 standards make POSIX conformance problem ('sh -e' & '+' command- o stand/66531 standards [libc] [patch] _gettemp uses a far smaller set of file o stand/70813 standards [PATCH] ls(1) not Posix compliant o stand/72006 standards floating point formating in non-C locales o stand/79056 standards regex(3) regression tests a stand/80293 standards sysconf() does not support well-defined unistd values o stand/81287 standards [PATCH]: fingerd(8) might send a line not ending in CR o stand/83845 standards [libm] [patch] add log2() and log2f() support for libm a stand/86484 standards [PATCH] mkfifo(1) uses wrong permissions o stand/92360 standards [headers] [patch] Missing TAB3 in kernel headers o stand/92362 standards [headers] [patch] Missing SIGPOLL in kernel headers o kern/93705 standards [headers] [patch] ENODATA and EGREGIOUS (for glibc com o stand/96016 standards [headers] clock_getres et al should be in o stand/96236 standards [PATCH] [POSIX] sed.1 incorrectly describes a function p stand/99517 standards Missing SIGRTMIN and SIGRTMAX signals o stand/99960 standards [Patch] make(1): Add -p flag o stand/100017 standards [Patch] Add fuser(1) functionality to fstat(1) o stand/104743 standards [headers] [patch] Wrong values for _POSIX_ minimal lim o stand/104841 standards [libm] [patch] C99 long double square root. o stand/107561 standards [libc] [patch] [request] Missing SUS function tcgetsid o kern/114578 standards [libc] wide character printing using swprintf(dst, n, o stand/116081 standards make does not work with the directive sinclude o stand/116221 standards [kernel] [patch] [request] SUS issue -- FreeBSD has no o bin/116413 standards incorrect getconf(1) handling of unsigned constants gi o stand/116826 standards [PATCH] sh support for POSIX character classes o stand/118047 standards SUGGESTION: /etc/printcap vs mergemaster o stand/119804 standards [timedef] [patch] Invalid (long)date format in pl_PL.I o stand/120947 standards xsm ignores system.xsm and .xsmstartup o stand/121921 standards [patch] Add leap second support to at(1), atrun(8) 48 problems total. From owner-freebsd-standards@FreeBSD.ORG Mon Mar 24 12:06:03 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 ECB181065678; Mon, 24 Mar 2008 12:06:03 +0000 (UTC) (envelope-from das@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id D3F818FC13; Mon, 24 Mar 2008 12:06:03 +0000 (UTC) (envelope-from das@FreeBSD.org) Received: from freefall.freebsd.org (das@localhost [127.0.0.1]) by freefall.freebsd.org (8.14.2/8.14.2) with ESMTP id m2OC63vl095618; Mon, 24 Mar 2008 12:06:03 GMT (envelope-from das@freefall.freebsd.org) Received: (from das@localhost) by freefall.freebsd.org (8.14.2/8.14.1/Submit) id m2OC633m095614; Mon, 24 Mar 2008 12:06:03 GMT (envelope-from das) Date: Mon, 24 Mar 2008 12:06:03 GMT Message-Id: <200803241206.m2OC633m095614@freefall.freebsd.org> To: kargl@troutmask.apl.washington.edu, das@FreeBSD.org, freebsd-standards@FreeBSD.org From: das@FreeBSD.org Cc: Subject: Re: standards/104841: [libm] [patch] C99 long double square root. X-BeenThere: freebsd-standards@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Standards compliance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 24 Mar 2008 12:06:04 -0000 Synopsis: [libm] [patch] C99 long double square root. State-Changed-From-To: open->closed State-Changed-By: das State-Changed-When: Mon Mar 24 12:05:24 UTC 2008 State-Changed-Why: A later version of this was committed, thanks! http://www.freebsd.org/cgi/query-pr.cgi?pr=104841 From owner-freebsd-standards@FreeBSD.ORG Mon Mar 24 15:40:04 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 2AB3F1065673 for ; Mon, 24 Mar 2008 15:40:04 +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 F12078FC35 for ; Mon, 24 Mar 2008 15:40:03 +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 m2OFe30Q016612 for ; Mon, 24 Mar 2008 15:40:03 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.2/8.14.1/Submit) id m2OFe3i2016611; Mon, 24 Mar 2008 15:40:03 GMT (envelope-from gnats) Resent-Date: Mon, 24 Mar 2008 15:40:03 GMT Resent-Message-Id: <200803241540.m2OFe3i2016611@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-standards@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Ed Schouten Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id D879B106566B for ; Mon, 24 Mar 2008 15:38:26 +0000 (UTC) (envelope-from ed@hoeg.nl) Received: from palm.hoeg.nl (mx0.hoeg.nl [IPv6:2001:610:652::211]) by mx1.freebsd.org (Postfix) with ESMTP id CD1EB8FC24 for ; Mon, 24 Mar 2008 15:38:24 +0000 (UTC) (envelope-from ed@hoeg.nl) Received: by palm.hoeg.nl (Postfix, from userid 1000) id E02241CC50; Mon, 24 Mar 2008 16:38:23 +0100 (CET) Message-Id: <20080324153823.E02241CC50@palm.hoeg.nl> Date: Mon, 24 Mar 2008 16:38:23 +0100 (CET) From: Ed Schouten To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Cc: Subject: 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 15:40:04 -0000 >Number: 122051 >Category: standards >Synopsis: Add posix_spawn(3) >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-standards >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Mon Mar 24 15:40:03 UTC 2008 >Closed-Date: >Last-Modified: >Originator: Ed Schouten >Release: FreeBSD 8.0-CURRENT amd64 >Organization: >Environment: System: FreeBSD flippo.80386.nl 8.0-CURRENT FreeBSD 8.0-CURRENT #0: Sun Mar 23 13:07:36 CET 2008 ed@flippo.80386.nl:/usr/obj/datadump/home/ed/p4/mpsafetty/sys/FLIPPO amd64 >Description: POSIX describes routines called posix_spawn() and posix_spawnp(), which can be used as replacements for exec/fork in a lot of cases. It doesn't really matter for FreeBSD, but there are some operating systems that want to implement POSIX routines, but don't use the MMU, which means forking is really expensive. FreeBSD doesn't have the routines in libc, which is bad, because we want to be as POSIX as possible. ;-) >How-To-Repeat: >Fix: The following patch adds posix_spawn() and posix_spawnp() to libc. I had to add yet another exec routine, namely execvpe(). We need to be able to override the environment, yet make it possible to search through $PATH. 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. This patch still misses a manual page. --- 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,206 @@ +/*- + * 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 PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * 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, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * 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 +#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 { + short sa_flags; + pid_t sa_pgroup; + struct sched_param sa_schedparam; + int sa_schedpolicy; + sigset_t sa_sigdefault; + sigset_t sa_sigmask; +} posix_spawnattr_t; + +typedef struct { + STAILQ_HEAD(, __posix_spawn_file_actions_entry_t) fa_list; +} 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 * __restrict, + 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 * __restrict, + 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 * __restrict, + int, const char * __restrict, int, mode_t); +int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *, int, int); +int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *, int); + +/* + * Spawn attributes + */ + +static __inline int +posix_spawnattr_init(posix_spawnattr_t *sa) +{ + sa->sa_flags = 0; + return (0); +} + +static __inline int +posix_spawnattr_destroy(posix_spawnattr_t *sa) +{ + return (0); +} + +static __inline int +posix_spawnattr_getflags(const posix_spawnattr_t * __restrict sa, + short * __restrict flags) +{ + *flags = sa->sa_flags; + return (0); +} + +static __inline int +posix_spawnattr_getpgroup(const posix_spawnattr_t * __restrict sa, + pid_t * __restrict pgroup) +{ + *pgroup = sa->sa_pgroup; + return (0); +} + +static __inline int +posix_spawnattr_getschedparam(const posix_spawnattr_t * __restrict sa, + struct sched_param * __restrict schedparam) +{ + *schedparam = sa->sa_schedparam; + return (0); +} + +static __inline int +posix_spawnattr_getschedpolicy(const posix_spawnattr_t * __restrict sa, + int * __restrict schedpolicy) +{ + *schedpolicy = sa->sa_schedpolicy; + return (0); +} + +static __inline int +posix_spawnattr_getsigdefault(const posix_spawnattr_t * __restrict sa, + sigset_t * __restrict sigdefault) +{ + *sigdefault = sa->sa_sigdefault; + return (0); +} + +static __inline int +posix_spawnattr_getsigmask(const posix_spawnattr_t * __restrict sa, + sigset_t * __restrict sigmask) +{ + *sigmask = sa->sa_sigmask; + return (0); +} + +static __inline int +posix_spawnattr_setflags(posix_spawnattr_t *sa, short flags) +{ + sa->sa_flags = flags; + return (0); +} + +static __inline int +posix_spawnattr_setpgroup(posix_spawnattr_t *sa, pid_t pgroup) +{ + sa->sa_pgroup = pgroup; + return (0); +} + +static __inline int +posix_spawnattr_setschedparam(posix_spawnattr_t *sa __restrict, + const struct sched_param * __restrict schedparam) +{ + sa->sa_schedparam = *schedparam; + return (0); +} + +static __inline int +posix_spawnattr_setschedpolicy(posix_spawnattr_t *sa, int schedpolicy) +{ + sa->sa_schedpolicy = schedpolicy; + return (0); +} + +static __inline int +posix_spawnattr_setsigdefault(posix_spawnattr_t * __restrict sa, + const sigset_t * __restrict sigdefault) +{ + sa->sa_sigdefault = *sigdefault; + return (0); +} + +static __inline int +posix_spawnattr_setsigmask(posix_spawnattr_t * __restrict sa, + const sigset_t * __restrict sigmask) +{ + sa->sa_sigmask = *sigmask; + return (0); +} + +#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+=exec.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+=fpclassify.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 @@ -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; --- 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 = getenv("PATH")) == NULL) - path = _PATH_DEFPATH; - - return (execvP(name, path, argv)); + return (execvpe(name, argv, environ)); } -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 = getenv("PATH")) == NULL) + path = _PATH_DEFPATH; + + return (execvPe(name, path, argv, envp)); +} --- lib/libc/gen/posix_spawn.c +++ lib/libc/gen/posix_spawn.c @@ -0,0 +1,301 @@ +/*- + * 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 PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * 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, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * 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 "un-namespace.h" + +extern char **environ; + +typedef struct __posix_spawn_file_actions_entry_t { + STAILQ_ENTRY(__posix_spawn_file_actions_entry_t) 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 = _open(fae->fae_path, fae->fae_oflag, fae->fae_mode); + if (fd < 0) + _exit(127); + if (fd != fae->fae_fildes) { + if (_dup2(fd, fae->fae_fildes) == -1) + _exit(127); + if (_close(fd) != 0) + _exit(127); + } + if (_fcntl(fae->fae_fildes, F_SETFD, 0) == -1) + _exit(127); + break; + case FAE_DUP2: + /* Perform a dup2() */ + if (_dup2(fae->fae_fildes, fae->fae_newfildes) == -1) + _exit(127); + if (_fcntl(fae->fae_newfildes, F_SETFD, 0) == -1) + _exit(127); + break; + case FAE_CLOSE: + /* Perform a close() */ + if (_close(fae->fae_fildes) != 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 = { .sa_flags = 0, .sa_handler = SIG_DFL }; + pid_t p; + int i; + + /* Off we go */ + p = fork(); + if (p != 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 = 1; i < NSIG; i++) { + if (sigismember(&sa->sa_sigdefault, i)) + if (_sigaction(i, &sigact, NULL) != 0) + _exit(127); + } + } + + /* Reset user ID's */ + if (sa->sa_flags & POSIX_SPAWN_RESETIDS) { + if (setegid(getgid()) != 0) + _exit(127); + if (seteuid(getuid()) != 0) + _exit(127); + } + + /* Set process group */ + if (sa->sa_flags & POSIX_SPAWN_SETPGROUP) { + if (setpgid(0, sa->sa_pgroup) != 0) + _exit(127); + } + + /* Set scheduler policy */ + if (sa->sa_flags & POSIX_SPAWN_SETSCHEDULER) { + if (sched_setscheduler(0, sa->sa_schedpolicy, + &sa->sa_schedparam) != 0) + _exit(127); + } else if (sa->sa_flags & POSIX_SPAWN_SETSCHEDPARAM) { + if (sched_setparam(0, &sa->sa_schedparam) != 0) + _exit(127); + } + + /* Replay all file descriptor modifications */ + if (fa != 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; + + p = do_posix_spawn(fa, sa); + + switch (p) { + case -1: + return (-1); + case 0: + _execve(path, argv, envp != NULL ? envp : environ); + _exit(127); + default: + *pid = 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; + + p = do_posix_spawn(fa, sa); + + switch (p) { + case -1: + return (-1); + case 0: + execvpe(path, argv, envp != NULL ? envp : environ); + _exit(127); + default: + *pid = p; + return (0); + } +} + +/* + * File descriptor actions + */ + +int +posix_spawn_file_actions_init(posix_spawn_file_actions_t *fa) +{ + STAILQ_INIT(&fa->fa_list); + return (0); +} + +int +posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *fa) +{ + posix_spawn_file_actions_entry_t *fae; + + while ((fae = STAILQ_FIRST(&fa->fa_list)) != NULL) { + /* Remove file action entry from the queue */ + STAILQ_REMOVE_HEAD(&fa->fa_list, fae_list); + + /* Deallocate file action entry */ + if (fae->fae_action == FAE_OPEN) + free(fae->fae_path); + free(fae); + } + + return (0); +} + +int +posix_spawn_file_actions_addopen(posix_spawn_file_actions_t * __restrict fa, + int fildes, const char * __restrict path, int oflag, mode_t mode) +{ + posix_spawn_file_actions_entry_t *fae; + + /* Allocate object */ + fae = malloc(sizeof(posix_spawn_file_actions_entry_t)); + if (fae == NULL) + return (-1); + + /* Set values and store in queue */ + fae->fae_action = FAE_OPEN; + fae->fae_path = strdup(path); + if (fae->fae_path == NULL) { + free(fae); + return (-1); + } + fae->fae_fildes = fildes; + fae->fae_oflag = oflag; + fae->fae_mode = 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 = malloc(sizeof(posix_spawn_file_actions_entry_t)); + if (fae == NULL) + return (-1); + + /* Set values and store in queue */ + fae->fae_action = FAE_DUP2; + fae->fae_fildes = fildes; + fae->fae_newfildes = 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 = malloc(sizeof(posix_spawn_file_actions_entry_t)); + if (fae == NULL) + return (-1); + + /* Set values and store in queue */ + fae->fae_action = FAE_CLOSE; + fae->fae_fildes = fildes; + + STAILQ_INSERT_TAIL(&fa->fa_list, fae, fae_list); + return (0); +} >Release-Note: >Audit-Trail: >Unformatted: From owner-freebsd-standards@FreeBSD.ORG Mon Mar 24 18:22:30 2008 Return-Path: Delivered-To: freebsd-standards@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 6EE56106566B for ; Mon, 24 Mar 2008 18:22:30 +0000 (UTC) (envelope-from ed@hoeg.nl) Received: from palm.hoeg.nl (mx0.hoeg.nl [IPv6:2001:610:652::211]) by mx1.freebsd.org (Postfix) with ESMTP id D19B88FC19 for ; Mon, 24 Mar 2008 18:22:27 +0000 (UTC) (envelope-from ed@hoeg.nl) Received: by palm.hoeg.nl (Postfix, from userid 1000) id 58CBC1CC7A; Mon, 24 Mar 2008 19:22:27 +0100 (CET) Resent-From: ed@80386.nl Resent-Date: Mon, 24 Mar 2008 19:22:27 +0100 Resent-Message-ID: <20080324182227.GS51074@hoeg.nl> Resent-To: freebsd-standards@FreeBSD.org Date: Mon, 24 Mar 2008 19:21:49 +0100 From: Ed Schouten To: Kostik Belousov Message-ID: <20080324182149.GQ51074@hoeg.nl> References: <20080324153823.E02241CC50@palm.hoeg.nl> <20080324160522.GL7965@deviant.kiev.zoral.com.ua> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="mW9eGbZzDIYYWqGs" Content-Disposition: inline In-Reply-To: <20080324160522.GL7965@deviant.kiev.zoral.com.ua> User-Agent: Mutt/1.5.17 (2007-11-01) Cc: Subject: Re: standards/122051: Add posix_spawn(3) X-BeenThere: freebsd-standards@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Standards compliance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 24 Mar 2008 18:22:30 -0000 --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-- 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-- From owner-freebsd-standards@FreeBSD.ORG Tue Mar 25 12:33:08 2008 Return-Path: Delivered-To: freebsd-standards@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id D9377106566C; Tue, 25 Mar 2008 12:33:08 +0000 (UTC) (envelope-from ed@hoeg.nl) Received: from palm.hoeg.nl (mx0.hoeg.nl [IPv6:2001:610:652::211]) by mx1.freebsd.org (Postfix) with ESMTP id 9F0468FC22; Tue, 25 Mar 2008 12:33:08 +0000 (UTC) (envelope-from ed@hoeg.nl) Received: by palm.hoeg.nl (Postfix, from userid 1000) id B4F971CC3F; Tue, 25 Mar 2008 13:33:06 +0100 (CET) Date: Tue, 25 Mar 2008 13:33:06 +0100 From: Ed Schouten To: Kostik Belousov , FreeBSD-gnats-submit@FreeBSD.org, freebsd-standards@FreeBSD.org Message-ID: <20080325123306.GT51074@hoeg.nl> References: <20080324153823.E02241CC50@palm.hoeg.nl> <20080324160522.GL7965@deviant.kiev.zoral.com.ua> <20080324182149.GQ51074@hoeg.nl> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="Wlbg71WMOPzcvmIn" Content-Disposition: inline In-Reply-To: <20080324182149.GQ51074@hoeg.nl> User-Agent: Mutt/1.5.17 (2007-11-01) Cc: Subject: Re: standards/122051: Add posix_spawn(3) X-BeenThere: freebsd-standards@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Standards compliance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 25 Mar 2008 12:33:09 -0000 --Wlbg71WMOPzcvmIn Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable * Ed Schouten wrote: > > > 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 >=20 > 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. As I was pointed out, Gnats probably eat big patches, but because it will do strange things with MIME, I've stored the patch online: http://g-rave.nl/unix/freebsd/freebsd-posix_spawn.diff It includes more fixes to be POSIX compliant (default values, etc). I've also added manual pages for all functions that are present in the header file. --=20 Ed Schouten WWW: http://g-rave.nl/ --Wlbg71WMOPzcvmIn Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.8 (FreeBSD) iEYEARECAAYFAkfo8QIACgkQ52SDGA2eCwVRagCfZqtNEoMq6/fgFRt6fBji4CWX xjAAnR7Oli5tIgwi1o7jP+uTZZsScuKT =UaGw -----END PGP SIGNATURE----- --Wlbg71WMOPzcvmIn-- From owner-freebsd-standards@FreeBSD.ORG Tue Mar 25 12:40:03 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 2049A106564A for ; Tue, 25 Mar 2008 12:40:03 +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 12E318FC15 for ; Tue, 25 Mar 2008 12:40:03 +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 m2PCe2Ok048779 for ; Tue, 25 Mar 2008 12:40:02 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.2/8.14.1/Submit) id m2PCe2OM048775; Tue, 25 Mar 2008 12:40:02 GMT (envelope-from gnats) Date: Tue, 25 Mar 2008 12:40:02 GMT Message-Id: <200803251240.m2PCe2OM048775@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: Tue, 25 Mar 2008 12:40:03 -0000 The following reply was made to PR standards/122051; it has been noted by GNATS. From: Ed Schouten To: Kostik Belousov , FreeBSD-gnats-submit@FreeBSD.org, freebsd-standards@FreeBSD.org Cc: Subject: Re: standards/122051: Add posix_spawn(3) Date: Tue, 25 Mar 2008 13:33:06 +0100 --Wlbg71WMOPzcvmIn Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable * Ed Schouten wrote: > > > 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 >=20 > 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. As I was pointed out, Gnats probably eat big patches, but because it will do strange things with MIME, I've stored the patch online: http://g-rave.nl/unix/freebsd/freebsd-posix_spawn.diff It includes more fixes to be POSIX compliant (default values, etc). I've also added manual pages for all functions that are present in the header file. --=20 Ed Schouten WWW: http://g-rave.nl/ --Wlbg71WMOPzcvmIn Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.8 (FreeBSD) iEYEARECAAYFAkfo8QIACgkQ52SDGA2eCwVRagCfZqtNEoMq6/fgFRt6fBji4CWX xjAAnR7Oli5tIgwi1o7jP+uTZZsScuKT =UaGw -----END PGP SIGNATURE----- --Wlbg71WMOPzcvmIn-- From owner-freebsd-standards@FreeBSD.ORG Fri Mar 28 13:03:58 2008 Return-Path: Delivered-To: freebsd-standards@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id DAE5B106564A for ; Fri, 28 Mar 2008 13:03:58 +0000 (UTC) (envelope-from ed@hoeg.nl) Received: from palm.hoeg.nl (mx0.hoeg.nl [IPv6:2001:610:652::211]) by mx1.freebsd.org (Postfix) with ESMTP id 98A5C8FC12 for ; Fri, 28 Mar 2008 13:03:58 +0000 (UTC) (envelope-from ed@hoeg.nl) Received: by palm.hoeg.nl (Postfix, from userid 1000) id F2FDA1CC50; Fri, 28 Mar 2008 14:03:57 +0100 (CET) Date: Fri, 28 Mar 2008 14:03:57 +0100 From: Ed Schouten To: FreeBSD Standards Message-ID: <20080328130357.GC51074@hoeg.nl> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="qsoMWdMv/ifdm7CC" Content-Disposition: inline User-Agent: Mutt/1.5.17 (2007-11-01) Subject: Ambiguous sentence in POSIX onlinepubs 11.1.11 X-BeenThere: freebsd-standards@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Standards compliance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 28 Mar 2008 13:03:59 -0000 --qsoMWdMv/ifdm7CC Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Hello everyone, The last couple of days I've been reading the POSIX onlinepubs now and then to find out how my new mpsafe TTY implementation conforms to POSIX. In section 11.1.11, there is the following sentence: "The last process to close a terminal device file shall cause any output to be sent to the device and any input to be discarded." This sentence is quite ambiguous. It could mean: "The last process to close a terminal device file shall cause any output to be sent to the device, [but] any input to be discarded." but it could also mean: "The last process to close a terminal device file shall cause any output [which still has] to be sent to the device and any input to be discarded." I know FreeBSD currently implements the first behaviour. It drains output on closure, but how can we know for sure this is the correct behaviour? After I read POSIX, I changed my mpsafetty branch to perform the second behaviour, but after that I reread the section and discovered the sentence was actually ambiguous. --=20 Ed Schouten WWW: http://g-rave.nl/ --qsoMWdMv/ifdm7CC Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.8 (FreeBSD) iEYEARECAAYFAkfs7L0ACgkQ52SDGA2eCwUtcgCeKXO1+lOui3PnQXJqrufWA8qk YGEAniW9GOY9B2Xom8wDBuZhZRxXlGkt =6DQI -----END PGP SIGNATURE----- --qsoMWdMv/ifdm7CC-- From owner-freebsd-standards@FreeBSD.ORG Fri Mar 28 19:05:53 2008 Return-Path: Delivered-To: freebsd-standards@FreeBSD.ORG Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 2CE9D1065676 for ; Fri, 28 Mar 2008 19:05:53 +0000 (UTC) (envelope-from das@FreeBSD.ORG) Received: from zim.MIT.EDU (ZIM.MIT.EDU [18.95.3.101]) by mx1.freebsd.org (Postfix) with ESMTP id DE71A8FC21 for ; Fri, 28 Mar 2008 19:05:52 +0000 (UTC) (envelope-from das@FreeBSD.ORG) Received: from zim.MIT.EDU (localhost [127.0.0.1]) by zim.MIT.EDU (8.14.2/8.14.2) with ESMTP id m2SIebH4065972; Fri, 28 Mar 2008 14:40:37 -0400 (EDT) (envelope-from das@FreeBSD.ORG) Received: (from das@localhost) by zim.MIT.EDU (8.14.2/8.14.2/Submit) id m2SIebYr065971; Fri, 28 Mar 2008 14:40:37 -0400 (EDT) (envelope-from das@FreeBSD.ORG) Date: Fri, 28 Mar 2008 14:40:37 -0400 From: David Schultz To: Ed Schouten Message-ID: <20080328184037.GA65795@zim.MIT.EDU> Mail-Followup-To: Ed Schouten , FreeBSD Standards References: <20080328130357.GC51074@hoeg.nl> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20080328130357.GC51074@hoeg.nl> Cc: FreeBSD Standards Subject: Re: Ambiguous sentence in POSIX onlinepubs 11.1.11 X-BeenThere: freebsd-standards@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Standards compliance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 28 Mar 2008 19:05:53 -0000 On Fri, Mar 28, 2008, Ed Schouten wrote: > The last couple of days I've been reading the POSIX onlinepubs now and > then to find out how my new mpsafe TTY implementation conforms to POSIX. > > In section 11.1.11, there is the following sentence: > > "The last process to close a terminal device file shall cause > any output to be sent to the device and any input to be > discarded." > > This sentence is quite ambiguous. It could mean: > > "The last process to close a terminal device file shall cause > any output to be sent to the device, [but] any input to be > discarded." > > but it could also mean: > > "The last process to close a terminal device file shall cause > any output [which still has] to be sent to the device and any > input to be discarded." I doubt that even the most incoherent standards author would deliberately use "to" as a participle, infinitive, AND preposition, all in the same sentence, so I'd go with the first interpretation. That's also the interpretation that makes more sense, right? From owner-freebsd-standards@FreeBSD.ORG Fri Mar 28 23:06:39 2008 Return-Path: Delivered-To: freebsd-standards@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 9603C1065675 for ; Fri, 28 Mar 2008 23:06:39 +0000 (UTC) (envelope-from brde@optusnet.com.au) Received: from fallbackmx09.syd.optusnet.com.au (fallbackmx09.syd.optusnet.com.au [211.29.132.242]) by mx1.freebsd.org (Postfix) with ESMTP id 08DDC8FC21 for ; Fri, 28 Mar 2008 23:06:37 +0000 (UTC) (envelope-from brde@optusnet.com.au) Received: from mail02.syd.optusnet.com.au (mail02.syd.optusnet.com.au [211.29.132.183]) by fallbackmx09.syd.optusnet.com.au (8.13.1/8.13.1) with ESMTP id m2SJV33Z022216 for ; Sat, 29 Mar 2008 06:31:04 +1100 Received: from besplex.bde.org (c220-239-252-11.carlnfd3.nsw.optusnet.com.au [220.239.252.11]) by mail02.syd.optusnet.com.au (8.13.1/8.13.1) with ESMTP id m2SJUdhX015985 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Sat, 29 Mar 2008 06:30:40 +1100 Date: Sat, 29 Mar 2008 06:30:39 +1100 (EST) From: Bruce Evans X-X-Sender: bde@besplex.bde.org To: Ed Schouten In-Reply-To: <20080328130357.GC51074@hoeg.nl> Message-ID: <20080329051836.V36709@besplex.bde.org> References: <20080328130357.GC51074@hoeg.nl> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed Cc: FreeBSD Standards Subject: Re: Ambiguous sentence in POSIX onlinepubs 11.1.11 X-BeenThere: freebsd-standards@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Standards compliance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 28 Mar 2008 23:06:39 -0000 On Fri, 28 Mar 2008, Ed Schouten wrote: > The last couple of days I've been reading the POSIX onlinepubs now and > then to find out how my new mpsafe TTY implementation conforms to POSIX. Also run a conformance test. I tested the sio and cy drivers with NIST PCTS. POSIX now has its own conformance tests but I haven't tried those. > In section 11.1.11, there is the following sentence: > > "The last process to close a terminal device file shall cause > any output to be sent to the device and any input to be > discarded." > > This sentence is quite ambiguous. It could mean: > > "The last process to close a terminal device file shall cause > any output to be sent to the device, [but] any input to be > discarded." > > but it could also mean: > > "The last process to close a terminal device file shall cause > any output [which still has] to be sent to the device and any > input to be discarded." > > I know FreeBSD currently implements the first behaviour. It drains > output on closure, but how can we know for sure this is the correct > behaviour? I think it means the first behaviour. If it meant flushing output then it shouldn't say "to be sent to the device". Anyway, waiting for output to drain has been the default in BSD since at least 1988, and standards shouldn't change that. The rationale in 1966 contradicts the above slightly (though POSIX.1-1996 says the above too). From the PCTS source code quoting POSIX.memble (the quote matches POSIX.1-1996 B.7.1.11): %%% POSIX.1 is silent on whether a close() will block on waiting for transmission to drain, or even if a close() might cause a flush of pending output. If the application is concerned about this, it should call the appropriate function, such as tcdrain(), to ensure the desired behavior. %%% This contradicts both interpretations of the standard, since if the standard requires output to be sent then sending it but flushing it is an unreasonable interpretation, while if the standard requires flushing then it is not silent. The standard is only silent on whether sending requires full blocking like tcdrain() would do and BSD almost does (old BSD can block forever, wasting lots of phone connection or modem resources, but FreeBSD has a timeout; the implementation of this timeout is not quite right, since it affects tcdrain() (not just last-close from exit() where it is most needed), and it gives an undocumented errno for tcdrain()). The rationale in POSIX.1.2001-draf7 is quite different from the above: %%% 2823 A.11.1.11Closing a Terminal Device File 2824 IEEE Std 1003.1-200x does not specify that a close( ) on a terminal device file include the 2825 equivalent of a call to tcflow(fd,TCOON). 2826 An implementation that discards output at the time close( ) is called after reporting the return 2827 value to the write( ) call that data was written does not conform with IEEE Std 1003.1-200x. An 2828 application has functions such as tcdrain( ), tcflush( ), and tcflow( ) available to obtain the detailed 2829 behavior it requires with respect to flushing of output. 2830 At the time of the last close on a terminal device, an application relinquishes any ability to exert 2831 flow control via tcflow( ). %%% This mentions tcflow() but not tcdrain(). I interpret this as meaning that the wording is now considered unambiguous and unsilent, since tcflow() is irrelevant if the output must be flushed, but tcflow() is very relevant if the output has been stopped by tcflow(...TCOOF) -- then the program has asked for an infinite blockage. Ah, it gives one case where output must not be flushed -- if write() has succeeded. This covers the usual case of buffered writes. I don't see how there can be any output "to be sent" unless a previous buffered write has queued it and has succeeded, except possibly in some non-POSIX exceptional cases involving things like revoke(). Otherwise, last-close cannot be called while there are writes in progress. 11.1.11 in .2001-draft7 and 7.1.11 in .1996 also require HUPCL to work. The timing of asserting HUP (dropping DTR) is unclear. The receiver is required to flush input when it sees the HUP so draining output after asserting HUP would be useless. BSD drains output first. The PCTS sources (file 7.1.1_69.c) have more comments about this. The test seems to cover generation of hangup on the sender according to HUPCL and the receiver's processing of hangup. Hmm, one of the comments claims that draining/flushing of output is irrelevant in the HUPCL case, since the receiver is required to flush input. But this depends on the timing. The receiver is quite likely to handle hangup asynchronously before handling all input, so it would flush input even if the sender generates the hangup synchronously after flushing all the output, but it might not. Bruce