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>
44 * posix_spawnattr_init
46 * Description: Initialize a spawn attributes object attr with default values
48 * Parameters: attr The spawn attributes object to be
52 * ENOMEM Insufficient memory exists to
53 * initialize the spawn attributes object.
55 * Note: As an implementation detail, the externally visibily type
56 * posix_spawnattr_t is defined to be a void *, and initialization
57 * involves allocation of a memory object. Subsequent changes to
58 * the spawn attributes may result in reallocation under the
61 * Reinitialization of an already initialized spawn attributes
62 * object will result in memory being leaked. Because spawn
63 * attributes are not required to be used in conjunction with a
64 * static initializer, there is no way to distinguish a spawn
65 * attribute with stack garbage from one that's been initialized.
66 * This is arguably an API design error.
69 posix_spawnattr_init(posix_spawnattr_t
*attr
)
71 _posix_spawnattr_t
*psattrp
= (_posix_spawnattr_t
*)attr
;
74 if ((*psattrp
= (_posix_spawnattr_t
)malloc(sizeof(struct _posix_spawnattr
))) == NULL
) {
79 * The default value of this attribute shall be as if no
82 (*psattrp
)->psa_flags
= 0;
85 * The default value of this attribute shall be an empty
88 (*psattrp
)->psa_sigdefault
= 0;
90 /* The default value of this attribute is unspecified */
91 (*psattrp
)->psa_sigmask
= 0;
93 /* The default value of this attribute shall be zero */
94 (*psattrp
)->psa_pgroup
= 0; /* doesn't matter */
96 /* Default is no binary preferences, i.e. use normal grading */
97 memset((*psattrp
)->psa_binprefs
, 0,
98 sizeof((*psattrp
)->psa_binprefs
));
100 /* Default is no port actions to take */
101 (*psattrp
)->psa_ports
= NULL
;
104 * The default value of this attribute shall be an no
105 * process control on resource starvation
107 (*psattrp
)->psa_pcontrol
= 0;
110 * Initializing the alignment paddings.
113 (*psattrp
)->short_padding
= 0;
114 (*psattrp
)->flags_padding
= 0;
115 (*psattrp
)->int_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_high_water_mark
= -1;
125 /* Default is no CPU usage monitor active. */
126 (*psattrp
)->psa_cpumonitor_percent
= 0;
127 (*psattrp
)->psa_cpumonitor_interval
= 0;
129 /* Default is no MAC policy extensions. */
130 (*psattrp
)->psa_mac_extensions
= NULL
;
132 /* Default is to inherit parent's coalition */
133 (*psattrp
)->psa_coalitionid
= 0;
135 /* Default is no new clamp */
136 (*psattrp
)->psa_qos_clamp
= POSIX_SPAWN_PROC_CLAMP_NONE
;
144 * posix_spawnattr_destroy
146 * Description: Destroy a spawn attributes object that was previously
147 * initialized via posix_spawnattr_init() by freeing any
148 * memory associated with it and setting it to an invalid value.
150 * Parameters: attr The spawn attributes object to be
155 * Notes: The destroyed spawn attribute results in the void * pointer
156 * being set to NULL; subsequent use without reinitialization
157 * will result in explicit program failure (rather than merely
158 * "undefined behaviour").
160 * NOTIMP: Allowed failures (checking NOT required):
161 * EINVAL The value specified by attr is invalid.
163 static int posix_spawn_destroyportactions_np(posix_spawnattr_t
*);
166 posix_spawnattr_destroy(posix_spawnattr_t
*attr
)
168 _posix_spawnattr_t psattr
;
170 if (attr
== NULL
|| *attr
== NULL
)
173 psattr
= *(_posix_spawnattr_t
*)attr
;
174 posix_spawn_destroyportactions_np(attr
);
184 * posix_spawnattr_setflags
186 * Description: Set the spawn flags attribute for the spawn attribute object
187 * referred to by 'attr'.
189 * Parameters: attr The spawn attributes object whose flags
191 * flags The flags value to set
195 * NOTIMP: Allowed failures (checking NOT required):
196 * EINVAL The value specified by attr is invalid.
197 * EINVAL The value of the attribute being set is not valid.
200 posix_spawnattr_setflags(posix_spawnattr_t
*attr
, short flags
)
202 _posix_spawnattr_t psattr
;
204 if (attr
== NULL
|| *attr
== NULL
)
207 psattr
= *(_posix_spawnattr_t
*)attr
;
208 psattr
->psa_flags
= flags
;
215 * posix_spawnattr_getflags
217 * Description: Retrieve the spawn attributes flag for the spawn attributes
218 * object referenced by 'attr' and place them in the memory
219 * location referenced by 'flagsp'
221 * Parameters: attr The spawn attributes object whose flags
222 * are to be retrieved
223 * flagsp A pointer to a short value to receive
229 * *flagps (modified) The flags value from the spawn
232 * NOTIMP: Allowed failures (checking NOT required):
233 * EINVAL The value specified by attr is invalid.
234 * EINVAL The value of the attribute being set is not valid.
237 posix_spawnattr_getflags(const posix_spawnattr_t
* __restrict attr
,
238 short * __restrict flagsp
)
240 _posix_spawnattr_t psattr
;
242 if (attr
== NULL
|| *attr
== NULL
)
245 psattr
= *(_posix_spawnattr_t
*)attr
;
246 *flagsp
= psattr
->psa_flags
;
253 * posix_spawnattr_getsigdefault
255 * Description: Retrieve the set of signals to be set to default according to
256 * the spawn attribute value referenced by 'attr' and place the
257 * result into the memory containing the sigset_t referenced by
260 * Parameters: attr The spawn attributes object whose
261 * signal set for default signals is to
263 * sigdefault A pointer to the sigset_t to receive
269 * *sigdefault (modified) The signal set of signals to default
270 * from the spawn attributes object
273 posix_spawnattr_getsigdefault(const posix_spawnattr_t
* __restrict attr
,
274 sigset_t
* __restrict sigdefault
)
276 _posix_spawnattr_t psattr
;
278 if (attr
== NULL
|| *attr
== NULL
)
281 psattr
= *(_posix_spawnattr_t
*)attr
;
282 *sigdefault
= psattr
->psa_sigdefault
;
289 * posix_spawnattr_getpgroup
291 * Description: Obtain the value of the spawn process group attribute from the
292 * spawn attributes object referenced by 'attr' and place the
293 * results in the memory location referenced by 'pgroup'
295 * Parameters: attr The spawn attributes object whose
296 * process group information is to be
298 * pgroup A pointer to the pid_t to receive the
304 * *pgroup (modified) The process group information from the
305 * spawn attributes object
308 posix_spawnattr_getpgroup(const posix_spawnattr_t
* __restrict attr
,
309 pid_t
* __restrict pgroup
)
311 _posix_spawnattr_t psattr
;
313 if (attr
== NULL
|| *attr
== NULL
)
316 psattr
= *(_posix_spawnattr_t
*)attr
;
317 *pgroup
= psattr
->psa_pgroup
;
324 * posix_spawnattr_getsigmask
326 * Description: Obtain the value of the spawn signal mask attribute from the
327 * spawn attributes object referenced by 'attr' and place the
328 * result into the memory containing the sigset_t referenced by
331 * Parameters: attr The spawn attributes object whose
332 * signal set for masked signals is to
334 * sigmask A pointer to the sigset_t to receive
340 * *sigmask (modified) The signal set of signals to mask
341 * from the spawn attributes object
344 posix_spawnattr_getsigmask(const posix_spawnattr_t
* __restrict attr
,
345 sigset_t
* __restrict sigmask
)
347 _posix_spawnattr_t psattr
;
349 if (attr
== NULL
|| *attr
== NULL
)
352 psattr
= *(_posix_spawnattr_t
*)attr
;
353 *sigmask
= psattr
->psa_sigmask
;
359 * posix_spawnattr_getbinpref_np
361 * Description: Obtain the value of the spawn binary preferences attribute from
362 * the spawn attributes object referenced by 'attr' and place the
363 * result into the memory referenced by 'pref'.
365 * Parameters: attr The spawn attributes object whose
366 * binary preferences are to be retrieved
367 * count The size of the cpu_type_t array
368 * pref An array of cpu types
369 * ocount The actual number copied
371 * Returns: 0 No binary preferences found
372 * > 0 The number of cpu types (less than
373 * count) copied over from 'attr'.
376 * *pref (modified) The binary preferences array
377 * from the spawn attributes object
380 posix_spawnattr_getbinpref_np(const posix_spawnattr_t
* __restrict attr
,
381 size_t count
, cpu_type_t
*pref
, size_t * __restrict ocount
)
383 _posix_spawnattr_t psattr
;
386 if (attr
== NULL
|| *attr
== NULL
)
389 psattr
= *(_posix_spawnattr_t
*)attr
;
390 for (i
= 0; i
< count
&& i
< 4; i
++) {
391 pref
[i
] = psattr
->psa_binprefs
[i
];
401 * posix_spawnattr_getpcontrol_np
403 * Description: Retrieve the process control property set default according to
404 * the spawn attribute value referenced by 'attr' and place the
405 * result into the memory containing the control referenced by
408 * Parameters: attr The spawn attributes object whose
409 * signal set for default signals is to
411 * pcontrol A pointer to an int to receive
412 * the process control info
417 * *pcontrol (modified) The signal set of signals to default
418 * from the spawn attributes object
421 posix_spawnattr_getpcontrol_np(const posix_spawnattr_t
* __restrict attr
,
422 int * __restrict pcontrol
)
424 _posix_spawnattr_t psattr
;
426 if (attr
== NULL
|| *attr
== NULL
)
429 psattr
= *(_posix_spawnattr_t
*)attr
;
430 *pcontrol
= psattr
->psa_pcontrol
;
436 * posix_spawnattr_getprocesstype_np
438 * Description: Retrieve the process specific behaviors and app launch types
439 * spawn attribute value referenced by 'attr' and place the
440 * result into the memory containing the control referenced by
443 * Parameters: attr The spawn attributes object whose
444 * signal set for default signals is to
446 * proctype A pointer to an int to receive
447 * the process type info
452 * *proctype (modified) The process type set to value
453 * from the spawn attributes object
456 posix_spawnattr_getprocesstype_np(const posix_spawnattr_t
* __restrict attr
,
457 int * __restrict proctype
)
459 _posix_spawnattr_t psattr
;
461 if (attr
== NULL
|| *attr
== NULL
)
464 psattr
= *(_posix_spawnattr_t
*)attr
;
465 *proctype
= psattr
->psa_apptype
;
470 * posix_spawnattr_setsigdefault
472 * Description: Set the set of signals to be set to default for the spawn
473 * attribute value referenced by 'attr' from the memory
474 * containing the sigset_t referenced by 'sigdefault'
476 * Parameters: attr The spawn attributes object whose
477 * signal set for default signals is to
479 * sigdefault A pointer to the sigset_t from which to
480 * obtain the signal set
485 posix_spawnattr_setsigdefault(posix_spawnattr_t
* __restrict attr
,
486 const sigset_t
* __restrict sigdefault
)
488 _posix_spawnattr_t psattr
;
490 if (attr
== NULL
|| *attr
== NULL
)
493 psattr
= *(_posix_spawnattr_t
*)attr
;
494 psattr
->psa_sigdefault
= *sigdefault
;
501 * posix_spawnattr_setpgroup
503 * Description: Set the value of the spawn process group attribute for the
504 * spawn attributes object referenced by 'attr' from the value
507 * Parameters: attr The spawn attributes object for which
508 * the process group information is to be
510 * pgroup The process group to set
515 posix_spawnattr_setpgroup(posix_spawnattr_t
* attr
, pid_t pgroup
)
517 _posix_spawnattr_t psattr
;
519 if (attr
== NULL
|| *attr
== NULL
)
522 psattr
= *(_posix_spawnattr_t
*)attr
;
523 psattr
->psa_pgroup
= pgroup
;
530 * posix_spawnattr_setsigmask
532 * Description: Set the set of signals to be masked for the spawn attribute
533 * value referenced by 'attr' from the memory containing the
534 * sigset_t referenced by 'sigmask'
536 * Parameters: attr The spawn attributes object whose
537 * signal set for masked signals is to
539 * sigmask A pointer to the sigset_t from which to
540 * obtain the signal set
545 posix_spawnattr_setsigmask(posix_spawnattr_t
* __restrict attr
,
546 const sigset_t
* __restrict sigmask
)
548 _posix_spawnattr_t psattr
;
550 if (attr
== NULL
|| *attr
== NULL
)
553 psattr
= *(_posix_spawnattr_t
*)attr
;
554 psattr
->psa_sigmask
= *sigmask
;
561 * posix_spawnattr_setbinpref_np
563 * Description: Set the universal binary preferences for the spawn attribute
564 * value referenced by 'attr' from the memory containing the
565 * cpu_type_t array referenced by 'pref', size of 'count'
567 * Parameters: attr The spawn attributes object whose
568 * binary preferences are to be set
569 * count Size of the array pointed to by 'pref'
570 * pref cpu_type_t array of binary preferences
571 * ocount The actual number copied
573 * Returns: 0 No preferences copied
574 * > 0 Number of preferences copied
576 * Note: The posix_spawnattr_t currently only holds four cpu_type_t's.
577 * If the caller provides more preferences than this limit, they
578 * will be ignored, as reflected in the return value.
581 posix_spawnattr_setbinpref_np(posix_spawnattr_t
* __restrict attr
,
582 size_t count
, cpu_type_t
*pref
, size_t * __restrict ocount
)
584 _posix_spawnattr_t psattr
;
587 if (attr
== NULL
|| *attr
== NULL
)
590 psattr
= *(_posix_spawnattr_t
*)attr
;
591 for (i
= 0; i
< count
&& i
< 4; i
++) {
592 psattr
->psa_binprefs
[i
] = pref
[i
];
595 /* return number of binprefs copied over */
603 * posix_spawnattr_setpcontrol_np
605 * Description: Set the process control property according to
606 * attribute value referenced by 'attr' from the memory
607 * containing the int value 'pcontrol'
609 * Parameters: attr The spawn attributes object whose
610 * signal set for default signals is to
612 * pcontrol An int value of the process control info
617 posix_spawnattr_setpcontrol_np(posix_spawnattr_t
* __restrict attr
,
620 _posix_spawnattr_t psattr
;
622 if (attr
== NULL
|| *attr
== NULL
)
625 psattr
= *(_posix_spawnattr_t
*)attr
;
626 psattr
->psa_pcontrol
= pcontrol
;
633 * posix_spawnattr_setprocesstype_np
635 * Description: Set the process specific behaviors and app launch type
636 * attribute value referenced by 'attr' from the memory
637 * containing the int value 'proctype'
639 * Parameters: attr The spawn attributes object whose
640 * signal set for default signals is to
642 * proctype An int value of the process type info
647 posix_spawnattr_setprocesstype_np(posix_spawnattr_t
* __restrict attr
,
650 _posix_spawnattr_t psattr
;
652 if (attr
== NULL
|| *attr
== NULL
)
655 psattr
= *(_posix_spawnattr_t
*)attr
;
656 psattr
->psa_apptype
= proctype
;
662 * posix_spawn_createportactions_np
663 * Description: create a new posix_spawn_port_actions struct and link
664 * it into the posix_spawnattr.
667 posix_spawn_createportactions_np(posix_spawnattr_t
*attr
)
669 _posix_spawnattr_t psattr
;
670 _posix_spawn_port_actions_t acts
;
672 if (attr
== NULL
|| *attr
== NULL
)
675 psattr
= *(_posix_spawnattr_t
*)attr
;
676 acts
= (_posix_spawn_port_actions_t
)malloc(PS_PORT_ACTIONS_SIZE(2));
680 acts
->pspa_alloc
= 2;
681 acts
->pspa_count
= 0;
683 psattr
->psa_ports
= acts
;
688 * posix_spawn_growportactions_np
689 * Description: Enlarge the size of portactions if necessary
692 posix_spawn_growportactions_np(posix_spawnattr_t
*attr
)
694 _posix_spawnattr_t psattr
;
695 _posix_spawn_port_actions_t acts
;
698 if (attr
== NULL
|| *attr
== NULL
)
701 psattr
= *(_posix_spawnattr_t
*)attr
;
702 acts
= psattr
->psa_ports
;
706 /* Double number of port actions allocated for */
707 newnum
= 2 * acts
->pspa_alloc
;
708 acts
= realloc(acts
, PS_PORT_ACTIONS_SIZE(newnum
));
712 acts
->pspa_alloc
= newnum
;
713 psattr
->psa_ports
= acts
;
718 * posix_spawn_destroyportactions_np
719 * Description: clean up portactions struct in posix_spawnattr_t attr
722 posix_spawn_destroyportactions_np(posix_spawnattr_t
*attr
)
724 _posix_spawnattr_t psattr
;
725 _posix_spawn_port_actions_t acts
;
727 if (attr
== NULL
|| *attr
== NULL
)
730 psattr
= *(_posix_spawnattr_t
*)attr
;
731 acts
= psattr
->psa_ports
;
740 * posix_spawn_appendportaction_np
741 * Description: append a port action, grow the array if necessary
744 posix_spawn_appendportaction_np(posix_spawnattr_t
*attr
, _ps_port_action_t
*act
)
746 _posix_spawnattr_t psattr
;
747 _posix_spawn_port_actions_t acts
;
749 if (attr
== NULL
|| *attr
== NULL
|| act
== NULL
) {
753 psattr
= *(_posix_spawnattr_t
*)attr
;
754 acts
= psattr
->psa_ports
;
756 // Have any port actions been created yet?
758 int err
= posix_spawn_createportactions_np(attr
);
762 acts
= psattr
->psa_ports
;
765 // Is there enough room?
766 if (acts
->pspa_alloc
== acts
->pspa_count
) {
767 int err
= posix_spawn_growportactions_np(attr
);
771 acts
= psattr
->psa_ports
;
774 // Add this action to next spot in array
775 acts
->pspa_actions
[acts
->pspa_count
] = *act
;
782 * posix_spawnattr_setspecialport_np
784 * Description: Set a new value for a mach special port in the spawned task.
786 * Parameters: attr The spawn attributes object for the
788 * new_port The new value for the special port
789 * which The particular port to be set
790 * (see task_set_special_port for details)
793 * ENOMEM Couldn't allocate memory
796 posix_spawnattr_setspecialport_np(
797 posix_spawnattr_t
*attr
,
798 mach_port_t new_port
,
801 _ps_port_action_t action
= {
802 .port_type
= PSPA_SPECIAL
,
803 .new_port
= new_port
,
806 return posix_spawn_appendportaction_np(attr
, &action
);
810 * posix_spawnattr_setexceptionports_np
812 * Description: Set a new port for a set of exception ports in the spawned task.
814 * Parameters: attr The spawn attributes object for the
816 * mask A bitfield indicating which exceptions
817 * to associate the port with
818 * new_port The new value for the exception port
819 * behavior The default behavior for the port
820 * flavor The default flavor for the port
821 * (see task_set_exception_ports)
826 posix_spawnattr_setexceptionports_np(
827 posix_spawnattr_t
*attr
,
828 exception_mask_t mask
,
829 mach_port_t new_port
,
830 exception_behavior_t behavior
,
831 thread_state_flavor_t flavor
)
833 _ps_port_action_t action
= {
834 .port_type
= PSPA_EXCEPTION
,
836 .new_port
= new_port
,
837 .behavior
= behavior
,
840 return posix_spawn_appendportaction_np(attr
, &action
);
844 * posix_spawnattr_setauditsessionport_np
846 * Description: Set the audit session port rights attribute in the spawned task.
847 * This is used to securely set the audit session information for
850 * Parameters: attr The spawn attributes object for the
852 * au_sessionport The audit session send port right
857 posix_spawnattr_setauditsessionport_np(
858 posix_spawnattr_t
*attr
,
859 mach_port_t au_sessionport
)
861 _ps_port_action_t action
= {
862 .port_type
= PSPA_AU_SESSION
,
863 .new_port
= au_sessionport
,
865 return posix_spawn_appendportaction_np(attr
, &action
);
870 * posix_spawn_file_actions_init
872 * Description: Initialize a spawn file actions object attr with default values
874 * Parameters: file_actions The spawn file actions object to be
878 * ENOMEM Insufficient memory exists to
879 * initialize the spawn file actions
882 * Note: As an implementation detail, the externally visibily type
883 * posix_spawn_file_actions_t is defined to be a void *, and
884 * initialization involves allocation of a memory object.
885 * Subsequent changes to the spawn file actions may result in
886 * reallocation under the covers.
888 * Reinitialization of an already initialized spawn file actions
889 * object will result in memory being leaked. Because spawn
890 * file actions are not required to be used in conjunction with a
891 * static initializer, there is no way to distinguish a spawn
892 * file actions with stack garbage from one that's been
893 * initialized. This is arguably an API design error.
896 posix_spawn_file_actions_init(posix_spawn_file_actions_t
*file_actions
)
898 _posix_spawn_file_actions_t
*psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
901 if ((*psactsp
= (_posix_spawn_file_actions_t
)malloc(PSF_ACTIONS_SIZE(PSF_ACTIONS_INIT_COUNT
))) == NULL
) {
904 (*psactsp
)->psfa_act_alloc
= PSF_ACTIONS_INIT_COUNT
;
905 (*psactsp
)->psfa_act_count
= 0;
913 * posix_spawn_file_actions_destroy
915 * Description: Destroy a spawn file actions object that was previously
916 * initialized via posix_spawn_file_actions_init() by freeing any
917 * memory associated with it and setting it to an invalid value.
919 * Parameters: attr The spawn file actions object to be
924 * Notes: The destroyed spawn file actions results in the void * pointer
925 * being set to NULL; subsequent use without reinitialization
926 * will result in explicit program failure (rather than merely
927 * "undefined behaviour").
929 * NOTIMP: Allowed failures (checking NOT required):
930 * EINVAL The value specified by file_actions is invalid.
933 posix_spawn_file_actions_destroy(posix_spawn_file_actions_t
*file_actions
)
935 _posix_spawn_file_actions_t psacts
;
937 if (file_actions
== NULL
|| *file_actions
== NULL
)
940 psacts
= *(_posix_spawn_file_actions_t
*)file_actions
;
942 *file_actions
= NULL
;
949 * _posix_spawn_file_actions_grow
951 * Description: Grow the available list of file actions associated with the
952 * pointer to the structure provided; replace the contents of the
953 * pointer as a side effect.
955 * Parameters: psactsp Pointer to _posix_spawn_file_actions_t
959 * ENOMEM Insufficient memory for operation
961 * Notes: This code is common to all posix_spawn_file_actions_*()
962 * functions, since we use a naieve data structure implementation
963 * at present. Future optimization will likely change this.
966 _posix_spawn_file_actions_grow(_posix_spawn_file_actions_t
*psactsp
)
968 int new_alloc
= (*psactsp
)->psfa_act_alloc
* 2;
969 _posix_spawn_file_actions_t new_psacts
;
972 * XXX may want to impose an administrative limit here; POSIX does
973 * XXX not provide for an administrative error return in this case,
974 * XXX so it's probably acceptable to just fail catastrophically
975 * XXX instead of implementing one.
977 if ((new_psacts
= (_posix_spawn_file_actions_t
)realloc((*psactsp
), PSF_ACTIONS_SIZE(new_alloc
))) == NULL
) {
980 new_psacts
->psfa_act_alloc
= new_alloc
;
981 *psactsp
= new_psacts
;
988 * posix_spawn_file_actions_addopen
990 * Description: Add an open action to the object referenced by 'file_actions'
991 * that will cause the file named by 'path' to be attempted to be
992 * opened with flags 'oflag' and mode 'mode', and, if successful,
993 * return as descriptor 'filedes' to the spawned process.
995 * Parameters: file_actions File action object to augment
996 * filedes fd that open is to use
997 * path path to file to open
998 * oflag open file flags
999 * mode open file mode
1001 * Returns: 0 Success
1002 * EBADF The value specified by fildes is
1003 * negative or greater than or equal to
1005 * ENOMEM Insufficient memory exists to add to
1006 * the spawn file actions object.
1008 * NOTIMP: Allowed failures (checking NOT required):
1009 * EINVAL The value specified by file_actions is invalid.
1012 posix_spawn_file_actions_addopen(
1013 posix_spawn_file_actions_t
* __restrict file_actions
,
1014 int filedes
, const char * __restrict path
, int oflag
,
1017 _posix_spawn_file_actions_t
*psactsp
;
1018 _psfa_action_t
*psfileact
;
1020 if (file_actions
== NULL
|| *file_actions
== NULL
)
1023 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1024 /* Range check; required by POSIX */
1025 if (filedes
< 0 || filedes
>= OPEN_MAX
)
1028 /* If we do not have enough slots, grow the structure */
1029 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1030 /* need to grow file actions structure */
1031 if (_posix_spawn_file_actions_grow(psactsp
))
1036 * Allocate next available slot and fill it out
1038 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1040 psfileact
->psfaa_type
= PSFA_OPEN
;
1041 psfileact
->psfaa_filedes
= filedes
;
1042 psfileact
->psfaa_openargs
.psfao_oflag
= oflag
;
1043 psfileact
->psfaa_openargs
.psfao_mode
= mode
;
1044 strlcpy(psfileact
->psfaa_openargs
.psfao_path
, path
, PATH_MAX
);
1051 * posix_spawn_file_actions_addclose
1053 * Description: Add a close action to the object referenced by 'file_actions'
1054 * that will cause the file referenced by 'filedes' to be
1055 * attempted to be closed in the spawned process.
1057 * Parameters: file_actions File action object to augment
1058 * filedes fd to close
1060 * Returns: 0 Success
1061 * EBADF The value specified by fildes is
1062 * negative or greater than or equal to
1064 * ENOMEM Insufficient memory exists to add to
1065 * the spawn file actions object.
1067 * NOTIMP: Allowed failures (checking NOT required):
1068 * EINVAL The value specified by file_actions is invalid.
1071 posix_spawn_file_actions_addclose(posix_spawn_file_actions_t
*file_actions
,
1074 _posix_spawn_file_actions_t
*psactsp
;
1075 _psfa_action_t
*psfileact
;
1077 if (file_actions
== NULL
|| *file_actions
== NULL
)
1080 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1081 /* Range check; required by POSIX */
1082 if (filedes
< 0 || filedes
>= OPEN_MAX
)
1085 /* If we do not have enough slots, grow the structure */
1086 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1087 /* need to grow file actions structure */
1088 if (_posix_spawn_file_actions_grow(psactsp
))
1093 * Allocate next available slot and fill it out
1095 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1097 psfileact
->psfaa_type
= PSFA_CLOSE
;
1098 psfileact
->psfaa_filedes
= filedes
;
1105 * posix_spawn_file_actions_adddup2
1107 * Description: Add a dup2 action to the object referenced by 'file_actions'
1108 * that will cause the file referenced by 'filedes' to be
1109 * attempted to be dup2'ed to the descriptor 'newfiledes' in the
1112 * Parameters: file_actions File action object to augment
1113 * filedes fd to dup2
1114 * newfiledes fd to dup2 it to
1116 * Returns: 0 Success
1117 * EBADF The value specified by either fildes
1118 * or by newfiledes is negative or greater
1119 * than or equal to {OPEN_MAX}.
1120 * ENOMEM Insufficient memory exists to add to
1121 * the spawn file actions object.
1123 * NOTIMP: Allowed failures (checking NOT required):
1124 * EINVAL The value specified by file_actions is invalid.
1127 posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t
*file_actions
,
1128 int filedes
, int newfiledes
)
1130 _posix_spawn_file_actions_t
*psactsp
;
1131 _psfa_action_t
*psfileact
;
1133 if (file_actions
== NULL
|| *file_actions
== NULL
)
1136 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1137 /* Range check; required by POSIX */
1138 if (filedes
< 0 || filedes
>= OPEN_MAX
||
1139 newfiledes
< 0 || newfiledes
>= OPEN_MAX
)
1142 /* If we do not have enough slots, grow the structure */
1143 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1144 /* need to grow file actions structure */
1145 if (_posix_spawn_file_actions_grow(psactsp
))
1150 * Allocate next available slot and fill it out
1152 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1154 psfileact
->psfaa_type
= PSFA_DUP2
;
1155 psfileact
->psfaa_filedes
= filedes
;
1156 psfileact
->psfaa_openargs
.psfao_oflag
= newfiledes
;
1162 * posix_spawn_file_actions_addinherit_np
1164 * Description: Add the "inherit" action to the object referenced by
1165 * 'file_actions' that will cause the file referenced by
1166 * 'filedes' to continue to be available in the spawned
1167 * process via the same descriptor.
1169 * Inheritance is the normal default behaviour for
1170 * file descriptors across exec and spawn; but if the
1171 * POSIX_SPAWN_CLOEXEC_DEFAULT flag is set, the usual
1172 * default is reversed for the purposes of the spawn
1173 * invocation. Any pre-existing descriptors that
1174 * need to be made available to the spawned process can
1175 * be marked explicitly as 'inherit' via this interface.
1176 * Otherwise they will be automatically closed.
1178 * Note that any descriptors created via the other file
1179 * actions interfaces are automatically marked as 'inherit'.
1181 * Parameters: file_actions File action object to augment
1182 * filedes fd to inherit.
1184 * Returns: 0 Success
1185 * EBADF The value specified by fildes is
1186 * negative or greater than or equal to
1188 * ENOMEM Insufficient memory exists to add to
1189 * the spawn file actions object.
1191 * NOTIMP: Allowed failures (checking NOT required):
1192 * EINVAL The value specified by file_actions is invalid.
1195 posix_spawn_file_actions_addinherit_np(posix_spawn_file_actions_t
*file_actions
,
1198 _posix_spawn_file_actions_t
*psactsp
;
1199 _psfa_action_t
*psfileact
;
1201 if (file_actions
== NULL
|| *file_actions
== NULL
)
1204 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1205 /* Range check; required by POSIX */
1206 if (filedes
< 0 || filedes
>= OPEN_MAX
)
1209 #if defined(POSIX_SPAWN_CLOEXEC_DEFAULT) // TODO: delete this check
1210 /* If we do not have enough slots, grow the structure */
1211 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1212 /* need to grow file actions structure */
1213 if (_posix_spawn_file_actions_grow(psactsp
))
1218 * Allocate next available slot and fill it out
1220 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1222 psfileact
->psfaa_type
= PSFA_INHERIT
;
1223 psfileact
->psfaa_filedes
= filedes
;
1229 posix_spawnattr_setcpumonitor_default(posix_spawnattr_t
* __restrict attr
)
1231 return (posix_spawnattr_setcpumonitor(attr
, PROC_POLICY_CPUMON_DEFAULTS
, 0));
1235 posix_spawnattr_setcpumonitor(posix_spawnattr_t
* __restrict attr
,
1236 uint64_t percent
, uint64_t interval
)
1238 _posix_spawnattr_t psattr
;
1240 if (attr
== NULL
|| *attr
== NULL
)
1243 psattr
= *(_posix_spawnattr_t
*)attr
;
1245 psattr
->psa_cpumonitor_percent
= percent
;
1246 psattr
->psa_cpumonitor_interval
= interval
;
1252 posix_spawnattr_getcpumonitor(posix_spawnattr_t
* __restrict attr
,
1253 uint64_t *percent
, uint64_t *interval
)
1255 _posix_spawnattr_t psattr
;
1257 if (attr
== NULL
|| *attr
== NULL
)
1260 psattr
= *(_posix_spawnattr_t
*)attr
;
1262 *percent
= psattr
->psa_cpumonitor_percent
;
1263 *interval
= psattr
->psa_cpumonitor_interval
;
1271 * posix_spawnattr_set_importancewatch_port_np
1273 * Description: Mark ports referred to by these rights
1274 * to boost the new task instead of their current task
1275 * for the spawn attribute object referred to by 'attr'.
1276 * Ports must be valid at posix_spawn time. They will NOT be
1277 * consumed by the kernel, so they must be deallocated after the spawn returns.
1278 * (If you are SETEXEC-ing, they are cleaned up by the exec operation).
1280 * The maximum number of watch ports allowed is defined by POSIX_SPAWN_IMPORTANCE_PORT_COUNT.
1282 * Parameters: count Number of ports in portarray
1283 * portarray Array of rights
1285 * Returns: 0 Success
1286 * EINVAL Bad port count
1287 * ENOMEM Insufficient memory exists to add to
1288 * the spawn port actions object.
1291 posix_spawnattr_set_importancewatch_port_np(posix_spawnattr_t
* __restrict attr
,
1292 int count
, mach_port_t portarray
[])
1296 if (count
< 0 || count
> POSIX_SPAWN_IMPORTANCE_PORT_COUNT
) {
1300 for (i
= 0; i
< count
; i
++) {
1301 _ps_port_action_t action
= {
1302 .port_type
= PSPA_IMP_WATCHPORTS
,
1303 .new_port
= portarray
[i
],
1305 int err
= posix_spawn_appendportaction_np(attr
, &action
);
1316 _ps_mac_policy_extension_t
*
1317 posix_spawnattr_macpolicyinfo_lookup(_posix_spawn_mac_policy_extensions_t psmx
, const char *policyname
)
1324 for (i
= 0; i
< psmx
->psmx_count
; i
++) {
1325 _ps_mac_policy_extension_t
*extension
= &psmx
->psmx_extensions
[i
];
1326 if (strcmp(extension
->policyname
, policyname
) == 0)
1333 posix_spawnattr_getmacpolicyinfo_np(const posix_spawnattr_t
* __restrict attr
,
1334 const char *policyname
, void **datap
, size_t *datalenp
)
1336 _posix_spawnattr_t psattr
;
1337 _ps_mac_policy_extension_t
*extension
;
1339 if (attr
== NULL
|| *attr
== NULL
|| policyname
== NULL
|| datap
== NULL
)
1342 psattr
= *(_posix_spawnattr_t
*)attr
;
1343 extension
= posix_spawnattr_macpolicyinfo_lookup(psattr
->psa_mac_extensions
, policyname
);
1344 if (extension
== NULL
)
1346 *datap
= (void *)(uintptr_t)extension
->data
;
1347 if (datalenp
!= NULL
) {
1348 *datalenp
= (size_t)extension
->datalen
;
1354 posix_spawnattr_setmacpolicyinfo_np(posix_spawnattr_t
* __restrict attr
,
1355 const char *policyname
, void *data
, size_t datalen
)
1357 _posix_spawnattr_t psattr
;
1358 _posix_spawn_mac_policy_extensions_t psmx
;
1359 _ps_mac_policy_extension_t
*extension
;
1361 if (attr
== NULL
|| *attr
== NULL
|| policyname
== NULL
)
1364 psattr
= *(_posix_spawnattr_t
*)attr
;
1365 psmx
= psattr
->psa_mac_extensions
;
1366 extension
= posix_spawnattr_macpolicyinfo_lookup(psattr
->psa_mac_extensions
, policyname
);
1367 if (extension
!= NULL
) {
1368 extension
->data
= (uintptr_t)data
;
1369 extension
->datalen
= datalen
;
1372 else if (psmx
== NULL
) {
1373 psmx
= psattr
->psa_mac_extensions
= malloc(PS_MAC_EXTENSIONS_SIZE(PS_MAC_EXTENSIONS_INIT_COUNT
));
1376 psmx
->psmx_alloc
= PS_MAC_EXTENSIONS_INIT_COUNT
;
1377 psmx
->psmx_count
= 0;
1379 else if (psmx
->psmx_count
== psmx
->psmx_alloc
) {
1380 psmx
= psattr
->psa_mac_extensions
= reallocf(psmx
, PS_MAC_EXTENSIONS_SIZE(psmx
->psmx_alloc
* 2));
1383 psmx
->psmx_alloc
*= 2;
1385 extension
= &psmx
->psmx_extensions
[psmx
->psmx_count
];
1386 strlcpy(extension
->policyname
, policyname
, sizeof(extension
->policyname
));
1387 extension
->data
= (uintptr_t)data
;
1388 extension
->datalen
= datalen
;
1389 psmx
->psmx_count
+= 1;
1393 int posix_spawnattr_setcoalition_np(const posix_spawnattr_t
* __restrict attr
, uint64_t coalitionid
)
1395 _posix_spawnattr_t psattr
;
1397 if (attr
== NULL
|| *attr
== NULL
) {
1401 psattr
= *(_posix_spawnattr_t
*)attr
;
1402 psattr
->psa_coalitionid
= coalitionid
;
1408 int posix_spawnattr_set_qos_clamp_np(const posix_spawnattr_t
* __restrict attr
, uint64_t qos_clamp
)
1410 _posix_spawnattr_t psattr
;
1412 if (attr
== NULL
|| *attr
== NULL
) {
1416 if (qos_clamp
>= POSIX_SPAWN_PROC_CLAMP_LAST
)
1419 psattr
= *(_posix_spawnattr_t
*)attr
;
1420 psattr
->psa_qos_clamp
= qos_clamp
;
1426 posix_spawnattr_get_qos_clamp_np(const posix_spawnattr_t
* __restrict attr
, uint64_t * __restrict qos_clampp
)
1428 _posix_spawnattr_t psattr
;
1430 if (attr
== NULL
|| *attr
== NULL
) {
1434 psattr
= *(_posix_spawnattr_t
*)attr
;
1435 *qos_clampp
= psattr
->psa_qos_clamp
;
1444 * Description: Create a new process from the process image corresponding to
1445 * the supplied 'path' argument.
1447 * Parameters: pid Pointer to pid_t to receive the
1448 * PID of the spawned process, if
1449 * successful and 'pid' != NULL
1450 * path Path of image file to spawn
1451 * file_actions spawn file actions object which
1452 * describes file actions to be
1453 * performed during the spawn
1454 * attrp spawn attributes object which
1455 * describes attributes to be
1456 * applied during the spawn
1457 * argv argument vector array; NULL
1459 * envp environment vector array; NULL
1462 * Returns: 0 Success
1463 * !0 An errno value indicating the
1464 * cause of the failure to spawn
1466 * Notes: Unlike other system calls, the return value of this system
1467 * call is expected to either be a 0 or an errno, rather than a
1468 * 0 or a -1, with the 'errno' variable being set.
1470 extern int __posix_spawn(pid_t
* __restrict
, const char * __restrict
,
1471 struct _posix_spawn_args_desc
*,
1472 char *const argv
[ __restrict
], char *const envp
[ __restrict
]);
1475 posix_spawn(pid_t
* __restrict pid
, const char * __restrict path
,
1476 const posix_spawn_file_actions_t
*file_actions
,
1477 const posix_spawnattr_t
* __restrict attrp
,
1478 char *const argv
[ __restrict
], char *const envp
[ __restrict
])
1480 int saveerrno
= errno
;
1483 * Only do extra work if we have file actions or attributes to push
1484 * down. We use a descriptor to push this information down, since we
1485 * want to have size information, which will let us (1) preallocate a
1486 * single chunk of memory for the copyin(), and (2) allow us to do a
1487 * single copyin() per attributes or file actions as a monlithic block.
1489 * Note: A future implementation may attempt to do the same
1490 * thing for the argv/envp data, which could potentially
1491 * result in a performance improvement due to increased
1492 * kernel efficiency, even though it would mean copying
1493 * the data in user space.
1495 if ((file_actions
!= NULL
&& (*file_actions
!= NULL
) && (*(_posix_spawn_file_actions_t
*)file_actions
)->psfa_act_count
> 0) || attrp
!= NULL
) {
1496 struct _posix_spawn_args_desc ad
;
1498 memset(&ad
, 0, sizeof(ad
));
1499 if (attrp
!= NULL
&& *attrp
!= NULL
) {
1500 _posix_spawnattr_t psattr
= *(_posix_spawnattr_t
*)attrp
;
1501 ad
.attr_size
= sizeof(struct _posix_spawnattr
);
1504 if (psattr
->psa_ports
!= NULL
) {
1505 ad
.port_actions
= psattr
->psa_ports
;
1506 ad
.port_actions_size
= PS_PORT_ACTIONS_SIZE(
1507 ad
.port_actions
->pspa_count
);
1509 if (psattr
->psa_mac_extensions
!= NULL
) {
1510 ad
.mac_extensions
= psattr
->psa_mac_extensions
;
1511 ad
.mac_extensions_size
= PS_MAC_EXTENSIONS_SIZE(
1512 ad
.mac_extensions
->psmx_count
);
1515 if (file_actions
!= NULL
&& *file_actions
!= NULL
) {
1516 _posix_spawn_file_actions_t psactsp
=
1517 *(_posix_spawn_file_actions_t
*)file_actions
;
1519 if (psactsp
->psfa_act_count
> 0) {
1520 ad
.file_actions_size
= PSF_ACTIONS_SIZE(psactsp
->psfa_act_count
);
1521 ad
.file_actions
= psactsp
;
1525 ret
= __posix_spawn(pid
, path
, &ad
, argv
, envp
);
1527 ret
= __posix_spawn(pid
, path
, NULL
, argv
, envp
);