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 */
42 #include <sys/kern_memorystatus.h>
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
)->psa_persona_info
= 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
*);
181 static int posix_spawn_destroypersona_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
);
194 posix_spawn_destroypersona_info_np(attr
);
204 * posix_spawnattr_setflags
206 * Description: Set the spawn flags attribute for the spawn attribute object
207 * referred to by 'attr'.
209 * Parameters: attr The spawn attributes object whose flags
211 * flags The flags value to set
215 * NOTIMP: Allowed failures (checking NOT required):
216 * EINVAL The value specified by attr is invalid.
217 * EINVAL The value of the attribute being set is not valid.
220 posix_spawnattr_setflags(posix_spawnattr_t
*attr
, short flags
)
222 _posix_spawnattr_t psattr
;
224 if (attr
== NULL
|| *attr
== NULL
)
227 psattr
= *(_posix_spawnattr_t
*)attr
;
228 psattr
->psa_flags
= flags
;
235 * posix_spawnattr_getflags
237 * Description: Retrieve the spawn attributes flag for the spawn attributes
238 * object referenced by 'attr' and place them in the memory
239 * location referenced by 'flagsp'
241 * Parameters: attr The spawn attributes object whose flags
242 * are to be retrieved
243 * flagsp A pointer to a short value to receive
249 * *flagps (modified) The flags value from the spawn
252 * NOTIMP: Allowed failures (checking NOT required):
253 * EINVAL The value specified by attr is invalid.
254 * EINVAL The value of the attribute being set is not valid.
257 posix_spawnattr_getflags(const posix_spawnattr_t
* __restrict attr
,
258 short * __restrict flagsp
)
260 _posix_spawnattr_t psattr
;
262 if (attr
== NULL
|| *attr
== NULL
)
265 psattr
= *(_posix_spawnattr_t
*)attr
;
266 *flagsp
= psattr
->psa_flags
;
273 * posix_spawnattr_getsigdefault
275 * Description: Retrieve the set of signals to be set to default according to
276 * the spawn attribute value referenced by 'attr' and place the
277 * result into the memory containing the sigset_t referenced by
280 * Parameters: attr The spawn attributes object whose
281 * signal set for default signals is to
283 * sigdefault A pointer to the sigset_t to receive
289 * *sigdefault (modified) The signal set of signals to default
290 * from the spawn attributes object
293 posix_spawnattr_getsigdefault(const posix_spawnattr_t
* __restrict attr
,
294 sigset_t
* __restrict sigdefault
)
296 _posix_spawnattr_t psattr
;
298 if (attr
== NULL
|| *attr
== NULL
)
301 psattr
= *(_posix_spawnattr_t
*)attr
;
302 *sigdefault
= psattr
->psa_sigdefault
;
309 * posix_spawnattr_getpgroup
311 * Description: Obtain the value of the spawn process group attribute from the
312 * spawn attributes object referenced by 'attr' and place the
313 * results in the memory location referenced by 'pgroup'
315 * Parameters: attr The spawn attributes object whose
316 * process group information is to be
318 * pgroup A pointer to the pid_t to receive the
324 * *pgroup (modified) The process group information from the
325 * spawn attributes object
328 posix_spawnattr_getpgroup(const posix_spawnattr_t
* __restrict attr
,
329 pid_t
* __restrict pgroup
)
331 _posix_spawnattr_t psattr
;
333 if (attr
== NULL
|| *attr
== NULL
)
336 psattr
= *(_posix_spawnattr_t
*)attr
;
337 *pgroup
= psattr
->psa_pgroup
;
344 * posix_spawnattr_getsigmask
346 * Description: Obtain the value of the spawn signal mask attribute from the
347 * spawn attributes object referenced by 'attr' and place the
348 * result into the memory containing the sigset_t referenced by
351 * Parameters: attr The spawn attributes object whose
352 * signal set for masked signals is to
354 * sigmask A pointer to the sigset_t to receive
360 * *sigmask (modified) The signal set of signals to mask
361 * from the spawn attributes object
364 posix_spawnattr_getsigmask(const posix_spawnattr_t
* __restrict attr
,
365 sigset_t
* __restrict sigmask
)
367 _posix_spawnattr_t psattr
;
369 if (attr
== NULL
|| *attr
== NULL
)
372 psattr
= *(_posix_spawnattr_t
*)attr
;
373 *sigmask
= psattr
->psa_sigmask
;
379 * posix_spawnattr_getbinpref_np
381 * Description: Obtain the value of the spawn binary preferences attribute from
382 * the spawn attributes object referenced by 'attr' and place the
383 * result into the memory referenced by 'pref'.
385 * Parameters: attr The spawn attributes object whose
386 * binary preferences are to be retrieved
387 * count The size of the cpu_type_t array
388 * pref An array of cpu types
389 * ocount The actual number copied
391 * Returns: 0 No binary preferences found
392 * > 0 The number of cpu types (less than
393 * count) copied over from 'attr'.
396 * *pref (modified) The binary preferences array
397 * from the spawn attributes object
400 posix_spawnattr_getbinpref_np(const posix_spawnattr_t
* __restrict attr
,
401 size_t count
, cpu_type_t
*pref
, size_t * __restrict ocount
)
403 _posix_spawnattr_t psattr
;
406 if (attr
== NULL
|| *attr
== NULL
)
409 psattr
= *(_posix_spawnattr_t
*)attr
;
410 for (i
= 0; i
< count
&& i
< 4; i
++) {
411 pref
[i
] = psattr
->psa_binprefs
[i
];
421 * posix_spawnattr_getpcontrol_np
423 * Description: Retrieve the process control property set default according to
424 * the spawn attribute value referenced by 'attr' and place the
425 * result into the memory containing the control referenced by
428 * Parameters: attr The spawn attributes object whose
429 * signal set for default signals is to
431 * pcontrol A pointer to an int to receive
432 * the process control info
437 * *pcontrol (modified) The signal set of signals to default
438 * from the spawn attributes object
441 posix_spawnattr_getpcontrol_np(const posix_spawnattr_t
* __restrict attr
,
442 int * __restrict pcontrol
)
444 _posix_spawnattr_t psattr
;
446 if (attr
== NULL
|| *attr
== NULL
)
449 psattr
= *(_posix_spawnattr_t
*)attr
;
450 *pcontrol
= psattr
->psa_pcontrol
;
456 * posix_spawnattr_getprocesstype_np
458 * Description: Retrieve the process specific behaviors and app launch types
459 * spawn attribute value referenced by 'attr' and place the
460 * result into the memory containing the control referenced by
463 * Parameters: attr The spawn attributes object whose
464 * signal set for default signals is to
466 * proctype A pointer to an int to receive
467 * the process type info
472 * *proctype (modified) The process type set to value
473 * from the spawn attributes object
476 posix_spawnattr_getprocesstype_np(const posix_spawnattr_t
* __restrict attr
,
477 int * __restrict proctype
)
479 _posix_spawnattr_t psattr
;
481 if (attr
== NULL
|| *attr
== NULL
)
484 psattr
= *(_posix_spawnattr_t
*)attr
;
485 *proctype
= psattr
->psa_apptype
;
490 * posix_spawnattr_setsigdefault
492 * Description: Set the set of signals to be set to default for the spawn
493 * attribute value referenced by 'attr' from the memory
494 * containing the sigset_t referenced by 'sigdefault'
496 * Parameters: attr The spawn attributes object whose
497 * signal set for default signals is to
499 * sigdefault A pointer to the sigset_t from which to
500 * obtain the signal set
505 posix_spawnattr_setsigdefault(posix_spawnattr_t
* __restrict attr
,
506 const sigset_t
* __restrict sigdefault
)
508 _posix_spawnattr_t psattr
;
510 if (attr
== NULL
|| *attr
== NULL
)
513 psattr
= *(_posix_spawnattr_t
*)attr
;
514 psattr
->psa_sigdefault
= *sigdefault
;
521 * posix_spawnattr_setpgroup
523 * Description: Set the value of the spawn process group attribute for the
524 * spawn attributes object referenced by 'attr' from the value
527 * Parameters: attr The spawn attributes object for which
528 * the process group information is to be
530 * pgroup The process group to set
535 posix_spawnattr_setpgroup(posix_spawnattr_t
* attr
, pid_t pgroup
)
537 _posix_spawnattr_t psattr
;
539 if (attr
== NULL
|| *attr
== NULL
)
542 psattr
= *(_posix_spawnattr_t
*)attr
;
543 psattr
->psa_pgroup
= pgroup
;
550 * posix_spawnattr_setsigmask
552 * Description: Set the set of signals to be masked for the spawn attribute
553 * value referenced by 'attr' from the memory containing the
554 * sigset_t referenced by 'sigmask'
556 * Parameters: attr The spawn attributes object whose
557 * signal set for masked signals is to
559 * sigmask A pointer to the sigset_t from which to
560 * obtain the signal set
565 posix_spawnattr_setsigmask(posix_spawnattr_t
* __restrict attr
,
566 const sigset_t
* __restrict sigmask
)
568 _posix_spawnattr_t psattr
;
570 if (attr
== NULL
|| *attr
== NULL
)
573 psattr
= *(_posix_spawnattr_t
*)attr
;
574 psattr
->psa_sigmask
= *sigmask
;
581 * posix_spawnattr_setbinpref_np
583 * Description: Set the universal binary preferences for the spawn attribute
584 * value referenced by 'attr' from the memory containing the
585 * cpu_type_t array referenced by 'pref', size of 'count'
587 * Parameters: attr The spawn attributes object whose
588 * binary preferences are to be set
589 * count Size of the array pointed to by 'pref'
590 * pref cpu_type_t array of binary preferences
591 * ocount The actual number copied
593 * Returns: 0 No preferences copied
594 * > 0 Number of preferences copied
596 * Note: The posix_spawnattr_t currently only holds four cpu_type_t's.
597 * If the caller provides more preferences than this limit, they
598 * will be ignored, as reflected in the return value.
601 posix_spawnattr_setbinpref_np(posix_spawnattr_t
* __restrict attr
,
602 size_t count
, cpu_type_t
*pref
, size_t * __restrict ocount
)
604 _posix_spawnattr_t psattr
;
607 if (attr
== NULL
|| *attr
== NULL
)
610 psattr
= *(_posix_spawnattr_t
*)attr
;
611 for (i
= 0; i
< count
&& i
< 4; i
++) {
612 psattr
->psa_binprefs
[i
] = pref
[i
];
615 /* return number of binprefs copied over */
623 * posix_spawnattr_setpcontrol_np
625 * Description: Set the process control property according to
626 * attribute value referenced by 'attr' from the memory
627 * containing the int value 'pcontrol'
629 * Parameters: attr The spawn attributes object whose
630 * signal set for default signals is to
632 * pcontrol An int value of the process control info
637 posix_spawnattr_setpcontrol_np(posix_spawnattr_t
* __restrict attr
,
640 _posix_spawnattr_t psattr
;
642 if (attr
== NULL
|| *attr
== NULL
)
645 psattr
= *(_posix_spawnattr_t
*)attr
;
646 psattr
->psa_pcontrol
= pcontrol
;
653 * posix_spawnattr_setprocesstype_np
655 * Description: Set the process specific behaviors and app launch type
656 * attribute value referenced by 'attr' from the memory
657 * containing the int value 'proctype'
659 * Parameters: attr The spawn attributes object whose
660 * signal set for default signals is to
662 * proctype An int value of the process type info
667 posix_spawnattr_setprocesstype_np(posix_spawnattr_t
* __restrict attr
,
670 _posix_spawnattr_t psattr
;
672 if (attr
== NULL
|| *attr
== NULL
)
675 psattr
= *(_posix_spawnattr_t
*)attr
;
676 psattr
->psa_apptype
= proctype
;
682 * posix_spawn_createportactions_np
683 * Description: create a new posix_spawn_port_actions struct and link
684 * it into the posix_spawnattr.
687 posix_spawn_createportactions_np(posix_spawnattr_t
*attr
)
689 _posix_spawnattr_t psattr
;
690 _posix_spawn_port_actions_t acts
;
692 if (attr
== NULL
|| *attr
== NULL
)
695 psattr
= *(_posix_spawnattr_t
*)attr
;
696 acts
= (_posix_spawn_port_actions_t
)malloc(PS_PORT_ACTIONS_SIZE(2));
700 acts
->pspa_alloc
= 2;
701 acts
->pspa_count
= 0;
703 psattr
->psa_ports
= acts
;
708 * posix_spawn_growportactions_np
709 * Description: Enlarge the size of portactions if necessary
712 posix_spawn_growportactions_np(posix_spawnattr_t
*attr
)
714 _posix_spawnattr_t psattr
;
715 _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 */
727 if (os_mul_overflow(acts
->pspa_alloc
, 2, &newnum
))
729 size_t newsize
= PS_PORT_ACTIONS_SIZE(newnum
);
733 acts
= realloc(acts
, newsize
);
737 acts
->pspa_alloc
= newnum
;
738 psattr
->psa_ports
= acts
;
743 * posix_spawn_destroyportactions_np
744 * Description: clean up portactions struct in posix_spawnattr_t attr
747 posix_spawn_destroyportactions_np(posix_spawnattr_t
*attr
)
749 _posix_spawnattr_t psattr
;
750 _posix_spawn_port_actions_t acts
;
752 if (attr
== NULL
|| *attr
== NULL
)
755 psattr
= *(_posix_spawnattr_t
*)attr
;
756 acts
= psattr
->psa_ports
;
765 * posix_spawn_destroycoalition_info_np
766 * Description: clean up coalition_info struct in posix_spawnattr_t attr
769 posix_spawn_destroycoalition_info_np(posix_spawnattr_t
*attr
)
771 _posix_spawnattr_t psattr
;
772 struct _posix_spawn_coalition_info
*coal_info
;
774 if (attr
== NULL
|| *attr
== NULL
)
777 psattr
= *(_posix_spawnattr_t
*)attr
;
778 coal_info
= psattr
->psa_coalition_info
;
779 if (coal_info
== NULL
)
782 psattr
->psa_coalition_info
= NULL
;
788 * posix_spawn_destroypersona_info_np
789 * Description: clean up persona_info struct in posix_spawnattr_t attr
792 posix_spawn_destroypersona_info_np(posix_spawnattr_t
*attr
)
794 _posix_spawnattr_t psattr
;
795 struct _posix_spawn_persona_info
*persona
;
797 if (attr
== NULL
|| *attr
== NULL
)
800 psattr
= *(_posix_spawnattr_t
*)attr
;
801 persona
= psattr
->psa_persona_info
;
805 psattr
->psa_persona_info
= NULL
;
811 * posix_spawn_appendportaction_np
812 * Description: append a port action, grow the array if necessary
815 posix_spawn_appendportaction_np(posix_spawnattr_t
*attr
, _ps_port_action_t
*act
)
817 _posix_spawnattr_t psattr
;
818 _posix_spawn_port_actions_t acts
;
820 if (attr
== NULL
|| *attr
== NULL
|| act
== NULL
) {
824 psattr
= *(_posix_spawnattr_t
*)attr
;
825 acts
= psattr
->psa_ports
;
827 // Have any port actions been created yet?
829 int err
= posix_spawn_createportactions_np(attr
);
833 acts
= psattr
->psa_ports
;
836 // Is there enough room?
837 if (acts
->pspa_alloc
== acts
->pspa_count
) {
838 int err
= posix_spawn_growportactions_np(attr
);
842 acts
= psattr
->psa_ports
;
845 // Add this action to next spot in array
846 acts
->pspa_actions
[acts
->pspa_count
] = *act
;
853 * posix_spawnattr_setspecialport_np
855 * Description: Set a new value for a mach special port in the spawned task.
857 * Parameters: attr The spawn attributes object for the
859 * new_port The new value for the special port
860 * which The particular port to be set
861 * (see task_set_special_port for details)
864 * ENOMEM Couldn't allocate memory
867 posix_spawnattr_setspecialport_np(
868 posix_spawnattr_t
*attr
,
869 mach_port_t new_port
,
872 _ps_port_action_t action
= {
873 .port_type
= PSPA_SPECIAL
,
874 .new_port
= new_port
,
877 return posix_spawn_appendportaction_np(attr
, &action
);
881 * posix_spawnattr_setexceptionports_np
883 * Description: Set a new port for a set of exception ports in the spawned task.
885 * Parameters: attr The spawn attributes object for the
887 * mask A bitfield indicating which exceptions
888 * to associate the port with
889 * new_port The new value for the exception port
890 * behavior The default behavior for the port
891 * flavor The default flavor for the port
892 * (see task_set_exception_ports)
897 posix_spawnattr_setexceptionports_np(
898 posix_spawnattr_t
*attr
,
899 exception_mask_t mask
,
900 mach_port_t new_port
,
901 exception_behavior_t behavior
,
902 thread_state_flavor_t flavor
)
904 _ps_port_action_t action
= {
905 .port_type
= PSPA_EXCEPTION
,
907 .new_port
= new_port
,
908 .behavior
= behavior
,
911 return posix_spawn_appendportaction_np(attr
, &action
);
915 * posix_spawnattr_setauditsessionport_np
917 * Description: Set the audit session port rights attribute in the spawned task.
918 * This is used to securely set the audit session information for
921 * Parameters: attr The spawn attributes object for the
923 * au_sessionport The audit session send port right
928 posix_spawnattr_setauditsessionport_np(
929 posix_spawnattr_t
*attr
,
930 mach_port_t au_sessionport
)
932 _ps_port_action_t action
= {
933 .port_type
= PSPA_AU_SESSION
,
934 .new_port
= au_sessionport
,
936 return posix_spawn_appendportaction_np(attr
, &action
);
941 * posix_spawn_file_actions_init
943 * Description: Initialize a spawn file actions object attr with default values
945 * Parameters: file_actions The spawn file actions object to be
949 * ENOMEM Insufficient memory exists to
950 * initialize the spawn file actions
953 * Note: As an implementation detail, the externally visibily type
954 * posix_spawn_file_actions_t is defined to be a void *, and
955 * initialization involves allocation of a memory object.
956 * Subsequent changes to the spawn file actions may result in
957 * reallocation under the covers.
959 * Reinitialization of an already initialized spawn file actions
960 * object will result in memory being leaked. Because spawn
961 * file actions are not required to be used in conjunction with a
962 * static initializer, there is no way to distinguish a spawn
963 * file actions with stack garbage from one that's been
964 * initialized. This is arguably an API design error.
967 posix_spawn_file_actions_init(posix_spawn_file_actions_t
*file_actions
)
969 _posix_spawn_file_actions_t
*psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
972 if ((*psactsp
= (_posix_spawn_file_actions_t
)malloc(PSF_ACTIONS_SIZE(PSF_ACTIONS_INIT_COUNT
))) == NULL
) {
975 (*psactsp
)->psfa_act_alloc
= PSF_ACTIONS_INIT_COUNT
;
976 (*psactsp
)->psfa_act_count
= 0;
984 * posix_spawn_file_actions_destroy
986 * Description: Destroy a spawn file actions object that was previously
987 * initialized via posix_spawn_file_actions_init() by freeing any
988 * memory associated with it and setting it to an invalid value.
990 * Parameters: attr The spawn file actions object to be
995 * Notes: The destroyed spawn file actions results in the void * pointer
996 * being set to NULL; subsequent use without reinitialization
997 * will result in explicit program failure (rather than merely
998 * "undefined behaviour").
1000 * NOTIMP: Allowed failures (checking NOT required):
1001 * EINVAL The value specified by file_actions is invalid.
1004 posix_spawn_file_actions_destroy(posix_spawn_file_actions_t
*file_actions
)
1006 _posix_spawn_file_actions_t psacts
;
1008 if (file_actions
== NULL
|| *file_actions
== NULL
)
1011 psacts
= *(_posix_spawn_file_actions_t
*)file_actions
;
1013 *file_actions
= NULL
;
1020 * _posix_spawn_file_actions_grow
1022 * Description: Grow the available list of file actions associated with the
1023 * pointer to the structure provided; replace the contents of the
1024 * pointer as a side effect.
1026 * Parameters: psactsp Pointer to _posix_spawn_file_actions_t
1029 * Returns: 0 Success
1030 * ENOMEM Insufficient memory for operation
1032 * Notes: This code is common to all posix_spawn_file_actions_*()
1033 * functions, since we use a naieve data structure implementation
1034 * at present. Future optimization will likely change this.
1037 _posix_spawn_file_actions_grow(_posix_spawn_file_actions_t
*psactsp
)
1040 if (os_mul_overflow((*psactsp
)->psfa_act_alloc
, 2, &newnum
))
1043 size_t newsize
= PSF_ACTIONS_SIZE(newnum
);
1048 * XXX may want to impose an administrative limit here; POSIX does
1049 * XXX not provide for an administrative error return in this case,
1050 * XXX so it's probably acceptable to just fail catastrophically
1051 * XXX instead of implementing one.
1053 _posix_spawn_file_actions_t new_psacts
;
1054 if ((new_psacts
= (_posix_spawn_file_actions_t
)realloc((*psactsp
), newsize
)) == NULL
) {
1057 new_psacts
->psfa_act_alloc
= newnum
;
1058 *psactsp
= new_psacts
;
1065 * posix_spawn_file_actions_addopen
1067 * Description: Add an open action to the object referenced by 'file_actions'
1068 * that will cause the file named by 'path' to be attempted to be
1069 * opened with flags 'oflag' and mode 'mode', and, if successful,
1070 * return as descriptor 'filedes' to the spawned process.
1072 * Parameters: file_actions File action object to augment
1073 * filedes fd that open is to use
1074 * path path to file to open
1075 * oflag open file flags
1076 * mode open file mode
1078 * Returns: 0 Success
1079 * EBADF The value specified by fildes is
1080 * negative or greater than or equal to
1082 * ENOMEM Insufficient memory exists to add to
1083 * the spawn file actions object.
1085 * NOTIMP: Allowed failures (checking NOT required):
1086 * EINVAL The value specified by file_actions is invalid.
1089 posix_spawn_file_actions_addopen(
1090 posix_spawn_file_actions_t
* __restrict file_actions
,
1091 int filedes
, const char * __restrict path
, int oflag
,
1094 _posix_spawn_file_actions_t
*psactsp
;
1095 _psfa_action_t
*psfileact
;
1097 if (file_actions
== NULL
|| *file_actions
== NULL
)
1100 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1101 /* Range check; required by POSIX */
1102 if (filedes
< 0 || filedes
>= OPEN_MAX
)
1105 /* If we do not have enough slots, grow the structure */
1106 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1107 /* need to grow file actions structure */
1108 if (_posix_spawn_file_actions_grow(psactsp
))
1113 * Allocate next available slot and fill it out
1115 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1117 psfileact
->psfaa_type
= PSFA_OPEN
;
1118 psfileact
->psfaa_filedes
= filedes
;
1119 psfileact
->psfaa_openargs
.psfao_oflag
= oflag
;
1120 psfileact
->psfaa_openargs
.psfao_mode
= mode
;
1121 strlcpy(psfileact
->psfaa_openargs
.psfao_path
, path
, PATH_MAX
);
1128 * posix_spawn_file_actions_addclose
1130 * Description: Add a close action to the object referenced by 'file_actions'
1131 * that will cause the file referenced by 'filedes' to be
1132 * attempted to be closed in the spawned process.
1134 * Parameters: file_actions File action object to augment
1135 * filedes fd to close
1137 * Returns: 0 Success
1138 * EBADF The value specified by fildes is
1139 * negative or greater than or equal to
1141 * ENOMEM Insufficient memory exists to add to
1142 * the spawn file actions object.
1144 * NOTIMP: Allowed failures (checking NOT required):
1145 * EINVAL The value specified by file_actions is invalid.
1148 posix_spawn_file_actions_addclose(posix_spawn_file_actions_t
*file_actions
,
1151 _posix_spawn_file_actions_t
*psactsp
;
1152 _psfa_action_t
*psfileact
;
1154 if (file_actions
== NULL
|| *file_actions
== NULL
)
1157 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1158 /* Range check; required by POSIX */
1159 if (filedes
< 0 || filedes
>= OPEN_MAX
)
1162 /* If we do not have enough slots, grow the structure */
1163 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1164 /* need to grow file actions structure */
1165 if (_posix_spawn_file_actions_grow(psactsp
))
1170 * Allocate next available slot and fill it out
1172 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1174 psfileact
->psfaa_type
= PSFA_CLOSE
;
1175 psfileact
->psfaa_filedes
= filedes
;
1182 * posix_spawn_file_actions_adddup2
1184 * Description: Add a dup2 action to the object referenced by 'file_actions'
1185 * that will cause the file referenced by 'filedes' to be
1186 * attempted to be dup2'ed to the descriptor 'newfiledes' in the
1189 * Parameters: file_actions File action object to augment
1190 * filedes fd to dup2
1191 * newfiledes fd to dup2 it to
1193 * Returns: 0 Success
1194 * EBADF The value specified by either fildes
1195 * or by newfiledes is negative or greater
1196 * than or equal to {OPEN_MAX}.
1197 * ENOMEM Insufficient memory exists to add to
1198 * the spawn file actions object.
1200 * NOTIMP: Allowed failures (checking NOT required):
1201 * EINVAL The value specified by file_actions is invalid.
1204 posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t
*file_actions
,
1205 int filedes
, int newfiledes
)
1207 _posix_spawn_file_actions_t
*psactsp
;
1208 _psfa_action_t
*psfileact
;
1210 if (file_actions
== NULL
|| *file_actions
== NULL
)
1213 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1214 /* Range check; required by POSIX */
1215 if (filedes
< 0 || filedes
>= OPEN_MAX
||
1216 newfiledes
< 0 || newfiledes
>= OPEN_MAX
)
1219 /* If we do not have enough slots, grow the structure */
1220 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1221 /* need to grow file actions structure */
1222 if (_posix_spawn_file_actions_grow(psactsp
))
1227 * Allocate next available slot and fill it out
1229 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1231 psfileact
->psfaa_type
= PSFA_DUP2
;
1232 psfileact
->psfaa_filedes
= filedes
;
1233 psfileact
->psfaa_openargs
.psfao_oflag
= newfiledes
;
1239 * posix_spawn_file_actions_addinherit_np
1241 * Description: Add the "inherit" action to the object referenced by
1242 * 'file_actions' that will cause the file referenced by
1243 * 'filedes' to continue to be available in the spawned
1244 * process via the same descriptor.
1246 * Inheritance is the normal default behaviour for
1247 * file descriptors across exec and spawn; but if the
1248 * POSIX_SPAWN_CLOEXEC_DEFAULT flag is set, the usual
1249 * default is reversed for the purposes of the spawn
1250 * invocation. Any pre-existing descriptors that
1251 * need to be made available to the spawned process can
1252 * be marked explicitly as 'inherit' via this interface.
1253 * Otherwise they will be automatically closed.
1255 * Note that any descriptors created via the other file
1256 * actions interfaces are automatically marked as 'inherit'.
1258 * Parameters: file_actions File action object to augment
1259 * filedes fd to inherit.
1261 * Returns: 0 Success
1262 * EBADF The value specified by fildes is
1263 * negative or greater than or equal to
1265 * ENOMEM Insufficient memory exists to add to
1266 * the spawn file actions object.
1268 * NOTIMP: Allowed failures (checking NOT required):
1269 * EINVAL The value specified by file_actions is invalid.
1272 posix_spawn_file_actions_addinherit_np(posix_spawn_file_actions_t
*file_actions
,
1275 _posix_spawn_file_actions_t
*psactsp
;
1276 _psfa_action_t
*psfileact
;
1278 if (file_actions
== NULL
|| *file_actions
== NULL
)
1281 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1282 /* Range check; required by POSIX */
1283 if (filedes
< 0 || filedes
>= OPEN_MAX
)
1286 #if defined(POSIX_SPAWN_CLOEXEC_DEFAULT) // TODO: delete this check
1287 /* If we do not have enough slots, grow the structure */
1288 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1289 /* need to grow file actions structure */
1290 if (_posix_spawn_file_actions_grow(psactsp
))
1295 * Allocate next available slot and fill it out
1297 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1299 psfileact
->psfaa_type
= PSFA_INHERIT
;
1300 psfileact
->psfaa_filedes
= filedes
;
1306 posix_spawnattr_setcpumonitor_default(posix_spawnattr_t
* __restrict attr
)
1308 return (posix_spawnattr_setcpumonitor(attr
, PROC_POLICY_CPUMON_DEFAULTS
, 0));
1312 posix_spawnattr_setcpumonitor(posix_spawnattr_t
* __restrict attr
,
1313 uint64_t percent
, uint64_t interval
)
1315 _posix_spawnattr_t psattr
;
1317 if (attr
== NULL
|| *attr
== NULL
)
1320 psattr
= *(_posix_spawnattr_t
*)attr
;
1322 psattr
->psa_cpumonitor_percent
= percent
;
1323 psattr
->psa_cpumonitor_interval
= interval
;
1329 posix_spawnattr_getcpumonitor(posix_spawnattr_t
* __restrict attr
,
1330 uint64_t *percent
, uint64_t *interval
)
1332 _posix_spawnattr_t psattr
;
1334 if (attr
== NULL
|| *attr
== NULL
)
1337 psattr
= *(_posix_spawnattr_t
*)attr
;
1339 *percent
= psattr
->psa_cpumonitor_percent
;
1340 *interval
= psattr
->psa_cpumonitor_interval
;
1345 #if TARGET_OS_EMBEDDED
1347 * posix_spawnattr_setjetsam
1349 * Description: Set jetsam attributes for the spawn attribute object
1350 * referred to by 'attr'.
1352 * Parameters: flags The flags value to set
1353 * priority Relative jetsam priority
1354 * memlimit Value in megabytes; a memory footprint
1355 * above this level may result in termination.
1356 * Implies both active and inactive limits.
1358 * Returns: 0 Success
1360 * Note: to be deprecated (not available on desktop)
1364 posix_spawnattr_setjetsam(posix_spawnattr_t
* __restrict attr
,
1365 short flags
, int priority
, int memlimit
)
1367 short flags_ext
= flags
;
1369 if (flags
& POSIX_SPAWN_JETSAM_MEMLIMIT_FATAL
) {
1370 flags_ext
|= POSIX_SPAWN_JETSAM_MEMLIMIT_ACTIVE_FATAL
;
1371 flags_ext
|= POSIX_SPAWN_JETSAM_MEMLIMIT_INACTIVE_FATAL
;
1373 flags_ext
&= ~POSIX_SPAWN_JETSAM_MEMLIMIT_ACTIVE_FATAL
;
1374 flags_ext
&= ~POSIX_SPAWN_JETSAM_MEMLIMIT_INACTIVE_FATAL
;
1377 return (posix_spawnattr_setjetsam_ext(attr
, flags_ext
, priority
, memlimit
, memlimit
));
1379 #endif /* TARGET_OS_EMBEDDED */
1382 * posix_spawnattr_setjetsam_ext
1384 * Description: Set jetsam attributes for the spawn attribute object
1385 * referred to by 'attr'.
1387 * Parameters: flags The flags value to set
1388 * priority Relative jetsam priority
1389 * memlimit_active Value in megabytes; memory footprint
1390 * above this level while process is
1391 * active may result in termination.
1392 * memlimit_inactive Value in megabytes; memory footprint
1393 * above this level while process is
1394 * inactive may result in termination.
1396 * Returns: 0 Success
1399 posix_spawnattr_setjetsam_ext(posix_spawnattr_t
* __restrict attr
,
1400 short flags
, int priority
, int memlimit_active
, int memlimit_inactive
)
1402 _posix_spawnattr_t psattr
;
1404 if (attr
== NULL
|| *attr
== NULL
)
1407 psattr
= *(_posix_spawnattr_t
*)attr
;
1409 psattr
->psa_jetsam_flags
= flags
;
1410 psattr
->psa_jetsam_flags
|= POSIX_SPAWN_JETSAM_SET
;
1411 psattr
->psa_priority
= priority
;
1412 psattr
->psa_memlimit_active
= memlimit_active
;
1413 psattr
->psa_memlimit_inactive
= memlimit_inactive
;
1420 * posix_spawnattr_set_importancewatch_port_np
1422 * Description: Mark ports referred to by these rights
1423 * to boost the new task instead of their current task
1424 * for the spawn attribute object referred to by 'attr'.
1425 * Ports must be valid at posix_spawn time. They will NOT be
1426 * consumed by the kernel, so they must be deallocated after the spawn returns.
1427 * (If you are SETEXEC-ing, they are cleaned up by the exec operation).
1429 * The maximum number of watch ports allowed is defined by POSIX_SPAWN_IMPORTANCE_PORT_COUNT.
1431 * Parameters: count Number of ports in portarray
1432 * portarray Array of rights
1434 * Returns: 0 Success
1435 * EINVAL Bad port count
1436 * ENOMEM Insufficient memory exists to add to
1437 * the spawn port actions object.
1440 posix_spawnattr_set_importancewatch_port_np(posix_spawnattr_t
* __restrict attr
,
1441 int count
, mach_port_t portarray
[])
1445 if (count
< 0 || count
> POSIX_SPAWN_IMPORTANCE_PORT_COUNT
) {
1449 for (i
= 0; i
< count
; i
++) {
1450 _ps_port_action_t action
= {
1451 .port_type
= PSPA_IMP_WATCHPORTS
,
1452 .new_port
= portarray
[i
],
1454 int err
= posix_spawn_appendportaction_np(attr
, &action
);
1465 _ps_mac_policy_extension_t
*
1466 posix_spawnattr_macpolicyinfo_lookup(_posix_spawn_mac_policy_extensions_t psmx
, const char *policyname
)
1473 for (i
= 0; i
< psmx
->psmx_count
; i
++) {
1474 _ps_mac_policy_extension_t
*extension
= &psmx
->psmx_extensions
[i
];
1475 if (strcmp(extension
->policyname
, policyname
) == 0)
1482 posix_spawnattr_getmacpolicyinfo_np(const posix_spawnattr_t
* __restrict attr
,
1483 const char *policyname
, void **datap
, size_t *datalenp
)
1485 _posix_spawnattr_t psattr
;
1486 _ps_mac_policy_extension_t
*extension
;
1488 if (attr
== NULL
|| *attr
== NULL
|| policyname
== NULL
|| datap
== NULL
)
1491 psattr
= *(_posix_spawnattr_t
*)attr
;
1492 extension
= posix_spawnattr_macpolicyinfo_lookup(psattr
->psa_mac_extensions
, policyname
);
1493 if (extension
== NULL
)
1495 *datap
= (void *)(uintptr_t)extension
->data
;
1496 if (datalenp
!= NULL
) {
1497 *datalenp
= (size_t)extension
->datalen
;
1503 posix_spawnattr_setmacpolicyinfo_np(posix_spawnattr_t
* __restrict attr
,
1504 const char *policyname
, void *data
, size_t datalen
)
1506 _posix_spawnattr_t psattr
;
1507 _posix_spawn_mac_policy_extensions_t psmx
;
1508 _ps_mac_policy_extension_t
*extension
;
1510 if (attr
== NULL
|| *attr
== NULL
|| policyname
== NULL
)
1513 psattr
= *(_posix_spawnattr_t
*)attr
;
1514 psmx
= psattr
->psa_mac_extensions
;
1515 extension
= posix_spawnattr_macpolicyinfo_lookup(psattr
->psa_mac_extensions
, policyname
);
1516 if (extension
!= NULL
) {
1517 extension
->data
= (uintptr_t)data
;
1518 extension
->datalen
= datalen
;
1521 else if (psmx
== NULL
) {
1522 psmx
= psattr
->psa_mac_extensions
= malloc(PS_MAC_EXTENSIONS_SIZE(PS_MAC_EXTENSIONS_INIT_COUNT
));
1525 psmx
->psmx_alloc
= PS_MAC_EXTENSIONS_INIT_COUNT
;
1526 psmx
->psmx_count
= 0;
1528 else if (psmx
->psmx_count
== psmx
->psmx_alloc
) {
1530 if (os_mul_overflow(psmx
->psmx_alloc
, 2, &newnum
))
1532 size_t extsize
= PS_MAC_EXTENSIONS_SIZE(newnum
);
1535 psmx
= psattr
->psa_mac_extensions
= reallocf(psmx
, extsize
);
1538 psmx
->psmx_alloc
= newnum
;
1540 extension
= &psmx
->psmx_extensions
[psmx
->psmx_count
];
1541 strlcpy(extension
->policyname
, policyname
, sizeof(extension
->policyname
));
1542 extension
->data
= (uintptr_t)data
;
1543 extension
->datalen
= datalen
;
1544 psmx
->psmx_count
+= 1;
1548 int posix_spawnattr_setcoalition_np(const posix_spawnattr_t
* __restrict attr
,
1549 uint64_t coalitionid
, int type
, int role
)
1551 _posix_spawnattr_t psattr
;
1552 struct _posix_spawn_coalition_info
*coal_info
;
1554 if (attr
== NULL
|| *attr
== NULL
) {
1557 if (type
< 0 || type
> COALITION_TYPE_MAX
)
1560 psattr
= *(_posix_spawnattr_t
*)attr
;
1562 coal_info
= psattr
->psa_coalition_info
;
1564 coal_info
= (struct _posix_spawn_coalition_info
*)malloc(sizeof(*coal_info
));
1567 memset(coal_info
, 0, sizeof(*coal_info
));
1568 psattr
->psa_coalition_info
= coal_info
;
1571 coal_info
->psci_info
[type
].psci_id
= coalitionid
;
1572 coal_info
->psci_info
[type
].psci_role
= role
;
1578 int posix_spawnattr_set_qos_clamp_np(const posix_spawnattr_t
* __restrict attr
, uint64_t qos_clamp
)
1580 _posix_spawnattr_t psattr
;
1582 if (attr
== NULL
|| *attr
== NULL
) {
1586 if (qos_clamp
>= POSIX_SPAWN_PROC_CLAMP_LAST
)
1589 psattr
= *(_posix_spawnattr_t
*)attr
;
1590 psattr
->psa_qos_clamp
= qos_clamp
;
1596 posix_spawnattr_get_qos_clamp_np(const posix_spawnattr_t
* __restrict attr
, uint64_t * __restrict qos_clampp
)
1598 _posix_spawnattr_t psattr
;
1600 if (attr
== NULL
|| *attr
== NULL
) {
1604 psattr
= *(_posix_spawnattr_t
*)attr
;
1605 *qos_clampp
= psattr
->psa_qos_clamp
;
1610 int posix_spawnattr_set_darwin_role_np(const posix_spawnattr_t
* __restrict attr
, uint64_t darwin_role
)
1612 _posix_spawnattr_t psattr
;
1614 if (attr
== NULL
|| *attr
== NULL
) {
1618 psattr
= *(_posix_spawnattr_t
*)attr
;
1619 psattr
->psa_darwin_role
= darwin_role
;
1625 posix_spawnattr_get_darwin_role_np(const posix_spawnattr_t
* __restrict attr
, uint64_t * __restrict darwin_rolep
)
1627 _posix_spawnattr_t psattr
;
1629 if (attr
== NULL
|| *attr
== NULL
) {
1633 psattr
= *(_posix_spawnattr_t
*)attr
;
1634 *darwin_rolep
= psattr
->psa_darwin_role
;
1641 posix_spawnattr_set_persona_np(const posix_spawnattr_t
* __restrict attr
, uid_t persona_id
, uint32_t flags
)
1643 _posix_spawnattr_t psattr
;
1644 struct _posix_spawn_persona_info
*persona
;
1646 if (attr
== NULL
|| *attr
== NULL
)
1649 if (flags
& ~POSIX_SPAWN_PERSONA_ALL_FLAGS
)
1652 psattr
= *(_posix_spawnattr_t
*)attr
;
1654 persona
= psattr
->psa_persona_info
;
1656 persona
= (struct _posix_spawn_persona_info
*)malloc(sizeof(*persona
));
1659 persona
->pspi_uid
= 0;
1660 persona
->pspi_gid
= 0;
1661 persona
->pspi_ngroups
= 0;
1662 persona
->pspi_groups
[0] = 0;
1664 psattr
->psa_persona_info
= persona
;
1667 persona
->pspi_id
= persona_id
;
1668 persona
->pspi_flags
= flags
;
1674 posix_spawnattr_set_persona_uid_np(const posix_spawnattr_t
* __restrict attr
, uid_t uid
)
1676 _posix_spawnattr_t psattr
;
1677 struct _posix_spawn_persona_info
*persona
;
1679 if (attr
== NULL
|| *attr
== NULL
)
1682 psattr
= *(_posix_spawnattr_t
*)attr
;
1683 persona
= psattr
->psa_persona_info
;
1687 if (!(persona
->pspi_flags
& (POSIX_SPAWN_PERSONA_FLAGS_OVERRIDE
| POSIX_SPAWN_PERSONA_FLAGS_VERIFY
)))
1690 persona
->pspi_uid
= uid
;
1692 persona
->pspi_flags
|= POSIX_SPAWN_PERSONA_UID
;
1698 posix_spawnattr_set_persona_gid_np(const posix_spawnattr_t
* __restrict attr
, gid_t gid
)
1700 _posix_spawnattr_t psattr
;
1701 struct _posix_spawn_persona_info
*persona
;
1703 if (attr
== NULL
|| *attr
== NULL
)
1706 psattr
= *(_posix_spawnattr_t
*)attr
;
1707 persona
= psattr
->psa_persona_info
;
1711 if (!(persona
->pspi_flags
& (POSIX_SPAWN_PERSONA_FLAGS_OVERRIDE
| POSIX_SPAWN_PERSONA_FLAGS_VERIFY
)))
1714 persona
->pspi_gid
= gid
;
1716 persona
->pspi_flags
|= POSIX_SPAWN_PERSONA_GID
;
1722 posix_spawnattr_set_persona_groups_np(const posix_spawnattr_t
* __restrict attr
, int ngroups
, gid_t
*gidarray
, uid_t gmuid
)
1724 _posix_spawnattr_t psattr
;
1725 struct _posix_spawn_persona_info
*persona
;
1727 if (attr
== NULL
|| *attr
== NULL
)
1730 if (gidarray
== NULL
)
1733 if (ngroups
> NGROUPS
|| ngroups
< 0)
1736 psattr
= *(_posix_spawnattr_t
*)attr
;
1737 persona
= psattr
->psa_persona_info
;
1741 if (!(persona
->pspi_flags
& (POSIX_SPAWN_PERSONA_FLAGS_OVERRIDE
| POSIX_SPAWN_PERSONA_FLAGS_VERIFY
)))
1744 persona
->pspi_ngroups
= ngroups
;
1745 for (int i
= 0; i
< ngroups
; i
++)
1746 persona
->pspi_groups
[i
] = gidarray
[i
];
1748 persona
->pspi_gmuid
= gmuid
;
1750 persona
->pspi_flags
|= POSIX_SPAWN_PERSONA_GROUPS
;
1760 * Description: Create a new process from the process image corresponding to
1761 * the supplied 'path' argument.
1763 * Parameters: pid Pointer to pid_t to receive the
1764 * PID of the spawned process, if
1765 * successful and 'pid' != NULL
1766 * path Path of image file to spawn
1767 * file_actions spawn file actions object which
1768 * describes file actions to be
1769 * performed during the spawn
1770 * attrp spawn attributes object which
1771 * describes attributes to be
1772 * applied during the spawn
1773 * argv argument vector array; NULL
1775 * envp environment vector array; NULL
1778 * Returns: 0 Success
1779 * !0 An errno value indicating the
1780 * cause of the failure to spawn
1782 * Notes: Unlike other system calls, the return value of this system
1783 * call is expected to either be a 0 or an errno, rather than a
1784 * 0 or a -1, with the 'errno' variable being set.
1786 extern int __posix_spawn(pid_t
* __restrict
, const char * __restrict
,
1787 struct _posix_spawn_args_desc
*,
1788 char *const argv
[ __restrict
], char *const envp
[ __restrict
]);
1791 posix_spawn(pid_t
* __restrict pid
, const char * __restrict path
,
1792 const posix_spawn_file_actions_t
*file_actions
,
1793 const posix_spawnattr_t
* __restrict attrp
,
1794 char *const argv
[ __restrict
], char *const envp
[ __restrict
])
1796 int saveerrno
= errno
;
1799 * Only do extra work if we have file actions or attributes to push
1800 * down. We use a descriptor to push this information down, since we
1801 * want to have size information, which will let us (1) preallocate a
1802 * single chunk of memory for the copyin(), and (2) allow us to do a
1803 * single copyin() per attributes or file actions as a monlithic block.
1805 * Note: A future implementation may attempt to do the same
1806 * thing for the argv/envp data, which could potentially
1807 * result in a performance improvement due to increased
1808 * kernel efficiency, even though it would mean copying
1809 * the data in user space.
1811 if ((file_actions
!= NULL
&& (*file_actions
!= NULL
) && (*(_posix_spawn_file_actions_t
*)file_actions
)->psfa_act_count
> 0) || attrp
!= NULL
) {
1812 struct _posix_spawn_args_desc ad
;
1814 memset(&ad
, 0, sizeof(ad
));
1815 if (attrp
!= NULL
&& *attrp
!= NULL
) {
1816 _posix_spawnattr_t psattr
= *(_posix_spawnattr_t
*)attrp
;
1817 ad
.attr_size
= sizeof(struct _posix_spawnattr
);
1820 if (psattr
->psa_ports
!= NULL
) {
1821 size_t psact_size
= PS_PORT_ACTIONS_SIZE(psattr
->psa_ports
->pspa_count
);
1822 if (psact_size
== 0 && psattr
->psa_ports
->pspa_count
!= 0) {
1827 ad
.port_actions
= psattr
->psa_ports
;
1828 ad
.port_actions_size
= psact_size
;
1830 if (psattr
->psa_mac_extensions
!= NULL
) {
1831 size_t macext_size
= PS_MAC_EXTENSIONS_SIZE(psattr
->psa_mac_extensions
->psmx_count
);
1832 if (macext_size
== 0 && psattr
->psa_mac_extensions
->psmx_count
!= 0) {
1837 ad
.mac_extensions
= psattr
->psa_mac_extensions
;
1838 ad
.mac_extensions_size
= macext_size
;
1840 if (psattr
->psa_coalition_info
!= NULL
) {
1841 ad
.coal_info_size
= sizeof(struct _posix_spawn_coalition_info
);
1842 ad
.coal_info
= psattr
->psa_coalition_info
;
1844 if (psattr
->psa_persona_info
!= NULL
) {
1845 ad
.persona_info_size
= sizeof(struct _posix_spawn_persona_info
);
1846 ad
.persona_info
= psattr
->psa_persona_info
;
1849 if (file_actions
!= NULL
&& *file_actions
!= NULL
) {
1850 _posix_spawn_file_actions_t psactsp
=
1851 *(_posix_spawn_file_actions_t
*)file_actions
;
1853 if (psactsp
->psfa_act_count
> 0) {
1854 size_t fa_size
= PSF_ACTIONS_SIZE(psactsp
->psfa_act_count
);
1855 if (fa_size
== 0 && psactsp
->psfa_act_count
!= 0) {
1860 ad
.file_actions_size
= fa_size
;
1861 ad
.file_actions
= psactsp
;
1865 ret
= __posix_spawn(pid
, path
, &ad
, argv
, envp
);
1867 ret
= __posix_spawn(pid
, path
, NULL
, argv
, envp
);