2 * Copyright (c) 2006-2012 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 * [SPN] Support for _POSIX_SPAWN
29 #include <spawn_private.h>
30 #include <sys/spawn_internal.h>
33 #include <limits.h> /* for OPEN_MAX, PATH_MAX */
34 #include <string.h> /* for strlcpy() */
35 #include <paths.h> /* for _PATH_DEFPATH */
36 #include <sys/stat.h> /* for struct stat */
41 * Description: Create a new process from the process image corresponding to
42 * the supplied 'file' argument and the parent processes path
45 * Parameters: pid Pointer to pid_t to receive the
46 * PID of the spawned process, if
47 * successful and 'pid' != NULL
48 * file Name of image file to spawn
49 * file_actions spawn file actions object which
50 * describes file actions to be
51 * performed during the spawn
52 * attrp spawn attributes object which
53 * describes attributes to be
54 * applied during the spawn
55 * argv argument vector array; NULL
57 * envp environment vector array; NULL
61 * !0 An errno value indicating the
62 * cause of the failure to spawn
64 * Notes: Much of this function is derived from code from execvP() from
65 * exec.c in libc; this common code should be factored out at
66 * some point to prevent code duplication or desynchronization vs.
67 * bug fixes applied to one set of code but not the other.
70 posix_spawnp(pid_t
* __restrict pid
, const char * __restrict file
,
71 const posix_spawn_file_actions_t
*file_actions
,
72 const posix_spawnattr_t
* __restrict attrp
,
73 char *const argv
[ __restrict
], char *const envp
[ __restrict
])
86 char path_buf
[PATH_MAX
];
88 if ((env_path
= getenv("PATH")) == NULL
)
89 env_path
= _PATH_DEFPATH
;
91 /* If it's an absolute or relative path name, it's easy. */
92 if (index(file
, '/')) {
99 /* If it's an empty path name, fail in the usual POSIX way. */
103 if ((cur
= alloca(strlen(env_path
) + 1)) == NULL
)
105 strcpy(cur
, env_path
);
106 while ((p
= strsep(&cur
, ":")) != NULL
) {
108 * It's a SHELL path -- double, leading and trailing colons
109 * mean the current directory.
120 * If the path is too long complain. This is a possible
121 * security issue; given a way to make the path too long
122 * the user may spawn the wrong program.
124 if (lp
+ ln
+ 2 > sizeof(path_buf
)) {
128 bcopy(p
, path_buf
, lp
);
130 bcopy(file
, path_buf
+ lp
+ 1, ln
);
131 path_buf
[lp
+ ln
+ 1] = '\0';
133 retry
: err
= posix_spawn(pid
, bp
, file_actions
, attrp
, argv
, envp
);
145 for (cnt
= 0; argv
[cnt
]; ++cnt
)
147 memp
= alloca((cnt
+ 2) * sizeof(char *));
149 /* errno = ENOMEM; XXX override ENOEXEC? */
154 bcopy(argv
+ 1, memp
+ 2, cnt
* sizeof(char *));
155 err
= posix_spawn(pid
, _PATH_BSHELL
, file_actions
, attrp
, memp
, envp
);
159 * EACCES may be for an inaccessible directory or
160 * a non-executable file. Call stat() to decide
161 * which. This also handles ambiguities for EFAULT
162 * and EIO, and undocumented errors like ESTALE.
163 * We hope that the race for a stat() is unimportant.
165 if (stat(bp
, &sb
) != 0)