2 * Copyright (c) 2006 Apple Computer, 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
28 #include <sys/types.h> /* for user_size_t */
30 #include <sys/spawn_internal.h>
33 #include <limits.h> /* for OPEN_MAX, PATH_MAX */
34 #include <stddef.h> /* for offsetof() */
35 #include <string.h> /* for strlcpy() */
36 #include <paths.h> /* for _PATH_DEFPATH */
37 #include <sys/stat.h> /* for struct stat */
38 #include <mach/port.h>
39 #include <mach/exception_types.h>
43 * posix_spawnattr_init
45 * Description: Initialize a spawn attributes object attr with default values
47 * Parameters: attr The spawn attributes object to be
51 * ENOMEM Insufficient memory exists to
52 * initialize the spawn attributes object.
54 * Note: As an implementation detail, the externally visibily type
55 * posix_spawnattr_t is defined to be a void *, and initialization
56 * involves allocation of a memory object. Subsequent changes to
57 * the spawn attributes may result in reallocation under the
60 * Reinitialization of an already initialized spawn attributes
61 * object will result in memory being leaked. Because spawn
62 * attributes are not required to be used in conjunction with a
63 * static initializer, there is no way to distinguish a spawn
64 * attribute with stack garbage from one that's been initialized.
65 * This is arguably an API design error.
68 posix_spawnattr_init(posix_spawnattr_t
*attr
)
70 _posix_spawnattr_t
*psattrp
= (_posix_spawnattr_t
*)attr
;
73 if ((*psattrp
= (_posix_spawnattr_t
)malloc(sizeof(struct _posix_spawnattr
))) == NULL
) {
78 * The default value of this attribute shall be as if no
81 (*psattrp
)->psa_flags
= 0;
84 * The default value of this attribute shall be an empty
87 (*psattrp
)->psa_sigdefault
= 0;
89 /* The default value of this attribute is unspecified */
90 (*psattrp
)->psa_sigmask
= 0;
92 /* The default value of this attribute shall be zero */
93 (*psattrp
)->psa_pgroup
= 0; /* doesn't matter */
95 /* Default is no binary preferences, i.e. use normal grading */
96 memset((*psattrp
)->psa_binprefs
, 0,
97 sizeof((*psattrp
)->psa_binprefs
));
99 /* Default is no port actions to take */
100 (*psattrp
)->psa_ports
= NULL
;
108 * posix_spawnattr_destroy
110 * Description: Destroy a spawn attributes object that was previously
111 * initialized via posix_spawnattr_init() by freeing any
112 * memory associated with it and setting it to an invalid value.
114 * Parameters: attr The spawn attributes object to be
119 * Notes: The destroyed spawn attribute results in the void * pointer
120 * being set to NULL; subsequent use without reinitialization
121 * will result in explicit program failure (rather than merely
122 * "undefined behaviour").
124 * NOTIMP: Allowed failures (checking NOT required):
125 * EINVAL The value specified by attr is invalid.
128 posix_spawnattr_destroy(posix_spawnattr_t
*attr
)
130 _posix_spawnattr_t psattr
;
132 if (attr
== NULL
|| *attr
== NULL
)
135 psattr
= *(_posix_spawnattr_t
*)attr
;
136 posix_spawn_destroyportactions_np(attr
);
146 * posix_spawnattr_setflags
148 * Description: Set the spawn flags attribute for the spawn attribute object
149 * referred to by 'attr'.
151 * Parameters: attr The spawn attributes object whose flags
153 * flags The flags value to set
157 * NOTIMP: Allowed failures (checking NOT required):
158 * EINVAL The value specified by attr is invalid.
159 * EINVAL The value of the attribute being set is not valid.
162 posix_spawnattr_setflags(posix_spawnattr_t
*attr
, short flags
)
164 _posix_spawnattr_t psattr
;
166 if (attr
== NULL
|| *attr
== NULL
)
169 psattr
= *(_posix_spawnattr_t
*)attr
;
170 psattr
->psa_flags
= flags
;
177 * posix_spawnattr_getflags
179 * Description: Retrieve the spawn attributes flag for the spawn attributes
180 * object referenced by 'attr' and place them in the memory
181 * location referenced by 'flagsp'
183 * Parameters: attr The spawn attributes object whose flags
184 * are to be retrieved
185 * flagsp A pointer to a short value to receive
191 * *flagps (modified) The flags value from the spawn
194 * NOTIMP: Allowed failures (checking NOT required):
195 * EINVAL The value specified by attr is invalid.
196 * EINVAL The value of the attribute being set is not valid.
199 posix_spawnattr_getflags(const posix_spawnattr_t
* __restrict attr
,
200 short * __restrict flagsp
)
202 _posix_spawnattr_t psattr
;
204 if (attr
== NULL
|| *attr
== NULL
)
207 psattr
= *(_posix_spawnattr_t
*)attr
;
208 *flagsp
= psattr
->psa_flags
;
215 * posix_spawnattr_getsigdefault
217 * Description: Retrieve the set of signals to be set to default according to
218 * the spawn attribute value referenced by 'attr' and place the
219 * result into the memory containing the sigset_t referenced by
222 * Parameters: attr The spawn attributes object whose
223 * signal set for default signals is to
225 * sigdefault A pointer to the sigset_t to receive
231 * *sigdefault (modified) The signal set of signals to default
232 * from the spawn attributes object
235 posix_spawnattr_getsigdefault(const posix_spawnattr_t
* __restrict attr
,
236 sigset_t
* __restrict sigdefault
)
238 _posix_spawnattr_t psattr
;
240 if (attr
== NULL
|| *attr
== NULL
)
243 psattr
= *(_posix_spawnattr_t
*)attr
;
244 *sigdefault
= psattr
->psa_sigdefault
;
251 * posix_spawnattr_getpgroup
253 * Description: Obtain the value of the spawn process group attribute from the
254 * spawn attributes object referenced by 'attr' and place the
255 * results in the memory location referenced by 'pgroup'
257 * Parameters: attr The spawn attributes object whose
258 * process group information is to be
260 * pgroup A pointer to the pid_t to receive the
266 * *pgroup (modified) The process group information from the
267 * spawn attributes object
270 posix_spawnattr_getpgroup(const posix_spawnattr_t
* __restrict attr
,
271 pid_t
* __restrict pgroup
)
273 _posix_spawnattr_t psattr
;
275 if (attr
== NULL
|| *attr
== NULL
)
278 psattr
= *(_posix_spawnattr_t
*)attr
;
279 *pgroup
= psattr
->psa_pgroup
;
286 * posix_spawnattr_getsigmask
288 * Description: Obtain the value of the spawn signal mask attribute from the
289 * spawn attributes object referenced by 'attr' and place the
290 * result into the memory containing the sigset_t referenced by
293 * Parameters: attr The spawn attributes object whose
294 * signal set for masked signals is to
296 * sigmask A pointer to the sigset_t to receive
302 * *sigmask (modified) The signal set of signals to mask
303 * from the spawn attributes object
306 posix_spawnattr_getsigmask(const posix_spawnattr_t
* __restrict attr
,
307 sigset_t
* __restrict sigmask
)
309 _posix_spawnattr_t psattr
;
311 if (attr
== NULL
|| *attr
== NULL
)
314 psattr
= *(_posix_spawnattr_t
*)attr
;
315 *sigmask
= psattr
->psa_sigmask
;
321 * posix_spawnattr_getbinpref_np
323 * Description: Obtain the value of the spawn binary preferences attribute from
324 * the spawn attributes object referenced by 'attr' and place the
325 * result into the memory referenced by 'pref'.
327 * Parameters: attr The spawn attributes object whose
328 * binary preferences are to be retrieved
329 * count The size of the cpu_type_t array
330 * pref An array of cpu types
331 * ocount The actual number copied
333 * Returns: 0 No binary preferences found
334 * > 0 The number of cpu types (less than
335 * count) copied over from 'attr'.
338 * *pref (modified) The binary preferences array
339 * from the spawn attributes object
342 posix_spawnattr_getbinpref_np(const posix_spawnattr_t
* __restrict attr
,
343 size_t count
, cpu_type_t
*pref
, size_t * __restrict ocount
)
345 _posix_spawnattr_t psattr
;
348 if (attr
== NULL
|| *attr
== NULL
)
351 psattr
= *(_posix_spawnattr_t
*)attr
;
352 for (i
= 0; i
< count
&& i
< 4; i
++) {
353 pref
[i
] = psattr
->psa_binprefs
[i
];
361 * posix_spawnattr_setsigdefault
363 * Description: Set the set of signals to be set to default for the spawn
364 * attribute value referenced by 'attr' from the memory
365 * containing the sigset_t referenced by 'sigdefault'
367 * Parameters: attr The spawn attributes object whose
368 * signal set for default signals is to
370 * sigdefault A pointer to the sigset_t from which to
371 * obtain the signal set
376 posix_spawnattr_setsigdefault(posix_spawnattr_t
* __restrict attr
,
377 const sigset_t
* __restrict sigdefault
)
379 _posix_spawnattr_t psattr
;
381 if (attr
== NULL
|| *attr
== NULL
)
384 psattr
= *(_posix_spawnattr_t
*)attr
;
385 psattr
->psa_sigdefault
= *sigdefault
;
392 * posix_spawnattr_setpgroup
394 * Description: Set the value of the spawn process group attribute for the
395 * spawn attributes object referenced by 'attr' from the value
398 * Parameters: attr The spawn attributes object for which
399 * the process group information is to be
401 * pgroup The process group to set
406 posix_spawnattr_setpgroup(posix_spawnattr_t
* attr
, pid_t pgroup
)
408 _posix_spawnattr_t psattr
;
410 if (attr
== NULL
|| *attr
== NULL
)
413 psattr
= *(_posix_spawnattr_t
*)attr
;
414 psattr
->psa_pgroup
= pgroup
;
421 * posix_spawnattr_setsigmask
423 * Description: Set the set of signals to be masked for the spawn attribute
424 * value referenced by 'attr' from the memory containing the
425 * sigset_t referenced by 'sigmask'
427 * Parameters: attr The spawn attributes object whose
428 * signal set for masked signals is to
430 * sigmask A pointer to the sigset_t from which to
431 * obtain the signal set
436 posix_spawnattr_setsigmask(posix_spawnattr_t
* __restrict attr
,
437 const sigset_t
* __restrict sigmask
)
439 _posix_spawnattr_t psattr
;
441 if (attr
== NULL
|| *attr
== NULL
)
444 psattr
= *(_posix_spawnattr_t
*)attr
;
445 psattr
->psa_sigmask
= *sigmask
;
452 * posix_spawnattr_setbinpref_np
454 * Description: Set the universal binary preferences for the spawn attribute
455 * value referenced by 'attr' from the memory containing the
456 * cpu_type_t array referenced by 'pref', size of 'count'
458 * Parameters: attr The spawn attributes object whose
459 * binary preferences are to be set
460 * count Size of the array pointed to by 'pref'
461 * pref cpu_type_t array of binary preferences
462 * ocount The actual number copied
464 * Returns: 0 No preferences copied
465 * > 0 Number of preferences copied
467 * Note: The posix_spawnattr_t currently only holds four cpu_type_t's.
468 * If the caller provides more preferences than this limit, they
469 * will be ignored, as reflected in the return value.
472 posix_spawnattr_setbinpref_np(posix_spawnattr_t
* __restrict attr
,
473 size_t count
, cpu_type_t
*pref
, size_t * __restrict ocount
)
475 _posix_spawnattr_t psattr
;
478 if (attr
== NULL
|| *attr
== NULL
)
481 psattr
= *(_posix_spawnattr_t
*)attr
;
482 for (i
= 0; i
< count
&& i
< 4; i
++) {
483 psattr
->psa_binprefs
[i
] = pref
[i
];
486 /* return number of binprefs copied over */
493 * posix_spawn_createportactions_np
494 * Description: create a new posix_spawn_port_actions struct and link
495 * it into the posix_spawnattr.
498 posix_spawn_createportactions_np(posix_spawnattr_t
*attr
)
500 _posix_spawnattr_t psattr
;
501 _posix_spawn_port_actions_t acts
;
503 if (attr
== NULL
|| *attr
== NULL
)
506 psattr
= *(_posix_spawnattr_t
*)attr
;
507 acts
= (_posix_spawn_port_actions_t
)malloc(PS_PORT_ACTIONS_SIZE(2));
511 acts
->pspa_alloc
= 2;
512 acts
->pspa_count
= 0;
514 psattr
->psa_ports
= acts
;
519 * posix_spawn_growportactions_np
520 * Description: Enlarge the size of portactions if necessary
523 posix_spawn_growportactions_np(posix_spawnattr_t
*attr
)
525 _posix_spawnattr_t psattr
;
526 _posix_spawn_port_actions_t acts
;
529 if (attr
== NULL
|| *attr
== NULL
)
532 psattr
= *(_posix_spawnattr_t
*)attr
;
533 acts
= psattr
->psa_ports
;
537 /* Double number of port actions allocated for */
538 newnum
= 2 * acts
->pspa_alloc
;
539 acts
= realloc(acts
, PS_PORT_ACTIONS_SIZE(newnum
));
543 acts
->pspa_alloc
= newnum
;
548 * posix_spawn_destroyportactions_np
549 * Description: clean up portactions struct in posix_spawnattr_t attr
552 posix_spawn_destroyportactions_np(posix_spawnattr_t
*attr
)
554 _posix_spawnattr_t psattr
;
555 _posix_spawn_port_actions_t acts
;
557 if (attr
== NULL
|| *attr
== NULL
)
560 psattr
= *(_posix_spawnattr_t
*)attr
;
561 acts
= psattr
->psa_ports
;
571 * posix_spawnattr_setspecialport_np
573 * Description: Set a new value for a mach special port in the spawned task.
575 * Parameters: attr The spawn attributes object for the
577 * new_port The new value for the special port
578 * which The particular port to be set
579 * (see task_set_special_port for details)
582 * ENOMEM Couldn't allocate memory
585 posix_spawnattr_setspecialport_np(
586 posix_spawnattr_t
*attr
,
587 mach_port_t new_port
,
590 _posix_spawnattr_t psattr
;
592 _ps_port_action_t
*action
;
593 _posix_spawn_port_actions_t ports
;
595 if (attr
== NULL
|| *attr
== NULL
)
598 psattr
= *(_posix_spawnattr_t
*)attr
;
599 ports
= psattr
->psa_ports
;
600 /* Have any port actions been created yet? */
602 err
= posix_spawn_createportactions_np(attr
);
605 ports
= psattr
->psa_ports
;
608 /* Is there enough room? */
609 if (ports
->pspa_alloc
== ports
->pspa_count
) {
610 err
= posix_spawn_growportactions_np(attr
);
615 /* Add this action to next spot in array */
616 action
= &ports
->pspa_actions
[ports
->pspa_count
];
617 action
->port_type
= PSPA_SPECIAL
;
618 action
->new_port
= new_port
;
619 action
->which
= which
;
626 * posix_spawnattr_setexceptionports_np
628 * Description: Set a new port for a set of exception ports in the spawned task.
630 * Parameters: attr The spawn attributes object for the
632 * mask A bitfield indicating which exceptions
633 * to associate the port with
634 * new_port The new value for the exception port
635 * behavior The default behavior for the port
636 * flavor The default flavor for the port
637 * (see task_set_exception_ports)
642 posix_spawnattr_setexceptionports_np(
643 posix_spawnattr_t
*attr
,
644 exception_mask_t mask
,
645 mach_port_t new_port
,
646 exception_behavior_t behavior
,
647 thread_state_flavor_t flavor
)
649 _posix_spawnattr_t psattr
;
651 _ps_port_action_t
*action
;
652 _posix_spawn_port_actions_t ports
;
654 if (attr
== NULL
|| *attr
== NULL
)
657 psattr
= *(_posix_spawnattr_t
*)attr
;
658 ports
= psattr
->psa_ports
;
659 /* Have any port actions been created yet? */
661 err
= posix_spawn_createportactions_np(attr
);
664 ports
= psattr
->psa_ports
;
667 /* Is there enough room? */
668 if (ports
->pspa_alloc
== ports
->pspa_count
) {
669 err
= posix_spawn_growportactions_np(attr
);
674 /* Add this action to next spot in array */
675 action
= &ports
->pspa_actions
[ports
->pspa_count
];
676 action
->port_type
= PSPA_EXCEPTION
;
678 action
->new_port
= new_port
;
679 action
->behavior
= behavior
;
680 action
->flavor
= flavor
;
688 * posix_spawn_file_actions_init
690 * Description: Initialize a spawn file actions object attr with default values
692 * Parameters: file_actions The spawn file actions object to be
696 * ENOMEM Insufficient memory exists to
697 * initialize the spawn file actions
700 * Note: As an implementation detail, the externally visibily type
701 * posix_spawn_file_actions_t is defined to be a void *, and
702 * initialization involves allocation of a memory object.
703 * Subsequent changes to the spawn file actions may result in
704 * reallocation under the covers.
706 * Reinitialization of an already initialized spawn file actions
707 * object will result in memory being leaked. Because spawn
708 * file actions are not required to be used in conjunction with a
709 * static initializer, there is no way to distinguish a spawn
710 * file actions with stack garbage from one that's been
711 * initialized. This is arguably an API design error.
714 posix_spawn_file_actions_init(posix_spawn_file_actions_t
*file_actions
)
716 _posix_spawn_file_actions_t
*psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
719 if ((*psactsp
= (_posix_spawn_file_actions_t
)malloc(PSF_ACTIONS_SIZE(PSF_ACTIONS_INIT_COUNT
))) == NULL
) {
722 (*psactsp
)->psfa_act_alloc
= PSF_ACTIONS_INIT_COUNT
;
723 (*psactsp
)->psfa_act_count
= 0;
731 * posix_spawn_file_actions_destroy
733 * Description: Destroy a spawn file actions object that was previously
734 * initialized via posix_spawn_file_actions_init() by freeing any
735 * memory associated with it and setting it to an invalid value.
737 * Parameters: attr The spawn file actions object to be
742 * Notes: The destroyed spawn file actions results in the void * pointer
743 * being set to NULL; subsequent use without reinitialization
744 * will result in explicit program failure (rather than merely
745 * "undefined behaviour").
747 * NOTIMP: Allowed failures (checking NOT required):
748 * EINVAL The value specified by file_actions is invalid.
751 posix_spawn_file_actions_destroy(posix_spawn_file_actions_t
*file_actions
)
753 _posix_spawn_file_actions_t psacts
;
755 if (file_actions
== NULL
|| *file_actions
== NULL
)
758 psacts
= *(_posix_spawn_file_actions_t
*)file_actions
;
760 *file_actions
= NULL
;
767 * _posix_spawn_file_actions_grow
769 * Description: Grow the available list of file actions associated with the
770 * pointer to the structure provided; replace the contents of the
771 * pointer as a side effect.
773 * Parameters: psactsp Pointer to _posix_spawn_file_actions_t
777 * ENOMEM Insufficient memory for operation
779 * Notes: This code is common to all posix_spawn_file_actions_*()
780 * functions, since we use a naieve data structure implementation
781 * at present. Future optimization will likely change this.
784 _posix_spawn_file_actions_grow(_posix_spawn_file_actions_t
*psactsp
)
786 int new_alloc
= (*psactsp
)->psfa_act_alloc
* 2;
787 _posix_spawn_file_actions_t new_psacts
;
790 * XXX may want to impose an administrative limit here; POSIX does
791 * XXX not provide for an administrative error return in this case,
792 * XXX so it's probably acceptable to just fail catastrophically
793 * XXX instead of implementing one.
795 if ((new_psacts
= (_posix_spawn_file_actions_t
)realloc((*psactsp
), PSF_ACTIONS_SIZE(new_alloc
))) == NULL
) {
798 new_psacts
->psfa_act_alloc
= new_alloc
;
799 *psactsp
= new_psacts
;
806 * posix_spawn_file_actions_addopen
808 * Description: Add an open action to the object referenced by 'file_actions'
809 * that will cause the file named by 'path' to be attempted to be
810 * opened with flags 'oflag' and mode 'mode', and, if successful,
811 * return as descriptor 'filedes' to the spawned process.
813 * Parameters: file_actions File action object to add open to
814 * filedes fd that open is to use
815 * path path to file to open
816 * oflag open file flags
817 * mode open file mode
820 * EBADF The value specified by fildes is
821 * negative or greater than or equal to
823 * ENOMEM Insufficient memory exists to add to
824 * the spawn file actions object.
826 * NOTIMP: Allowed failures (checking NOT required):
827 * EINVAL The value specified by file_actions is invalid.
830 posix_spawn_file_actions_addopen(
831 posix_spawn_file_actions_t
* __restrict file_actions
,
832 int filedes
, const char * __restrict path
, int oflag
,
835 _posix_spawn_file_actions_t
*psactsp
;
836 _psfa_action_t
*psfileact
;
838 if (file_actions
== NULL
|| *file_actions
== NULL
)
841 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
842 /* Range check; required by POSIX */
843 if (filedes
< 0 || filedes
>= OPEN_MAX
)
846 /* If we do not have enough slots, grow the structure */
847 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
848 /* need to grow file actions structure */
849 if (_posix_spawn_file_actions_grow(psactsp
))
854 * Allocate next available slot and fill it out
856 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
858 psfileact
->psfaa_type
= PSFA_OPEN
;
859 psfileact
->psfaa_filedes
= filedes
;
860 psfileact
->psfaa_openargs
.psfao_oflag
= oflag
;
861 psfileact
->psfaa_openargs
.psfao_mode
= mode
;
862 strlcpy(psfileact
->psfaa_openargs
.psfao_path
, path
, PATH_MAX
);
869 * posix_spawn_file_actions_addclose
871 * Description: Add a close action to the object referenced by 'file_actions'
872 * that will cause the file referenced by 'filedes' to be
873 * attempted to be closed in the spawned process.
875 * Parameters: file_actions File action object to add open to
876 * filedes fd to close
879 * EBADF The value specified by fildes is
880 * negative or greater than or equal to
882 * ENOMEM Insufficient memory exists to add to
883 * the spawn file actions object.
885 * NOTIMP: Allowed failures (checking NOT required):
886 * EINVAL The value specified by file_actions is invalid.
889 posix_spawn_file_actions_addclose(posix_spawn_file_actions_t
*file_actions
,
892 _posix_spawn_file_actions_t
*psactsp
;
893 _psfa_action_t
*psfileact
;
895 if (file_actions
== NULL
|| *file_actions
== NULL
)
898 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
899 /* Range check; required by POSIX */
900 if (filedes
< 0 || filedes
>= OPEN_MAX
)
903 /* If we do not have enough slots, grow the structure */
904 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
905 /* need to grow file actions structure */
906 if (_posix_spawn_file_actions_grow(psactsp
))
911 * Allocate next available slot and fill it out
913 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
915 psfileact
->psfaa_type
= PSFA_CLOSE
;
916 psfileact
->psfaa_filedes
= filedes
;
923 * posix_spawn_file_actions_adddup2
925 * Description: Add a dpu2 action to the object referenced by 'file_actions'
926 * that will cause the file referenced by 'filedes' to be
927 * attempted to be dup2'ed to the descriptor 'newfiledes' in the
930 * Parameters: file_actions File action object to add open to
932 * newfiledes fd to dup2 it to
935 * EBADF The value specified by either fildes
936 * or by newfiledes is negative or greater
937 * than or equal to {OPEN_MAX}.
938 * ENOMEM Insufficient memory exists to add to
939 * the spawn file actions object.
941 * NOTIMP: Allowed failures (checking NOT required):
942 * EINVAL The value specified by file_actions is invalid.
945 posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t
*file_actions
,
946 int filedes
, int newfiledes
)
948 _posix_spawn_file_actions_t
*psactsp
;
949 _psfa_action_t
*psfileact
;
951 if (file_actions
== NULL
|| *file_actions
== NULL
)
954 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
955 /* Range check; required by POSIX */
956 if (filedes
< 0 || filedes
>= OPEN_MAX
||
957 newfiledes
< 0 || newfiledes
>= OPEN_MAX
)
960 /* If we do not have enough slots, grow the structure */
961 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
962 /* need to grow file actions structure */
963 if (_posix_spawn_file_actions_grow(psactsp
))
968 * Allocate next available slot and fill it out
970 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
972 psfileact
->psfaa_type
= PSFA_DUP2
;
973 psfileact
->psfaa_filedes
= filedes
;
974 psfileact
->psfaa_openargs
.psfao_oflag
= newfiledes
;
983 * Description: Create a new process from the process image corresponding to
984 * the supplied 'file' argument and the parent processes path
987 * Parameters: pid Pointer to pid_t to receive the
988 * PID of the spawned process, if
989 * successful and 'pid' != NULL
990 * file Name of image file to spawn
991 * file_actions spawn file actions object which
992 * describes file actions to be
993 * performed during the spawn
994 * attrp spawn attributes object which
995 * describes attributes to be
996 * applied during the spawn
997 * argv argument vector array; NULL
999 * envp environment vector array; NULL
1002 * Returns: 0 Success
1003 * !0 An errno value indicating the
1004 * cause of the failure to spawn
1006 * Notes: Much of this function is derived from code from execvP() from
1007 * exec.c in libc; this common code should be factored out at
1008 * some point to prevent code duplication or desynchronization vs.
1009 * bug fixes applied to one set of code but not the other.
1012 posix_spawnp(pid_t
* __restrict pid
, const char * __restrict file
,
1013 const posix_spawn_file_actions_t
*file_actions
,
1014 const posix_spawnattr_t
* __restrict attrp
,
1015 char *const argv
[ __restrict
], char *const envp
[ __restrict
])
1017 const char *env_path
;
1028 char path_buf
[PATH_MAX
];
1030 if ((env_path
= getenv("PATH")) == NULL
)
1031 env_path
= _PATH_DEFPATH
;
1033 /* If it's an absolute or relative path name, it's easy. */
1034 if (index(file
, '/')) {
1041 /* If it's an empty path name, fail in the usual POSIX way. */
1045 if ((cur
= alloca(strlen(env_path
) + 1)) == NULL
)
1047 strcpy(cur
, env_path
);
1048 while ((p
= strsep(&cur
, ":")) != NULL
) {
1050 * It's a SHELL path -- double, leading and trailing colons
1051 * mean the current directory.
1062 * If the path is too long complain. This is a possible
1063 * security issue; given a way to make the path too long
1064 * the user may spawn the wrong program.
1066 if (lp
+ ln
+ 2 > sizeof(path_buf
)) {
1070 bcopy(p
, path_buf
, lp
);
1072 bcopy(file
, path_buf
+ lp
+ 1, ln
);
1073 path_buf
[lp
+ ln
+ 1] = '\0';
1075 retry
: err
= posix_spawn(pid
, bp
, file_actions
, attrp
, argv
, envp
);
1087 for (cnt
= 0; argv
[cnt
]; ++cnt
)
1089 memp
= alloca((cnt
+ 2) * sizeof(char *));
1091 /* errno = ENOMEM; XXX override ENOEXEC? */
1096 bcopy(argv
+ 1, memp
+ 2, cnt
* sizeof(char *));
1097 err
= posix_spawn(pid
, _PATH_BSHELL
, file_actions
, attrp
, memp
, envp
);
1101 * EACCES may be for an inaccessible directory or
1102 * a non-executable file. Call stat() to decide
1103 * which. This also handles ambiguities for EFAULT
1104 * and EIO, and undocumented errors like ESTALE.
1105 * We hope that the race for a stat() is unimportant.
1107 if (stat(bp
, &sb
) != 0)
1109 if (err
== EACCES
) {
1128 * Description: Create a new process from the process image corresponding to
1129 * the supplied 'path' argument.
1131 * Parameters: pid Pointer to pid_t to receive the
1132 * PID of the spawned process, if
1133 * successful and 'pid' != NULL
1134 * path Path of image file to spawn
1135 * file_actions spawn file actions object which
1136 * describes file actions to be
1137 * performed during the spawn
1138 * attrp spawn attributes object which
1139 * describes attributes to be
1140 * applied during the spawn
1141 * argv argument vector array; NULL
1143 * envp environment vector array; NULL
1146 * Returns: 0 Success
1147 * !0 An errno value indicating the
1148 * cause of the failure to spawn
1150 * Notes: Unlike other system calls, the return value of this system
1151 * call is expected to either be a 0 or an errno, rather than a
1152 * 0 or a -1, with the 'errno' variable being set.
1154 extern int __posix_spawn(pid_t
* __restrict
, const char * __restrict
,
1155 struct _posix_spawn_args_desc
*,
1156 char *const argv
[ __restrict
], char *const envp
[ __restrict
]);
1159 posix_spawn(pid_t
* __restrict pid
, const char * __restrict path
,
1160 const posix_spawn_file_actions_t
*file_actions
,
1161 const posix_spawnattr_t
* __restrict attrp
,
1162 char *const argv
[ __restrict
], char *const envp
[ __restrict
])
1164 int saveerrno
= errno
;
1167 * Only do extra work if we have file actions or attributes to push
1168 * down. We use a descriptor to push this information down, since we
1169 * want to have size information, which will let us (1) preallocate a
1170 * single chunk of memory for the copyin(), and (2) allow us to do a
1171 * single copyin() per attributes or file actions as a monlithic block.
1173 * Note: A future implementation may attempt to do the same
1174 * thing for the argv/envp data, which could potentially
1175 * result in a performance improvement due to increased
1176 * kernel efficiency, even though it would mean copying
1177 * the data in user space.
1179 if ((file_actions
!= NULL
&& (*file_actions
!= NULL
) && (*(_posix_spawn_file_actions_t
*)file_actions
)->psfa_act_count
> 0) || attrp
!= NULL
) {
1180 struct _posix_spawn_args_desc ad
;
1182 memset(&ad
, 0, sizeof(ad
));
1183 if (attrp
!= NULL
&& *attrp
!= NULL
) {
1184 _posix_spawnattr_t psattr
= *(_posix_spawnattr_t
*)attrp
;
1185 ad
.attr_size
= sizeof(struct _posix_spawnattr
);
1188 if (psattr
->psa_ports
!= NULL
) {
1189 ad
.port_actions
= psattr
->psa_ports
;
1190 ad
.port_actions_size
= PS_PORT_ACTIONS_SIZE(
1191 ad
.port_actions
->pspa_count
);
1194 if (file_actions
!= NULL
&& *file_actions
!= NULL
) {
1195 _posix_spawn_file_actions_t psactsp
=
1196 *(_posix_spawn_file_actions_t
*)file_actions
;
1198 if (psactsp
->psfa_act_count
> 0) {
1199 ad
.file_actions_size
= PSF_ACTIONS_SIZE(psactsp
->psfa_act_count
);
1200 ad
.file_actions
= psactsp
;
1204 ret
= __posix_spawn(pid
, path
, &ad
, argv
, envp
);
1206 ret
= __posix_spawn(pid
, path
, NULL
, argv
, envp
);