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>
42 #if TARGET_OS_EMBEDDED
43 #include <sys/kern_memorystatus.h>
47 * posix_spawnattr_init
49 * Description: Initialize a spawn attributes object attr with default values
51 * Parameters: attr The spawn attributes object to be
55 * ENOMEM Insufficient memory exists to
56 * initialize the spawn attributes object.
58 * Note: As an implementation detail, the externally visibily type
59 * posix_spawnattr_t is defined to be a void *, and initialization
60 * involves allocation of a memory object. Subsequent changes to
61 * the spawn attributes may result in reallocation under the
64 * Reinitialization of an already initialized spawn attributes
65 * object will result in memory being leaked. Because spawn
66 * attributes are not required to be used in conjunction with a
67 * static initializer, there is no way to distinguish a spawn
68 * attribute with stack garbage from one that's been initialized.
69 * This is arguably an API design error.
72 posix_spawnattr_init(posix_spawnattr_t
*attr
)
74 _posix_spawnattr_t
*psattrp
= (_posix_spawnattr_t
*)attr
;
77 if ((*psattrp
= (_posix_spawnattr_t
)malloc(sizeof(struct _posix_spawnattr
))) == NULL
) {
82 * The default value of this attribute shall be as if no
85 (*psattrp
)->psa_flags
= 0;
88 * The default value of this attribute shall be an empty
91 (*psattrp
)->psa_sigdefault
= 0;
93 /* The default value of this attribute is unspecified */
94 (*psattrp
)->psa_sigmask
= 0;
96 /* The default value of this attribute shall be zero */
97 (*psattrp
)->psa_pgroup
= 0; /* doesn't matter */
99 /* Default is no binary preferences, i.e. use normal grading */
100 memset((*psattrp
)->psa_binprefs
, 0,
101 sizeof((*psattrp
)->psa_binprefs
));
103 /* Default is no port actions to take */
104 (*psattrp
)->psa_ports
= NULL
;
107 * The default value of this attribute shall be an no
108 * process control on resource starvation
110 (*psattrp
)->psa_pcontrol
= 0;
113 * The default value of this attribute shall be an no
114 * process control on resource starvation
116 (*psattrp
)->psa_apptype
= 0;
118 #if TARGET_OS_EMBEDDED
120 (*psattrp
)->psa_jetsam_flags
= 0;
121 (*psattrp
)->psa_priority
= DEFAULT_JETSAM_PRIORITY
;
122 (*psattrp
)->psa_high_water_mark
= -1;
125 /* Default is no CPU usage monitor active. */
126 (*psattrp
)->psa_cpumonitor_percent
= 0;
127 (*psattrp
)->psa_cpumonitor_interval
= 0;
135 * posix_spawnattr_destroy
137 * Description: Destroy a spawn attributes object that was previously
138 * initialized via posix_spawnattr_init() by freeing any
139 * memory associated with it and setting it to an invalid value.
141 * Parameters: attr The spawn attributes object to be
146 * Notes: The destroyed spawn attribute results in the void * pointer
147 * being set to NULL; subsequent use without reinitialization
148 * will result in explicit program failure (rather than merely
149 * "undefined behaviour").
151 * NOTIMP: Allowed failures (checking NOT required):
152 * EINVAL The value specified by attr is invalid.
154 static int posix_spawn_destroyportactions_np(posix_spawnattr_t
*);
157 posix_spawnattr_destroy(posix_spawnattr_t
*attr
)
159 _posix_spawnattr_t psattr
;
161 if (attr
== NULL
|| *attr
== NULL
)
164 psattr
= *(_posix_spawnattr_t
*)attr
;
165 posix_spawn_destroyportactions_np(attr
);
175 * posix_spawnattr_setflags
177 * Description: Set the spawn flags attribute for the spawn attribute object
178 * referred to by 'attr'.
180 * Parameters: attr The spawn attributes object whose flags
182 * flags The flags value to set
186 * NOTIMP: Allowed failures (checking NOT required):
187 * EINVAL The value specified by attr is invalid.
188 * EINVAL The value of the attribute being set is not valid.
191 posix_spawnattr_setflags(posix_spawnattr_t
*attr
, short flags
)
193 _posix_spawnattr_t psattr
;
195 if (attr
== NULL
|| *attr
== NULL
)
198 psattr
= *(_posix_spawnattr_t
*)attr
;
199 psattr
->psa_flags
= flags
;
206 * posix_spawnattr_getflags
208 * Description: Retrieve the spawn attributes flag for the spawn attributes
209 * object referenced by 'attr' and place them in the memory
210 * location referenced by 'flagsp'
212 * Parameters: attr The spawn attributes object whose flags
213 * are to be retrieved
214 * flagsp A pointer to a short value to receive
220 * *flagps (modified) The flags value from the spawn
223 * NOTIMP: Allowed failures (checking NOT required):
224 * EINVAL The value specified by attr is invalid.
225 * EINVAL The value of the attribute being set is not valid.
228 posix_spawnattr_getflags(const posix_spawnattr_t
* __restrict attr
,
229 short * __restrict flagsp
)
231 _posix_spawnattr_t psattr
;
233 if (attr
== NULL
|| *attr
== NULL
)
236 psattr
= *(_posix_spawnattr_t
*)attr
;
237 *flagsp
= psattr
->psa_flags
;
244 * posix_spawnattr_getsigdefault
246 * Description: Retrieve the set of signals to be set to default according to
247 * the spawn attribute value referenced by 'attr' and place the
248 * result into the memory containing the sigset_t referenced by
251 * Parameters: attr The spawn attributes object whose
252 * signal set for default signals is to
254 * sigdefault A pointer to the sigset_t to receive
260 * *sigdefault (modified) The signal set of signals to default
261 * from the spawn attributes object
264 posix_spawnattr_getsigdefault(const posix_spawnattr_t
* __restrict attr
,
265 sigset_t
* __restrict sigdefault
)
267 _posix_spawnattr_t psattr
;
269 if (attr
== NULL
|| *attr
== NULL
)
272 psattr
= *(_posix_spawnattr_t
*)attr
;
273 *sigdefault
= psattr
->psa_sigdefault
;
280 * posix_spawnattr_getpgroup
282 * Description: Obtain the value of the spawn process group attribute from the
283 * spawn attributes object referenced by 'attr' and place the
284 * results in the memory location referenced by 'pgroup'
286 * Parameters: attr The spawn attributes object whose
287 * process group information is to be
289 * pgroup A pointer to the pid_t to receive the
295 * *pgroup (modified) The process group information from the
296 * spawn attributes object
299 posix_spawnattr_getpgroup(const posix_spawnattr_t
* __restrict attr
,
300 pid_t
* __restrict pgroup
)
302 _posix_spawnattr_t psattr
;
304 if (attr
== NULL
|| *attr
== NULL
)
307 psattr
= *(_posix_spawnattr_t
*)attr
;
308 *pgroup
= psattr
->psa_pgroup
;
315 * posix_spawnattr_getsigmask
317 * Description: Obtain the value of the spawn signal mask attribute from the
318 * spawn attributes object referenced by 'attr' and place the
319 * result into the memory containing the sigset_t referenced by
322 * Parameters: attr The spawn attributes object whose
323 * signal set for masked signals is to
325 * sigmask A pointer to the sigset_t to receive
331 * *sigmask (modified) The signal set of signals to mask
332 * from the spawn attributes object
335 posix_spawnattr_getsigmask(const posix_spawnattr_t
* __restrict attr
,
336 sigset_t
* __restrict sigmask
)
338 _posix_spawnattr_t psattr
;
340 if (attr
== NULL
|| *attr
== NULL
)
343 psattr
= *(_posix_spawnattr_t
*)attr
;
344 *sigmask
= psattr
->psa_sigmask
;
350 * posix_spawnattr_getbinpref_np
352 * Description: Obtain the value of the spawn binary preferences attribute from
353 * the spawn attributes object referenced by 'attr' and place the
354 * result into the memory referenced by 'pref'.
356 * Parameters: attr The spawn attributes object whose
357 * binary preferences are to be retrieved
358 * count The size of the cpu_type_t array
359 * pref An array of cpu types
360 * ocount The actual number copied
362 * Returns: 0 No binary preferences found
363 * > 0 The number of cpu types (less than
364 * count) copied over from 'attr'.
367 * *pref (modified) The binary preferences array
368 * from the spawn attributes object
371 posix_spawnattr_getbinpref_np(const posix_spawnattr_t
* __restrict attr
,
372 size_t count
, cpu_type_t
*pref
, size_t * __restrict ocount
)
374 _posix_spawnattr_t psattr
;
377 if (attr
== NULL
|| *attr
== NULL
)
380 psattr
= *(_posix_spawnattr_t
*)attr
;
381 for (i
= 0; i
< count
&& i
< 4; i
++) {
382 pref
[i
] = psattr
->psa_binprefs
[i
];
392 * posix_spawnattr_getpcontrol_np
394 * Description: Retrieve the process control property set default according to
395 * the spawn attribute value referenced by 'attr' and place the
396 * result into the memory containing the control referenced by
399 * Parameters: attr The spawn attributes object whose
400 * signal set for default signals is to
402 * pcontrol A pointer to an int to receive
403 * the process control info
408 * *pcontrol (modified) The signal set of signals to default
409 * from the spawn attributes object
412 posix_spawnattr_getpcontrol_np(const posix_spawnattr_t
* __restrict attr
,
413 int * __restrict pcontrol
)
415 _posix_spawnattr_t psattr
;
417 if (attr
== NULL
|| *attr
== NULL
)
420 psattr
= *(_posix_spawnattr_t
*)attr
;
421 *pcontrol
= psattr
->psa_pcontrol
;
427 * posix_spawnattr_getapptype_np
429 * Description: Retrieve the process specific behaviors and app launch typea
430 * spawn attribute value referenced by 'attr' and place the
431 * result into the memory containing the control referenced by
434 * Parameters: attr The spawn attributes object whose
435 * signal set for default signals is to
437 * apptype A pointer to an int to receive
438 * the process control info
443 * *pcontrol (modified) The signal set of signals to default
444 * from the spawn attributes object
447 posix_spawnattr_getapptype_np(const posix_spawnattr_t
* __restrict attr
,
448 int * __restrict apptype
)
450 _posix_spawnattr_t psattr
;
452 if (attr
== NULL
|| *attr
== NULL
)
455 psattr
= *(_posix_spawnattr_t
*)attr
;
456 *apptype
= psattr
->psa_apptype
;
462 * posix_spawnattr_setsigdefault
464 * Description: Set the set of signals to be set to default for the spawn
465 * attribute value referenced by 'attr' from the memory
466 * containing the sigset_t referenced by 'sigdefault'
468 * Parameters: attr The spawn attributes object whose
469 * signal set for default signals is to
471 * sigdefault A pointer to the sigset_t from which to
472 * obtain the signal set
477 posix_spawnattr_setsigdefault(posix_spawnattr_t
* __restrict attr
,
478 const sigset_t
* __restrict sigdefault
)
480 _posix_spawnattr_t psattr
;
482 if (attr
== NULL
|| *attr
== NULL
)
485 psattr
= *(_posix_spawnattr_t
*)attr
;
486 psattr
->psa_sigdefault
= *sigdefault
;
493 * posix_spawnattr_setpgroup
495 * Description: Set the value of the spawn process group attribute for the
496 * spawn attributes object referenced by 'attr' from the value
499 * Parameters: attr The spawn attributes object for which
500 * the process group information is to be
502 * pgroup The process group to set
507 posix_spawnattr_setpgroup(posix_spawnattr_t
* attr
, pid_t pgroup
)
509 _posix_spawnattr_t psattr
;
511 if (attr
== NULL
|| *attr
== NULL
)
514 psattr
= *(_posix_spawnattr_t
*)attr
;
515 psattr
->psa_pgroup
= pgroup
;
522 * posix_spawnattr_setsigmask
524 * Description: Set the set of signals to be masked for the spawn attribute
525 * value referenced by 'attr' from the memory containing the
526 * sigset_t referenced by 'sigmask'
528 * Parameters: attr The spawn attributes object whose
529 * signal set for masked signals is to
531 * sigmask A pointer to the sigset_t from which to
532 * obtain the signal set
537 posix_spawnattr_setsigmask(posix_spawnattr_t
* __restrict attr
,
538 const sigset_t
* __restrict sigmask
)
540 _posix_spawnattr_t psattr
;
542 if (attr
== NULL
|| *attr
== NULL
)
545 psattr
= *(_posix_spawnattr_t
*)attr
;
546 psattr
->psa_sigmask
= *sigmask
;
553 * posix_spawnattr_setbinpref_np
555 * Description: Set the universal binary preferences for the spawn attribute
556 * value referenced by 'attr' from the memory containing the
557 * cpu_type_t array referenced by 'pref', size of 'count'
559 * Parameters: attr The spawn attributes object whose
560 * binary preferences are to be set
561 * count Size of the array pointed to by 'pref'
562 * pref cpu_type_t array of binary preferences
563 * ocount The actual number copied
565 * Returns: 0 No preferences copied
566 * > 0 Number of preferences copied
568 * Note: The posix_spawnattr_t currently only holds four cpu_type_t's.
569 * If the caller provides more preferences than this limit, they
570 * will be ignored, as reflected in the return value.
573 posix_spawnattr_setbinpref_np(posix_spawnattr_t
* __restrict attr
,
574 size_t count
, cpu_type_t
*pref
, size_t * __restrict ocount
)
576 _posix_spawnattr_t psattr
;
579 if (attr
== NULL
|| *attr
== NULL
)
582 psattr
= *(_posix_spawnattr_t
*)attr
;
583 for (i
= 0; i
< count
&& i
< 4; i
++) {
584 psattr
->psa_binprefs
[i
] = pref
[i
];
587 /* return number of binprefs copied over */
595 * posix_spawnattr_setpcontrol_np
597 * Description: Set the process control property according to
598 * attribute value referenced by 'attr' from the memory
599 * containing the int value 'pcontrol'
601 * Parameters: attr The spawn attributes object whose
602 * signal set for default signals is to
604 * pcontrol An int value of the process control info
609 posix_spawnattr_setpcontrol_np(posix_spawnattr_t
* __restrict attr
,
612 _posix_spawnattr_t psattr
;
614 if (attr
== NULL
|| *attr
== NULL
)
617 psattr
= *(_posix_spawnattr_t
*)attr
;
618 psattr
->psa_pcontrol
= pcontrol
;
625 * posix_spawnattr_setapptype_np
627 * Description: Set the process specific behaviors and app launch type
628 * attribute value referenced by 'attr' from the memory
629 * containing the int value 'apptype'
631 * Parameters: attr The spawn attributes object whose
632 * signal set for default signals is to
634 * apptype An int value of the apptype info
639 posix_spawnattr_setapptype_np(posix_spawnattr_t
* __restrict attr
,
642 _posix_spawnattr_t psattr
;
644 if (attr
== NULL
|| *attr
== NULL
)
647 psattr
= *(_posix_spawnattr_t
*)attr
;
648 psattr
->psa_apptype
= apptype
;
654 * posix_spawn_createportactions_np
655 * Description: create a new posix_spawn_port_actions struct and link
656 * it into the posix_spawnattr.
659 posix_spawn_createportactions_np(posix_spawnattr_t
*attr
)
661 _posix_spawnattr_t psattr
;
662 _posix_spawn_port_actions_t acts
;
664 if (attr
== NULL
|| *attr
== NULL
)
667 psattr
= *(_posix_spawnattr_t
*)attr
;
668 acts
= (_posix_spawn_port_actions_t
)malloc(PS_PORT_ACTIONS_SIZE(2));
672 acts
->pspa_alloc
= 2;
673 acts
->pspa_count
= 0;
675 psattr
->psa_ports
= acts
;
680 * posix_spawn_growportactions_np
681 * Description: Enlarge the size of portactions if necessary
684 posix_spawn_growportactions_np(posix_spawnattr_t
*attr
)
686 _posix_spawnattr_t psattr
;
687 _posix_spawn_port_actions_t acts
;
690 if (attr
== NULL
|| *attr
== NULL
)
693 psattr
= *(_posix_spawnattr_t
*)attr
;
694 acts
= psattr
->psa_ports
;
698 /* Double number of port actions allocated for */
699 newnum
= 2 * acts
->pspa_alloc
;
700 acts
= realloc(acts
, PS_PORT_ACTIONS_SIZE(newnum
));
704 acts
->pspa_alloc
= newnum
;
709 * posix_spawn_destroyportactions_np
710 * Description: clean up portactions struct in posix_spawnattr_t attr
713 posix_spawn_destroyportactions_np(posix_spawnattr_t
*attr
)
715 _posix_spawnattr_t psattr
;
716 _posix_spawn_port_actions_t acts
;
718 if (attr
== NULL
|| *attr
== NULL
)
721 psattr
= *(_posix_spawnattr_t
*)attr
;
722 acts
= psattr
->psa_ports
;
732 * posix_spawnattr_setspecialport_np
734 * Description: Set a new value for a mach special port in the spawned task.
736 * Parameters: attr The spawn attributes object for the
738 * new_port The new value for the special port
739 * which The particular port to be set
740 * (see task_set_special_port for details)
743 * ENOMEM Couldn't allocate memory
746 posix_spawnattr_setspecialport_np(
747 posix_spawnattr_t
*attr
,
748 mach_port_t new_port
,
751 _posix_spawnattr_t psattr
;
753 _ps_port_action_t
*action
;
754 _posix_spawn_port_actions_t ports
;
756 if (attr
== NULL
|| *attr
== NULL
)
759 psattr
= *(_posix_spawnattr_t
*)attr
;
760 ports
= psattr
->psa_ports
;
761 /* Have any port actions been created yet? */
763 err
= posix_spawn_createportactions_np(attr
);
766 ports
= psattr
->psa_ports
;
769 /* Is there enough room? */
770 if (ports
->pspa_alloc
== ports
->pspa_count
) {
771 err
= posix_spawn_growportactions_np(attr
);
776 /* Add this action to next spot in array */
777 action
= &ports
->pspa_actions
[ports
->pspa_count
];
778 action
->port_type
= PSPA_SPECIAL
;
779 action
->new_port
= new_port
;
780 action
->which
= which
;
787 * posix_spawnattr_setexceptionports_np
789 * Description: Set a new port for a set of exception ports in the spawned task.
791 * Parameters: attr The spawn attributes object for the
793 * mask A bitfield indicating which exceptions
794 * to associate the port with
795 * new_port The new value for the exception port
796 * behavior The default behavior for the port
797 * flavor The default flavor for the port
798 * (see task_set_exception_ports)
803 posix_spawnattr_setexceptionports_np(
804 posix_spawnattr_t
*attr
,
805 exception_mask_t mask
,
806 mach_port_t new_port
,
807 exception_behavior_t behavior
,
808 thread_state_flavor_t flavor
)
810 _posix_spawnattr_t psattr
;
812 _ps_port_action_t
*action
;
813 _posix_spawn_port_actions_t ports
;
815 if (attr
== NULL
|| *attr
== NULL
)
818 psattr
= *(_posix_spawnattr_t
*)attr
;
819 ports
= psattr
->psa_ports
;
820 /* Have any port actions been created yet? */
822 err
= posix_spawn_createportactions_np(attr
);
825 ports
= psattr
->psa_ports
;
828 /* Is there enough room? */
829 if (ports
->pspa_alloc
== ports
->pspa_count
) {
830 err
= posix_spawn_growportactions_np(attr
);
835 /* Add this action to next spot in array */
836 action
= &ports
->pspa_actions
[ports
->pspa_count
];
837 action
->port_type
= PSPA_EXCEPTION
;
839 action
->new_port
= new_port
;
840 action
->behavior
= behavior
;
841 action
->flavor
= flavor
;
848 * posix_spawnattr_setauditsessionport_np
850 * Description: Set the audit session port rights attribute in the spawned task.
851 * This is used to securely set the audit session information for
854 * Parameters: attr The spawn attributes object for the
856 * au_sessionport The audit session send port right
861 posix_spawnattr_setauditsessionport_np(
862 posix_spawnattr_t
*attr
,
863 mach_port_t au_sessionport
)
865 _posix_spawnattr_t psattr
;
867 _ps_port_action_t
*action
;
868 _posix_spawn_port_actions_t ports
;
870 if (attr
== NULL
|| *attr
== NULL
)
873 psattr
= *(_posix_spawnattr_t
*)attr
;
874 ports
= psattr
->psa_ports
;
875 /* Have any port actions been created yet? */
877 err
= posix_spawn_createportactions_np(attr
);
880 ports
= psattr
->psa_ports
;
883 /* Is there enough room? */
884 if (ports
->pspa_alloc
== ports
->pspa_count
) {
885 err
= posix_spawn_growportactions_np(attr
);
890 /* Add this action to next spot in array */
891 action
= &ports
->pspa_actions
[ports
->pspa_count
];
892 action
->port_type
= PSPA_AU_SESSION
;
893 action
->new_port
= au_sessionport
;
901 * posix_spawn_file_actions_init
903 * Description: Initialize a spawn file actions object attr with default values
905 * Parameters: file_actions The spawn file actions object to be
909 * ENOMEM Insufficient memory exists to
910 * initialize the spawn file actions
913 * Note: As an implementation detail, the externally visibily type
914 * posix_spawn_file_actions_t is defined to be a void *, and
915 * initialization involves allocation of a memory object.
916 * Subsequent changes to the spawn file actions may result in
917 * reallocation under the covers.
919 * Reinitialization of an already initialized spawn file actions
920 * object will result in memory being leaked. Because spawn
921 * file actions are not required to be used in conjunction with a
922 * static initializer, there is no way to distinguish a spawn
923 * file actions with stack garbage from one that's been
924 * initialized. This is arguably an API design error.
927 posix_spawn_file_actions_init(posix_spawn_file_actions_t
*file_actions
)
929 _posix_spawn_file_actions_t
*psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
932 if ((*psactsp
= (_posix_spawn_file_actions_t
)malloc(PSF_ACTIONS_SIZE(PSF_ACTIONS_INIT_COUNT
))) == NULL
) {
935 (*psactsp
)->psfa_act_alloc
= PSF_ACTIONS_INIT_COUNT
;
936 (*psactsp
)->psfa_act_count
= 0;
944 * posix_spawn_file_actions_destroy
946 * Description: Destroy a spawn file actions object that was previously
947 * initialized via posix_spawn_file_actions_init() by freeing any
948 * memory associated with it and setting it to an invalid value.
950 * Parameters: attr The spawn file actions object to be
955 * Notes: The destroyed spawn file actions results in the void * pointer
956 * being set to NULL; subsequent use without reinitialization
957 * will result in explicit program failure (rather than merely
958 * "undefined behaviour").
960 * NOTIMP: Allowed failures (checking NOT required):
961 * EINVAL The value specified by file_actions is invalid.
964 posix_spawn_file_actions_destroy(posix_spawn_file_actions_t
*file_actions
)
966 _posix_spawn_file_actions_t psacts
;
968 if (file_actions
== NULL
|| *file_actions
== NULL
)
971 psacts
= *(_posix_spawn_file_actions_t
*)file_actions
;
973 *file_actions
= NULL
;
980 * _posix_spawn_file_actions_grow
982 * Description: Grow the available list of file actions associated with the
983 * pointer to the structure provided; replace the contents of the
984 * pointer as a side effect.
986 * Parameters: psactsp Pointer to _posix_spawn_file_actions_t
990 * ENOMEM Insufficient memory for operation
992 * Notes: This code is common to all posix_spawn_file_actions_*()
993 * functions, since we use a naieve data structure implementation
994 * at present. Future optimization will likely change this.
997 _posix_spawn_file_actions_grow(_posix_spawn_file_actions_t
*psactsp
)
999 int new_alloc
= (*psactsp
)->psfa_act_alloc
* 2;
1000 _posix_spawn_file_actions_t new_psacts
;
1003 * XXX may want to impose an administrative limit here; POSIX does
1004 * XXX not provide for an administrative error return in this case,
1005 * XXX so it's probably acceptable to just fail catastrophically
1006 * XXX instead of implementing one.
1008 if ((new_psacts
= (_posix_spawn_file_actions_t
)realloc((*psactsp
), PSF_ACTIONS_SIZE(new_alloc
))) == NULL
) {
1011 new_psacts
->psfa_act_alloc
= new_alloc
;
1012 *psactsp
= new_psacts
;
1019 * posix_spawn_file_actions_addopen
1021 * Description: Add an open action to the object referenced by 'file_actions'
1022 * that will cause the file named by 'path' to be attempted to be
1023 * opened with flags 'oflag' and mode 'mode', and, if successful,
1024 * return as descriptor 'filedes' to the spawned process.
1026 * Parameters: file_actions File action object to augment
1027 * filedes fd that open is to use
1028 * path path to file to open
1029 * oflag open file flags
1030 * mode open file mode
1032 * Returns: 0 Success
1033 * EBADF The value specified by fildes is
1034 * negative or greater than or equal to
1036 * ENOMEM Insufficient memory exists to add to
1037 * the spawn file actions object.
1039 * NOTIMP: Allowed failures (checking NOT required):
1040 * EINVAL The value specified by file_actions is invalid.
1043 posix_spawn_file_actions_addopen(
1044 posix_spawn_file_actions_t
* __restrict file_actions
,
1045 int filedes
, const char * __restrict path
, int oflag
,
1048 _posix_spawn_file_actions_t
*psactsp
;
1049 _psfa_action_t
*psfileact
;
1051 if (file_actions
== NULL
|| *file_actions
== NULL
)
1054 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1055 /* Range check; required by POSIX */
1056 if (filedes
< 0 || filedes
>= OPEN_MAX
)
1059 /* If we do not have enough slots, grow the structure */
1060 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1061 /* need to grow file actions structure */
1062 if (_posix_spawn_file_actions_grow(psactsp
))
1067 * Allocate next available slot and fill it out
1069 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1071 psfileact
->psfaa_type
= PSFA_OPEN
;
1072 psfileact
->psfaa_filedes
= filedes
;
1073 psfileact
->psfaa_openargs
.psfao_oflag
= oflag
;
1074 psfileact
->psfaa_openargs
.psfao_mode
= mode
;
1075 strlcpy(psfileact
->psfaa_openargs
.psfao_path
, path
, PATH_MAX
);
1082 * posix_spawn_file_actions_addclose
1084 * Description: Add a close action to the object referenced by 'file_actions'
1085 * that will cause the file referenced by 'filedes' to be
1086 * attempted to be closed in the spawned process.
1088 * Parameters: file_actions File action object to augment
1089 * filedes fd to close
1091 * Returns: 0 Success
1092 * EBADF The value specified by fildes is
1093 * negative or greater than or equal to
1095 * ENOMEM Insufficient memory exists to add to
1096 * the spawn file actions object.
1098 * NOTIMP: Allowed failures (checking NOT required):
1099 * EINVAL The value specified by file_actions is invalid.
1102 posix_spawn_file_actions_addclose(posix_spawn_file_actions_t
*file_actions
,
1105 _posix_spawn_file_actions_t
*psactsp
;
1106 _psfa_action_t
*psfileact
;
1108 if (file_actions
== NULL
|| *file_actions
== NULL
)
1111 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1112 /* Range check; required by POSIX */
1113 if (filedes
< 0 || filedes
>= OPEN_MAX
)
1116 /* If we do not have enough slots, grow the structure */
1117 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1118 /* need to grow file actions structure */
1119 if (_posix_spawn_file_actions_grow(psactsp
))
1124 * Allocate next available slot and fill it out
1126 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1128 psfileact
->psfaa_type
= PSFA_CLOSE
;
1129 psfileact
->psfaa_filedes
= filedes
;
1136 * posix_spawn_file_actions_adddup2
1138 * Description: Add a dup2 action to the object referenced by 'file_actions'
1139 * that will cause the file referenced by 'filedes' to be
1140 * attempted to be dup2'ed to the descriptor 'newfiledes' in the
1143 * Parameters: file_actions File action object to augment
1144 * filedes fd to dup2
1145 * newfiledes fd to dup2 it to
1147 * Returns: 0 Success
1148 * EBADF The value specified by either fildes
1149 * or by newfiledes is negative or greater
1150 * than or equal to {OPEN_MAX}.
1151 * ENOMEM Insufficient memory exists to add to
1152 * the spawn file actions object.
1154 * NOTIMP: Allowed failures (checking NOT required):
1155 * EINVAL The value specified by file_actions is invalid.
1158 posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t
*file_actions
,
1159 int filedes
, int newfiledes
)
1161 _posix_spawn_file_actions_t
*psactsp
;
1162 _psfa_action_t
*psfileact
;
1164 if (file_actions
== NULL
|| *file_actions
== NULL
)
1167 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1168 /* Range check; required by POSIX */
1169 if (filedes
< 0 || filedes
>= OPEN_MAX
||
1170 newfiledes
< 0 || newfiledes
>= OPEN_MAX
)
1173 /* If we do not have enough slots, grow the structure */
1174 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1175 /* need to grow file actions structure */
1176 if (_posix_spawn_file_actions_grow(psactsp
))
1181 * Allocate next available slot and fill it out
1183 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1185 psfileact
->psfaa_type
= PSFA_DUP2
;
1186 psfileact
->psfaa_filedes
= filedes
;
1187 psfileact
->psfaa_openargs
.psfao_oflag
= newfiledes
;
1193 * posix_spawn_file_actions_addinherit_np
1195 * Description: Add the "inherit" action to the object referenced by
1196 * 'file_actions' that will cause the file referenced by
1197 * 'filedes' to continue to be available in the spawned
1198 * process via the same descriptor.
1200 * Inheritance is the normal default behaviour for
1201 * file descriptors across exec and spawn; but if the
1202 * POSIX_SPAWN_CLOEXEC_DEFAULT flag is set, the usual
1203 * default is reversed for the purposes of the spawn
1204 * invocation. Any pre-existing descriptors that
1205 * need to be made available to the spawned process can
1206 * be marked explicitly as 'inherit' via this interface.
1207 * Otherwise they will be automatically closed.
1209 * Note that any descriptors created via the other file
1210 * actions interfaces are automatically marked as 'inherit'.
1212 * Parameters: file_actions File action object to augment
1213 * filedes fd to inherit.
1215 * Returns: 0 Success
1216 * EBADF The value specified by fildes is
1217 * negative or greater than or equal to
1219 * ENOMEM Insufficient memory exists to add to
1220 * the spawn file actions object.
1222 * NOTIMP: Allowed failures (checking NOT required):
1223 * EINVAL The value specified by file_actions is invalid.
1226 posix_spawn_file_actions_addinherit_np(posix_spawn_file_actions_t
*file_actions
,
1229 _posix_spawn_file_actions_t
*psactsp
;
1230 _psfa_action_t
*psfileact
;
1232 if (file_actions
== NULL
|| *file_actions
== NULL
)
1235 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1236 /* Range check; required by POSIX */
1237 if (filedes
< 0 || filedes
>= OPEN_MAX
)
1240 #if defined(POSIX_SPAWN_CLOEXEC_DEFAULT) // TODO: delete this check
1241 /* If we do not have enough slots, grow the structure */
1242 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1243 /* need to grow file actions structure */
1244 if (_posix_spawn_file_actions_grow(psactsp
))
1249 * Allocate next available slot and fill it out
1251 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1253 psfileact
->psfaa_type
= PSFA_INHERIT
;
1254 psfileact
->psfaa_filedes
= filedes
;
1260 posix_spawnattr_setcpumonitor(posix_spawnattr_t
* __restrict attr
,
1261 uint64_t percent
, uint64_t interval
)
1263 _posix_spawnattr_t psattr
;
1265 if (attr
== NULL
|| *attr
== NULL
|| percent
== 0 || percent
> 100)
1268 psattr
= *(_posix_spawnattr_t
*)attr
;
1270 psattr
->psa_cpumonitor_percent
= percent
;
1271 psattr
->psa_cpumonitor_interval
= interval
;
1277 posix_spawnattr_getcpumonitor(posix_spawnattr_t
* __restrict attr
,
1278 uint64_t *percent
, uint64_t *interval
)
1280 _posix_spawnattr_t psattr
;
1282 if (attr
== NULL
|| *attr
== NULL
)
1285 psattr
= *(_posix_spawnattr_t
*)attr
;
1287 *percent
= psattr
->psa_cpumonitor_percent
;
1288 *interval
= psattr
->psa_cpumonitor_interval
;
1293 #if TARGET_OS_EMBEDDED
1295 * posix_spawnattr_setjetsam
1297 * Description: Set jetsam attributes for the spawn attribute object
1298 * referred to by 'attr'.
1300 * Parameters: flags The flags value to set
1301 * priority Relative jetsam priority
1302 * high_water_mark Value in pages; resident page
1303 * counts above this level can
1304 * result in termination
1306 * Returns: 0 Success
1309 posix_spawnattr_setjetsam(posix_spawnattr_t
* __restrict attr
,
1310 short flags
, int priority
, int high_water_mark
)
1312 _posix_spawnattr_t psattr
;
1314 if (attr
== NULL
|| *attr
== NULL
)
1317 psattr
= *(_posix_spawnattr_t
*)attr
;
1319 psattr
->psa_jetsam_flags
= flags
;
1320 psattr
->psa_priority
= priority
;
1321 psattr
->psa_high_water_mark
= high_water_mark
;
1330 * Description: Create a new process from the process image corresponding to
1331 * the supplied 'file' argument and the parent processes path
1334 * Parameters: pid Pointer to pid_t to receive the
1335 * PID of the spawned process, if
1336 * successful and 'pid' != NULL
1337 * file Name of image file to spawn
1338 * file_actions spawn file actions object which
1339 * describes file actions to be
1340 * performed during the spawn
1341 * attrp spawn attributes object which
1342 * describes attributes to be
1343 * applied during the spawn
1344 * argv argument vector array; NULL
1346 * envp environment vector array; NULL
1349 * Returns: 0 Success
1350 * !0 An errno value indicating the
1351 * cause of the failure to spawn
1353 * Notes: Much of this function is derived from code from execvP() from
1354 * exec.c in libc; this common code should be factored out at
1355 * some point to prevent code duplication or desynchronization vs.
1356 * bug fixes applied to one set of code but not the other.
1359 posix_spawnp(pid_t
* __restrict pid
, const char * __restrict file
,
1360 const posix_spawn_file_actions_t
*file_actions
,
1361 const posix_spawnattr_t
* __restrict attrp
,
1362 char *const argv
[ __restrict
], char *const envp
[ __restrict
])
1364 const char *env_path
;
1375 char path_buf
[PATH_MAX
];
1377 if ((env_path
= getenv("PATH")) == NULL
)
1378 env_path
= _PATH_DEFPATH
;
1380 /* If it's an absolute or relative path name, it's easy. */
1381 if (index(file
, '/')) {
1388 /* If it's an empty path name, fail in the usual POSIX way. */
1392 if ((cur
= alloca(strlen(env_path
) + 1)) == NULL
)
1394 strcpy(cur
, env_path
);
1395 while ((p
= strsep(&cur
, ":")) != NULL
) {
1397 * It's a SHELL path -- double, leading and trailing colons
1398 * mean the current directory.
1409 * If the path is too long complain. This is a possible
1410 * security issue; given a way to make the path too long
1411 * the user may spawn the wrong program.
1413 if (lp
+ ln
+ 2 > sizeof(path_buf
)) {
1417 bcopy(p
, path_buf
, lp
);
1419 bcopy(file
, path_buf
+ lp
+ 1, ln
);
1420 path_buf
[lp
+ ln
+ 1] = '\0';
1422 retry
: err
= posix_spawn(pid
, bp
, file_actions
, attrp
, argv
, envp
);
1434 for (cnt
= 0; argv
[cnt
]; ++cnt
)
1436 memp
= alloca((cnt
+ 2) * sizeof(char *));
1438 /* errno = ENOMEM; XXX override ENOEXEC? */
1443 bcopy(argv
+ 1, memp
+ 2, cnt
* sizeof(char *));
1444 err
= posix_spawn(pid
, _PATH_BSHELL
, file_actions
, attrp
, memp
, envp
);
1448 * EACCES may be for an inaccessible directory or
1449 * a non-executable file. Call stat() to decide
1450 * which. This also handles ambiguities for EFAULT
1451 * and EIO, and undocumented errors like ESTALE.
1452 * We hope that the race for a stat() is unimportant.
1454 if (stat(bp
, &sb
) != 0)
1456 if (err
== EACCES
) {
1475 * Description: Create a new process from the process image corresponding to
1476 * the supplied 'path' argument.
1478 * Parameters: pid Pointer to pid_t to receive the
1479 * PID of the spawned process, if
1480 * successful and 'pid' != NULL
1481 * path Path of image file to spawn
1482 * file_actions spawn file actions object which
1483 * describes file actions to be
1484 * performed during the spawn
1485 * attrp spawn attributes object which
1486 * describes attributes to be
1487 * applied during the spawn
1488 * argv argument vector array; NULL
1490 * envp environment vector array; NULL
1493 * Returns: 0 Success
1494 * !0 An errno value indicating the
1495 * cause of the failure to spawn
1497 * Notes: Unlike other system calls, the return value of this system
1498 * call is expected to either be a 0 or an errno, rather than a
1499 * 0 or a -1, with the 'errno' variable being set.
1501 extern int __posix_spawn(pid_t
* __restrict
, const char * __restrict
,
1502 struct _posix_spawn_args_desc
*,
1503 char *const argv
[ __restrict
], char *const envp
[ __restrict
]);
1506 posix_spawn(pid_t
* __restrict pid
, const char * __restrict path
,
1507 const posix_spawn_file_actions_t
*file_actions
,
1508 const posix_spawnattr_t
* __restrict attrp
,
1509 char *const argv
[ __restrict
], char *const envp
[ __restrict
])
1511 int saveerrno
= errno
;
1514 * Only do extra work if we have file actions or attributes to push
1515 * down. We use a descriptor to push this information down, since we
1516 * want to have size information, which will let us (1) preallocate a
1517 * single chunk of memory for the copyin(), and (2) allow us to do a
1518 * single copyin() per attributes or file actions as a monlithic block.
1520 * Note: A future implementation may attempt to do the same
1521 * thing for the argv/envp data, which could potentially
1522 * result in a performance improvement due to increased
1523 * kernel efficiency, even though it would mean copying
1524 * the data in user space.
1526 if ((file_actions
!= NULL
&& (*file_actions
!= NULL
) && (*(_posix_spawn_file_actions_t
*)file_actions
)->psfa_act_count
> 0) || attrp
!= NULL
) {
1527 struct _posix_spawn_args_desc ad
;
1529 memset(&ad
, 0, sizeof(ad
));
1530 if (attrp
!= NULL
&& *attrp
!= NULL
) {
1531 _posix_spawnattr_t psattr
= *(_posix_spawnattr_t
*)attrp
;
1532 ad
.attr_size
= sizeof(struct _posix_spawnattr
);
1535 if (psattr
->psa_ports
!= NULL
) {
1536 ad
.port_actions
= psattr
->psa_ports
;
1537 ad
.port_actions_size
= PS_PORT_ACTIONS_SIZE(
1538 ad
.port_actions
->pspa_count
);
1541 if (file_actions
!= NULL
&& *file_actions
!= NULL
) {
1542 _posix_spawn_file_actions_t psactsp
=
1543 *(_posix_spawn_file_actions_t
*)file_actions
;
1545 if (psactsp
->psfa_act_count
> 0) {
1546 ad
.file_actions_size
= PSF_ACTIONS_SIZE(psactsp
->psfa_act_count
);
1547 ad
.file_actions
= psactsp
;
1551 ret
= __posix_spawn(pid
, path
, &ad
, argv
, envp
);
1553 ret
= __posix_spawn(pid
, path
, NULL
, argv
, envp
);