2 * Copyright (c) 2006-2008 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 <spawn_private.h>
31 #include <sys/spawn_internal.h>
34 #include <limits.h> /* for OPEN_MAX, PATH_MAX */
35 #include <stddef.h> /* for offsetof() */
36 #include <string.h> /* for strlcpy() */
37 #include <paths.h> /* for _PATH_DEFPATH */
38 #include <sys/stat.h> /* for struct stat */
39 #include <mach/port.h>
40 #include <mach/exception_types.h>
44 * posix_spawnattr_init
46 * Description: Initialize a spawn attributes object attr with default values
48 * Parameters: attr The spawn attributes object to be
52 * ENOMEM Insufficient memory exists to
53 * initialize the spawn attributes object.
55 * Note: As an implementation detail, the externally visibily type
56 * posix_spawnattr_t is defined to be a void *, and initialization
57 * involves allocation of a memory object. Subsequent changes to
58 * the spawn attributes may result in reallocation under the
61 * Reinitialization of an already initialized spawn attributes
62 * object will result in memory being leaked. Because spawn
63 * attributes are not required to be used in conjunction with a
64 * static initializer, there is no way to distinguish a spawn
65 * attribute with stack garbage from one that's been initialized.
66 * This is arguably an API design error.
69 posix_spawnattr_init(posix_spawnattr_t
*attr
)
71 _posix_spawnattr_t
*psattrp
= (_posix_spawnattr_t
*)attr
;
74 if ((*psattrp
= (_posix_spawnattr_t
)malloc(sizeof(struct _posix_spawnattr
))) == NULL
) {
79 * The default value of this attribute shall be as if no
82 (*psattrp
)->psa_flags
= 0;
85 * The default value of this attribute shall be an empty
88 (*psattrp
)->psa_sigdefault
= 0;
90 /* The default value of this attribute is unspecified */
91 (*psattrp
)->psa_sigmask
= 0;
93 /* The default value of this attribute shall be zero */
94 (*psattrp
)->psa_pgroup
= 0; /* doesn't matter */
96 /* Default is no binary preferences, i.e. use normal grading */
97 memset((*psattrp
)->psa_binprefs
, 0,
98 sizeof((*psattrp
)->psa_binprefs
));
100 /* Default is no port actions to take */
101 (*psattrp
)->psa_ports
= NULL
;
104 * The default value of this attribute shall be an no
105 * process control on resource starvation
107 (*psattrp
)->psa_pcontrol
= 0;
115 * posix_spawnattr_destroy
117 * Description: Destroy a spawn attributes object that was previously
118 * initialized via posix_spawnattr_init() by freeing any
119 * memory associated with it and setting it to an invalid value.
121 * Parameters: attr The spawn attributes object to be
126 * Notes: The destroyed spawn attribute results in the void * pointer
127 * being set to NULL; subsequent use without reinitialization
128 * will result in explicit program failure (rather than merely
129 * "undefined behaviour").
131 * NOTIMP: Allowed failures (checking NOT required):
132 * EINVAL The value specified by attr is invalid.
134 static int posix_spawn_destroyportactions_np(posix_spawnattr_t
*);
137 posix_spawnattr_destroy(posix_spawnattr_t
*attr
)
139 _posix_spawnattr_t psattr
;
141 if (attr
== NULL
|| *attr
== NULL
)
144 psattr
= *(_posix_spawnattr_t
*)attr
;
145 posix_spawn_destroyportactions_np(attr
);
155 * posix_spawnattr_setflags
157 * Description: Set the spawn flags attribute for the spawn attribute object
158 * referred to by 'attr'.
160 * Parameters: attr The spawn attributes object whose flags
162 * flags The flags value to set
166 * NOTIMP: Allowed failures (checking NOT required):
167 * EINVAL The value specified by attr is invalid.
168 * EINVAL The value of the attribute being set is not valid.
171 posix_spawnattr_setflags(posix_spawnattr_t
*attr
, short flags
)
173 _posix_spawnattr_t psattr
;
175 if (attr
== NULL
|| *attr
== NULL
)
178 psattr
= *(_posix_spawnattr_t
*)attr
;
179 psattr
->psa_flags
= flags
;
186 * posix_spawnattr_getflags
188 * Description: Retrieve the spawn attributes flag for the spawn attributes
189 * object referenced by 'attr' and place them in the memory
190 * location referenced by 'flagsp'
192 * Parameters: attr The spawn attributes object whose flags
193 * are to be retrieved
194 * flagsp A pointer to a short value to receive
200 * *flagps (modified) The flags value from the spawn
203 * NOTIMP: Allowed failures (checking NOT required):
204 * EINVAL The value specified by attr is invalid.
205 * EINVAL The value of the attribute being set is not valid.
208 posix_spawnattr_getflags(const posix_spawnattr_t
* __restrict attr
,
209 short * __restrict flagsp
)
211 _posix_spawnattr_t psattr
;
213 if (attr
== NULL
|| *attr
== NULL
)
216 psattr
= *(_posix_spawnattr_t
*)attr
;
217 *flagsp
= psattr
->psa_flags
;
224 * posix_spawnattr_getsigdefault
226 * Description: Retrieve the set of signals to be set to default according to
227 * the spawn attribute value referenced by 'attr' and place the
228 * result into the memory containing the sigset_t referenced by
231 * Parameters: attr The spawn attributes object whose
232 * signal set for default signals is to
234 * sigdefault A pointer to the sigset_t to receive
240 * *sigdefault (modified) The signal set of signals to default
241 * from the spawn attributes object
244 posix_spawnattr_getsigdefault(const posix_spawnattr_t
* __restrict attr
,
245 sigset_t
* __restrict sigdefault
)
247 _posix_spawnattr_t psattr
;
249 if (attr
== NULL
|| *attr
== NULL
)
252 psattr
= *(_posix_spawnattr_t
*)attr
;
253 *sigdefault
= psattr
->psa_sigdefault
;
260 * posix_spawnattr_getpgroup
262 * Description: Obtain the value of the spawn process group attribute from the
263 * spawn attributes object referenced by 'attr' and place the
264 * results in the memory location referenced by 'pgroup'
266 * Parameters: attr The spawn attributes object whose
267 * process group information is to be
269 * pgroup A pointer to the pid_t to receive the
275 * *pgroup (modified) The process group information from the
276 * spawn attributes object
279 posix_spawnattr_getpgroup(const posix_spawnattr_t
* __restrict attr
,
280 pid_t
* __restrict pgroup
)
282 _posix_spawnattr_t psattr
;
284 if (attr
== NULL
|| *attr
== NULL
)
287 psattr
= *(_posix_spawnattr_t
*)attr
;
288 *pgroup
= psattr
->psa_pgroup
;
295 * posix_spawnattr_getsigmask
297 * Description: Obtain the value of the spawn signal mask attribute from the
298 * spawn attributes object referenced by 'attr' and place the
299 * result into the memory containing the sigset_t referenced by
302 * Parameters: attr The spawn attributes object whose
303 * signal set for masked signals is to
305 * sigmask A pointer to the sigset_t to receive
311 * *sigmask (modified) The signal set of signals to mask
312 * from the spawn attributes object
315 posix_spawnattr_getsigmask(const posix_spawnattr_t
* __restrict attr
,
316 sigset_t
* __restrict sigmask
)
318 _posix_spawnattr_t psattr
;
320 if (attr
== NULL
|| *attr
== NULL
)
323 psattr
= *(_posix_spawnattr_t
*)attr
;
324 *sigmask
= psattr
->psa_sigmask
;
330 * posix_spawnattr_getbinpref_np
332 * Description: Obtain the value of the spawn binary preferences attribute from
333 * the spawn attributes object referenced by 'attr' and place the
334 * result into the memory referenced by 'pref'.
336 * Parameters: attr The spawn attributes object whose
337 * binary preferences are to be retrieved
338 * count The size of the cpu_type_t array
339 * pref An array of cpu types
340 * ocount The actual number copied
342 * Returns: 0 No binary preferences found
343 * > 0 The number of cpu types (less than
344 * count) copied over from 'attr'.
347 * *pref (modified) The binary preferences array
348 * from the spawn attributes object
351 posix_spawnattr_getbinpref_np(const posix_spawnattr_t
* __restrict attr
,
352 size_t count
, cpu_type_t
*pref
, size_t * __restrict ocount
)
354 _posix_spawnattr_t psattr
;
357 if (attr
== NULL
|| *attr
== NULL
)
360 psattr
= *(_posix_spawnattr_t
*)attr
;
361 for (i
= 0; i
< count
&& i
< 4; i
++) {
362 pref
[i
] = psattr
->psa_binprefs
[i
];
372 * posix_spawnattr_getpcontrol_np
374 * Description: Retrieve the process control property set default according to
375 * the spawn attribute value referenced by 'attr' and place the
376 * result into the memory containing the control referenced by
379 * Parameters: attr The spawn attributes object whose
380 * signal set for default signals is to
382 * pcontrol A pointer to an int to receive
383 * the process control info
388 * *pcontrol (modified) The signal set of signals to default
389 * from the spawn attributes object
392 posix_spawnattr_getpcontrol_np(const posix_spawnattr_t
* __restrict attr
,
393 int * __restrict pcontrol
)
395 _posix_spawnattr_t psattr
;
397 if (attr
== NULL
|| *attr
== NULL
)
400 psattr
= *(_posix_spawnattr_t
*)attr
;
401 *pcontrol
= psattr
->psa_pcontrol
;
407 * posix_spawnattr_setsigdefault
409 * Description: Set the set of signals to be set to default for the spawn
410 * attribute value referenced by 'attr' from the memory
411 * containing the sigset_t referenced by 'sigdefault'
413 * Parameters: attr The spawn attributes object whose
414 * signal set for default signals is to
416 * sigdefault A pointer to the sigset_t from which to
417 * obtain the signal set
422 posix_spawnattr_setsigdefault(posix_spawnattr_t
* __restrict attr
,
423 const sigset_t
* __restrict sigdefault
)
425 _posix_spawnattr_t psattr
;
427 if (attr
== NULL
|| *attr
== NULL
)
430 psattr
= *(_posix_spawnattr_t
*)attr
;
431 psattr
->psa_sigdefault
= *sigdefault
;
438 * posix_spawnattr_setpgroup
440 * Description: Set the value of the spawn process group attribute for the
441 * spawn attributes object referenced by 'attr' from the value
444 * Parameters: attr The spawn attributes object for which
445 * the process group information is to be
447 * pgroup The process group to set
452 posix_spawnattr_setpgroup(posix_spawnattr_t
* attr
, pid_t pgroup
)
454 _posix_spawnattr_t psattr
;
456 if (attr
== NULL
|| *attr
== NULL
)
459 psattr
= *(_posix_spawnattr_t
*)attr
;
460 psattr
->psa_pgroup
= pgroup
;
467 * posix_spawnattr_setsigmask
469 * Description: Set the set of signals to be masked for the spawn attribute
470 * value referenced by 'attr' from the memory containing the
471 * sigset_t referenced by 'sigmask'
473 * Parameters: attr The spawn attributes object whose
474 * signal set for masked signals is to
476 * sigmask A pointer to the sigset_t from which to
477 * obtain the signal set
482 posix_spawnattr_setsigmask(posix_spawnattr_t
* __restrict attr
,
483 const sigset_t
* __restrict sigmask
)
485 _posix_spawnattr_t psattr
;
487 if (attr
== NULL
|| *attr
== NULL
)
490 psattr
= *(_posix_spawnattr_t
*)attr
;
491 psattr
->psa_sigmask
= *sigmask
;
498 * posix_spawnattr_setbinpref_np
500 * Description: Set the universal binary preferences for the spawn attribute
501 * value referenced by 'attr' from the memory containing the
502 * cpu_type_t array referenced by 'pref', size of 'count'
504 * Parameters: attr The spawn attributes object whose
505 * binary preferences are to be set
506 * count Size of the array pointed to by 'pref'
507 * pref cpu_type_t array of binary preferences
508 * ocount The actual number copied
510 * Returns: 0 No preferences copied
511 * > 0 Number of preferences copied
513 * Note: The posix_spawnattr_t currently only holds four cpu_type_t's.
514 * If the caller provides more preferences than this limit, they
515 * will be ignored, as reflected in the return value.
518 posix_spawnattr_setbinpref_np(posix_spawnattr_t
* __restrict attr
,
519 size_t count
, cpu_type_t
*pref
, size_t * __restrict ocount
)
521 _posix_spawnattr_t psattr
;
524 if (attr
== NULL
|| *attr
== NULL
)
527 psattr
= *(_posix_spawnattr_t
*)attr
;
528 for (i
= 0; i
< count
&& i
< 4; i
++) {
529 psattr
->psa_binprefs
[i
] = pref
[i
];
532 /* return number of binprefs copied over */
540 * posix_spawnattr_setpcontrol_np
542 * Description: Set the process control property according to
543 * attribute value referenced by 'attr' from the memory
544 * containing the int value 'pcontrol'
546 * Parameters: attr The spawn attributes object whose
547 * signal set for default signals is to
549 * pcontrol An int value of the process control info
554 posix_spawnattr_setpcontrol_np(posix_spawnattr_t
* __restrict attr
,
557 _posix_spawnattr_t psattr
;
559 if (attr
== NULL
|| *attr
== NULL
)
562 psattr
= *(_posix_spawnattr_t
*)attr
;
563 psattr
->psa_pcontrol
= pcontrol
;
568 * posix_spawn_createportactions_np
569 * Description: create a new posix_spawn_port_actions struct and link
570 * it into the posix_spawnattr.
573 posix_spawn_createportactions_np(posix_spawnattr_t
*attr
)
575 _posix_spawnattr_t psattr
;
576 _posix_spawn_port_actions_t acts
;
578 if (attr
== NULL
|| *attr
== NULL
)
581 psattr
= *(_posix_spawnattr_t
*)attr
;
582 acts
= (_posix_spawn_port_actions_t
)malloc(PS_PORT_ACTIONS_SIZE(2));
586 acts
->pspa_alloc
= 2;
587 acts
->pspa_count
= 0;
589 psattr
->psa_ports
= acts
;
594 * posix_spawn_growportactions_np
595 * Description: Enlarge the size of portactions if necessary
598 posix_spawn_growportactions_np(posix_spawnattr_t
*attr
)
600 _posix_spawnattr_t psattr
;
601 _posix_spawn_port_actions_t acts
;
604 if (attr
== NULL
|| *attr
== NULL
)
607 psattr
= *(_posix_spawnattr_t
*)attr
;
608 acts
= psattr
->psa_ports
;
612 /* Double number of port actions allocated for */
613 newnum
= 2 * acts
->pspa_alloc
;
614 acts
= realloc(acts
, PS_PORT_ACTIONS_SIZE(newnum
));
618 acts
->pspa_alloc
= newnum
;
623 * posix_spawn_destroyportactions_np
624 * Description: clean up portactions struct in posix_spawnattr_t attr
627 posix_spawn_destroyportactions_np(posix_spawnattr_t
*attr
)
629 _posix_spawnattr_t psattr
;
630 _posix_spawn_port_actions_t acts
;
632 if (attr
== NULL
|| *attr
== NULL
)
635 psattr
= *(_posix_spawnattr_t
*)attr
;
636 acts
= psattr
->psa_ports
;
646 * posix_spawnattr_setspecialport_np
648 * Description: Set a new value for a mach special port in the spawned task.
650 * Parameters: attr The spawn attributes object for the
652 * new_port The new value for the special port
653 * which The particular port to be set
654 * (see task_set_special_port for details)
657 * ENOMEM Couldn't allocate memory
660 posix_spawnattr_setspecialport_np(
661 posix_spawnattr_t
*attr
,
662 mach_port_t new_port
,
665 _posix_spawnattr_t psattr
;
667 _ps_port_action_t
*action
;
668 _posix_spawn_port_actions_t ports
;
670 if (attr
== NULL
|| *attr
== NULL
)
673 psattr
= *(_posix_spawnattr_t
*)attr
;
674 ports
= psattr
->psa_ports
;
675 /* Have any port actions been created yet? */
677 err
= posix_spawn_createportactions_np(attr
);
680 ports
= psattr
->psa_ports
;
683 /* Is there enough room? */
684 if (ports
->pspa_alloc
== ports
->pspa_count
) {
685 err
= posix_spawn_growportactions_np(attr
);
690 /* Add this action to next spot in array */
691 action
= &ports
->pspa_actions
[ports
->pspa_count
];
692 action
->port_type
= PSPA_SPECIAL
;
693 action
->new_port
= new_port
;
694 action
->which
= which
;
701 * posix_spawnattr_setexceptionports_np
703 * Description: Set a new port for a set of exception ports in the spawned task.
705 * Parameters: attr The spawn attributes object for the
707 * mask A bitfield indicating which exceptions
708 * to associate the port with
709 * new_port The new value for the exception port
710 * behavior The default behavior for the port
711 * flavor The default flavor for the port
712 * (see task_set_exception_ports)
717 posix_spawnattr_setexceptionports_np(
718 posix_spawnattr_t
*attr
,
719 exception_mask_t mask
,
720 mach_port_t new_port
,
721 exception_behavior_t behavior
,
722 thread_state_flavor_t flavor
)
724 _posix_spawnattr_t psattr
;
726 _ps_port_action_t
*action
;
727 _posix_spawn_port_actions_t ports
;
729 if (attr
== NULL
|| *attr
== NULL
)
732 psattr
= *(_posix_spawnattr_t
*)attr
;
733 ports
= psattr
->psa_ports
;
734 /* Have any port actions been created yet? */
736 err
= posix_spawn_createportactions_np(attr
);
739 ports
= psattr
->psa_ports
;
742 /* Is there enough room? */
743 if (ports
->pspa_alloc
== ports
->pspa_count
) {
744 err
= posix_spawn_growportactions_np(attr
);
749 /* Add this action to next spot in array */
750 action
= &ports
->pspa_actions
[ports
->pspa_count
];
751 action
->port_type
= PSPA_EXCEPTION
;
753 action
->new_port
= new_port
;
754 action
->behavior
= behavior
;
755 action
->flavor
= flavor
;
762 * posix_spawnattr_setauditsessionport_np
764 * Description: Set the audit session port rights attribute in the spawned task.
765 * This is used to securely set the audit session information for
768 * Parameters: attr The spawn attributes object for the
770 * au_sessionport The audit session send port right
775 posix_spawnattr_setauditsessionport_np(
776 posix_spawnattr_t
*attr
,
777 mach_port_t au_sessionport
)
779 _posix_spawnattr_t psattr
;
781 _ps_port_action_t
*action
;
782 _posix_spawn_port_actions_t ports
;
784 if (attr
== NULL
|| *attr
== NULL
)
787 psattr
= *(_posix_spawnattr_t
*)attr
;
788 ports
= psattr
->psa_ports
;
789 /* Have any port actions been created yet? */
791 err
= posix_spawn_createportactions_np(attr
);
794 ports
= psattr
->psa_ports
;
797 /* Is there enough room? */
798 if (ports
->pspa_alloc
== ports
->pspa_count
) {
799 err
= posix_spawn_growportactions_np(attr
);
804 /* Add this action to next spot in array */
805 action
= &ports
->pspa_actions
[ports
->pspa_count
];
806 action
->port_type
= PSPA_AU_SESSION
;
807 action
->new_port
= au_sessionport
;
815 * posix_spawn_file_actions_init
817 * Description: Initialize a spawn file actions object attr with default values
819 * Parameters: file_actions The spawn file actions object to be
823 * ENOMEM Insufficient memory exists to
824 * initialize the spawn file actions
827 * Note: As an implementation detail, the externally visibily type
828 * posix_spawn_file_actions_t is defined to be a void *, and
829 * initialization involves allocation of a memory object.
830 * Subsequent changes to the spawn file actions may result in
831 * reallocation under the covers.
833 * Reinitialization of an already initialized spawn file actions
834 * object will result in memory being leaked. Because spawn
835 * file actions are not required to be used in conjunction with a
836 * static initializer, there is no way to distinguish a spawn
837 * file actions with stack garbage from one that's been
838 * initialized. This is arguably an API design error.
841 posix_spawn_file_actions_init(posix_spawn_file_actions_t
*file_actions
)
843 _posix_spawn_file_actions_t
*psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
846 if ((*psactsp
= (_posix_spawn_file_actions_t
)malloc(PSF_ACTIONS_SIZE(PSF_ACTIONS_INIT_COUNT
))) == NULL
) {
849 (*psactsp
)->psfa_act_alloc
= PSF_ACTIONS_INIT_COUNT
;
850 (*psactsp
)->psfa_act_count
= 0;
858 * posix_spawn_file_actions_destroy
860 * Description: Destroy a spawn file actions object that was previously
861 * initialized via posix_spawn_file_actions_init() by freeing any
862 * memory associated with it and setting it to an invalid value.
864 * Parameters: attr The spawn file actions object to be
869 * Notes: The destroyed spawn file actions results in the void * pointer
870 * being set to NULL; subsequent use without reinitialization
871 * will result in explicit program failure (rather than merely
872 * "undefined behaviour").
874 * NOTIMP: Allowed failures (checking NOT required):
875 * EINVAL The value specified by file_actions is invalid.
878 posix_spawn_file_actions_destroy(posix_spawn_file_actions_t
*file_actions
)
880 _posix_spawn_file_actions_t psacts
;
882 if (file_actions
== NULL
|| *file_actions
== NULL
)
885 psacts
= *(_posix_spawn_file_actions_t
*)file_actions
;
887 *file_actions
= NULL
;
894 * _posix_spawn_file_actions_grow
896 * Description: Grow the available list of file actions associated with the
897 * pointer to the structure provided; replace the contents of the
898 * pointer as a side effect.
900 * Parameters: psactsp Pointer to _posix_spawn_file_actions_t
904 * ENOMEM Insufficient memory for operation
906 * Notes: This code is common to all posix_spawn_file_actions_*()
907 * functions, since we use a naieve data structure implementation
908 * at present. Future optimization will likely change this.
911 _posix_spawn_file_actions_grow(_posix_spawn_file_actions_t
*psactsp
)
913 int new_alloc
= (*psactsp
)->psfa_act_alloc
* 2;
914 _posix_spawn_file_actions_t new_psacts
;
917 * XXX may want to impose an administrative limit here; POSIX does
918 * XXX not provide for an administrative error return in this case,
919 * XXX so it's probably acceptable to just fail catastrophically
920 * XXX instead of implementing one.
922 if ((new_psacts
= (_posix_spawn_file_actions_t
)realloc((*psactsp
), PSF_ACTIONS_SIZE(new_alloc
))) == NULL
) {
925 new_psacts
->psfa_act_alloc
= new_alloc
;
926 *psactsp
= new_psacts
;
933 * posix_spawn_file_actions_addopen
935 * Description: Add an open action to the object referenced by 'file_actions'
936 * that will cause the file named by 'path' to be attempted to be
937 * opened with flags 'oflag' and mode 'mode', and, if successful,
938 * return as descriptor 'filedes' to the spawned process.
940 * Parameters: file_actions File action object to augment
941 * filedes fd that open is to use
942 * path path to file to open
943 * oflag open file flags
944 * mode open file mode
947 * EBADF The value specified by fildes is
948 * negative or greater than or equal to
950 * ENOMEM Insufficient memory exists to add to
951 * the spawn file actions object.
953 * NOTIMP: Allowed failures (checking NOT required):
954 * EINVAL The value specified by file_actions is invalid.
957 posix_spawn_file_actions_addopen(
958 posix_spawn_file_actions_t
* __restrict file_actions
,
959 int filedes
, const char * __restrict path
, int oflag
,
962 _posix_spawn_file_actions_t
*psactsp
;
963 _psfa_action_t
*psfileact
;
965 if (file_actions
== NULL
|| *file_actions
== NULL
)
968 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
969 /* Range check; required by POSIX */
970 if (filedes
< 0 || filedes
>= OPEN_MAX
)
973 /* If we do not have enough slots, grow the structure */
974 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
975 /* need to grow file actions structure */
976 if (_posix_spawn_file_actions_grow(psactsp
))
981 * Allocate next available slot and fill it out
983 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
985 psfileact
->psfaa_type
= PSFA_OPEN
;
986 psfileact
->psfaa_filedes
= filedes
;
987 psfileact
->psfaa_openargs
.psfao_oflag
= oflag
;
988 psfileact
->psfaa_openargs
.psfao_mode
= mode
;
989 strlcpy(psfileact
->psfaa_openargs
.psfao_path
, path
, PATH_MAX
);
996 * posix_spawn_file_actions_addclose
998 * Description: Add a close action to the object referenced by 'file_actions'
999 * that will cause the file referenced by 'filedes' to be
1000 * attempted to be closed in the spawned process.
1002 * Parameters: file_actions File action object to augment
1003 * filedes fd to close
1005 * Returns: 0 Success
1006 * EBADF The value specified by fildes is
1007 * negative or greater than or equal to
1009 * ENOMEM Insufficient memory exists to add to
1010 * the spawn file actions object.
1012 * NOTIMP: Allowed failures (checking NOT required):
1013 * EINVAL The value specified by file_actions is invalid.
1016 posix_spawn_file_actions_addclose(posix_spawn_file_actions_t
*file_actions
,
1019 _posix_spawn_file_actions_t
*psactsp
;
1020 _psfa_action_t
*psfileact
;
1022 if (file_actions
== NULL
|| *file_actions
== NULL
)
1025 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1026 /* Range check; required by POSIX */
1027 if (filedes
< 0 || filedes
>= OPEN_MAX
)
1030 /* If we do not have enough slots, grow the structure */
1031 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1032 /* need to grow file actions structure */
1033 if (_posix_spawn_file_actions_grow(psactsp
))
1038 * Allocate next available slot and fill it out
1040 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1042 psfileact
->psfaa_type
= PSFA_CLOSE
;
1043 psfileact
->psfaa_filedes
= filedes
;
1050 * posix_spawn_file_actions_adddup2
1052 * Description: Add a dup2 action to the object referenced by 'file_actions'
1053 * that will cause the file referenced by 'filedes' to be
1054 * attempted to be dup2'ed to the descriptor 'newfiledes' in the
1057 * Parameters: file_actions File action object to augment
1058 * filedes fd to dup2
1059 * newfiledes fd to dup2 it to
1061 * Returns: 0 Success
1062 * EBADF The value specified by either fildes
1063 * or by newfiledes is negative or greater
1064 * than or equal to {OPEN_MAX}.
1065 * ENOMEM Insufficient memory exists to add to
1066 * the spawn file actions object.
1068 * NOTIMP: Allowed failures (checking NOT required):
1069 * EINVAL The value specified by file_actions is invalid.
1072 posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t
*file_actions
,
1073 int filedes
, int newfiledes
)
1075 _posix_spawn_file_actions_t
*psactsp
;
1076 _psfa_action_t
*psfileact
;
1078 if (file_actions
== NULL
|| *file_actions
== NULL
)
1081 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1082 /* Range check; required by POSIX */
1083 if (filedes
< 0 || filedes
>= OPEN_MAX
||
1084 newfiledes
< 0 || newfiledes
>= OPEN_MAX
)
1087 /* If we do not have enough slots, grow the structure */
1088 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1089 /* need to grow file actions structure */
1090 if (_posix_spawn_file_actions_grow(psactsp
))
1095 * Allocate next available slot and fill it out
1097 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1099 psfileact
->psfaa_type
= PSFA_DUP2
;
1100 psfileact
->psfaa_filedes
= filedes
;
1101 psfileact
->psfaa_openargs
.psfao_oflag
= newfiledes
;
1107 * posix_spawn_file_actions_addinherit_np
1109 * Description: Add the "inherit" action to the object referenced by
1110 * 'file_actions' that will cause the file referenced by
1111 * 'filedes' to continue to be available in the spawned
1112 * process via the same descriptor.
1114 * Inheritance is the normal default behaviour for
1115 * file descriptors across exec and spawn; but if the
1116 * POSIX_SPAWN_CLOEXEC_DEFAULT flag is set, the usual
1117 * default is reversed for the purposes of the spawn
1118 * invocation. Any pre-existing descriptors that
1119 * need to be made available to the spawned process can
1120 * be marked explicitly as 'inherit' via this interface.
1121 * Otherwise they will be automatically closed.
1123 * Note that any descriptors created via the other file
1124 * actions interfaces are automatically marked as 'inherit'.
1126 * Parameters: file_actions File action object to augment
1127 * filedes fd to inherit.
1129 * Returns: 0 Success
1130 * EBADF The value specified by fildes is
1131 * negative or greater than or equal to
1133 * ENOMEM Insufficient memory exists to add to
1134 * the spawn file actions object.
1136 * NOTIMP: Allowed failures (checking NOT required):
1137 * EINVAL The value specified by file_actions is invalid.
1140 posix_spawn_file_actions_addinherit_np(posix_spawn_file_actions_t
*file_actions
,
1143 _posix_spawn_file_actions_t
*psactsp
;
1144 _psfa_action_t
*psfileact
;
1146 if (file_actions
== NULL
|| *file_actions
== NULL
)
1149 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1150 /* Range check; required by POSIX */
1151 if (filedes
< 0 || filedes
>= OPEN_MAX
)
1154 #if defined(POSIX_SPAWN_CLOEXEC_DEFAULT) // TODO: delete this check
1155 /* If we do not have enough slots, grow the structure */
1156 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1157 /* need to grow file actions structure */
1158 if (_posix_spawn_file_actions_grow(psactsp
))
1163 * Allocate next available slot and fill it out
1165 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1167 psfileact
->psfaa_type
= PSFA_INHERIT
;
1168 psfileact
->psfaa_filedes
= filedes
;
1177 * Description: Create a new process from the process image corresponding to
1178 * the supplied 'file' argument and the parent processes path
1181 * Parameters: pid Pointer to pid_t to receive the
1182 * PID of the spawned process, if
1183 * successful and 'pid' != NULL
1184 * file Name of image file to spawn
1185 * file_actions spawn file actions object which
1186 * describes file actions to be
1187 * performed during the spawn
1188 * attrp spawn attributes object which
1189 * describes attributes to be
1190 * applied during the spawn
1191 * argv argument vector array; NULL
1193 * envp environment vector array; NULL
1196 * Returns: 0 Success
1197 * !0 An errno value indicating the
1198 * cause of the failure to spawn
1200 * Notes: Much of this function is derived from code from execvP() from
1201 * exec.c in libc; this common code should be factored out at
1202 * some point to prevent code duplication or desynchronization vs.
1203 * bug fixes applied to one set of code but not the other.
1206 posix_spawnp(pid_t
* __restrict pid
, const char * __restrict file
,
1207 const posix_spawn_file_actions_t
*file_actions
,
1208 const posix_spawnattr_t
* __restrict attrp
,
1209 char *const argv
[ __restrict
], char *const envp
[ __restrict
])
1211 const char *env_path
;
1222 char path_buf
[PATH_MAX
];
1224 if ((env_path
= getenv("PATH")) == NULL
)
1225 env_path
= _PATH_DEFPATH
;
1227 /* If it's an absolute or relative path name, it's easy. */
1228 if (index(file
, '/')) {
1235 /* If it's an empty path name, fail in the usual POSIX way. */
1239 if ((cur
= alloca(strlen(env_path
) + 1)) == NULL
)
1241 strcpy(cur
, env_path
);
1242 while ((p
= strsep(&cur
, ":")) != NULL
) {
1244 * It's a SHELL path -- double, leading and trailing colons
1245 * mean the current directory.
1256 * If the path is too long complain. This is a possible
1257 * security issue; given a way to make the path too long
1258 * the user may spawn the wrong program.
1260 if (lp
+ ln
+ 2 > sizeof(path_buf
)) {
1264 bcopy(p
, path_buf
, lp
);
1266 bcopy(file
, path_buf
+ lp
+ 1, ln
);
1267 path_buf
[lp
+ ln
+ 1] = '\0';
1269 retry
: err
= posix_spawn(pid
, bp
, file_actions
, attrp
, argv
, envp
);
1281 for (cnt
= 0; argv
[cnt
]; ++cnt
)
1283 memp
= alloca((cnt
+ 2) * sizeof(char *));
1285 /* errno = ENOMEM; XXX override ENOEXEC? */
1290 bcopy(argv
+ 1, memp
+ 2, cnt
* sizeof(char *));
1291 err
= posix_spawn(pid
, _PATH_BSHELL
, file_actions
, attrp
, memp
, envp
);
1295 * EACCES may be for an inaccessible directory or
1296 * a non-executable file. Call stat() to decide
1297 * which. This also handles ambiguities for EFAULT
1298 * and EIO, and undocumented errors like ESTALE.
1299 * We hope that the race for a stat() is unimportant.
1301 if (stat(bp
, &sb
) != 0)
1303 if (err
== EACCES
) {
1322 * Description: Create a new process from the process image corresponding to
1323 * the supplied 'path' argument.
1325 * Parameters: pid Pointer to pid_t to receive the
1326 * PID of the spawned process, if
1327 * successful and 'pid' != NULL
1328 * path Path of image file to spawn
1329 * file_actions spawn file actions object which
1330 * describes file actions to be
1331 * performed during the spawn
1332 * attrp spawn attributes object which
1333 * describes attributes to be
1334 * applied during the spawn
1335 * argv argument vector array; NULL
1337 * envp environment vector array; NULL
1340 * Returns: 0 Success
1341 * !0 An errno value indicating the
1342 * cause of the failure to spawn
1344 * Notes: Unlike other system calls, the return value of this system
1345 * call is expected to either be a 0 or an errno, rather than a
1346 * 0 or a -1, with the 'errno' variable being set.
1348 extern int __posix_spawn(pid_t
* __restrict
, const char * __restrict
,
1349 struct _posix_spawn_args_desc
*,
1350 char *const argv
[ __restrict
], char *const envp
[ __restrict
]);
1353 posix_spawn(pid_t
* __restrict pid
, const char * __restrict path
,
1354 const posix_spawn_file_actions_t
*file_actions
,
1355 const posix_spawnattr_t
* __restrict attrp
,
1356 char *const argv
[ __restrict
], char *const envp
[ __restrict
])
1358 int saveerrno
= errno
;
1361 * Only do extra work if we have file actions or attributes to push
1362 * down. We use a descriptor to push this information down, since we
1363 * want to have size information, which will let us (1) preallocate a
1364 * single chunk of memory for the copyin(), and (2) allow us to do a
1365 * single copyin() per attributes or file actions as a monlithic block.
1367 * Note: A future implementation may attempt to do the same
1368 * thing for the argv/envp data, which could potentially
1369 * result in a performance improvement due to increased
1370 * kernel efficiency, even though it would mean copying
1371 * the data in user space.
1373 if ((file_actions
!= NULL
&& (*file_actions
!= NULL
) && (*(_posix_spawn_file_actions_t
*)file_actions
)->psfa_act_count
> 0) || attrp
!= NULL
) {
1374 struct _posix_spawn_args_desc ad
;
1376 memset(&ad
, 0, sizeof(ad
));
1377 if (attrp
!= NULL
&& *attrp
!= NULL
) {
1378 _posix_spawnattr_t psattr
= *(_posix_spawnattr_t
*)attrp
;
1379 ad
.attr_size
= sizeof(struct _posix_spawnattr
);
1382 if (psattr
->psa_ports
!= NULL
) {
1383 ad
.port_actions
= psattr
->psa_ports
;
1384 ad
.port_actions_size
= PS_PORT_ACTIONS_SIZE(
1385 ad
.port_actions
->pspa_count
);
1388 if (file_actions
!= NULL
&& *file_actions
!= NULL
) {
1389 _posix_spawn_file_actions_t psactsp
=
1390 *(_posix_spawn_file_actions_t
*)file_actions
;
1392 if (psactsp
->psfa_act_count
> 0) {
1393 ad
.file_actions_size
= PSF_ACTIONS_SIZE(psactsp
->psfa_act_count
);
1394 ad
.file_actions
= psactsp
;
1398 ret
= __posix_spawn(pid
, path
, &ad
, argv
, envp
);
1400 ret
= __posix_spawn(pid
, path
, NULL
, argv
, envp
);