2 * Copyright (c) 2006-2012 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 * [SPN] Support for _POSIX_SPAWN
28 #define CONFIG_MEMORYSTATUS 1 // <rdar://problem/13604997>
29 #include <sys/types.h> /* for user_size_t */
31 #include <spawn_private.h>
32 #include <sys/spawn_internal.h>
33 #include <sys/process_policy.h>
36 #include <limits.h> /* for OPEN_MAX, PATH_MAX */
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 * Initializing the alignment paddings.
116 (*psattrp
)->short_padding
= 0;
117 (*psattrp
)->flags_padding
= 0;
118 (*psattrp
)->int_padding
= 0;
122 * The default value of this attribute shall be an no
123 * process control on resource starvation
125 (*psattrp
)->psa_apptype
= 0;
128 (*psattrp
)->psa_jetsam_flags
= 0;
129 (*psattrp
)->psa_priority
= -1;
130 (*psattrp
)->psa_high_water_mark
= -1;
132 /* Default is no CPU usage monitor active. */
133 (*psattrp
)->psa_cpumonitor_percent
= 0;
134 (*psattrp
)->psa_cpumonitor_interval
= 0;
136 /* Default is no MAC policy extensions. */
137 (*psattrp
)->psa_mac_extensions
= NULL
;
145 * posix_spawnattr_destroy
147 * Description: Destroy a spawn attributes object that was previously
148 * initialized via posix_spawnattr_init() by freeing any
149 * memory associated with it and setting it to an invalid value.
151 * Parameters: attr The spawn attributes object to be
156 * Notes: The destroyed spawn attribute results in the void * pointer
157 * being set to NULL; subsequent use without reinitialization
158 * will result in explicit program failure (rather than merely
159 * "undefined behaviour").
161 * NOTIMP: Allowed failures (checking NOT required):
162 * EINVAL The value specified by attr is invalid.
164 static int posix_spawn_destroyportactions_np(posix_spawnattr_t
*);
167 posix_spawnattr_destroy(posix_spawnattr_t
*attr
)
169 _posix_spawnattr_t psattr
;
171 if (attr
== NULL
|| *attr
== NULL
)
174 psattr
= *(_posix_spawnattr_t
*)attr
;
175 posix_spawn_destroyportactions_np(attr
);
185 * posix_spawnattr_setflags
187 * Description: Set the spawn flags attribute for the spawn attribute object
188 * referred to by 'attr'.
190 * Parameters: attr The spawn attributes object whose flags
192 * flags The flags value to set
196 * NOTIMP: Allowed failures (checking NOT required):
197 * EINVAL The value specified by attr is invalid.
198 * EINVAL The value of the attribute being set is not valid.
201 posix_spawnattr_setflags(posix_spawnattr_t
*attr
, short flags
)
203 _posix_spawnattr_t psattr
;
205 if (attr
== NULL
|| *attr
== NULL
)
208 psattr
= *(_posix_spawnattr_t
*)attr
;
209 psattr
->psa_flags
= flags
;
216 * posix_spawnattr_getflags
218 * Description: Retrieve the spawn attributes flag for the spawn attributes
219 * object referenced by 'attr' and place them in the memory
220 * location referenced by 'flagsp'
222 * Parameters: attr The spawn attributes object whose flags
223 * are to be retrieved
224 * flagsp A pointer to a short value to receive
230 * *flagps (modified) The flags value from the spawn
233 * NOTIMP: Allowed failures (checking NOT required):
234 * EINVAL The value specified by attr is invalid.
235 * EINVAL The value of the attribute being set is not valid.
238 posix_spawnattr_getflags(const posix_spawnattr_t
* __restrict attr
,
239 short * __restrict flagsp
)
241 _posix_spawnattr_t psattr
;
243 if (attr
== NULL
|| *attr
== NULL
)
246 psattr
= *(_posix_spawnattr_t
*)attr
;
247 *flagsp
= psattr
->psa_flags
;
254 * posix_spawnattr_getsigdefault
256 * Description: Retrieve the set of signals to be set to default according to
257 * the spawn attribute value referenced by 'attr' and place the
258 * result into the memory containing the sigset_t referenced by
261 * Parameters: attr The spawn attributes object whose
262 * signal set for default signals is to
264 * sigdefault A pointer to the sigset_t to receive
270 * *sigdefault (modified) The signal set of signals to default
271 * from the spawn attributes object
274 posix_spawnattr_getsigdefault(const posix_spawnattr_t
* __restrict attr
,
275 sigset_t
* __restrict sigdefault
)
277 _posix_spawnattr_t psattr
;
279 if (attr
== NULL
|| *attr
== NULL
)
282 psattr
= *(_posix_spawnattr_t
*)attr
;
283 *sigdefault
= psattr
->psa_sigdefault
;
290 * posix_spawnattr_getpgroup
292 * Description: Obtain the value of the spawn process group attribute from the
293 * spawn attributes object referenced by 'attr' and place the
294 * results in the memory location referenced by 'pgroup'
296 * Parameters: attr The spawn attributes object whose
297 * process group information is to be
299 * pgroup A pointer to the pid_t to receive the
305 * *pgroup (modified) The process group information from the
306 * spawn attributes object
309 posix_spawnattr_getpgroup(const posix_spawnattr_t
* __restrict attr
,
310 pid_t
* __restrict pgroup
)
312 _posix_spawnattr_t psattr
;
314 if (attr
== NULL
|| *attr
== NULL
)
317 psattr
= *(_posix_spawnattr_t
*)attr
;
318 *pgroup
= psattr
->psa_pgroup
;
325 * posix_spawnattr_getsigmask
327 * Description: Obtain the value of the spawn signal mask attribute from the
328 * spawn attributes object referenced by 'attr' and place the
329 * result into the memory containing the sigset_t referenced by
332 * Parameters: attr The spawn attributes object whose
333 * signal set for masked signals is to
335 * sigmask A pointer to the sigset_t to receive
341 * *sigmask (modified) The signal set of signals to mask
342 * from the spawn attributes object
345 posix_spawnattr_getsigmask(const posix_spawnattr_t
* __restrict attr
,
346 sigset_t
* __restrict sigmask
)
348 _posix_spawnattr_t psattr
;
350 if (attr
== NULL
|| *attr
== NULL
)
353 psattr
= *(_posix_spawnattr_t
*)attr
;
354 *sigmask
= psattr
->psa_sigmask
;
360 * posix_spawnattr_getbinpref_np
362 * Description: Obtain the value of the spawn binary preferences attribute from
363 * the spawn attributes object referenced by 'attr' and place the
364 * result into the memory referenced by 'pref'.
366 * Parameters: attr The spawn attributes object whose
367 * binary preferences are to be retrieved
368 * count The size of the cpu_type_t array
369 * pref An array of cpu types
370 * ocount The actual number copied
372 * Returns: 0 No binary preferences found
373 * > 0 The number of cpu types (less than
374 * count) copied over from 'attr'.
377 * *pref (modified) The binary preferences array
378 * from the spawn attributes object
381 posix_spawnattr_getbinpref_np(const posix_spawnattr_t
* __restrict attr
,
382 size_t count
, cpu_type_t
*pref
, size_t * __restrict ocount
)
384 _posix_spawnattr_t psattr
;
387 if (attr
== NULL
|| *attr
== NULL
)
390 psattr
= *(_posix_spawnattr_t
*)attr
;
391 for (i
= 0; i
< count
&& i
< 4; i
++) {
392 pref
[i
] = psattr
->psa_binprefs
[i
];
402 * posix_spawnattr_getpcontrol_np
404 * Description: Retrieve the process control property set default according to
405 * the spawn attribute value referenced by 'attr' and place the
406 * result into the memory containing the control referenced by
409 * Parameters: attr The spawn attributes object whose
410 * signal set for default signals is to
412 * pcontrol A pointer to an int to receive
413 * the process control info
418 * *pcontrol (modified) The signal set of signals to default
419 * from the spawn attributes object
422 posix_spawnattr_getpcontrol_np(const posix_spawnattr_t
* __restrict attr
,
423 int * __restrict pcontrol
)
425 _posix_spawnattr_t psattr
;
427 if (attr
== NULL
|| *attr
== NULL
)
430 psattr
= *(_posix_spawnattr_t
*)attr
;
431 *pcontrol
= psattr
->psa_pcontrol
;
437 * posix_spawnattr_getprocesstype_np
439 * Description: Retrieve the process specific behaviors and app launch types
440 * spawn attribute value referenced by 'attr' and place the
441 * result into the memory containing the control referenced by
444 * Parameters: attr The spawn attributes object whose
445 * signal set for default signals is to
447 * proctype A pointer to an int to receive
448 * the process type info
453 * *proctype (modified) The process type set to value
454 * from the spawn attributes object
457 posix_spawnattr_getprocesstype_np(const posix_spawnattr_t
* __restrict attr
,
458 int * __restrict proctype
)
460 _posix_spawnattr_t psattr
;
462 if (attr
== NULL
|| *attr
== NULL
)
465 psattr
= *(_posix_spawnattr_t
*)attr
;
466 *proctype
= psattr
->psa_apptype
;
471 * posix_spawnattr_setsigdefault
473 * Description: Set the set of signals to be set to default for the spawn
474 * attribute value referenced by 'attr' from the memory
475 * containing the sigset_t referenced by 'sigdefault'
477 * Parameters: attr The spawn attributes object whose
478 * signal set for default signals is to
480 * sigdefault A pointer to the sigset_t from which to
481 * obtain the signal set
486 posix_spawnattr_setsigdefault(posix_spawnattr_t
* __restrict attr
,
487 const sigset_t
* __restrict sigdefault
)
489 _posix_spawnattr_t psattr
;
491 if (attr
== NULL
|| *attr
== NULL
)
494 psattr
= *(_posix_spawnattr_t
*)attr
;
495 psattr
->psa_sigdefault
= *sigdefault
;
502 * posix_spawnattr_setpgroup
504 * Description: Set the value of the spawn process group attribute for the
505 * spawn attributes object referenced by 'attr' from the value
508 * Parameters: attr The spawn attributes object for which
509 * the process group information is to be
511 * pgroup The process group to set
516 posix_spawnattr_setpgroup(posix_spawnattr_t
* attr
, pid_t pgroup
)
518 _posix_spawnattr_t psattr
;
520 if (attr
== NULL
|| *attr
== NULL
)
523 psattr
= *(_posix_spawnattr_t
*)attr
;
524 psattr
->psa_pgroup
= pgroup
;
531 * posix_spawnattr_setsigmask
533 * Description: Set the set of signals to be masked for the spawn attribute
534 * value referenced by 'attr' from the memory containing the
535 * sigset_t referenced by 'sigmask'
537 * Parameters: attr The spawn attributes object whose
538 * signal set for masked signals is to
540 * sigmask A pointer to the sigset_t from which to
541 * obtain the signal set
546 posix_spawnattr_setsigmask(posix_spawnattr_t
* __restrict attr
,
547 const sigset_t
* __restrict sigmask
)
549 _posix_spawnattr_t psattr
;
551 if (attr
== NULL
|| *attr
== NULL
)
554 psattr
= *(_posix_spawnattr_t
*)attr
;
555 psattr
->psa_sigmask
= *sigmask
;
562 * posix_spawnattr_setbinpref_np
564 * Description: Set the universal binary preferences for the spawn attribute
565 * value referenced by 'attr' from the memory containing the
566 * cpu_type_t array referenced by 'pref', size of 'count'
568 * Parameters: attr The spawn attributes object whose
569 * binary preferences are to be set
570 * count Size of the array pointed to by 'pref'
571 * pref cpu_type_t array of binary preferences
572 * ocount The actual number copied
574 * Returns: 0 No preferences copied
575 * > 0 Number of preferences copied
577 * Note: The posix_spawnattr_t currently only holds four cpu_type_t's.
578 * If the caller provides more preferences than this limit, they
579 * will be ignored, as reflected in the return value.
582 posix_spawnattr_setbinpref_np(posix_spawnattr_t
* __restrict attr
,
583 size_t count
, cpu_type_t
*pref
, size_t * __restrict ocount
)
585 _posix_spawnattr_t psattr
;
588 if (attr
== NULL
|| *attr
== NULL
)
591 psattr
= *(_posix_spawnattr_t
*)attr
;
592 for (i
= 0; i
< count
&& i
< 4; i
++) {
593 psattr
->psa_binprefs
[i
] = pref
[i
];
596 /* return number of binprefs copied over */
604 * posix_spawnattr_setpcontrol_np
606 * Description: Set the process control property according to
607 * attribute value referenced by 'attr' from the memory
608 * containing the int value 'pcontrol'
610 * Parameters: attr The spawn attributes object whose
611 * signal set for default signals is to
613 * pcontrol An int value of the process control info
618 posix_spawnattr_setpcontrol_np(posix_spawnattr_t
* __restrict attr
,
621 _posix_spawnattr_t psattr
;
623 if (attr
== NULL
|| *attr
== NULL
)
626 psattr
= *(_posix_spawnattr_t
*)attr
;
627 psattr
->psa_pcontrol
= pcontrol
;
634 * posix_spawnattr_setprocesstype_np
636 * Description: Set the process specific behaviors and app launch type
637 * attribute value referenced by 'attr' from the memory
638 * containing the int value 'proctype'
640 * Parameters: attr The spawn attributes object whose
641 * signal set for default signals is to
643 * proctype An int value of the process type info
648 posix_spawnattr_setprocesstype_np(posix_spawnattr_t
* __restrict attr
,
651 _posix_spawnattr_t psattr
;
653 if (attr
== NULL
|| *attr
== NULL
)
656 psattr
= *(_posix_spawnattr_t
*)attr
;
657 psattr
->psa_apptype
= proctype
;
663 * posix_spawn_createportactions_np
664 * Description: create a new posix_spawn_port_actions struct and link
665 * it into the posix_spawnattr.
668 posix_spawn_createportactions_np(posix_spawnattr_t
*attr
)
670 _posix_spawnattr_t psattr
;
671 _posix_spawn_port_actions_t acts
;
673 if (attr
== NULL
|| *attr
== NULL
)
676 psattr
= *(_posix_spawnattr_t
*)attr
;
677 acts
= (_posix_spawn_port_actions_t
)malloc(PS_PORT_ACTIONS_SIZE(2));
681 acts
->pspa_alloc
= 2;
682 acts
->pspa_count
= 0;
684 psattr
->psa_ports
= acts
;
689 * posix_spawn_growportactions_np
690 * Description: Enlarge the size of portactions if necessary
693 posix_spawn_growportactions_np(posix_spawnattr_t
*attr
)
695 _posix_spawnattr_t psattr
;
696 _posix_spawn_port_actions_t acts
;
699 if (attr
== NULL
|| *attr
== NULL
)
702 psattr
= *(_posix_spawnattr_t
*)attr
;
703 acts
= psattr
->psa_ports
;
707 /* Double number of port actions allocated for */
708 newnum
= 2 * acts
->pspa_alloc
;
709 acts
= realloc(acts
, PS_PORT_ACTIONS_SIZE(newnum
));
713 acts
->pspa_alloc
= newnum
;
714 psattr
->psa_ports
= acts
;
719 * posix_spawn_destroyportactions_np
720 * Description: clean up portactions struct in posix_spawnattr_t attr
723 posix_spawn_destroyportactions_np(posix_spawnattr_t
*attr
)
725 _posix_spawnattr_t psattr
;
726 _posix_spawn_port_actions_t acts
;
728 if (attr
== NULL
|| *attr
== NULL
)
731 psattr
= *(_posix_spawnattr_t
*)attr
;
732 acts
= psattr
->psa_ports
;
741 * posix_spawn_appendportaction_np
742 * Description: append a port action, grow the array if necessary
745 posix_spawn_appendportaction_np(posix_spawnattr_t
*attr
, _ps_port_action_t
*act
)
747 _posix_spawnattr_t psattr
;
748 _posix_spawn_port_actions_t acts
;
750 if (attr
== NULL
|| *attr
== NULL
|| act
== NULL
) {
754 psattr
= *(_posix_spawnattr_t
*)attr
;
755 acts
= psattr
->psa_ports
;
757 // Have any port actions been created yet?
759 int err
= posix_spawn_createportactions_np(attr
);
763 acts
= psattr
->psa_ports
;
766 // Is there enough room?
767 if (acts
->pspa_alloc
== acts
->pspa_count
) {
768 int err
= posix_spawn_growportactions_np(attr
);
772 acts
= psattr
->psa_ports
;
775 // Add this action to next spot in array
776 acts
->pspa_actions
[acts
->pspa_count
] = *act
;
783 * posix_spawnattr_setspecialport_np
785 * Description: Set a new value for a mach special port in the spawned task.
787 * Parameters: attr The spawn attributes object for the
789 * new_port The new value for the special port
790 * which The particular port to be set
791 * (see task_set_special_port for details)
794 * ENOMEM Couldn't allocate memory
797 posix_spawnattr_setspecialport_np(
798 posix_spawnattr_t
*attr
,
799 mach_port_t new_port
,
802 _ps_port_action_t action
= {
803 .port_type
= PSPA_SPECIAL
,
804 .new_port
= new_port
,
807 return posix_spawn_appendportaction_np(attr
, &action
);
811 * posix_spawnattr_setexceptionports_np
813 * Description: Set a new port for a set of exception ports in the spawned task.
815 * Parameters: attr The spawn attributes object for the
817 * mask A bitfield indicating which exceptions
818 * to associate the port with
819 * new_port The new value for the exception port
820 * behavior The default behavior for the port
821 * flavor The default flavor for the port
822 * (see task_set_exception_ports)
827 posix_spawnattr_setexceptionports_np(
828 posix_spawnattr_t
*attr
,
829 exception_mask_t mask
,
830 mach_port_t new_port
,
831 exception_behavior_t behavior
,
832 thread_state_flavor_t flavor
)
834 _ps_port_action_t action
= {
835 .port_type
= PSPA_EXCEPTION
,
837 .new_port
= new_port
,
838 .behavior
= behavior
,
841 return posix_spawn_appendportaction_np(attr
, &action
);
845 * posix_spawnattr_setauditsessionport_np
847 * Description: Set the audit session port rights attribute in the spawned task.
848 * This is used to securely set the audit session information for
851 * Parameters: attr The spawn attributes object for the
853 * au_sessionport The audit session send port right
858 posix_spawnattr_setauditsessionport_np(
859 posix_spawnattr_t
*attr
,
860 mach_port_t au_sessionport
)
862 _ps_port_action_t action
= {
863 .port_type
= PSPA_AU_SESSION
,
864 .new_port
= au_sessionport
,
866 return posix_spawn_appendportaction_np(attr
, &action
);
871 * posix_spawn_file_actions_init
873 * Description: Initialize a spawn file actions object attr with default values
875 * Parameters: file_actions The spawn file actions object to be
879 * ENOMEM Insufficient memory exists to
880 * initialize the spawn file actions
883 * Note: As an implementation detail, the externally visibily type
884 * posix_spawn_file_actions_t is defined to be a void *, and
885 * initialization involves allocation of a memory object.
886 * Subsequent changes to the spawn file actions may result in
887 * reallocation under the covers.
889 * Reinitialization of an already initialized spawn file actions
890 * object will result in memory being leaked. Because spawn
891 * file actions are not required to be used in conjunction with a
892 * static initializer, there is no way to distinguish a spawn
893 * file actions with stack garbage from one that's been
894 * initialized. This is arguably an API design error.
897 posix_spawn_file_actions_init(posix_spawn_file_actions_t
*file_actions
)
899 _posix_spawn_file_actions_t
*psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
902 if ((*psactsp
= (_posix_spawn_file_actions_t
)malloc(PSF_ACTIONS_SIZE(PSF_ACTIONS_INIT_COUNT
))) == NULL
) {
905 (*psactsp
)->psfa_act_alloc
= PSF_ACTIONS_INIT_COUNT
;
906 (*psactsp
)->psfa_act_count
= 0;
914 * posix_spawn_file_actions_destroy
916 * Description: Destroy a spawn file actions object that was previously
917 * initialized via posix_spawn_file_actions_init() by freeing any
918 * memory associated with it and setting it to an invalid value.
920 * Parameters: attr The spawn file actions object to be
925 * Notes: The destroyed spawn file actions results in the void * pointer
926 * being set to NULL; subsequent use without reinitialization
927 * will result in explicit program failure (rather than merely
928 * "undefined behaviour").
930 * NOTIMP: Allowed failures (checking NOT required):
931 * EINVAL The value specified by file_actions is invalid.
934 posix_spawn_file_actions_destroy(posix_spawn_file_actions_t
*file_actions
)
936 _posix_spawn_file_actions_t psacts
;
938 if (file_actions
== NULL
|| *file_actions
== NULL
)
941 psacts
= *(_posix_spawn_file_actions_t
*)file_actions
;
943 *file_actions
= NULL
;
950 * _posix_spawn_file_actions_grow
952 * Description: Grow the available list of file actions associated with the
953 * pointer to the structure provided; replace the contents of the
954 * pointer as a side effect.
956 * Parameters: psactsp Pointer to _posix_spawn_file_actions_t
960 * ENOMEM Insufficient memory for operation
962 * Notes: This code is common to all posix_spawn_file_actions_*()
963 * functions, since we use a naieve data structure implementation
964 * at present. Future optimization will likely change this.
967 _posix_spawn_file_actions_grow(_posix_spawn_file_actions_t
*psactsp
)
969 int new_alloc
= (*psactsp
)->psfa_act_alloc
* 2;
970 _posix_spawn_file_actions_t new_psacts
;
973 * XXX may want to impose an administrative limit here; POSIX does
974 * XXX not provide for an administrative error return in this case,
975 * XXX so it's probably acceptable to just fail catastrophically
976 * XXX instead of implementing one.
978 if ((new_psacts
= (_posix_spawn_file_actions_t
)realloc((*psactsp
), PSF_ACTIONS_SIZE(new_alloc
))) == NULL
) {
981 new_psacts
->psfa_act_alloc
= new_alloc
;
982 *psactsp
= new_psacts
;
989 * posix_spawn_file_actions_addopen
991 * Description: Add an open action to the object referenced by 'file_actions'
992 * that will cause the file named by 'path' to be attempted to be
993 * opened with flags 'oflag' and mode 'mode', and, if successful,
994 * return as descriptor 'filedes' to the spawned process.
996 * Parameters: file_actions File action object to augment
997 * filedes fd that open is to use
998 * path path to file to open
999 * oflag open file flags
1000 * mode open file mode
1002 * Returns: 0 Success
1003 * EBADF The value specified by fildes is
1004 * negative or greater than or equal to
1006 * ENOMEM Insufficient memory exists to add to
1007 * the spawn file actions object.
1009 * NOTIMP: Allowed failures (checking NOT required):
1010 * EINVAL The value specified by file_actions is invalid.
1013 posix_spawn_file_actions_addopen(
1014 posix_spawn_file_actions_t
* __restrict file_actions
,
1015 int filedes
, const char * __restrict path
, int oflag
,
1018 _posix_spawn_file_actions_t
*psactsp
;
1019 _psfa_action_t
*psfileact
;
1021 if (file_actions
== NULL
|| *file_actions
== NULL
)
1024 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1025 /* Range check; required by POSIX */
1026 if (filedes
< 0 || filedes
>= OPEN_MAX
)
1029 /* If we do not have enough slots, grow the structure */
1030 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1031 /* need to grow file actions structure */
1032 if (_posix_spawn_file_actions_grow(psactsp
))
1037 * Allocate next available slot and fill it out
1039 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1041 psfileact
->psfaa_type
= PSFA_OPEN
;
1042 psfileact
->psfaa_filedes
= filedes
;
1043 psfileact
->psfaa_openargs
.psfao_oflag
= oflag
;
1044 psfileact
->psfaa_openargs
.psfao_mode
= mode
;
1045 strlcpy(psfileact
->psfaa_openargs
.psfao_path
, path
, PATH_MAX
);
1052 * posix_spawn_file_actions_addclose
1054 * Description: Add a close action to the object referenced by 'file_actions'
1055 * that will cause the file referenced by 'filedes' to be
1056 * attempted to be closed in the spawned process.
1058 * Parameters: file_actions File action object to augment
1059 * filedes fd to close
1061 * Returns: 0 Success
1062 * EBADF The value specified by fildes is
1063 * negative or greater than or equal to
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_addclose(posix_spawn_file_actions_t
*file_actions
,
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
)
1086 /* If we do not have enough slots, grow the structure */
1087 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1088 /* need to grow file actions structure */
1089 if (_posix_spawn_file_actions_grow(psactsp
))
1094 * Allocate next available slot and fill it out
1096 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1098 psfileact
->psfaa_type
= PSFA_CLOSE
;
1099 psfileact
->psfaa_filedes
= filedes
;
1106 * posix_spawn_file_actions_adddup2
1108 * Description: Add a dup2 action to the object referenced by 'file_actions'
1109 * that will cause the file referenced by 'filedes' to be
1110 * attempted to be dup2'ed to the descriptor 'newfiledes' in the
1113 * Parameters: file_actions File action object to augment
1114 * filedes fd to dup2
1115 * newfiledes fd to dup2 it to
1117 * Returns: 0 Success
1118 * EBADF The value specified by either fildes
1119 * or by newfiledes is negative or greater
1120 * than or equal to {OPEN_MAX}.
1121 * ENOMEM Insufficient memory exists to add to
1122 * the spawn file actions object.
1124 * NOTIMP: Allowed failures (checking NOT required):
1125 * EINVAL The value specified by file_actions is invalid.
1128 posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t
*file_actions
,
1129 int filedes
, int newfiledes
)
1131 _posix_spawn_file_actions_t
*psactsp
;
1132 _psfa_action_t
*psfileact
;
1134 if (file_actions
== NULL
|| *file_actions
== NULL
)
1137 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1138 /* Range check; required by POSIX */
1139 if (filedes
< 0 || filedes
>= OPEN_MAX
||
1140 newfiledes
< 0 || newfiledes
>= OPEN_MAX
)
1143 /* If we do not have enough slots, grow the structure */
1144 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1145 /* need to grow file actions structure */
1146 if (_posix_spawn_file_actions_grow(psactsp
))
1151 * Allocate next available slot and fill it out
1153 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1155 psfileact
->psfaa_type
= PSFA_DUP2
;
1156 psfileact
->psfaa_filedes
= filedes
;
1157 psfileact
->psfaa_openargs
.psfao_oflag
= newfiledes
;
1163 * posix_spawn_file_actions_addinherit_np
1165 * Description: Add the "inherit" action to the object referenced by
1166 * 'file_actions' that will cause the file referenced by
1167 * 'filedes' to continue to be available in the spawned
1168 * process via the same descriptor.
1170 * Inheritance is the normal default behaviour for
1171 * file descriptors across exec and spawn; but if the
1172 * POSIX_SPAWN_CLOEXEC_DEFAULT flag is set, the usual
1173 * default is reversed for the purposes of the spawn
1174 * invocation. Any pre-existing descriptors that
1175 * need to be made available to the spawned process can
1176 * be marked explicitly as 'inherit' via this interface.
1177 * Otherwise they will be automatically closed.
1179 * Note that any descriptors created via the other file
1180 * actions interfaces are automatically marked as 'inherit'.
1182 * Parameters: file_actions File action object to augment
1183 * filedes fd to inherit.
1185 * Returns: 0 Success
1186 * EBADF The value specified by fildes is
1187 * negative or greater than or equal to
1189 * ENOMEM Insufficient memory exists to add to
1190 * the spawn file actions object.
1192 * NOTIMP: Allowed failures (checking NOT required):
1193 * EINVAL The value specified by file_actions is invalid.
1196 posix_spawn_file_actions_addinherit_np(posix_spawn_file_actions_t
*file_actions
,
1199 _posix_spawn_file_actions_t
*psactsp
;
1200 _psfa_action_t
*psfileact
;
1202 if (file_actions
== NULL
|| *file_actions
== NULL
)
1205 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1206 /* Range check; required by POSIX */
1207 if (filedes
< 0 || filedes
>= OPEN_MAX
)
1210 #if defined(POSIX_SPAWN_CLOEXEC_DEFAULT) // TODO: delete this check
1211 /* If we do not have enough slots, grow the structure */
1212 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1213 /* need to grow file actions structure */
1214 if (_posix_spawn_file_actions_grow(psactsp
))
1219 * Allocate next available slot and fill it out
1221 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1223 psfileact
->psfaa_type
= PSFA_INHERIT
;
1224 psfileact
->psfaa_filedes
= filedes
;
1230 posix_spawnattr_setcpumonitor_default(posix_spawnattr_t
* __restrict attr
)
1232 return (posix_spawnattr_setcpumonitor(attr
, PROC_POLICY_CPUMON_DEFAULTS
, 0));
1236 posix_spawnattr_setcpumonitor(posix_spawnattr_t
* __restrict attr
,
1237 uint64_t percent
, uint64_t interval
)
1239 _posix_spawnattr_t psattr
;
1241 if (attr
== NULL
|| *attr
== NULL
)
1244 psattr
= *(_posix_spawnattr_t
*)attr
;
1246 psattr
->psa_cpumonitor_percent
= percent
;
1247 psattr
->psa_cpumonitor_interval
= interval
;
1253 posix_spawnattr_getcpumonitor(posix_spawnattr_t
* __restrict attr
,
1254 uint64_t *percent
, uint64_t *interval
)
1256 _posix_spawnattr_t psattr
;
1258 if (attr
== NULL
|| *attr
== NULL
)
1261 psattr
= *(_posix_spawnattr_t
*)attr
;
1263 *percent
= psattr
->psa_cpumonitor_percent
;
1264 *interval
= psattr
->psa_cpumonitor_interval
;
1269 #if TARGET_OS_EMBEDDED
1271 * posix_spawnattr_setjetsam
1273 * Description: Set jetsam attributes for the spawn attribute object
1274 * referred to by 'attr'.
1276 * Parameters: flags The flags value to set
1277 * priority Relative jetsam priority
1278 * high_water_mark Value in pages; resident page
1279 * counts above this level can
1280 * result in termination
1282 * Returns: 0 Success
1285 posix_spawnattr_setjetsam(posix_spawnattr_t
* __restrict attr
,
1286 short flags
, int priority
, int high_water_mark
)
1288 _posix_spawnattr_t psattr
;
1290 if (attr
== NULL
|| *attr
== NULL
)
1293 psattr
= *(_posix_spawnattr_t
*)attr
;
1295 psattr
->psa_jetsam_flags
= flags
;
1296 psattr
->psa_jetsam_flags
|= POSIX_SPAWN_JETSAM_SET
;
1297 psattr
->psa_priority
= priority
;
1298 psattr
->psa_high_water_mark
= high_water_mark
;
1306 * posix_spawnattr_set_importancewatch_port_np
1308 * Description: Mark ports referred to by these rights
1309 * to boost the new task instead of their current task
1310 * for the spawn attribute object referred to by 'attr'.
1311 * Ports must be valid at posix_spawn time. They will NOT be
1312 * consumed by the kernel, so they must be deallocated after the spawn returns.
1313 * (If you are SETEXEC-ing, they are cleaned up by the exec operation).
1315 * The maximum number of watch ports allowed is defined by POSIX_SPAWN_IMPORTANCE_PORT_COUNT.
1317 * Parameters: count Number of ports in portarray
1318 * portarray Array of rights
1320 * Returns: 0 Success
1321 * EINVAL Bad port count
1322 * ENOMEM Insufficient memory exists to add to
1323 * the spawn port actions object.
1326 posix_spawnattr_set_importancewatch_port_np(posix_spawnattr_t
* __restrict attr
,
1327 int count
, mach_port_t portarray
[])
1331 if (count
< 0 || count
> POSIX_SPAWN_IMPORTANCE_PORT_COUNT
) {
1335 for (i
= 0; i
< count
; i
++) {
1336 _ps_port_action_t action
= {
1337 .port_type
= PSPA_IMP_WATCHPORTS
,
1338 .new_port
= portarray
[i
],
1340 int err
= posix_spawn_appendportaction_np(attr
, &action
);
1351 _ps_mac_policy_extension_t
*
1352 posix_spawnattr_macpolicyinfo_lookup(_posix_spawn_mac_policy_extensions_t psmx
, const char *policyname
)
1359 for (i
= 0; i
< psmx
->psmx_count
; i
++) {
1360 _ps_mac_policy_extension_t
*extension
= &psmx
->psmx_extensions
[i
];
1361 if (strcmp(extension
->policyname
, policyname
) == 0)
1368 posix_spawnattr_getmacpolicyinfo_np(const posix_spawnattr_t
* __restrict attr
,
1369 const char *policyname
, void **datap
, size_t *datalenp
)
1371 _posix_spawnattr_t psattr
;
1372 _ps_mac_policy_extension_t
*extension
;
1374 if (attr
== NULL
|| *attr
== NULL
|| policyname
== NULL
|| datap
== NULL
)
1377 psattr
= *(_posix_spawnattr_t
*)attr
;
1378 extension
= posix_spawnattr_macpolicyinfo_lookup(psattr
->psa_mac_extensions
, policyname
);
1379 if (extension
== NULL
)
1381 *datap
= (void *)(uintptr_t)extension
->data
;
1382 if (datalenp
!= NULL
)
1383 *datalenp
= extension
->datalen
;
1388 posix_spawnattr_setmacpolicyinfo_np(posix_spawnattr_t
* __restrict attr
,
1389 const char *policyname
, void *data
, size_t datalen
)
1391 _posix_spawnattr_t psattr
;
1392 _posix_spawn_mac_policy_extensions_t psmx
;
1393 _ps_mac_policy_extension_t
*extension
;
1395 if (attr
== NULL
|| *attr
== NULL
|| policyname
== NULL
)
1398 psattr
= *(_posix_spawnattr_t
*)attr
;
1399 psmx
= psattr
->psa_mac_extensions
;
1400 extension
= posix_spawnattr_macpolicyinfo_lookup(psattr
->psa_mac_extensions
, policyname
);
1401 if (extension
!= NULL
) {
1402 extension
->data
= (uintptr_t)data
;
1403 extension
->datalen
= datalen
;
1406 else if (psmx
== NULL
) {
1407 psmx
= psattr
->psa_mac_extensions
= malloc(PS_MAC_EXTENSIONS_SIZE(PS_MAC_EXTENSIONS_INIT_COUNT
));
1410 psmx
->psmx_alloc
= PS_MAC_EXTENSIONS_INIT_COUNT
;
1411 psmx
->psmx_count
= 0;
1413 else if (psmx
->psmx_count
== psmx
->psmx_alloc
) {
1414 psmx
= psattr
->psa_mac_extensions
= reallocf(psmx
, PS_MAC_EXTENSIONS_SIZE(psmx
->psmx_alloc
* 2));
1417 psmx
->psmx_alloc
*= 2;
1419 extension
= &psmx
->psmx_extensions
[psmx
->psmx_count
];
1420 strlcpy(extension
->policyname
, policyname
, sizeof(extension
->policyname
));
1421 extension
->data
= (uintptr_t)data
;
1422 extension
->datalen
= datalen
;
1423 psmx
->psmx_count
+= 1;
1430 * Description: Create a new process from the process image corresponding to
1431 * the supplied 'path' argument.
1433 * Parameters: pid Pointer to pid_t to receive the
1434 * PID of the spawned process, if
1435 * successful and 'pid' != NULL
1436 * path Path of image file to spawn
1437 * file_actions spawn file actions object which
1438 * describes file actions to be
1439 * performed during the spawn
1440 * attrp spawn attributes object which
1441 * describes attributes to be
1442 * applied during the spawn
1443 * argv argument vector array; NULL
1445 * envp environment vector array; NULL
1448 * Returns: 0 Success
1449 * !0 An errno value indicating the
1450 * cause of the failure to spawn
1452 * Notes: Unlike other system calls, the return value of this system
1453 * call is expected to either be a 0 or an errno, rather than a
1454 * 0 or a -1, with the 'errno' variable being set.
1456 extern int __posix_spawn(pid_t
* __restrict
, const char * __restrict
,
1457 struct _posix_spawn_args_desc
*,
1458 char *const argv
[ __restrict
], char *const envp
[ __restrict
]);
1461 posix_spawn(pid_t
* __restrict pid
, const char * __restrict path
,
1462 const posix_spawn_file_actions_t
*file_actions
,
1463 const posix_spawnattr_t
* __restrict attrp
,
1464 char *const argv
[ __restrict
], char *const envp
[ __restrict
])
1466 int saveerrno
= errno
;
1469 * Only do extra work if we have file actions or attributes to push
1470 * down. We use a descriptor to push this information down, since we
1471 * want to have size information, which will let us (1) preallocate a
1472 * single chunk of memory for the copyin(), and (2) allow us to do a
1473 * single copyin() per attributes or file actions as a monlithic block.
1475 * Note: A future implementation may attempt to do the same
1476 * thing for the argv/envp data, which could potentially
1477 * result in a performance improvement due to increased
1478 * kernel efficiency, even though it would mean copying
1479 * the data in user space.
1481 if ((file_actions
!= NULL
&& (*file_actions
!= NULL
) && (*(_posix_spawn_file_actions_t
*)file_actions
)->psfa_act_count
> 0) || attrp
!= NULL
) {
1482 struct _posix_spawn_args_desc ad
;
1484 memset(&ad
, 0, sizeof(ad
));
1485 if (attrp
!= NULL
&& *attrp
!= NULL
) {
1486 _posix_spawnattr_t psattr
= *(_posix_spawnattr_t
*)attrp
;
1487 ad
.attr_size
= sizeof(struct _posix_spawnattr
);
1490 if (psattr
->psa_ports
!= NULL
) {
1491 ad
.port_actions
= psattr
->psa_ports
;
1492 ad
.port_actions_size
= PS_PORT_ACTIONS_SIZE(
1493 ad
.port_actions
->pspa_count
);
1495 if (psattr
->psa_mac_extensions
!= NULL
) {
1496 ad
.mac_extensions
= psattr
->psa_mac_extensions
;
1497 ad
.mac_extensions_size
= PS_MAC_EXTENSIONS_SIZE(
1498 ad
.mac_extensions
->psmx_count
);
1501 if (file_actions
!= NULL
&& *file_actions
!= NULL
) {
1502 _posix_spawn_file_actions_t psactsp
=
1503 *(_posix_spawn_file_actions_t
*)file_actions
;
1505 if (psactsp
->psfa_act_count
> 0) {
1506 ad
.file_actions_size
= PSF_ACTIONS_SIZE(psactsp
->psfa_act_count
);
1507 ad
.file_actions
= psactsp
;
1511 ret
= __posix_spawn(pid
, path
, &ad
, argv
, envp
);
1513 ret
= __posix_spawn(pid
, path
, NULL
, argv
, envp
);