10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 52248Sraf * Common Development and Distribution License (the "License"). 62248Sraf * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 212248Sraf 220Sstevel@tonic-gate /* 232248Sraf * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 280Sstevel@tonic-gate 290Sstevel@tonic-gate #include "lint.h" 300Sstevel@tonic-gate #include "thr_uberdata.h" 313086Sraf #include <sys/libc_kernel.h> 320Sstevel@tonic-gate #include <sys/procset.h> 330Sstevel@tonic-gate #include <sys/rtpriocntl.h> 340Sstevel@tonic-gate #include <sys/tspriocntl.h> 35*3235Sraf #include <sys/fork.h> 360Sstevel@tonic-gate #include <sys/rt.h> 370Sstevel@tonic-gate #include <sys/ts.h> 380Sstevel@tonic-gate #include <alloca.h> 390Sstevel@tonic-gate #include <spawn.h> 402248Sraf #include "rtsched.h" 410Sstevel@tonic-gate 420Sstevel@tonic-gate #define ALL_POSIX_SPAWN_FLAGS \ 430Sstevel@tonic-gate (POSIX_SPAWN_RESETIDS | \ 440Sstevel@tonic-gate POSIX_SPAWN_SETPGROUP | \ 450Sstevel@tonic-gate POSIX_SPAWN_SETSIGDEF | \ 460Sstevel@tonic-gate POSIX_SPAWN_SETSIGMASK | \ 470Sstevel@tonic-gate POSIX_SPAWN_SETSCHEDPARAM | \ 48*3235Sraf POSIX_SPAWN_SETSCHEDULER | \ 49*3235Sraf POSIX_SPAWN_NOSIGCHLD_NP | \ 50*3235Sraf POSIX_SPAWN_WAITPID_NP) 510Sstevel@tonic-gate 520Sstevel@tonic-gate typedef struct { 530Sstevel@tonic-gate short sa_psflags; /* POSIX_SPAWN_* flags */ 540Sstevel@tonic-gate pri_t sa_priority; 550Sstevel@tonic-gate int sa_schedpolicy; 560Sstevel@tonic-gate pid_t sa_pgroup; 570Sstevel@tonic-gate sigset_t sa_sigdefault; 580Sstevel@tonic-gate sigset_t sa_sigmask; 590Sstevel@tonic-gate } spawn_attr_t; 600Sstevel@tonic-gate 610Sstevel@tonic-gate typedef struct file_attr { 620Sstevel@tonic-gate struct file_attr *fa_next; /* circular list of file actions */ 630Sstevel@tonic-gate struct file_attr *fa_prev; 640Sstevel@tonic-gate enum {FA_OPEN, FA_CLOSE, FA_DUP2} fa_type; 650Sstevel@tonic-gate uint_t fa_pathsize; /* size of fa_path[] array */ 660Sstevel@tonic-gate char *fa_path; /* copied pathname for open() */ 670Sstevel@tonic-gate int fa_oflag; /* oflag for open() */ 680Sstevel@tonic-gate mode_t fa_mode; /* mode for open() */ 690Sstevel@tonic-gate int fa_filedes; /* file descriptor for open()/close() */ 700Sstevel@tonic-gate int fa_newfiledes; /* new file descriptor for dup2() */ 710Sstevel@tonic-gate } file_attr_t; 720Sstevel@tonic-gate 732248Sraf extern struct pcclass ts_class, rt_class; 742248Sraf 75*3235Sraf extern pid_t _vforkx(int); 76*3235Sraf #pragma unknown_control_flow(_vforkx) 770Sstevel@tonic-gate extern void *_private_memset(void *, int, size_t); 780Sstevel@tonic-gate extern int __lwp_sigmask(int, const sigset_t *, sigset_t *); 790Sstevel@tonic-gate extern int __open(const char *, int, mode_t); 800Sstevel@tonic-gate extern int __sigaction(int, const struct sigaction *, struct sigaction *); 810Sstevel@tonic-gate extern int _private_close(int); 820Sstevel@tonic-gate extern int _private_execve(const char *, char *const *, char *const *); 830Sstevel@tonic-gate extern int _private_fcntl(int, int, intptr_t); 840Sstevel@tonic-gate extern int _private_setgid(gid_t); 850Sstevel@tonic-gate extern int _private_setpgid(pid_t, pid_t); 860Sstevel@tonic-gate extern int _private_setuid(uid_t); 870Sstevel@tonic-gate extern int _private_sigismember(sigset_t *, int); 880Sstevel@tonic-gate extern gid_t _private_getgid(void); 890Sstevel@tonic-gate extern uid_t _private_getuid(void); 900Sstevel@tonic-gate extern uid_t _private_geteuid(void); 910Sstevel@tonic-gate extern void _private_exit(int); 920Sstevel@tonic-gate 930Sstevel@tonic-gate /* 940Sstevel@tonic-gate * We call this function rather than priocntl() because we must not call 950Sstevel@tonic-gate * any function that is exported from libc while in the child of vfork(). 960Sstevel@tonic-gate * Also, we are not using PC_GETXPARMS or PC_SETXPARMS so we can use 970Sstevel@tonic-gate * the simple call to __priocntlset() rather than the varargs version. 980Sstevel@tonic-gate */ 990Sstevel@tonic-gate static long 1000Sstevel@tonic-gate _private_priocntl(idtype_t idtype, id_t id, int cmd, caddr_t arg) 1010Sstevel@tonic-gate { 1020Sstevel@tonic-gate extern long _private__priocntlset(int, procset_t *, int, caddr_t, ...); 1030Sstevel@tonic-gate procset_t procset; 1040Sstevel@tonic-gate 1050Sstevel@tonic-gate setprocset(&procset, POP_AND, idtype, id, P_ALL, 0); 1060Sstevel@tonic-gate return (_private__priocntlset(PC_VERSION, &procset, cmd, arg, 0)); 1070Sstevel@tonic-gate } 1080Sstevel@tonic-gate 1090Sstevel@tonic-gate /* 1100Sstevel@tonic-gate * The following two functions are blatently stolen from 1110Sstevel@tonic-gate * sched_setscheduler() and sched_setparam() in librt. 1120Sstevel@tonic-gate * This would be a lot easier if librt were folded into libc. 1130Sstevel@tonic-gate */ 1140Sstevel@tonic-gate static int 1150Sstevel@tonic-gate setscheduler(int policy, pri_t prio) 1160Sstevel@tonic-gate { 1170Sstevel@tonic-gate pcparms_t pcparm; 1180Sstevel@tonic-gate tsinfo_t *tsi; 1190Sstevel@tonic-gate tsparms_t *tsp; 1200Sstevel@tonic-gate int scale; 1210Sstevel@tonic-gate 1220Sstevel@tonic-gate switch (policy) { 1230Sstevel@tonic-gate case SCHED_FIFO: 1240Sstevel@tonic-gate case SCHED_RR: 1250Sstevel@tonic-gate if (prio < rt_class.pcc_primin || prio > rt_class.pcc_primax) { 1260Sstevel@tonic-gate errno = EINVAL; 1270Sstevel@tonic-gate return (-1); 1280Sstevel@tonic-gate } 1290Sstevel@tonic-gate pcparm.pc_cid = rt_class.pcc_info.pc_cid; 1300Sstevel@tonic-gate ((rtparms_t *)pcparm.pc_clparms)->rt_pri = prio; 1310Sstevel@tonic-gate ((rtparms_t *)pcparm.pc_clparms)->rt_tqnsecs = 1320Sstevel@tonic-gate (policy == SCHED_RR ? RT_TQDEF : RT_TQINF); 1330Sstevel@tonic-gate break; 1340Sstevel@tonic-gate 1350Sstevel@tonic-gate case SCHED_OTHER: 1360Sstevel@tonic-gate pcparm.pc_cid = ts_class.pcc_info.pc_cid; 1370Sstevel@tonic-gate tsi = (tsinfo_t *)ts_class.pcc_info.pc_clinfo; 1380Sstevel@tonic-gate scale = tsi->ts_maxupri; 1390Sstevel@tonic-gate tsp = (tsparms_t *)pcparm.pc_clparms; 1400Sstevel@tonic-gate tsp->ts_uprilim = tsp->ts_upri = -(scale * prio) / 20; 1410Sstevel@tonic-gate break; 1420Sstevel@tonic-gate 1430Sstevel@tonic-gate default: 1440Sstevel@tonic-gate errno = EINVAL; 1450Sstevel@tonic-gate return (-1); 1460Sstevel@tonic-gate } 1470Sstevel@tonic-gate 1480Sstevel@tonic-gate return (_private_priocntl(P_PID, P_MYID, 1490Sstevel@tonic-gate PC_SETPARMS, (caddr_t)&pcparm)); 1500Sstevel@tonic-gate } 1510Sstevel@tonic-gate 1520Sstevel@tonic-gate static int 1530Sstevel@tonic-gate setparam(pcparms_t *pcparmp, pri_t prio) 1540Sstevel@tonic-gate { 1550Sstevel@tonic-gate tsparms_t *tsp; 1560Sstevel@tonic-gate tsinfo_t *tsi; 1570Sstevel@tonic-gate int scale; 1580Sstevel@tonic-gate 1590Sstevel@tonic-gate if (pcparmp->pc_cid == rt_class.pcc_info.pc_cid) { 1600Sstevel@tonic-gate /* SCHED_FIFO or SCHED_RR policy */ 1610Sstevel@tonic-gate if (prio < rt_class.pcc_primin || prio > rt_class.pcc_primax) { 1620Sstevel@tonic-gate errno = EINVAL; 1630Sstevel@tonic-gate return (-1); 1640Sstevel@tonic-gate } 1650Sstevel@tonic-gate ((rtparms_t *)pcparmp->pc_clparms)->rt_tqnsecs = RT_NOCHANGE; 1660Sstevel@tonic-gate ((rtparms_t *)pcparmp->pc_clparms)->rt_pri = prio; 1670Sstevel@tonic-gate } else if (pcparmp->pc_cid == ts_class.pcc_info.pc_cid) { 1680Sstevel@tonic-gate /* SCHED_OTHER policy */ 1690Sstevel@tonic-gate tsi = (tsinfo_t *)ts_class.pcc_info.pc_clinfo; 1700Sstevel@tonic-gate scale = tsi->ts_maxupri; 1710Sstevel@tonic-gate tsp = (tsparms_t *)pcparmp->pc_clparms; 1720Sstevel@tonic-gate tsp->ts_uprilim = tsp->ts_upri = -(scale * prio) / 20; 1730Sstevel@tonic-gate } else { 1740Sstevel@tonic-gate errno = EINVAL; 1750Sstevel@tonic-gate return (-1); 1760Sstevel@tonic-gate } 1770Sstevel@tonic-gate 1780Sstevel@tonic-gate return (_private_priocntl(P_PID, P_MYID, 1790Sstevel@tonic-gate PC_SETPARMS, (caddr_t)pcparmp)); 1800Sstevel@tonic-gate } 1810Sstevel@tonic-gate 1823086Sraf static int 1830Sstevel@tonic-gate perform_flag_actions(spawn_attr_t *sap) 1840Sstevel@tonic-gate { 1850Sstevel@tonic-gate int sig; 1860Sstevel@tonic-gate 1870Sstevel@tonic-gate if (sap->sa_psflags & POSIX_SPAWN_SETSIGMASK) { 1880Sstevel@tonic-gate (void) __lwp_sigmask(SIG_SETMASK, &sap->sa_sigmask, NULL); 1890Sstevel@tonic-gate } 1900Sstevel@tonic-gate 1910Sstevel@tonic-gate if (sap->sa_psflags & POSIX_SPAWN_SETSIGDEF) { 1920Sstevel@tonic-gate struct sigaction sigdfl; 1930Sstevel@tonic-gate 1940Sstevel@tonic-gate (void) _private_memset(&sigdfl, 0, sizeof (sigdfl)); 1950Sstevel@tonic-gate for (sig = 1; sig < NSIG; sig++) { 1960Sstevel@tonic-gate if (_private_sigismember(&sap->sa_sigdefault, sig)) 1970Sstevel@tonic-gate (void) __sigaction(sig, &sigdfl, NULL); 1980Sstevel@tonic-gate } 1990Sstevel@tonic-gate } 2000Sstevel@tonic-gate 2010Sstevel@tonic-gate if (sap->sa_psflags & POSIX_SPAWN_RESETIDS) { 2020Sstevel@tonic-gate if (_private_setgid(_private_getgid()) != 0 || 2030Sstevel@tonic-gate _private_setuid(_private_getuid()) != 0) 2043086Sraf return (errno); 2050Sstevel@tonic-gate } 2060Sstevel@tonic-gate 2070Sstevel@tonic-gate if (sap->sa_psflags & POSIX_SPAWN_SETPGROUP) { 2080Sstevel@tonic-gate if (_private_setpgid(0, sap->sa_pgroup) != 0) 2093086Sraf return (errno); 2100Sstevel@tonic-gate } 2110Sstevel@tonic-gate 2120Sstevel@tonic-gate if (sap->sa_psflags & POSIX_SPAWN_SETSCHEDULER) { 2130Sstevel@tonic-gate if (setscheduler(sap->sa_schedpolicy, sap->sa_priority) != 0) 2143086Sraf return (errno); 2150Sstevel@tonic-gate } else if (sap->sa_psflags & POSIX_SPAWN_SETSCHEDPARAM) { 2160Sstevel@tonic-gate /* 2170Sstevel@tonic-gate * Get the process's current scheduling parameters, 2180Sstevel@tonic-gate * then modify to set the new priority. 2190Sstevel@tonic-gate */ 2200Sstevel@tonic-gate pcparms_t pcparm; 2210Sstevel@tonic-gate 2220Sstevel@tonic-gate pcparm.pc_cid = PC_CLNULL; 2230Sstevel@tonic-gate if (_private_priocntl(P_PID, P_MYID, 2240Sstevel@tonic-gate PC_GETPARMS, (caddr_t)&pcparm) == -1) 2253086Sraf return (errno); 2260Sstevel@tonic-gate if (setparam(&pcparm, sap->sa_priority) != 0) 2273086Sraf return (errno); 2280Sstevel@tonic-gate } 2293086Sraf 2303086Sraf return (0); 2310Sstevel@tonic-gate } 2320Sstevel@tonic-gate 2333086Sraf static int 2340Sstevel@tonic-gate perform_file_actions(file_attr_t *fap) 2350Sstevel@tonic-gate { 2360Sstevel@tonic-gate file_attr_t *froot = fap; 2370Sstevel@tonic-gate int fd; 2380Sstevel@tonic-gate 2390Sstevel@tonic-gate do { 2400Sstevel@tonic-gate switch (fap->fa_type) { 2410Sstevel@tonic-gate case FA_OPEN: 2420Sstevel@tonic-gate fd = __open(fap->fa_path, fap->fa_oflag, fap->fa_mode); 2430Sstevel@tonic-gate if (fd < 0) 2443086Sraf return (errno); 2450Sstevel@tonic-gate if (fd != fap->fa_filedes) { 2460Sstevel@tonic-gate if (_private_fcntl(fd, F_DUP2FD, 2470Sstevel@tonic-gate fap->fa_filedes) < 0) 2483086Sraf return (errno); 2490Sstevel@tonic-gate (void) _private_close(fd); 2500Sstevel@tonic-gate } 2510Sstevel@tonic-gate break; 2520Sstevel@tonic-gate case FA_CLOSE: 2530Sstevel@tonic-gate if (_private_close(fap->fa_filedes) == -1) 2543086Sraf return (errno); 2550Sstevel@tonic-gate break; 2560Sstevel@tonic-gate case FA_DUP2: 2570Sstevel@tonic-gate fd = _private_fcntl(fap->fa_filedes, F_DUP2FD, 2580Sstevel@tonic-gate fap->fa_newfiledes); 2590Sstevel@tonic-gate if (fd < 0) 2603086Sraf return (errno); 2610Sstevel@tonic-gate break; 2620Sstevel@tonic-gate } 2630Sstevel@tonic-gate } while ((fap = fap->fa_next) != froot); 2643086Sraf 2653086Sraf return (0); 2663086Sraf } 2673086Sraf 268*3235Sraf static int 269*3235Sraf forkflags(spawn_attr_t *sap) 270*3235Sraf { 271*3235Sraf int flags = 0; 272*3235Sraf 273*3235Sraf if (sap != NULL) { 274*3235Sraf if (sap->sa_psflags & POSIX_SPAWN_NOSIGCHLD_NP) 275*3235Sraf flags |= FORK_NOSIGCHLD; 276*3235Sraf if (sap->sa_psflags & POSIX_SPAWN_WAITPID_NP) 277*3235Sraf flags |= FORK_WAITPID; 278*3235Sraf } 279*3235Sraf 280*3235Sraf return (flags); 281*3235Sraf } 282*3235Sraf 2833086Sraf /* 2843086Sraf * set_error() / get_error() are used to guarantee that the local variable 2853086Sraf * 'error' is set correctly in memory on return from vfork() in the parent. 2863086Sraf */ 2873086Sraf 2883086Sraf static int 2893086Sraf set_error(int *errp, int err) 2903086Sraf { 2913086Sraf return (*errp = err); 2923086Sraf } 2933086Sraf 2943086Sraf static int 2953086Sraf get_error(int *errp) 2963086Sraf { 2973086Sraf return (*errp); 2980Sstevel@tonic-gate } 2990Sstevel@tonic-gate 3000Sstevel@tonic-gate /* 3010Sstevel@tonic-gate * For MT safety, do not invoke the dynamic linker after calling vfork(). 3020Sstevel@tonic-gate * If some other thread was in the dynamic linker when this thread's parent 3030Sstevel@tonic-gate * called vfork() then the dynamic linker's lock would still be held here 3040Sstevel@tonic-gate * (with a defunct owner) and we would deadlock ourself if we invoked it. 3050Sstevel@tonic-gate * 3060Sstevel@tonic-gate * Therefore, all of the functions we call here after returning from 307*3235Sraf * _vforkx() in the child are not and must never be exported from libc 3080Sstevel@tonic-gate * as global symbols. To do so would risk invoking the dynamic linker. 3090Sstevel@tonic-gate */ 3100Sstevel@tonic-gate 3110Sstevel@tonic-gate #pragma weak posix_spawn = _posix_spawn 3120Sstevel@tonic-gate int 3130Sstevel@tonic-gate _posix_spawn( 3140Sstevel@tonic-gate pid_t *pidp, 3150Sstevel@tonic-gate const char *path, 3160Sstevel@tonic-gate const posix_spawn_file_actions_t *file_actions, 3170Sstevel@tonic-gate const posix_spawnattr_t *attrp, 3180Sstevel@tonic-gate char *const argv[], 3190Sstevel@tonic-gate char *const envp[]) 3200Sstevel@tonic-gate { 3210Sstevel@tonic-gate spawn_attr_t *sap = attrp? attrp->__spawn_attrp : NULL; 3220Sstevel@tonic-gate file_attr_t *fap = file_actions? file_actions->__file_attrp : NULL; 3233086Sraf int error; /* this will be set by the child */ 3240Sstevel@tonic-gate pid_t pid; 3250Sstevel@tonic-gate 3260Sstevel@tonic-gate if (attrp != NULL && sap == NULL) 3270Sstevel@tonic-gate return (EINVAL); 3280Sstevel@tonic-gate 329*3235Sraf switch (pid = _vforkx(forkflags(sap))) { 3300Sstevel@tonic-gate case 0: /* child */ 3310Sstevel@tonic-gate break; 3320Sstevel@tonic-gate case -1: /* parent, failure */ 3330Sstevel@tonic-gate return (errno); 3340Sstevel@tonic-gate default: /* parent, success */ 3353086Sraf /* 3363086Sraf * We don't get here until the child exec()s or exit()s 3373086Sraf */ 3383086Sraf if (pidp != NULL && get_error(&error) == 0) 3390Sstevel@tonic-gate *pidp = pid; 3403086Sraf return (get_error(&error)); 3410Sstevel@tonic-gate } 3420Sstevel@tonic-gate 3430Sstevel@tonic-gate if (sap != NULL) 3443086Sraf if (set_error(&error, perform_flag_actions(sap)) != 0) 3453086Sraf _private_exit(_EVAPORATE); 3460Sstevel@tonic-gate 3470Sstevel@tonic-gate if (fap != NULL) 3483086Sraf if (set_error(&error, perform_file_actions(fap)) != 0) 3493086Sraf _private_exit(_EVAPORATE); 3500Sstevel@tonic-gate 3513086Sraf (void) set_error(&error, 0); 3520Sstevel@tonic-gate (void) _private_execve(path, argv, envp); 3533086Sraf (void) set_error(&error, errno); 3543086Sraf _private_exit(_EVAPORATE); 3550Sstevel@tonic-gate return (0); /* not reached */ 3560Sstevel@tonic-gate } 3570Sstevel@tonic-gate 3580Sstevel@tonic-gate /* 3590Sstevel@tonic-gate * Much of posix_spawnp() blatently stolen from execvp() (port/gen/execvp.c). 3600Sstevel@tonic-gate */ 3610Sstevel@tonic-gate 3620Sstevel@tonic-gate extern int __xpg4; /* defined in xpg4.c; 0 if not xpg4-compiled program */ 3630Sstevel@tonic-gate 3640Sstevel@tonic-gate static const char * 3650Sstevel@tonic-gate execat(const char *s1, const char *s2, char *si) 3660Sstevel@tonic-gate { 3670Sstevel@tonic-gate int cnt = PATH_MAX + 1; 3680Sstevel@tonic-gate char *s; 3690Sstevel@tonic-gate char c; 3700Sstevel@tonic-gate 3710Sstevel@tonic-gate for (s = si; (c = *s1) != '\0' && c != ':'; s1++) { 3720Sstevel@tonic-gate if (cnt > 0) { 3730Sstevel@tonic-gate *s++ = c; 3740Sstevel@tonic-gate cnt--; 3750Sstevel@tonic-gate } 3760Sstevel@tonic-gate } 3770Sstevel@tonic-gate if (si != s && cnt > 0) { 3780Sstevel@tonic-gate *s++ = '/'; 3790Sstevel@tonic-gate cnt--; 3800Sstevel@tonic-gate } 3810Sstevel@tonic-gate for (; (c = *s2) != '\0' && cnt > 0; s2++) { 3820Sstevel@tonic-gate *s++ = c; 3830Sstevel@tonic-gate cnt--; 3840Sstevel@tonic-gate } 3850Sstevel@tonic-gate *s = '\0'; 3860Sstevel@tonic-gate return (*s1? ++s1: NULL); 3870Sstevel@tonic-gate } 3880Sstevel@tonic-gate 3890Sstevel@tonic-gate #pragma weak posix_spawnp = _posix_spawnp 3900Sstevel@tonic-gate /* ARGSUSED */ 3910Sstevel@tonic-gate int 3920Sstevel@tonic-gate _posix_spawnp( 3930Sstevel@tonic-gate pid_t *pidp, 3940Sstevel@tonic-gate const char *file, 3950Sstevel@tonic-gate const posix_spawn_file_actions_t *file_actions, 3960Sstevel@tonic-gate const posix_spawnattr_t *attrp, 3970Sstevel@tonic-gate char *const argv[], 3980Sstevel@tonic-gate char *const envp[]) 3990Sstevel@tonic-gate { 4000Sstevel@tonic-gate spawn_attr_t *sap = attrp? attrp->__spawn_attrp : NULL; 4010Sstevel@tonic-gate file_attr_t *fap = file_actions? file_actions->__file_attrp : NULL; 4020Sstevel@tonic-gate const char *pathstr = (strchr(file, '/') == NULL)? getenv("PATH") : ""; 4030Sstevel@tonic-gate int xpg4 = __xpg4; 4043086Sraf int error; /* this will be set by the child */ 4050Sstevel@tonic-gate char path[PATH_MAX+4]; 4060Sstevel@tonic-gate const char *cp; 4070Sstevel@tonic-gate pid_t pid; 4080Sstevel@tonic-gate char **newargs; 4090Sstevel@tonic-gate int argc; 4100Sstevel@tonic-gate int i; 4110Sstevel@tonic-gate static const char *sun_path = "/bin/sh"; 4120Sstevel@tonic-gate static const char *xpg4_path = "/usr/xpg4/bin/sh"; 4130Sstevel@tonic-gate static const char *shell = "sh"; 4140Sstevel@tonic-gate 4150Sstevel@tonic-gate if (attrp != NULL && sap == NULL) 4160Sstevel@tonic-gate return (EINVAL); 4170Sstevel@tonic-gate 4183086Sraf if (*file == '\0') 4193086Sraf return (EACCES); 4203086Sraf 4210Sstevel@tonic-gate /* 4220Sstevel@tonic-gate * We may need to invoke the shell with a slightly modified 4230Sstevel@tonic-gate * argv[] array. To do this we need to preallocate the array. 4240Sstevel@tonic-gate * We must call alloca() before calling vfork() because doing 4250Sstevel@tonic-gate * it after vfork() (in the child) would corrupt the parent. 4260Sstevel@tonic-gate */ 4270Sstevel@tonic-gate for (argc = 0; argv[argc] != NULL; argc++) 4280Sstevel@tonic-gate continue; 4290Sstevel@tonic-gate newargs = alloca((argc + 2) * sizeof (char *)); 4300Sstevel@tonic-gate 431*3235Sraf switch (pid = _vforkx(forkflags(sap))) { 4320Sstevel@tonic-gate case 0: /* child */ 4330Sstevel@tonic-gate break; 4340Sstevel@tonic-gate case -1: /* parent, failure */ 4350Sstevel@tonic-gate return (errno); 4360Sstevel@tonic-gate default: /* parent, success */ 4373086Sraf /* 4383086Sraf * We don't get here until the child exec()s or exit()s 4393086Sraf */ 4403086Sraf if (pidp != NULL && get_error(&error) == 0) 4410Sstevel@tonic-gate *pidp = pid; 4423086Sraf return (get_error(&error)); 4430Sstevel@tonic-gate } 4440Sstevel@tonic-gate 4450Sstevel@tonic-gate if (sap != NULL) 4463086Sraf if (set_error(&error, perform_flag_actions(sap)) != 0) 4473086Sraf _private_exit(_EVAPORATE); 4480Sstevel@tonic-gate 4490Sstevel@tonic-gate if (fap != NULL) 4503086Sraf if (set_error(&error, perform_file_actions(fap)) != 0) 4513086Sraf _private_exit(_EVAPORATE); 4520Sstevel@tonic-gate 4530Sstevel@tonic-gate if (pathstr == NULL) { 4540Sstevel@tonic-gate /* 4550Sstevel@tonic-gate * XPG4: pathstr is equivalent to _CS_PATH, except that 4560Sstevel@tonic-gate * :/usr/sbin is appended when root, and pathstr must end 4570Sstevel@tonic-gate * with a colon when not root. Keep these paths in sync 4580Sstevel@tonic-gate * with _CS_PATH in confstr.c. Note that pathstr must end 4590Sstevel@tonic-gate * with a colon when not root so that when file doesn't 4600Sstevel@tonic-gate * contain '/', the last call to execat() will result in an 4610Sstevel@tonic-gate * attempt to execv file from the current directory. 4620Sstevel@tonic-gate */ 4630Sstevel@tonic-gate if (_private_geteuid() == 0 || _private_getuid() == 0) { 4640Sstevel@tonic-gate if (!xpg4) 4650Sstevel@tonic-gate pathstr = "/usr/sbin:/usr/ccs/bin:/usr/bin"; 4660Sstevel@tonic-gate else 4670Sstevel@tonic-gate pathstr = "/usr/xpg4/bin:/usr/ccs/bin:" 4680Sstevel@tonic-gate "/usr/bin:/opt/SUNWspro/bin:/usr/sbin"; 4690Sstevel@tonic-gate } else { 4700Sstevel@tonic-gate if (!xpg4) 4710Sstevel@tonic-gate pathstr = "/usr/ccs/bin:/usr/bin:"; 4720Sstevel@tonic-gate else 4730Sstevel@tonic-gate pathstr = "/usr/xpg4/bin:/usr/ccs/bin:" 4740Sstevel@tonic-gate "/usr/bin:/opt/SUNWspro/bin:"; 4750Sstevel@tonic-gate } 4760Sstevel@tonic-gate } 4770Sstevel@tonic-gate 4780Sstevel@tonic-gate cp = pathstr; 4790Sstevel@tonic-gate do { 4800Sstevel@tonic-gate cp = execat(cp, file, path); 4810Sstevel@tonic-gate /* 4820Sstevel@tonic-gate * 4025035 and 4038378 4830Sstevel@tonic-gate * if a filename begins with a "-" prepend "./" so that 4840Sstevel@tonic-gate * the shell can't interpret it as an option 4850Sstevel@tonic-gate */ 4860Sstevel@tonic-gate if (*path == '-') { 4870Sstevel@tonic-gate char *s; 4880Sstevel@tonic-gate 4890Sstevel@tonic-gate for (s = path; *s != '\0'; s++) 4900Sstevel@tonic-gate continue; 4910Sstevel@tonic-gate for (; s >= path; s--) 4920Sstevel@tonic-gate *(s + 2) = *s; 4930Sstevel@tonic-gate path[0] = '.'; 4940Sstevel@tonic-gate path[1] = '/'; 4950Sstevel@tonic-gate } 4963086Sraf (void) set_error(&error, 0); 4970Sstevel@tonic-gate (void) _private_execve(path, argv, envp); 4983086Sraf if (set_error(&error, errno) == ENOEXEC) { 4990Sstevel@tonic-gate newargs[0] = (char *)shell; 5000Sstevel@tonic-gate newargs[1] = path; 5010Sstevel@tonic-gate for (i = 1; i <= argc; i++) 5020Sstevel@tonic-gate newargs[i + 1] = argv[i]; 5033086Sraf (void) set_error(&error, 0); 5040Sstevel@tonic-gate (void) _private_execve(xpg4? xpg4_path : sun_path, 5053086Sraf newargs, envp); 5063086Sraf (void) set_error(&error, errno); 5073086Sraf _private_exit(_EVAPORATE); 5080Sstevel@tonic-gate } 5090Sstevel@tonic-gate } while (cp); 5103086Sraf _private_exit(_EVAPORATE); 5110Sstevel@tonic-gate return (0); /* not reached */ 5120Sstevel@tonic-gate } 5130Sstevel@tonic-gate 5140Sstevel@tonic-gate #pragma weak posix_spawn_file_actions_init = \ 5150Sstevel@tonic-gate _posix_spawn_file_actions_init 5160Sstevel@tonic-gate int 5170Sstevel@tonic-gate _posix_spawn_file_actions_init( 5180Sstevel@tonic-gate posix_spawn_file_actions_t *file_actions) 5190Sstevel@tonic-gate { 5200Sstevel@tonic-gate file_actions->__file_attrp = NULL; 5210Sstevel@tonic-gate return (0); 5220Sstevel@tonic-gate } 5230Sstevel@tonic-gate 5240Sstevel@tonic-gate #pragma weak posix_spawn_file_actions_destroy = \ 5250Sstevel@tonic-gate _posix_spawn_file_actions_destroy 5260Sstevel@tonic-gate int 5270Sstevel@tonic-gate _posix_spawn_file_actions_destroy( 5280Sstevel@tonic-gate posix_spawn_file_actions_t *file_actions) 5290Sstevel@tonic-gate { 5300Sstevel@tonic-gate file_attr_t *froot = file_actions->__file_attrp; 5310Sstevel@tonic-gate file_attr_t *fap; 5320Sstevel@tonic-gate file_attr_t *next; 5330Sstevel@tonic-gate 5340Sstevel@tonic-gate if ((fap = froot) != NULL) { 5350Sstevel@tonic-gate do { 5360Sstevel@tonic-gate next = fap->fa_next; 5370Sstevel@tonic-gate if (fap-> fa_type == FA_OPEN) 5380Sstevel@tonic-gate lfree(fap->fa_path, fap->fa_pathsize); 5390Sstevel@tonic-gate lfree(fap, sizeof (*fap)); 5400Sstevel@tonic-gate } while ((fap = next) != froot); 5410Sstevel@tonic-gate } 5420Sstevel@tonic-gate file_actions->__file_attrp = NULL; 5430Sstevel@tonic-gate return (0); 5440Sstevel@tonic-gate } 5450Sstevel@tonic-gate 5460Sstevel@tonic-gate static void 5470Sstevel@tonic-gate add_file_attr(posix_spawn_file_actions_t *file_actions, file_attr_t *fap) 5480Sstevel@tonic-gate { 5490Sstevel@tonic-gate file_attr_t *froot = file_actions->__file_attrp; 5500Sstevel@tonic-gate 5510Sstevel@tonic-gate if (froot == NULL) { 5520Sstevel@tonic-gate fap->fa_next = fap->fa_prev = fap; 5530Sstevel@tonic-gate file_actions->__file_attrp = fap; 5540Sstevel@tonic-gate } else { 5550Sstevel@tonic-gate fap->fa_next = froot; 5560Sstevel@tonic-gate fap->fa_prev = froot->fa_prev; 5570Sstevel@tonic-gate froot->fa_prev->fa_next = fap; 5580Sstevel@tonic-gate froot->fa_prev = fap; 5590Sstevel@tonic-gate } 5600Sstevel@tonic-gate } 5610Sstevel@tonic-gate 5620Sstevel@tonic-gate #pragma weak posix_spawn_file_actions_addopen = \ 5630Sstevel@tonic-gate _posix_spawn_file_actions_addopen 5640Sstevel@tonic-gate int 5650Sstevel@tonic-gate _posix_spawn_file_actions_addopen( 5660Sstevel@tonic-gate posix_spawn_file_actions_t *file_actions, 5670Sstevel@tonic-gate int filedes, 5680Sstevel@tonic-gate const char *path, 5690Sstevel@tonic-gate int oflag, 5700Sstevel@tonic-gate mode_t mode) 5710Sstevel@tonic-gate { 5720Sstevel@tonic-gate file_attr_t *fap; 5730Sstevel@tonic-gate 5740Sstevel@tonic-gate if (filedes < 0) 5750Sstevel@tonic-gate return (EBADF); 5760Sstevel@tonic-gate if ((fap = lmalloc(sizeof (*fap))) == NULL) 5770Sstevel@tonic-gate return (ENOMEM); 5780Sstevel@tonic-gate 5790Sstevel@tonic-gate fap->fa_pathsize = strlen(path) + 1; 5800Sstevel@tonic-gate if ((fap->fa_path = lmalloc(fap->fa_pathsize)) == NULL) { 5810Sstevel@tonic-gate lfree(fap, sizeof (*fap)); 5820Sstevel@tonic-gate return (ENOMEM); 5830Sstevel@tonic-gate } 5840Sstevel@tonic-gate (void) strcpy(fap->fa_path, path); 5850Sstevel@tonic-gate 5860Sstevel@tonic-gate fap->fa_type = FA_OPEN; 5870Sstevel@tonic-gate fap->fa_oflag = oflag; 5880Sstevel@tonic-gate fap->fa_mode = mode; 5890Sstevel@tonic-gate fap->fa_filedes = filedes; 5900Sstevel@tonic-gate add_file_attr(file_actions, fap); 5910Sstevel@tonic-gate 5920Sstevel@tonic-gate return (0); 5930Sstevel@tonic-gate } 5940Sstevel@tonic-gate 5950Sstevel@tonic-gate #pragma weak posix_spawn_file_actions_addclose = \ 5960Sstevel@tonic-gate _posix_spawn_file_actions_addclose 5970Sstevel@tonic-gate int 5980Sstevel@tonic-gate _posix_spawn_file_actions_addclose( 5990Sstevel@tonic-gate posix_spawn_file_actions_t *file_actions, 6000Sstevel@tonic-gate int filedes) 6010Sstevel@tonic-gate { 6020Sstevel@tonic-gate file_attr_t *fap; 6030Sstevel@tonic-gate 6040Sstevel@tonic-gate if (filedes < 0) 6050Sstevel@tonic-gate return (EBADF); 6060Sstevel@tonic-gate if ((fap = lmalloc(sizeof (*fap))) == NULL) 6070Sstevel@tonic-gate return (ENOMEM); 6080Sstevel@tonic-gate 6090Sstevel@tonic-gate fap->fa_type = FA_CLOSE; 6100Sstevel@tonic-gate fap->fa_filedes = filedes; 6110Sstevel@tonic-gate add_file_attr(file_actions, fap); 6120Sstevel@tonic-gate 6130Sstevel@tonic-gate return (0); 6140Sstevel@tonic-gate } 6150Sstevel@tonic-gate 6160Sstevel@tonic-gate #pragma weak posix_spawn_file_actions_adddup2 = \ 6170Sstevel@tonic-gate _posix_spawn_file_actions_adddup2 6180Sstevel@tonic-gate int 6190Sstevel@tonic-gate _posix_spawn_file_actions_adddup2( 6200Sstevel@tonic-gate posix_spawn_file_actions_t *file_actions, 6210Sstevel@tonic-gate int filedes, 6220Sstevel@tonic-gate int newfiledes) 6230Sstevel@tonic-gate { 6240Sstevel@tonic-gate file_attr_t *fap; 6250Sstevel@tonic-gate 6260Sstevel@tonic-gate if (filedes < 0 || newfiledes < 0) 6270Sstevel@tonic-gate return (EBADF); 6280Sstevel@tonic-gate if ((fap = lmalloc(sizeof (*fap))) == NULL) 6290Sstevel@tonic-gate return (ENOMEM); 6300Sstevel@tonic-gate 6310Sstevel@tonic-gate fap->fa_type = FA_DUP2; 6320Sstevel@tonic-gate fap->fa_filedes = filedes; 6330Sstevel@tonic-gate fap->fa_newfiledes = newfiledes; 6340Sstevel@tonic-gate add_file_attr(file_actions, fap); 6350Sstevel@tonic-gate 6360Sstevel@tonic-gate return (0); 6370Sstevel@tonic-gate } 6380Sstevel@tonic-gate 6390Sstevel@tonic-gate #pragma weak posix_spawnattr_init = \ 6400Sstevel@tonic-gate _posix_spawnattr_init 6410Sstevel@tonic-gate int 6420Sstevel@tonic-gate _posix_spawnattr_init( 6430Sstevel@tonic-gate posix_spawnattr_t *attr) 6440Sstevel@tonic-gate { 645*3235Sraf if ((attr->__spawn_attrp = lmalloc(sizeof (posix_spawnattr_t))) == NULL) 6460Sstevel@tonic-gate return (ENOMEM); 6470Sstevel@tonic-gate /* 6480Sstevel@tonic-gate * Add default stuff here? 6490Sstevel@tonic-gate */ 6500Sstevel@tonic-gate return (0); 6510Sstevel@tonic-gate } 6520Sstevel@tonic-gate 6530Sstevel@tonic-gate #pragma weak posix_spawnattr_destroy = \ 6540Sstevel@tonic-gate _posix_spawnattr_destroy 6550Sstevel@tonic-gate int 6560Sstevel@tonic-gate _posix_spawnattr_destroy( 6570Sstevel@tonic-gate posix_spawnattr_t *attr) 6580Sstevel@tonic-gate { 6590Sstevel@tonic-gate spawn_attr_t *sap = attr->__spawn_attrp; 6600Sstevel@tonic-gate 6610Sstevel@tonic-gate if (sap == NULL) 6620Sstevel@tonic-gate return (EINVAL); 6630Sstevel@tonic-gate 6640Sstevel@tonic-gate /* 6650Sstevel@tonic-gate * deallocate stuff here? 6660Sstevel@tonic-gate */ 6670Sstevel@tonic-gate lfree(sap, sizeof (*sap)); 6680Sstevel@tonic-gate attr->__spawn_attrp = NULL; 6690Sstevel@tonic-gate return (0); 6700Sstevel@tonic-gate } 6710Sstevel@tonic-gate 6720Sstevel@tonic-gate #pragma weak posix_spawnattr_setflags = \ 6730Sstevel@tonic-gate _posix_spawnattr_setflags 6740Sstevel@tonic-gate int 6750Sstevel@tonic-gate _posix_spawnattr_setflags( 6760Sstevel@tonic-gate posix_spawnattr_t *attr, 6770Sstevel@tonic-gate short flags) 6780Sstevel@tonic-gate { 6790Sstevel@tonic-gate spawn_attr_t *sap = attr->__spawn_attrp; 6800Sstevel@tonic-gate 6810Sstevel@tonic-gate if (sap == NULL || 6820Sstevel@tonic-gate (flags & ~ALL_POSIX_SPAWN_FLAGS)) 6830Sstevel@tonic-gate return (EINVAL); 6840Sstevel@tonic-gate 6850Sstevel@tonic-gate if (flags & (POSIX_SPAWN_SETSCHEDPARAM | POSIX_SPAWN_SETSCHEDULER)) { 6860Sstevel@tonic-gate /* 6870Sstevel@tonic-gate * Populate ts_class and rt_class. 6880Sstevel@tonic-gate * We will need them in the child of vfork(). 6890Sstevel@tonic-gate */ 6902248Sraf if (rt_class.pcc_state == 0) 6912248Sraf (void) get_info_by_policy(SCHED_FIFO); 6922248Sraf if (ts_class.pcc_state == 0) 6932248Sraf (void) get_info_by_policy(SCHED_OTHER); 6940Sstevel@tonic-gate } 6950Sstevel@tonic-gate 6960Sstevel@tonic-gate sap->sa_psflags = flags; 6970Sstevel@tonic-gate return (0); 6980Sstevel@tonic-gate } 6990Sstevel@tonic-gate 7000Sstevel@tonic-gate #pragma weak posix_spawnattr_getflags = \ 7010Sstevel@tonic-gate _posix_spawnattr_getflags 7020Sstevel@tonic-gate int 7030Sstevel@tonic-gate _posix_spawnattr_getflags( 7040Sstevel@tonic-gate const posix_spawnattr_t *attr, 7050Sstevel@tonic-gate short *flags) 7060Sstevel@tonic-gate { 7070Sstevel@tonic-gate spawn_attr_t *sap = attr->__spawn_attrp; 7080Sstevel@tonic-gate 7090Sstevel@tonic-gate if (sap == NULL) 7100Sstevel@tonic-gate return (EINVAL); 7110Sstevel@tonic-gate 7120Sstevel@tonic-gate *flags = sap->sa_psflags; 7130Sstevel@tonic-gate return (0); 7140Sstevel@tonic-gate } 7150Sstevel@tonic-gate 7160Sstevel@tonic-gate #pragma weak posix_spawnattr_setpgroup = \ 7170Sstevel@tonic-gate _posix_spawnattr_setpgroup 7180Sstevel@tonic-gate int 7190Sstevel@tonic-gate _posix_spawnattr_setpgroup( 7200Sstevel@tonic-gate posix_spawnattr_t *attr, 7210Sstevel@tonic-gate pid_t pgroup) 7220Sstevel@tonic-gate { 7230Sstevel@tonic-gate spawn_attr_t *sap = attr->__spawn_attrp; 7240Sstevel@tonic-gate 7250Sstevel@tonic-gate if (sap == NULL) 7260Sstevel@tonic-gate return (EINVAL); 7270Sstevel@tonic-gate 7280Sstevel@tonic-gate sap->sa_pgroup = pgroup; 7290Sstevel@tonic-gate return (0); 7300Sstevel@tonic-gate } 7310Sstevel@tonic-gate 7320Sstevel@tonic-gate #pragma weak posix_spawnattr_getpgroup = \ 7330Sstevel@tonic-gate _posix_spawnattr_getpgroup 7340Sstevel@tonic-gate int 7350Sstevel@tonic-gate _posix_spawnattr_getpgroup( 7360Sstevel@tonic-gate const posix_spawnattr_t *attr, 7370Sstevel@tonic-gate pid_t *pgroup) 7380Sstevel@tonic-gate { 7390Sstevel@tonic-gate spawn_attr_t *sap = attr->__spawn_attrp; 7400Sstevel@tonic-gate 7410Sstevel@tonic-gate if (sap == NULL) 7420Sstevel@tonic-gate return (EINVAL); 7430Sstevel@tonic-gate 7440Sstevel@tonic-gate *pgroup = sap->sa_pgroup; 7450Sstevel@tonic-gate return (0); 7460Sstevel@tonic-gate } 7470Sstevel@tonic-gate 7480Sstevel@tonic-gate #pragma weak posix_spawnattr_setschedparam = \ 7490Sstevel@tonic-gate _posix_spawnattr_setschedparam 7500Sstevel@tonic-gate int 7510Sstevel@tonic-gate _posix_spawnattr_setschedparam( 7520Sstevel@tonic-gate posix_spawnattr_t *attr, 7530Sstevel@tonic-gate const struct sched_param *schedparam) 7540Sstevel@tonic-gate { 7550Sstevel@tonic-gate spawn_attr_t *sap = attr->__spawn_attrp; 7560Sstevel@tonic-gate 7570Sstevel@tonic-gate if (sap == NULL) 7580Sstevel@tonic-gate return (EINVAL); 7590Sstevel@tonic-gate 7600Sstevel@tonic-gate /* 7610Sstevel@tonic-gate * Check validity? 7620Sstevel@tonic-gate */ 7630Sstevel@tonic-gate sap->sa_priority = schedparam->sched_priority; 7640Sstevel@tonic-gate return (0); 7650Sstevel@tonic-gate } 7660Sstevel@tonic-gate 7670Sstevel@tonic-gate #pragma weak posix_spawnattr_getschedparam = \ 7680Sstevel@tonic-gate _posix_spawnattr_getschedparam 7690Sstevel@tonic-gate int 7700Sstevel@tonic-gate _posix_spawnattr_getschedparam( 7710Sstevel@tonic-gate const posix_spawnattr_t *attr, 7720Sstevel@tonic-gate struct sched_param *schedparam) 7730Sstevel@tonic-gate { 7740Sstevel@tonic-gate spawn_attr_t *sap = attr->__spawn_attrp; 7750Sstevel@tonic-gate 7760Sstevel@tonic-gate if (sap == NULL) 7770Sstevel@tonic-gate return (EINVAL); 7780Sstevel@tonic-gate 7790Sstevel@tonic-gate schedparam->sched_priority = sap->sa_priority; 7800Sstevel@tonic-gate return (0); 7810Sstevel@tonic-gate } 7820Sstevel@tonic-gate 7830Sstevel@tonic-gate #pragma weak posix_spawnattr_setschedpolicy = \ 7840Sstevel@tonic-gate _posix_spawnattr_setschedpolicy 7850Sstevel@tonic-gate int 7860Sstevel@tonic-gate _posix_spawnattr_setschedpolicy( 7870Sstevel@tonic-gate posix_spawnattr_t *attr, 7880Sstevel@tonic-gate int schedpolicy) 7890Sstevel@tonic-gate { 7900Sstevel@tonic-gate spawn_attr_t *sap = attr->__spawn_attrp; 7910Sstevel@tonic-gate 7920Sstevel@tonic-gate if (sap == NULL) 7930Sstevel@tonic-gate return (EINVAL); 7940Sstevel@tonic-gate 7950Sstevel@tonic-gate switch (schedpolicy) { 7960Sstevel@tonic-gate case SCHED_OTHER: 7970Sstevel@tonic-gate case SCHED_FIFO: 7980Sstevel@tonic-gate case SCHED_RR: 7990Sstevel@tonic-gate break; 8000Sstevel@tonic-gate default: 8010Sstevel@tonic-gate return (EINVAL); 8020Sstevel@tonic-gate } 8030Sstevel@tonic-gate 8040Sstevel@tonic-gate sap->sa_schedpolicy = schedpolicy; 8050Sstevel@tonic-gate return (0); 8060Sstevel@tonic-gate } 8070Sstevel@tonic-gate 8080Sstevel@tonic-gate #pragma weak posix_spawnattr_getschedpolicy = \ 8090Sstevel@tonic-gate _posix_spawnattr_getschedpolicy 8100Sstevel@tonic-gate int 8110Sstevel@tonic-gate _posix_spawnattr_getschedpolicy( 8120Sstevel@tonic-gate const posix_spawnattr_t *attr, 8130Sstevel@tonic-gate int *schedpolicy) 8140Sstevel@tonic-gate { 8150Sstevel@tonic-gate spawn_attr_t *sap = attr->__spawn_attrp; 8160Sstevel@tonic-gate 8170Sstevel@tonic-gate if (sap == NULL) 8180Sstevel@tonic-gate return (EINVAL); 8190Sstevel@tonic-gate 8200Sstevel@tonic-gate *schedpolicy = sap->sa_schedpolicy; 8210Sstevel@tonic-gate return (0); 8220Sstevel@tonic-gate } 8230Sstevel@tonic-gate 8240Sstevel@tonic-gate #pragma weak posix_spawnattr_setsigdefault = \ 8250Sstevel@tonic-gate _posix_spawnattr_setsigdefault 8260Sstevel@tonic-gate int 8270Sstevel@tonic-gate _posix_spawnattr_setsigdefault( 8280Sstevel@tonic-gate posix_spawnattr_t *attr, 8290Sstevel@tonic-gate const sigset_t *sigdefault) 8300Sstevel@tonic-gate { 8310Sstevel@tonic-gate spawn_attr_t *sap = attr->__spawn_attrp; 8320Sstevel@tonic-gate 8330Sstevel@tonic-gate if (sap == NULL) 8340Sstevel@tonic-gate return (EINVAL); 8350Sstevel@tonic-gate 8360Sstevel@tonic-gate sap->sa_sigdefault = *sigdefault; 8370Sstevel@tonic-gate return (0); 8380Sstevel@tonic-gate } 8390Sstevel@tonic-gate 8400Sstevel@tonic-gate #pragma weak posix_spawnattr_getsigdefault = \ 8410Sstevel@tonic-gate _posix_spawnattr_getsigdefault 8420Sstevel@tonic-gate int 8430Sstevel@tonic-gate _posix_spawnattr_getsigdefault( 8440Sstevel@tonic-gate const posix_spawnattr_t *attr, 8450Sstevel@tonic-gate sigset_t *sigdefault) 8460Sstevel@tonic-gate { 8470Sstevel@tonic-gate spawn_attr_t *sap = attr->__spawn_attrp; 8480Sstevel@tonic-gate 8490Sstevel@tonic-gate if (sap == NULL) 8500Sstevel@tonic-gate return (EINVAL); 8510Sstevel@tonic-gate 8520Sstevel@tonic-gate *sigdefault = sap->sa_sigdefault; 8530Sstevel@tonic-gate return (0); 8540Sstevel@tonic-gate } 8550Sstevel@tonic-gate 8560Sstevel@tonic-gate #pragma weak posix_spawnattr_setsigmask = \ 8570Sstevel@tonic-gate _posix_spawnattr_setsigmask 8580Sstevel@tonic-gate int 8590Sstevel@tonic-gate _posix_spawnattr_setsigmask( 8600Sstevel@tonic-gate posix_spawnattr_t *attr, 8610Sstevel@tonic-gate const sigset_t *sigmask) 8620Sstevel@tonic-gate { 8630Sstevel@tonic-gate spawn_attr_t *sap = attr->__spawn_attrp; 8640Sstevel@tonic-gate 8650Sstevel@tonic-gate if (sap == NULL) 8660Sstevel@tonic-gate return (EINVAL); 8670Sstevel@tonic-gate 8680Sstevel@tonic-gate sap->sa_sigmask = *sigmask; 8690Sstevel@tonic-gate return (0); 8700Sstevel@tonic-gate } 8710Sstevel@tonic-gate 8720Sstevel@tonic-gate #pragma weak posix_spawnattr_getsigmask = \ 8730Sstevel@tonic-gate _posix_spawnattr_getsigmask 8740Sstevel@tonic-gate int 8750Sstevel@tonic-gate _posix_spawnattr_getsigmask( 8760Sstevel@tonic-gate const posix_spawnattr_t *attr, 8770Sstevel@tonic-gate sigset_t *sigmask) 8780Sstevel@tonic-gate { 8790Sstevel@tonic-gate spawn_attr_t *sap = attr->__spawn_attrp; 8800Sstevel@tonic-gate 8810Sstevel@tonic-gate if (sap == NULL) 8820Sstevel@tonic-gate return (EINVAL); 8830Sstevel@tonic-gate 8840Sstevel@tonic-gate *sigmask = sap->sa_sigmask; 8850Sstevel@tonic-gate return (0); 8860Sstevel@tonic-gate } 887