+int
+posix_spawnattr_set_max_addr_np(const posix_spawnattr_t * __restrict attr, uint64_t max_addr)
+{
+ _posix_spawnattr_t psattr;
+
+ if (attr == NULL || *attr == NULL) {
+ return EINVAL;
+ }
+
+ psattr = *(_posix_spawnattr_t *)attr;
+ psattr->psa_max_addr = max_addr;
+
+ return 0;
+}
+
+static struct _posix_spawn_posix_cred_info *
+_posix_spawnattr_get_posix_creds_info(_posix_spawnattr_t psattr)
+{
+ struct _posix_spawn_posix_cred_info *pspci = psattr->psa_posix_cred_info;
+
+ if (pspci == NULL) {
+ pspci = malloc(sizeof(struct _posix_spawn_posix_cred_info));
+ if (pspci != NULL) {
+ pspci->pspci_flags = 0;
+ pspci->pspci_uid = 0;
+ pspci->pspci_gid = 0;
+ pspci->pspci_ngroups = 0;
+ pspci->pspci_groups[0] = 0;
+ pspci->pspci_gmuid = 0;
+ pspci->pspci_login[0] = '\0';
+ psattr->psa_posix_cred_info = pspci;
+ }
+ }
+ return pspci;
+}
+
+int
+posix_spawnattr_set_uid_np(const posix_spawnattr_t *attr, uid_t uid)
+{
+ struct _posix_spawn_posix_cred_info *pspci;
+
+ if (attr == NULL || *attr == NULL) {
+ return EINVAL;
+ }
+
+ pspci = _posix_spawnattr_get_posix_creds_info(*(_posix_spawnattr_t *)attr);
+ if (pspci == NULL) {
+ return ENOMEM;
+ }
+
+ pspci->pspci_uid = uid;
+
+ pspci->pspci_flags |= POSIX_SPAWN_POSIX_CRED_UID;
+
+ return 0;
+}
+
+int
+posix_spawnattr_set_gid_np(const posix_spawnattr_t *attr, gid_t gid)
+{
+ struct _posix_spawn_posix_cred_info *pspci;
+
+ if (attr == NULL || *attr == NULL) {
+ return EINVAL;
+ }
+
+ pspci = _posix_spawnattr_get_posix_creds_info(*(_posix_spawnattr_t *)attr);
+ if (pspci == NULL) {
+ return ENOMEM;
+ }
+
+ pspci->pspci_gid = gid;
+
+ pspci->pspci_flags |= POSIX_SPAWN_POSIX_CRED_GID;
+
+ return 0;
+}
+
+int
+posix_spawnattr_set_groups_np(const posix_spawnattr_t *attr,
+ int ngroups, gid_t *gidarray, uid_t gmuid)
+{
+ struct _posix_spawn_posix_cred_info *pspci;
+
+ if (attr == NULL || *attr == NULL) {
+ return EINVAL;
+ }
+
+ if (gidarray == NULL) {
+ return EINVAL;
+ }
+
+ if (ngroups > NGROUPS || ngroups < 0) {
+ return EINVAL;
+ }
+
+ pspci = _posix_spawnattr_get_posix_creds_info(*(_posix_spawnattr_t *)attr);
+ if (pspci == NULL) {
+ return ENOMEM;
+ }
+
+ pspci->pspci_ngroups = ngroups;
+ for (int i = 0; i < ngroups; i++) {
+ pspci->pspci_groups[i] = gidarray[i];
+ }
+
+ pspci->pspci_gmuid = gmuid;
+
+ pspci->pspci_flags |= POSIX_SPAWN_POSIX_CRED_GROUPS;
+
+ return 0;
+}
+
+int
+posix_spawnattr_set_login_np(const posix_spawnattr_t *attr, const char *login)
+{
+ struct _posix_spawn_posix_cred_info *pspci;
+
+ if (attr == NULL || *attr == NULL) {
+ return EINVAL;
+ }
+
+ if (strlen(login) > MAXLOGNAME) {
+ return ERANGE;
+ }
+
+ pspci = _posix_spawnattr_get_posix_creds_info(*(_posix_spawnattr_t *)attr);
+ if (pspci == NULL) {
+ return ENOMEM;
+ }
+
+ strlcpy(pspci->pspci_login, login, sizeof(pspci->pspci_login));
+
+ pspci->pspci_flags |= POSIX_SPAWN_POSIX_CRED_LOGIN;
+
+ return 0;
+}
+
+/*
+ * posix_spawnattr_set_jetsam_ttr_np
+ *
+ * Description: Pass data regarding recent relaunch behavior when jetsammed for the process.
+ * The recent history is effectively converted into a histogram and the highest
+ * frequency bucket defines the "type" of the process. The type is passed along
+ * to the jetsam code as part of psa_jetsam_flags.
+ *
+ * Parameters: count Number of entries in the ttrs_millis array
+ * ttrs_millis Array of raw data for relaunch behavior
+ *
+ * Returns: 0 Success
+ * EINVAL Bad attr pointer or empty data array
+ */
+int
+posix_spawnattr_set_jetsam_ttr_np(const posix_spawnattr_t * __restrict attr, uint32_t count, uint32_t *ttrs_millis)
+{
+ _posix_spawnattr_t psattr;
+
+ /*
+ * Define the bucketizing policy which would be used to generate the histogram. These
+ * values are based on looking at data from various Avg. Joanna runs.
+ */
+ static const uint32_t relaunch_buckets_msecs[POSIX_SPAWN_JETSAM_RELAUNCH_BEHAVIOR_BUCKETS] = {
+ 5000,
+ 10000,
+ UINT32_MAX
+ };
+ static const uint32_t relaunch_jetsam_flags[POSIX_SPAWN_JETSAM_RELAUNCH_BEHAVIOR_BUCKETS] = {
+ POSIX_SPAWN_JETSAM_RELAUNCH_BEHAVIOR_HIGH,
+ POSIX_SPAWN_JETSAM_RELAUNCH_BEHAVIOR_MED,
+ POSIX_SPAWN_JETSAM_RELAUNCH_BEHAVIOR_LOW
+ };