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>
41 #include <mach/coalition.h> /* for COALITION_TYPE_MAX */
45 * posix_spawnattr_init
47 * Description: Initialize a spawn attributes object attr with default values
49 * Parameters: attr The spawn attributes object to be
53 * ENOMEM Insufficient memory exists to
54 * initialize the spawn attributes object.
56 * Note: As an implementation detail, the externally visibily type
57 * posix_spawnattr_t is defined to be a void *, and initialization
58 * involves allocation of a memory object. Subsequent changes to
59 * the spawn attributes may result in reallocation under the
62 * Reinitialization of an already initialized spawn attributes
63 * object will result in memory being leaked. Because spawn
64 * attributes are not required to be used in conjunction with a
65 * static initializer, there is no way to distinguish a spawn
66 * attribute with stack garbage from one that's been initialized.
67 * This is arguably an API design error.
70 posix_spawnattr_init(posix_spawnattr_t
*attr
)
72 _posix_spawnattr_t
*psattrp
= (_posix_spawnattr_t
*)attr
;
75 if ((*psattrp
= (_posix_spawnattr_t
)malloc(sizeof(struct _posix_spawnattr
))) == NULL
) {
80 * The default value of this attribute shall be as if no
83 (*psattrp
)->psa_flags
= 0;
86 * The default value of this attribute shall be an empty
89 (*psattrp
)->psa_sigdefault
= 0;
91 /* The default value of this attribute is unspecified */
92 (*psattrp
)->psa_sigmask
= 0;
94 /* The default value of this attribute shall be zero */
95 (*psattrp
)->psa_pgroup
= 0; /* doesn't matter */
97 /* Default is no binary preferences, i.e. use normal grading */
98 memset((*psattrp
)->psa_binprefs
, 0,
99 sizeof((*psattrp
)->psa_binprefs
));
101 /* Default is no port actions to take */
102 (*psattrp
)->psa_ports
= NULL
;
105 * The default value of this attribute shall be an no
106 * process control on resource starvation
108 (*psattrp
)->psa_pcontrol
= 0;
111 * Initializing the alignment paddings.
114 (*psattrp
)->short_padding
= 0;
115 (*psattrp
)->flags_padding
= 0;
117 /* Default is no new apptype requested */
118 (*psattrp
)->psa_apptype
= POSIX_SPAWN_PROCESS_TYPE_DEFAULT
;
121 (*psattrp
)->psa_jetsam_flags
= 0;
122 (*psattrp
)->psa_priority
= -1;
123 (*psattrp
)->psa_memlimit_active
= -1;
124 (*psattrp
)->psa_memlimit_inactive
= -1;
126 /* Default is no CPU usage monitor active. */
127 (*psattrp
)->psa_cpumonitor_percent
= 0;
128 (*psattrp
)->psa_cpumonitor_interval
= 0;
130 /* Default is no MAC policy extensions. */
131 (*psattrp
)->psa_mac_extensions
= NULL
;
133 /* Default is to inherit parent's coalition(s) */
134 (*psattrp
)->psa_coalition_info
= NULL
;
136 (*psattrp
)->reserved
= NULL
;
139 * old coalition field
140 * For backwards compatibility reasons, we set this to 1
141 * which is the first valid coalition id. This will allow
142 * newer user space code to properly spawn processes on
144 * (they will just all end up in the same coalition).
146 (*psattrp
)->psa_reserved
= 1;
148 /* Default is no new clamp */
149 (*psattrp
)->psa_qos_clamp
= POSIX_SPAWN_PROC_CLAMP_NONE
;
151 /* Default is no change to role */
152 (*psattrp
)->psa_darwin_role
= POSIX_SPAWN_DARWIN_ROLE_NONE
;
160 * posix_spawnattr_destroy
162 * Description: Destroy a spawn attributes object that was previously
163 * initialized via posix_spawnattr_init() by freeing any
164 * memory associated with it and setting it to an invalid value.
166 * Parameters: attr The spawn attributes object to be
171 * Notes: The destroyed spawn attribute results in the void * pointer
172 * being set to NULL; subsequent use without reinitialization
173 * will result in explicit program failure (rather than merely
174 * "undefined behaviour").
176 * NOTIMP: Allowed failures (checking NOT required):
177 * EINVAL The value specified by attr is invalid.
179 static int posix_spawn_destroyportactions_np(posix_spawnattr_t
*);
180 static int posix_spawn_destroycoalition_info_np(posix_spawnattr_t
*);
184 posix_spawnattr_destroy(posix_spawnattr_t
*attr
)
186 _posix_spawnattr_t psattr
;
188 if (attr
== NULL
|| *attr
== NULL
)
191 psattr
= *(_posix_spawnattr_t
*)attr
;
192 posix_spawn_destroyportactions_np(attr
);
193 posix_spawn_destroycoalition_info_np(attr
);
203 * posix_spawnattr_setflags
205 * Description: Set the spawn flags attribute for the spawn attribute object
206 * referred to by 'attr'.
208 * Parameters: attr The spawn attributes object whose flags
210 * flags The flags value to set
214 * NOTIMP: Allowed failures (checking NOT required):
215 * EINVAL The value specified by attr is invalid.
216 * EINVAL The value of the attribute being set is not valid.
219 posix_spawnattr_setflags(posix_spawnattr_t
*attr
, short flags
)
221 _posix_spawnattr_t psattr
;
223 if (attr
== NULL
|| *attr
== NULL
)
226 psattr
= *(_posix_spawnattr_t
*)attr
;
227 psattr
->psa_flags
= flags
;
234 * posix_spawnattr_getflags
236 * Description: Retrieve the spawn attributes flag for the spawn attributes
237 * object referenced by 'attr' and place them in the memory
238 * location referenced by 'flagsp'
240 * Parameters: attr The spawn attributes object whose flags
241 * are to be retrieved
242 * flagsp A pointer to a short value to receive
248 * *flagps (modified) The flags value from the spawn
251 * NOTIMP: Allowed failures (checking NOT required):
252 * EINVAL The value specified by attr is invalid.
253 * EINVAL The value of the attribute being set is not valid.
256 posix_spawnattr_getflags(const posix_spawnattr_t
* __restrict attr
,
257 short * __restrict flagsp
)
259 _posix_spawnattr_t psattr
;
261 if (attr
== NULL
|| *attr
== NULL
)
264 psattr
= *(_posix_spawnattr_t
*)attr
;
265 *flagsp
= psattr
->psa_flags
;
272 * posix_spawnattr_getsigdefault
274 * Description: Retrieve the set of signals to be set to default according to
275 * the spawn attribute value referenced by 'attr' and place the
276 * result into the memory containing the sigset_t referenced by
279 * Parameters: attr The spawn attributes object whose
280 * signal set for default signals is to
282 * sigdefault A pointer to the sigset_t to receive
288 * *sigdefault (modified) The signal set of signals to default
289 * from the spawn attributes object
292 posix_spawnattr_getsigdefault(const posix_spawnattr_t
* __restrict attr
,
293 sigset_t
* __restrict sigdefault
)
295 _posix_spawnattr_t psattr
;
297 if (attr
== NULL
|| *attr
== NULL
)
300 psattr
= *(_posix_spawnattr_t
*)attr
;
301 *sigdefault
= psattr
->psa_sigdefault
;
308 * posix_spawnattr_getpgroup
310 * Description: Obtain the value of the spawn process group attribute from the
311 * spawn attributes object referenced by 'attr' and place the
312 * results in the memory location referenced by 'pgroup'
314 * Parameters: attr The spawn attributes object whose
315 * process group information is to be
317 * pgroup A pointer to the pid_t to receive the
323 * *pgroup (modified) The process group information from the
324 * spawn attributes object
327 posix_spawnattr_getpgroup(const posix_spawnattr_t
* __restrict attr
,
328 pid_t
* __restrict pgroup
)
330 _posix_spawnattr_t psattr
;
332 if (attr
== NULL
|| *attr
== NULL
)
335 psattr
= *(_posix_spawnattr_t
*)attr
;
336 *pgroup
= psattr
->psa_pgroup
;
343 * posix_spawnattr_getsigmask
345 * Description: Obtain the value of the spawn signal mask attribute from the
346 * spawn attributes object referenced by 'attr' and place the
347 * result into the memory containing the sigset_t referenced by
350 * Parameters: attr The spawn attributes object whose
351 * signal set for masked signals is to
353 * sigmask A pointer to the sigset_t to receive
359 * *sigmask (modified) The signal set of signals to mask
360 * from the spawn attributes object
363 posix_spawnattr_getsigmask(const posix_spawnattr_t
* __restrict attr
,
364 sigset_t
* __restrict sigmask
)
366 _posix_spawnattr_t psattr
;
368 if (attr
== NULL
|| *attr
== NULL
)
371 psattr
= *(_posix_spawnattr_t
*)attr
;
372 *sigmask
= psattr
->psa_sigmask
;
378 * posix_spawnattr_getbinpref_np
380 * Description: Obtain the value of the spawn binary preferences attribute from
381 * the spawn attributes object referenced by 'attr' and place the
382 * result into the memory referenced by 'pref'.
384 * Parameters: attr The spawn attributes object whose
385 * binary preferences are to be retrieved
386 * count The size of the cpu_type_t array
387 * pref An array of cpu types
388 * ocount The actual number copied
390 * Returns: 0 No binary preferences found
391 * > 0 The number of cpu types (less than
392 * count) copied over from 'attr'.
395 * *pref (modified) The binary preferences array
396 * from the spawn attributes object
399 posix_spawnattr_getbinpref_np(const posix_spawnattr_t
* __restrict attr
,
400 size_t count
, cpu_type_t
*pref
, size_t * __restrict ocount
)
402 _posix_spawnattr_t psattr
;
405 if (attr
== NULL
|| *attr
== NULL
)
408 psattr
= *(_posix_spawnattr_t
*)attr
;
409 for (i
= 0; i
< count
&& i
< 4; i
++) {
410 pref
[i
] = psattr
->psa_binprefs
[i
];
420 * posix_spawnattr_getpcontrol_np
422 * Description: Retrieve the process control property set default according to
423 * the spawn attribute value referenced by 'attr' and place the
424 * result into the memory containing the control referenced by
427 * Parameters: attr The spawn attributes object whose
428 * signal set for default signals is to
430 * pcontrol A pointer to an int to receive
431 * the process control info
436 * *pcontrol (modified) The signal set of signals to default
437 * from the spawn attributes object
440 posix_spawnattr_getpcontrol_np(const posix_spawnattr_t
* __restrict attr
,
441 int * __restrict pcontrol
)
443 _posix_spawnattr_t psattr
;
445 if (attr
== NULL
|| *attr
== NULL
)
448 psattr
= *(_posix_spawnattr_t
*)attr
;
449 *pcontrol
= psattr
->psa_pcontrol
;
455 * posix_spawnattr_getprocesstype_np
457 * Description: Retrieve the process specific behaviors and app launch types
458 * spawn attribute value referenced by 'attr' and place the
459 * result into the memory containing the control referenced by
462 * Parameters: attr The spawn attributes object whose
463 * signal set for default signals is to
465 * proctype A pointer to an int to receive
466 * the process type info
471 * *proctype (modified) The process type set to value
472 * from the spawn attributes object
475 posix_spawnattr_getprocesstype_np(const posix_spawnattr_t
* __restrict attr
,
476 int * __restrict proctype
)
478 _posix_spawnattr_t psattr
;
480 if (attr
== NULL
|| *attr
== NULL
)
483 psattr
= *(_posix_spawnattr_t
*)attr
;
484 *proctype
= psattr
->psa_apptype
;
489 * posix_spawnattr_setsigdefault
491 * Description: Set the set of signals to be set to default for the spawn
492 * attribute value referenced by 'attr' from the memory
493 * containing the sigset_t referenced by 'sigdefault'
495 * Parameters: attr The spawn attributes object whose
496 * signal set for default signals is to
498 * sigdefault A pointer to the sigset_t from which to
499 * obtain the signal set
504 posix_spawnattr_setsigdefault(posix_spawnattr_t
* __restrict attr
,
505 const sigset_t
* __restrict sigdefault
)
507 _posix_spawnattr_t psattr
;
509 if (attr
== NULL
|| *attr
== NULL
)
512 psattr
= *(_posix_spawnattr_t
*)attr
;
513 psattr
->psa_sigdefault
= *sigdefault
;
520 * posix_spawnattr_setpgroup
522 * Description: Set the value of the spawn process group attribute for the
523 * spawn attributes object referenced by 'attr' from the value
526 * Parameters: attr The spawn attributes object for which
527 * the process group information is to be
529 * pgroup The process group to set
534 posix_spawnattr_setpgroup(posix_spawnattr_t
* attr
, pid_t pgroup
)
536 _posix_spawnattr_t psattr
;
538 if (attr
== NULL
|| *attr
== NULL
)
541 psattr
= *(_posix_spawnattr_t
*)attr
;
542 psattr
->psa_pgroup
= pgroup
;
549 * posix_spawnattr_setsigmask
551 * Description: Set the set of signals to be masked for the spawn attribute
552 * value referenced by 'attr' from the memory containing the
553 * sigset_t referenced by 'sigmask'
555 * Parameters: attr The spawn attributes object whose
556 * signal set for masked signals is to
558 * sigmask A pointer to the sigset_t from which to
559 * obtain the signal set
564 posix_spawnattr_setsigmask(posix_spawnattr_t
* __restrict attr
,
565 const sigset_t
* __restrict sigmask
)
567 _posix_spawnattr_t psattr
;
569 if (attr
== NULL
|| *attr
== NULL
)
572 psattr
= *(_posix_spawnattr_t
*)attr
;
573 psattr
->psa_sigmask
= *sigmask
;
580 * posix_spawnattr_setbinpref_np
582 * Description: Set the universal binary preferences for the spawn attribute
583 * value referenced by 'attr' from the memory containing the
584 * cpu_type_t array referenced by 'pref', size of 'count'
586 * Parameters: attr The spawn attributes object whose
587 * binary preferences are to be set
588 * count Size of the array pointed to by 'pref'
589 * pref cpu_type_t array of binary preferences
590 * ocount The actual number copied
592 * Returns: 0 No preferences copied
593 * > 0 Number of preferences copied
595 * Note: The posix_spawnattr_t currently only holds four cpu_type_t's.
596 * If the caller provides more preferences than this limit, they
597 * will be ignored, as reflected in the return value.
600 posix_spawnattr_setbinpref_np(posix_spawnattr_t
* __restrict attr
,
601 size_t count
, cpu_type_t
*pref
, size_t * __restrict ocount
)
603 _posix_spawnattr_t psattr
;
606 if (attr
== NULL
|| *attr
== NULL
)
609 psattr
= *(_posix_spawnattr_t
*)attr
;
610 for (i
= 0; i
< count
&& i
< 4; i
++) {
611 psattr
->psa_binprefs
[i
] = pref
[i
];
614 /* return number of binprefs copied over */
622 * posix_spawnattr_setpcontrol_np
624 * Description: Set the process control property according to
625 * attribute value referenced by 'attr' from the memory
626 * containing the int value 'pcontrol'
628 * Parameters: attr The spawn attributes object whose
629 * signal set for default signals is to
631 * pcontrol An int value of the process control info
636 posix_spawnattr_setpcontrol_np(posix_spawnattr_t
* __restrict attr
,
639 _posix_spawnattr_t psattr
;
641 if (attr
== NULL
|| *attr
== NULL
)
644 psattr
= *(_posix_spawnattr_t
*)attr
;
645 psattr
->psa_pcontrol
= pcontrol
;
652 * posix_spawnattr_setprocesstype_np
654 * Description: Set the process specific behaviors and app launch type
655 * attribute value referenced by 'attr' from the memory
656 * containing the int value 'proctype'
658 * Parameters: attr The spawn attributes object whose
659 * signal set for default signals is to
661 * proctype An int value of the process type info
666 posix_spawnattr_setprocesstype_np(posix_spawnattr_t
* __restrict attr
,
669 _posix_spawnattr_t psattr
;
671 if (attr
== NULL
|| *attr
== NULL
)
674 psattr
= *(_posix_spawnattr_t
*)attr
;
675 psattr
->psa_apptype
= proctype
;
681 * posix_spawn_createportactions_np
682 * Description: create a new posix_spawn_port_actions struct and link
683 * it into the posix_spawnattr.
686 posix_spawn_createportactions_np(posix_spawnattr_t
*attr
)
688 _posix_spawnattr_t psattr
;
689 _posix_spawn_port_actions_t acts
;
691 if (attr
== NULL
|| *attr
== NULL
)
694 psattr
= *(_posix_spawnattr_t
*)attr
;
695 acts
= (_posix_spawn_port_actions_t
)malloc(PS_PORT_ACTIONS_SIZE(2));
699 acts
->pspa_alloc
= 2;
700 acts
->pspa_count
= 0;
702 psattr
->psa_ports
= acts
;
707 * posix_spawn_growportactions_np
708 * Description: Enlarge the size of portactions if necessary
711 posix_spawn_growportactions_np(posix_spawnattr_t
*attr
)
713 _posix_spawnattr_t psattr
;
714 _posix_spawn_port_actions_t acts
;
717 if (attr
== NULL
|| *attr
== NULL
)
720 psattr
= *(_posix_spawnattr_t
*)attr
;
721 acts
= psattr
->psa_ports
;
725 /* Double number of port actions allocated for */
726 newnum
= 2 * acts
->pspa_alloc
;
727 acts
= realloc(acts
, PS_PORT_ACTIONS_SIZE(newnum
));
731 acts
->pspa_alloc
= newnum
;
732 psattr
->psa_ports
= acts
;
737 * posix_spawn_destroyportactions_np
738 * Description: clean up portactions struct in posix_spawnattr_t attr
741 posix_spawn_destroyportactions_np(posix_spawnattr_t
*attr
)
743 _posix_spawnattr_t psattr
;
744 _posix_spawn_port_actions_t acts
;
746 if (attr
== NULL
|| *attr
== NULL
)
749 psattr
= *(_posix_spawnattr_t
*)attr
;
750 acts
= psattr
->psa_ports
;
759 * posix_spawn_destroycoalition_info_np
760 * Description: clean up coalition_info struct in posix_spawnattr_t attr
763 posix_spawn_destroycoalition_info_np(posix_spawnattr_t
*attr
)
765 _posix_spawnattr_t psattr
;
766 struct _posix_spawn_coalition_info
*coal_info
;
768 if (attr
== NULL
|| *attr
== NULL
)
771 psattr
= *(_posix_spawnattr_t
*)attr
;
772 coal_info
= psattr
->psa_coalition_info
;
773 if (coal_info
== NULL
)
776 psattr
->psa_coalition_info
= NULL
;
782 * posix_spawn_appendportaction_np
783 * Description: append a port action, grow the array if necessary
786 posix_spawn_appendportaction_np(posix_spawnattr_t
*attr
, _ps_port_action_t
*act
)
788 _posix_spawnattr_t psattr
;
789 _posix_spawn_port_actions_t acts
;
791 if (attr
== NULL
|| *attr
== NULL
|| act
== NULL
) {
795 psattr
= *(_posix_spawnattr_t
*)attr
;
796 acts
= psattr
->psa_ports
;
798 // Have any port actions been created yet?
800 int err
= posix_spawn_createportactions_np(attr
);
804 acts
= psattr
->psa_ports
;
807 // Is there enough room?
808 if (acts
->pspa_alloc
== acts
->pspa_count
) {
809 int err
= posix_spawn_growportactions_np(attr
);
813 acts
= psattr
->psa_ports
;
816 // Add this action to next spot in array
817 acts
->pspa_actions
[acts
->pspa_count
] = *act
;
824 * posix_spawnattr_setspecialport_np
826 * Description: Set a new value for a mach special port in the spawned task.
828 * Parameters: attr The spawn attributes object for the
830 * new_port The new value for the special port
831 * which The particular port to be set
832 * (see task_set_special_port for details)
835 * ENOMEM Couldn't allocate memory
838 posix_spawnattr_setspecialport_np(
839 posix_spawnattr_t
*attr
,
840 mach_port_t new_port
,
843 _ps_port_action_t action
= {
844 .port_type
= PSPA_SPECIAL
,
845 .new_port
= new_port
,
848 return posix_spawn_appendportaction_np(attr
, &action
);
852 * posix_spawnattr_setexceptionports_np
854 * Description: Set a new port for a set of exception ports in the spawned task.
856 * Parameters: attr The spawn attributes object for the
858 * mask A bitfield indicating which exceptions
859 * to associate the port with
860 * new_port The new value for the exception port
861 * behavior The default behavior for the port
862 * flavor The default flavor for the port
863 * (see task_set_exception_ports)
868 posix_spawnattr_setexceptionports_np(
869 posix_spawnattr_t
*attr
,
870 exception_mask_t mask
,
871 mach_port_t new_port
,
872 exception_behavior_t behavior
,
873 thread_state_flavor_t flavor
)
875 _ps_port_action_t action
= {
876 .port_type
= PSPA_EXCEPTION
,
878 .new_port
= new_port
,
879 .behavior
= behavior
,
882 return posix_spawn_appendportaction_np(attr
, &action
);
886 * posix_spawnattr_setauditsessionport_np
888 * Description: Set the audit session port rights attribute in the spawned task.
889 * This is used to securely set the audit session information for
892 * Parameters: attr The spawn attributes object for the
894 * au_sessionport The audit session send port right
899 posix_spawnattr_setauditsessionport_np(
900 posix_spawnattr_t
*attr
,
901 mach_port_t au_sessionport
)
903 _ps_port_action_t action
= {
904 .port_type
= PSPA_AU_SESSION
,
905 .new_port
= au_sessionport
,
907 return posix_spawn_appendportaction_np(attr
, &action
);
912 * posix_spawn_file_actions_init
914 * Description: Initialize a spawn file actions object attr with default values
916 * Parameters: file_actions The spawn file actions object to be
920 * ENOMEM Insufficient memory exists to
921 * initialize the spawn file actions
924 * Note: As an implementation detail, the externally visibily type
925 * posix_spawn_file_actions_t is defined to be a void *, and
926 * initialization involves allocation of a memory object.
927 * Subsequent changes to the spawn file actions may result in
928 * reallocation under the covers.
930 * Reinitialization of an already initialized spawn file actions
931 * object will result in memory being leaked. Because spawn
932 * file actions are not required to be used in conjunction with a
933 * static initializer, there is no way to distinguish a spawn
934 * file actions with stack garbage from one that's been
935 * initialized. This is arguably an API design error.
938 posix_spawn_file_actions_init(posix_spawn_file_actions_t
*file_actions
)
940 _posix_spawn_file_actions_t
*psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
943 if ((*psactsp
= (_posix_spawn_file_actions_t
)malloc(PSF_ACTIONS_SIZE(PSF_ACTIONS_INIT_COUNT
))) == NULL
) {
946 (*psactsp
)->psfa_act_alloc
= PSF_ACTIONS_INIT_COUNT
;
947 (*psactsp
)->psfa_act_count
= 0;
955 * posix_spawn_file_actions_destroy
957 * Description: Destroy a spawn file actions object that was previously
958 * initialized via posix_spawn_file_actions_init() by freeing any
959 * memory associated with it and setting it to an invalid value.
961 * Parameters: attr The spawn file actions object to be
966 * Notes: The destroyed spawn file actions results in the void * pointer
967 * being set to NULL; subsequent use without reinitialization
968 * will result in explicit program failure (rather than merely
969 * "undefined behaviour").
971 * NOTIMP: Allowed failures (checking NOT required):
972 * EINVAL The value specified by file_actions is invalid.
975 posix_spawn_file_actions_destroy(posix_spawn_file_actions_t
*file_actions
)
977 _posix_spawn_file_actions_t psacts
;
979 if (file_actions
== NULL
|| *file_actions
== NULL
)
982 psacts
= *(_posix_spawn_file_actions_t
*)file_actions
;
984 *file_actions
= NULL
;
991 * _posix_spawn_file_actions_grow
993 * Description: Grow the available list of file actions associated with the
994 * pointer to the structure provided; replace the contents of the
995 * pointer as a side effect.
997 * Parameters: psactsp Pointer to _posix_spawn_file_actions_t
1000 * Returns: 0 Success
1001 * ENOMEM Insufficient memory for operation
1003 * Notes: This code is common to all posix_spawn_file_actions_*()
1004 * functions, since we use a naieve data structure implementation
1005 * at present. Future optimization will likely change this.
1008 _posix_spawn_file_actions_grow(_posix_spawn_file_actions_t
*psactsp
)
1010 int new_alloc
= (*psactsp
)->psfa_act_alloc
* 2;
1011 _posix_spawn_file_actions_t new_psacts
;
1014 * XXX may want to impose an administrative limit here; POSIX does
1015 * XXX not provide for an administrative error return in this case,
1016 * XXX so it's probably acceptable to just fail catastrophically
1017 * XXX instead of implementing one.
1019 if ((new_psacts
= (_posix_spawn_file_actions_t
)realloc((*psactsp
), PSF_ACTIONS_SIZE(new_alloc
))) == NULL
) {
1022 new_psacts
->psfa_act_alloc
= new_alloc
;
1023 *psactsp
= new_psacts
;
1030 * posix_spawn_file_actions_addopen
1032 * Description: Add an open action to the object referenced by 'file_actions'
1033 * that will cause the file named by 'path' to be attempted to be
1034 * opened with flags 'oflag' and mode 'mode', and, if successful,
1035 * return as descriptor 'filedes' to the spawned process.
1037 * Parameters: file_actions File action object to augment
1038 * filedes fd that open is to use
1039 * path path to file to open
1040 * oflag open file flags
1041 * mode open file mode
1043 * Returns: 0 Success
1044 * EBADF The value specified by fildes is
1045 * negative or greater than or equal to
1047 * ENOMEM Insufficient memory exists to add to
1048 * the spawn file actions object.
1050 * NOTIMP: Allowed failures (checking NOT required):
1051 * EINVAL The value specified by file_actions is invalid.
1054 posix_spawn_file_actions_addopen(
1055 posix_spawn_file_actions_t
* __restrict file_actions
,
1056 int filedes
, const char * __restrict path
, int oflag
,
1059 _posix_spawn_file_actions_t
*psactsp
;
1060 _psfa_action_t
*psfileact
;
1062 if (file_actions
== NULL
|| *file_actions
== NULL
)
1065 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1066 /* Range check; required by POSIX */
1067 if (filedes
< 0 || filedes
>= OPEN_MAX
)
1070 /* If we do not have enough slots, grow the structure */
1071 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1072 /* need to grow file actions structure */
1073 if (_posix_spawn_file_actions_grow(psactsp
))
1078 * Allocate next available slot and fill it out
1080 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1082 psfileact
->psfaa_type
= PSFA_OPEN
;
1083 psfileact
->psfaa_filedes
= filedes
;
1084 psfileact
->psfaa_openargs
.psfao_oflag
= oflag
;
1085 psfileact
->psfaa_openargs
.psfao_mode
= mode
;
1086 strlcpy(psfileact
->psfaa_openargs
.psfao_path
, path
, PATH_MAX
);
1093 * posix_spawn_file_actions_addclose
1095 * Description: Add a close action to the object referenced by 'file_actions'
1096 * that will cause the file referenced by 'filedes' to be
1097 * attempted to be closed in the spawned process.
1099 * Parameters: file_actions File action object to augment
1100 * filedes fd to close
1102 * Returns: 0 Success
1103 * EBADF The value specified by fildes is
1104 * negative or greater than or equal to
1106 * ENOMEM Insufficient memory exists to add to
1107 * the spawn file actions object.
1109 * NOTIMP: Allowed failures (checking NOT required):
1110 * EINVAL The value specified by file_actions is invalid.
1113 posix_spawn_file_actions_addclose(posix_spawn_file_actions_t
*file_actions
,
1116 _posix_spawn_file_actions_t
*psactsp
;
1117 _psfa_action_t
*psfileact
;
1119 if (file_actions
== NULL
|| *file_actions
== NULL
)
1122 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1123 /* Range check; required by POSIX */
1124 if (filedes
< 0 || filedes
>= OPEN_MAX
)
1127 /* If we do not have enough slots, grow the structure */
1128 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1129 /* need to grow file actions structure */
1130 if (_posix_spawn_file_actions_grow(psactsp
))
1135 * Allocate next available slot and fill it out
1137 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1139 psfileact
->psfaa_type
= PSFA_CLOSE
;
1140 psfileact
->psfaa_filedes
= filedes
;
1147 * posix_spawn_file_actions_adddup2
1149 * Description: Add a dup2 action to the object referenced by 'file_actions'
1150 * that will cause the file referenced by 'filedes' to be
1151 * attempted to be dup2'ed to the descriptor 'newfiledes' in the
1154 * Parameters: file_actions File action object to augment
1155 * filedes fd to dup2
1156 * newfiledes fd to dup2 it to
1158 * Returns: 0 Success
1159 * EBADF The value specified by either fildes
1160 * or by newfiledes is negative or greater
1161 * than or equal to {OPEN_MAX}.
1162 * ENOMEM Insufficient memory exists to add to
1163 * the spawn file actions object.
1165 * NOTIMP: Allowed failures (checking NOT required):
1166 * EINVAL The value specified by file_actions is invalid.
1169 posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t
*file_actions
,
1170 int filedes
, int newfiledes
)
1172 _posix_spawn_file_actions_t
*psactsp
;
1173 _psfa_action_t
*psfileact
;
1175 if (file_actions
== NULL
|| *file_actions
== NULL
)
1178 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1179 /* Range check; required by POSIX */
1180 if (filedes
< 0 || filedes
>= OPEN_MAX
||
1181 newfiledes
< 0 || newfiledes
>= OPEN_MAX
)
1184 /* If we do not have enough slots, grow the structure */
1185 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1186 /* need to grow file actions structure */
1187 if (_posix_spawn_file_actions_grow(psactsp
))
1192 * Allocate next available slot and fill it out
1194 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1196 psfileact
->psfaa_type
= PSFA_DUP2
;
1197 psfileact
->psfaa_filedes
= filedes
;
1198 psfileact
->psfaa_openargs
.psfao_oflag
= newfiledes
;
1204 * posix_spawn_file_actions_addinherit_np
1206 * Description: Add the "inherit" action to the object referenced by
1207 * 'file_actions' that will cause the file referenced by
1208 * 'filedes' to continue to be available in the spawned
1209 * process via the same descriptor.
1211 * Inheritance is the normal default behaviour for
1212 * file descriptors across exec and spawn; but if the
1213 * POSIX_SPAWN_CLOEXEC_DEFAULT flag is set, the usual
1214 * default is reversed for the purposes of the spawn
1215 * invocation. Any pre-existing descriptors that
1216 * need to be made available to the spawned process can
1217 * be marked explicitly as 'inherit' via this interface.
1218 * Otherwise they will be automatically closed.
1220 * Note that any descriptors created via the other file
1221 * actions interfaces are automatically marked as 'inherit'.
1223 * Parameters: file_actions File action object to augment
1224 * filedes fd to inherit.
1226 * Returns: 0 Success
1227 * EBADF The value specified by fildes is
1228 * negative or greater than or equal to
1230 * ENOMEM Insufficient memory exists to add to
1231 * the spawn file actions object.
1233 * NOTIMP: Allowed failures (checking NOT required):
1234 * EINVAL The value specified by file_actions is invalid.
1237 posix_spawn_file_actions_addinherit_np(posix_spawn_file_actions_t
*file_actions
,
1240 _posix_spawn_file_actions_t
*psactsp
;
1241 _psfa_action_t
*psfileact
;
1243 if (file_actions
== NULL
|| *file_actions
== NULL
)
1246 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1247 /* Range check; required by POSIX */
1248 if (filedes
< 0 || filedes
>= OPEN_MAX
)
1251 #if defined(POSIX_SPAWN_CLOEXEC_DEFAULT) // TODO: delete this check
1252 /* If we do not have enough slots, grow the structure */
1253 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1254 /* need to grow file actions structure */
1255 if (_posix_spawn_file_actions_grow(psactsp
))
1260 * Allocate next available slot and fill it out
1262 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1264 psfileact
->psfaa_type
= PSFA_INHERIT
;
1265 psfileact
->psfaa_filedes
= filedes
;
1271 posix_spawnattr_setcpumonitor_default(posix_spawnattr_t
* __restrict attr
)
1273 return (posix_spawnattr_setcpumonitor(attr
, PROC_POLICY_CPUMON_DEFAULTS
, 0));
1277 posix_spawnattr_setcpumonitor(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 psattr
->psa_cpumonitor_percent
= percent
;
1288 psattr
->psa_cpumonitor_interval
= interval
;
1294 posix_spawnattr_getcpumonitor(posix_spawnattr_t
* __restrict attr
,
1295 uint64_t *percent
, uint64_t *interval
)
1297 _posix_spawnattr_t psattr
;
1299 if (attr
== NULL
|| *attr
== NULL
)
1302 psattr
= *(_posix_spawnattr_t
*)attr
;
1304 *percent
= psattr
->psa_cpumonitor_percent
;
1305 *interval
= psattr
->psa_cpumonitor_interval
;
1313 * posix_spawnattr_set_importancewatch_port_np
1315 * Description: Mark ports referred to by these rights
1316 * to boost the new task instead of their current task
1317 * for the spawn attribute object referred to by 'attr'.
1318 * Ports must be valid at posix_spawn time. They will NOT be
1319 * consumed by the kernel, so they must be deallocated after the spawn returns.
1320 * (If you are SETEXEC-ing, they are cleaned up by the exec operation).
1322 * The maximum number of watch ports allowed is defined by POSIX_SPAWN_IMPORTANCE_PORT_COUNT.
1324 * Parameters: count Number of ports in portarray
1325 * portarray Array of rights
1327 * Returns: 0 Success
1328 * EINVAL Bad port count
1329 * ENOMEM Insufficient memory exists to add to
1330 * the spawn port actions object.
1333 posix_spawnattr_set_importancewatch_port_np(posix_spawnattr_t
* __restrict attr
,
1334 int count
, mach_port_t portarray
[])
1338 if (count
< 0 || count
> POSIX_SPAWN_IMPORTANCE_PORT_COUNT
) {
1342 for (i
= 0; i
< count
; i
++) {
1343 _ps_port_action_t action
= {
1344 .port_type
= PSPA_IMP_WATCHPORTS
,
1345 .new_port
= portarray
[i
],
1347 int err
= posix_spawn_appendportaction_np(attr
, &action
);
1358 _ps_mac_policy_extension_t
*
1359 posix_spawnattr_macpolicyinfo_lookup(_posix_spawn_mac_policy_extensions_t psmx
, const char *policyname
)
1366 for (i
= 0; i
< psmx
->psmx_count
; i
++) {
1367 _ps_mac_policy_extension_t
*extension
= &psmx
->psmx_extensions
[i
];
1368 if (strcmp(extension
->policyname
, policyname
) == 0)
1375 posix_spawnattr_getmacpolicyinfo_np(const posix_spawnattr_t
* __restrict attr
,
1376 const char *policyname
, void **datap
, size_t *datalenp
)
1378 _posix_spawnattr_t psattr
;
1379 _ps_mac_policy_extension_t
*extension
;
1381 if (attr
== NULL
|| *attr
== NULL
|| policyname
== NULL
|| datap
== NULL
)
1384 psattr
= *(_posix_spawnattr_t
*)attr
;
1385 extension
= posix_spawnattr_macpolicyinfo_lookup(psattr
->psa_mac_extensions
, policyname
);
1386 if (extension
== NULL
)
1388 *datap
= (void *)(uintptr_t)extension
->data
;
1389 if (datalenp
!= NULL
) {
1390 *datalenp
= (size_t)extension
->datalen
;
1396 posix_spawnattr_setmacpolicyinfo_np(posix_spawnattr_t
* __restrict attr
,
1397 const char *policyname
, void *data
, size_t datalen
)
1399 _posix_spawnattr_t psattr
;
1400 _posix_spawn_mac_policy_extensions_t psmx
;
1401 _ps_mac_policy_extension_t
*extension
;
1403 if (attr
== NULL
|| *attr
== NULL
|| policyname
== NULL
)
1406 psattr
= *(_posix_spawnattr_t
*)attr
;
1407 psmx
= psattr
->psa_mac_extensions
;
1408 extension
= posix_spawnattr_macpolicyinfo_lookup(psattr
->psa_mac_extensions
, policyname
);
1409 if (extension
!= NULL
) {
1410 extension
->data
= (uintptr_t)data
;
1411 extension
->datalen
= datalen
;
1414 else if (psmx
== NULL
) {
1415 psmx
= psattr
->psa_mac_extensions
= malloc(PS_MAC_EXTENSIONS_SIZE(PS_MAC_EXTENSIONS_INIT_COUNT
));
1418 psmx
->psmx_alloc
= PS_MAC_EXTENSIONS_INIT_COUNT
;
1419 psmx
->psmx_count
= 0;
1421 else if (psmx
->psmx_count
== psmx
->psmx_alloc
) {
1422 psmx
= psattr
->psa_mac_extensions
= reallocf(psmx
, PS_MAC_EXTENSIONS_SIZE(psmx
->psmx_alloc
* 2));
1425 psmx
->psmx_alloc
*= 2;
1427 extension
= &psmx
->psmx_extensions
[psmx
->psmx_count
];
1428 strlcpy(extension
->policyname
, policyname
, sizeof(extension
->policyname
));
1429 extension
->data
= (uintptr_t)data
;
1430 extension
->datalen
= datalen
;
1431 psmx
->psmx_count
+= 1;
1435 int posix_spawnattr_setcoalition_np(const posix_spawnattr_t
* __restrict attr
,
1436 uint64_t coalitionid
, int type
, int role
)
1438 _posix_spawnattr_t psattr
;
1439 struct _posix_spawn_coalition_info
*coal_info
;
1441 if (attr
== NULL
|| *attr
== NULL
) {
1444 if (type
< 0 || type
> COALITION_TYPE_MAX
)
1447 psattr
= *(_posix_spawnattr_t
*)attr
;
1449 coal_info
= psattr
->psa_coalition_info
;
1451 coal_info
= (struct _posix_spawn_coalition_info
*)malloc(sizeof(*coal_info
));
1454 memset(coal_info
, 0, sizeof(*coal_info
));
1455 psattr
->psa_coalition_info
= coal_info
;
1458 coal_info
->psci_info
[type
].psci_id
= coalitionid
;
1459 coal_info
->psci_info
[type
].psci_role
= role
;
1465 int posix_spawnattr_set_qos_clamp_np(const posix_spawnattr_t
* __restrict attr
, uint64_t qos_clamp
)
1467 _posix_spawnattr_t psattr
;
1469 if (attr
== NULL
|| *attr
== NULL
) {
1473 if (qos_clamp
>= POSIX_SPAWN_PROC_CLAMP_LAST
)
1476 psattr
= *(_posix_spawnattr_t
*)attr
;
1477 psattr
->psa_qos_clamp
= qos_clamp
;
1483 posix_spawnattr_get_qos_clamp_np(const posix_spawnattr_t
* __restrict attr
, uint64_t * __restrict qos_clampp
)
1485 _posix_spawnattr_t psattr
;
1487 if (attr
== NULL
|| *attr
== NULL
) {
1491 psattr
= *(_posix_spawnattr_t
*)attr
;
1492 *qos_clampp
= psattr
->psa_qos_clamp
;
1497 int posix_spawnattr_set_darwin_role_np(const posix_spawnattr_t
* __restrict attr
, uint64_t darwin_role
)
1499 _posix_spawnattr_t psattr
;
1501 if (attr
== NULL
|| *attr
== NULL
) {
1505 psattr
= *(_posix_spawnattr_t
*)attr
;
1506 psattr
->psa_darwin_role
= darwin_role
;
1512 posix_spawnattr_get_darwin_role_np(const posix_spawnattr_t
* __restrict attr
, uint64_t * __restrict darwin_rolep
)
1514 _posix_spawnattr_t psattr
;
1516 if (attr
== NULL
|| *attr
== NULL
) {
1520 psattr
= *(_posix_spawnattr_t
*)attr
;
1521 *darwin_rolep
= psattr
->psa_darwin_role
;
1529 * Description: Create a new process from the process image corresponding to
1530 * the supplied 'path' argument.
1532 * Parameters: pid Pointer to pid_t to receive the
1533 * PID of the spawned process, if
1534 * successful and 'pid' != NULL
1535 * path Path of image file to spawn
1536 * file_actions spawn file actions object which
1537 * describes file actions to be
1538 * performed during the spawn
1539 * attrp spawn attributes object which
1540 * describes attributes to be
1541 * applied during the spawn
1542 * argv argument vector array; NULL
1544 * envp environment vector array; NULL
1547 * Returns: 0 Success
1548 * !0 An errno value indicating the
1549 * cause of the failure to spawn
1551 * Notes: Unlike other system calls, the return value of this system
1552 * call is expected to either be a 0 or an errno, rather than a
1553 * 0 or a -1, with the 'errno' variable being set.
1555 extern int __posix_spawn(pid_t
* __restrict
, const char * __restrict
,
1556 struct _posix_spawn_args_desc
*,
1557 char *const argv
[ __restrict
], char *const envp
[ __restrict
]);
1560 posix_spawn(pid_t
* __restrict pid
, const char * __restrict path
,
1561 const posix_spawn_file_actions_t
*file_actions
,
1562 const posix_spawnattr_t
* __restrict attrp
,
1563 char *const argv
[ __restrict
], char *const envp
[ __restrict
])
1565 int saveerrno
= errno
;
1568 * Only do extra work if we have file actions or attributes to push
1569 * down. We use a descriptor to push this information down, since we
1570 * want to have size information, which will let us (1) preallocate a
1571 * single chunk of memory for the copyin(), and (2) allow us to do a
1572 * single copyin() per attributes or file actions as a monlithic block.
1574 * Note: A future implementation may attempt to do the same
1575 * thing for the argv/envp data, which could potentially
1576 * result in a performance improvement due to increased
1577 * kernel efficiency, even though it would mean copying
1578 * the data in user space.
1580 if ((file_actions
!= NULL
&& (*file_actions
!= NULL
) && (*(_posix_spawn_file_actions_t
*)file_actions
)->psfa_act_count
> 0) || attrp
!= NULL
) {
1581 struct _posix_spawn_args_desc ad
;
1583 memset(&ad
, 0, sizeof(ad
));
1584 if (attrp
!= NULL
&& *attrp
!= NULL
) {
1585 _posix_spawnattr_t psattr
= *(_posix_spawnattr_t
*)attrp
;
1586 ad
.attr_size
= sizeof(struct _posix_spawnattr
);
1589 if (psattr
->psa_ports
!= NULL
) {
1590 ad
.port_actions
= psattr
->psa_ports
;
1591 ad
.port_actions_size
= PS_PORT_ACTIONS_SIZE(
1592 ad
.port_actions
->pspa_count
);
1594 if (psattr
->psa_mac_extensions
!= NULL
) {
1595 ad
.mac_extensions
= psattr
->psa_mac_extensions
;
1596 ad
.mac_extensions_size
= PS_MAC_EXTENSIONS_SIZE(
1597 ad
.mac_extensions
->psmx_count
);
1599 if (psattr
->psa_coalition_info
!= NULL
) {
1600 ad
.coal_info_size
= sizeof(struct _posix_spawn_coalition_info
);
1601 ad
.coal_info
= psattr
->psa_coalition_info
;
1604 if (file_actions
!= NULL
&& *file_actions
!= NULL
) {
1605 _posix_spawn_file_actions_t psactsp
=
1606 *(_posix_spawn_file_actions_t
*)file_actions
;
1608 if (psactsp
->psfa_act_count
> 0) {
1609 ad
.file_actions_size
= PSF_ACTIONS_SIZE(psactsp
->psfa_act_count
);
1610 ad
.file_actions
= psactsp
;
1614 ret
= __posix_spawn(pid
, path
, &ad
, argv
, envp
);
1616 ret
= __posix_spawn(pid
, path
, NULL
, argv
, envp
);