posix_spawn.c revision 179866
1179838Sdavidxu/*- 2179840Sed * Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org> 3179838Sdavidxu * All rights reserved. 4179838Sdavidxu * 5179838Sdavidxu * Redistribution and use in source and binary forms, with or without 6179838Sdavidxu * modification, are permitted provided that the following conditions 7179838Sdavidxu * are met: 8179838Sdavidxu * 1. Redistributions of source code must retain the above copyright 9179838Sdavidxu * notice, this list of conditions and the following disclaimer. 10179838Sdavidxu * 2. Redistributions in binary form must reproduce the above copyright 11179838Sdavidxu * notice, this list of conditions and the following disclaimer in the 12179838Sdavidxu * documentation and/or other materials provided with the distribution. 13179838Sdavidxu * 14179838Sdavidxu * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15179838Sdavidxu * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16179838Sdavidxu * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17179838Sdavidxu * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18179838Sdavidxu * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19179838Sdavidxu * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20179838Sdavidxu * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21179838Sdavidxu * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22179838Sdavidxu * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23179838Sdavidxu * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24179838Sdavidxu * SUCH DAMAGE. 25179838Sdavidxu */ 26179838Sdavidxu 27179838Sdavidxu#include <sys/cdefs.h> 28179838Sdavidxu__FBSDID("$FreeBSD: head/lib/libc/gen/posix_spawn.c 179866 2008-06-19 02:42:50Z davidxu $"); 29179838Sdavidxu 30179838Sdavidxu#include "namespace.h" 31179838Sdavidxu#include <sys/queue.h> 32179838Sdavidxu 33179838Sdavidxu#include <errno.h> 34179838Sdavidxu#include <fcntl.h> 35179838Sdavidxu#include <sched.h> 36179838Sdavidxu#include <spawn.h> 37179838Sdavidxu#include <signal.h> 38179838Sdavidxu#include <stdlib.h> 39179838Sdavidxu#include <string.h> 40179838Sdavidxu#include <unistd.h> 41179838Sdavidxu#include "un-namespace.h" 42179838Sdavidxu 43179838Sdavidxuextern char **environ; 44179838Sdavidxu 45179838Sdavidxustruct __posix_spawnattr { 46179838Sdavidxu short sa_flags; 47179838Sdavidxu pid_t sa_pgroup; 48179838Sdavidxu struct sched_param sa_schedparam; 49179838Sdavidxu int sa_schedpolicy; 50179838Sdavidxu sigset_t sa_sigdefault; 51179838Sdavidxu sigset_t sa_sigmask; 52179838Sdavidxu}; 53179838Sdavidxu 54179838Sdavidxustruct __posix_spawn_file_actions { 55179838Sdavidxu STAILQ_HEAD(, __posix_spawn_file_actions_entry) fa_list; 56179838Sdavidxu}; 57179838Sdavidxu 58179838Sdavidxutypedef struct __posix_spawn_file_actions_entry { 59179838Sdavidxu STAILQ_ENTRY(__posix_spawn_file_actions_entry) fae_list; 60179838Sdavidxu enum { FAE_OPEN, FAE_DUP2, FAE_CLOSE } fae_action; 61179838Sdavidxu 62179838Sdavidxu int fae_fildes; 63179838Sdavidxu union { 64179838Sdavidxu struct { 65179838Sdavidxu char *path; 66179838Sdavidxu#define fae_path fae_data.open.path 67179838Sdavidxu int oflag; 68179838Sdavidxu#define fae_oflag fae_data.open.oflag 69179838Sdavidxu mode_t mode; 70179838Sdavidxu#define fae_mode fae_data.open.mode 71179838Sdavidxu } open; 72179838Sdavidxu struct { 73179838Sdavidxu int newfildes; 74179838Sdavidxu#define fae_newfildes fae_data.dup2.newfildes 75179838Sdavidxu } dup2; 76179838Sdavidxu } fae_data; 77179838Sdavidxu} posix_spawn_file_actions_entry_t; 78179838Sdavidxu 79179838Sdavidxu/* 80179838Sdavidxu * Spawn routines 81179838Sdavidxu */ 82179838Sdavidxu 83179838Sdavidxustatic int 84179838Sdavidxuprocess_spawnattr(const posix_spawnattr_t sa) 85179838Sdavidxu{ 86179838Sdavidxu struct sigaction sigact = { .sa_flags = 0, .sa_handler = SIG_DFL }; 87179838Sdavidxu int i; 88179838Sdavidxu 89179838Sdavidxu /* 90179838Sdavidxu * POSIX doesn't really describe in which order everything 91179838Sdavidxu * should be set. We'll just set them in the order in which they 92179838Sdavidxu * are mentioned. 93179838Sdavidxu */ 94179838Sdavidxu 95179838Sdavidxu /* Set process group */ 96179838Sdavidxu if (sa->sa_flags & POSIX_SPAWN_SETPGROUP) { 97179838Sdavidxu if (setpgid(0, sa->sa_pgroup) != 0) 98179838Sdavidxu return (errno); 99179838Sdavidxu } 100179838Sdavidxu 101179838Sdavidxu /* Set scheduler policy */ 102179838Sdavidxu if (sa->sa_flags & POSIX_SPAWN_SETSCHEDULER) { 103179838Sdavidxu if (sched_setscheduler(0, sa->sa_schedpolicy, 104179838Sdavidxu &sa->sa_schedparam) != 0) 105179838Sdavidxu return (errno); 106179838Sdavidxu } else if (sa->sa_flags & POSIX_SPAWN_SETSCHEDPARAM) { 107179838Sdavidxu if (sched_setparam(0, &sa->sa_schedparam) != 0) 108179838Sdavidxu return (errno); 109179838Sdavidxu } 110179866Sdavidxu 111179866Sdavidxu /* Reset user ID's */ 112179866Sdavidxu if (sa->sa_flags & POSIX_SPAWN_RESETIDS) { 113179866Sdavidxu if (setegid(getgid()) != 0) 114179866Sdavidxu return (errno); 115179866Sdavidxu if (seteuid(getuid()) != 0) 116179866Sdavidxu return (errno); 117179866Sdavidxu } 118179866Sdavidxu 119179866Sdavidxu /* Set signal masks/defaults */ 120179866Sdavidxu if (sa->sa_flags & POSIX_SPAWN_SETSIGMASK) { 121179866Sdavidxu _sigprocmask(SIG_SETMASK, &sa->sa_sigmask, NULL); 122179866Sdavidxu } 123179866Sdavidxu 124179866Sdavidxu if (sa->sa_flags & POSIX_SPAWN_SETSIGDEF) { 125179866Sdavidxu for (i = 1; i <= _SIG_MAXSIG; i++) { 126179866Sdavidxu if (sigismember(&sa->sa_sigdefault, i)) 127179866Sdavidxu if (_sigaction(i, &sigact, NULL) != 0) 128179866Sdavidxu return (errno); 129179866Sdavidxu } 130179866Sdavidxu } 131179866Sdavidxu 132179838Sdavidxu return (0); 133179838Sdavidxu} 134179838Sdavidxu 135179838Sdavidxustatic int 136179838Sdavidxuprocess_file_actions_entry(posix_spawn_file_actions_entry_t *fae) 137179838Sdavidxu{ 138179838Sdavidxu int fd; 139179838Sdavidxu 140179838Sdavidxu switch (fae->fae_action) { 141179838Sdavidxu case FAE_OPEN: 142179838Sdavidxu /* Perform an open(), make it use the right fd */ 143179838Sdavidxu fd = _open(fae->fae_path, fae->fae_oflag, fae->fae_mode); 144179838Sdavidxu if (fd < 0) 145179838Sdavidxu return (errno); 146179838Sdavidxu if (fd != fae->fae_fildes) { 147179838Sdavidxu if (_dup2(fd, fae->fae_fildes) == -1) 148179838Sdavidxu return (errno); 149179838Sdavidxu if (_close(fd) != 0) { 150179838Sdavidxu if (errno == EBADF) 151179838Sdavidxu return (EBADF); 152179838Sdavidxu } 153179838Sdavidxu } 154179838Sdavidxu if (_fcntl(fae->fae_fildes, F_SETFD, 0) == -1) 155179838Sdavidxu return (errno); 156179838Sdavidxu break; 157179838Sdavidxu case FAE_DUP2: 158179838Sdavidxu /* Perform a dup2() */ 159179838Sdavidxu if (_dup2(fae->fae_fildes, fae->fae_newfildes) == -1) 160179838Sdavidxu return (errno); 161179838Sdavidxu if (_fcntl(fae->fae_newfildes, F_SETFD, 0) == -1) 162179838Sdavidxu return (errno); 163179838Sdavidxu break; 164179838Sdavidxu case FAE_CLOSE: 165179838Sdavidxu /* Perform a close() */ 166179838Sdavidxu if (_close(fae->fae_fildes) != 0) { 167179838Sdavidxu if (errno == EBADF) 168179838Sdavidxu return (EBADF); 169179838Sdavidxu } 170179838Sdavidxu break; 171179838Sdavidxu } 172179838Sdavidxu return (0); 173179838Sdavidxu} 174179838Sdavidxu 175179838Sdavidxustatic int 176179838Sdavidxuprocess_file_actions(const posix_spawn_file_actions_t fa) 177179838Sdavidxu{ 178179838Sdavidxu posix_spawn_file_actions_entry_t *fae; 179179838Sdavidxu int error; 180179838Sdavidxu 181179838Sdavidxu /* Replay all file descriptor modifications */ 182179838Sdavidxu STAILQ_FOREACH(fae, &fa->fa_list, fae_list) { 183179838Sdavidxu error = process_file_actions_entry(fae); 184179838Sdavidxu if (error) 185179838Sdavidxu return (error); 186179838Sdavidxu } 187179838Sdavidxu return (0); 188179838Sdavidxu} 189179838Sdavidxu 190179838Sdavidxustatic int 191179838Sdavidxudo_posix_spawn(pid_t *pid, const char *path, 192179838Sdavidxu const posix_spawn_file_actions_t *fa, 193179838Sdavidxu const posix_spawnattr_t *sa, 194179838Sdavidxu char * const argv[], char * const envp[], int use_env_path) 195179838Sdavidxu{ 196179838Sdavidxu pid_t p; 197179838Sdavidxu volatile int error = 0; 198179838Sdavidxu 199179838Sdavidxu p = vfork(); 200179838Sdavidxu switch (p) { 201179838Sdavidxu case -1: 202179838Sdavidxu return (errno); 203179838Sdavidxu case 0: 204179838Sdavidxu if (sa != NULL) { 205179838Sdavidxu error = process_spawnattr(*sa); 206179838Sdavidxu if (error) 207179838Sdavidxu _exit(127); 208179838Sdavidxu } 209179838Sdavidxu if (fa != NULL) { 210179838Sdavidxu error = process_file_actions(*fa); 211179838Sdavidxu if (error) 212179838Sdavidxu _exit(127); 213179838Sdavidxu } 214179838Sdavidxu if (use_env_path) 215179838Sdavidxu execvpe(path, argv, envp != NULL ? envp : environ); 216179838Sdavidxu else 217179838Sdavidxu _execve(path, argv, envp != NULL ? envp : environ); 218179838Sdavidxu error = errno; 219179838Sdavidxu _exit(127); 220179838Sdavidxu default: 221179838Sdavidxu if (pid != NULL) 222179838Sdavidxu *pid = p; 223179838Sdavidxu return (error); 224179838Sdavidxu } 225179838Sdavidxu} 226179838Sdavidxu 227179838Sdavidxuint 228179838Sdavidxuposix_spawn(pid_t *pid, const char *path, 229179838Sdavidxu const posix_spawn_file_actions_t *fa, 230179838Sdavidxu const posix_spawnattr_t *sa, 231179838Sdavidxu char * const argv[], char * const envp[]) 232179838Sdavidxu{ 233179838Sdavidxu return do_posix_spawn(pid, path, fa, sa, argv, envp, 0); 234179838Sdavidxu} 235179838Sdavidxu 236179838Sdavidxuint 237179838Sdavidxuposix_spawnp(pid_t *pid, const char *path, 238179838Sdavidxu const posix_spawn_file_actions_t *fa, 239179838Sdavidxu const posix_spawnattr_t *sa, 240179838Sdavidxu char * const argv[], char * const envp[]) 241179838Sdavidxu{ 242179838Sdavidxu return do_posix_spawn(pid, path, fa, sa, argv, envp, 1); 243179838Sdavidxu} 244179838Sdavidxu 245179838Sdavidxu/* 246179838Sdavidxu * File descriptor actions 247179838Sdavidxu */ 248179838Sdavidxu 249179838Sdavidxuint 250179838Sdavidxuposix_spawn_file_actions_init(posix_spawn_file_actions_t *ret) 251179838Sdavidxu{ 252179838Sdavidxu posix_spawn_file_actions_t fa; 253179838Sdavidxu 254179838Sdavidxu fa = malloc(sizeof(struct __posix_spawn_file_actions)); 255179838Sdavidxu if (fa == NULL) 256179838Sdavidxu return (-1); 257179838Sdavidxu 258179838Sdavidxu STAILQ_INIT(&fa->fa_list); 259179838Sdavidxu *ret = fa; 260179838Sdavidxu return (0); 261179838Sdavidxu} 262179838Sdavidxu 263179838Sdavidxuint 264179838Sdavidxuposix_spawn_file_actions_destroy(posix_spawn_file_actions_t *fa) 265179838Sdavidxu{ 266179838Sdavidxu posix_spawn_file_actions_entry_t *fae; 267179838Sdavidxu 268179838Sdavidxu while ((fae = STAILQ_FIRST(&(*fa)->fa_list)) != NULL) { 269179838Sdavidxu /* Remove file action entry from the queue */ 270179838Sdavidxu STAILQ_REMOVE_HEAD(&(*fa)->fa_list, fae_list); 271179838Sdavidxu 272179838Sdavidxu /* Deallocate file action entry */ 273179838Sdavidxu if (fae->fae_action == FAE_OPEN) 274179838Sdavidxu free(fae->fae_path); 275179838Sdavidxu free(fae); 276179838Sdavidxu } 277179838Sdavidxu 278179838Sdavidxu free(*fa); 279179838Sdavidxu return (0); 280179838Sdavidxu} 281179838Sdavidxu 282179838Sdavidxuint 283179838Sdavidxuposix_spawn_file_actions_addopen(posix_spawn_file_actions_t * __restrict fa, 284179838Sdavidxu int fildes, const char * __restrict path, int oflag, mode_t mode) 285179838Sdavidxu{ 286179838Sdavidxu posix_spawn_file_actions_entry_t *fae; 287179838Sdavidxu int error; 288179838Sdavidxu 289179838Sdavidxu if (fildes < 0) 290179838Sdavidxu return (EBADF); 291179838Sdavidxu 292179838Sdavidxu /* Allocate object */ 293179838Sdavidxu fae = malloc(sizeof(posix_spawn_file_actions_entry_t)); 294179838Sdavidxu if (fae == NULL) 295179838Sdavidxu return (errno); 296179838Sdavidxu 297179838Sdavidxu /* Set values and store in queue */ 298179838Sdavidxu fae->fae_action = FAE_OPEN; 299179838Sdavidxu fae->fae_path = strdup(path); 300179838Sdavidxu if (fae->fae_path == NULL) { 301179838Sdavidxu error = errno; 302179838Sdavidxu free(fae); 303179838Sdavidxu return (error); 304179838Sdavidxu } 305179838Sdavidxu fae->fae_fildes = fildes; 306179838Sdavidxu fae->fae_oflag = oflag; 307179838Sdavidxu fae->fae_mode = mode; 308179838Sdavidxu 309179838Sdavidxu STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list); 310179838Sdavidxu return (0); 311179838Sdavidxu} 312179838Sdavidxu 313179838Sdavidxuint 314179838Sdavidxuposix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *fa, 315179838Sdavidxu int fildes, int newfildes) 316179838Sdavidxu{ 317179838Sdavidxu posix_spawn_file_actions_entry_t *fae; 318179838Sdavidxu 319179838Sdavidxu if (fildes < 0 || newfildes < 0) 320179838Sdavidxu return (EBADF); 321179838Sdavidxu 322179838Sdavidxu /* Allocate object */ 323179838Sdavidxu fae = malloc(sizeof(posix_spawn_file_actions_entry_t)); 324179838Sdavidxu if (fae == NULL) 325179838Sdavidxu return (errno); 326179838Sdavidxu 327179838Sdavidxu /* Set values and store in queue */ 328179838Sdavidxu fae->fae_action = FAE_DUP2; 329179838Sdavidxu fae->fae_fildes = fildes; 330179838Sdavidxu fae->fae_newfildes = newfildes; 331179838Sdavidxu 332179838Sdavidxu STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list); 333179838Sdavidxu return (0); 334179838Sdavidxu} 335179838Sdavidxu 336179841Sdavidxuint 337179841Sdavidxuposix_spawn_file_actions_addclose(posix_spawn_file_actions_t *fa, 338179838Sdavidxu int fildes) 339179838Sdavidxu{ 340179838Sdavidxu posix_spawn_file_actions_entry_t *fae; 341179838Sdavidxu 342179838Sdavidxu if (fildes < 0) 343179838Sdavidxu return (EBADF); 344179838Sdavidxu 345179838Sdavidxu /* Allocate object */ 346179838Sdavidxu fae = malloc(sizeof(posix_spawn_file_actions_entry_t)); 347179838Sdavidxu if (fae == NULL) 348179838Sdavidxu return (errno); 349179838Sdavidxu 350179838Sdavidxu /* Set values and store in queue */ 351179838Sdavidxu fae->fae_action = FAE_CLOSE; 352179838Sdavidxu fae->fae_fildes = fildes; 353179838Sdavidxu 354179838Sdavidxu STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list); 355179838Sdavidxu return (0); 356179838Sdavidxu} 357179838Sdavidxu 358179838Sdavidxu/* 359179838Sdavidxu * Spawn attributes 360179838Sdavidxu */ 361179838Sdavidxu 362179838Sdavidxuint 363179838Sdavidxuposix_spawnattr_init(posix_spawnattr_t *ret) 364179838Sdavidxu{ 365179838Sdavidxu posix_spawnattr_t sa; 366179838Sdavidxu 367179838Sdavidxu sa = calloc(1, sizeof(struct __posix_spawnattr)); 368179838Sdavidxu if (sa == NULL) 369179838Sdavidxu return (errno); 370179838Sdavidxu 371179838Sdavidxu /* Set defaults as specified by POSIX, cleared above */ 372179838Sdavidxu *ret = sa; 373179838Sdavidxu return (0); 374179838Sdavidxu} 375179838Sdavidxu 376179838Sdavidxuint 377179838Sdavidxuposix_spawnattr_destroy(posix_spawnattr_t *sa) 378179838Sdavidxu{ 379179838Sdavidxu free(*sa); 380179838Sdavidxu return (0); 381179838Sdavidxu} 382179838Sdavidxu 383179838Sdavidxuint 384179838Sdavidxuposix_spawnattr_getflags(const posix_spawnattr_t * __restrict sa, 385179838Sdavidxu short * __restrict flags) 386179838Sdavidxu{ 387179838Sdavidxu *flags = (*sa)->sa_flags; 388179838Sdavidxu return (0); 389179838Sdavidxu} 390179838Sdavidxu 391179838Sdavidxuint 392179838Sdavidxuposix_spawnattr_getpgroup(const posix_spawnattr_t * __restrict sa, 393179838Sdavidxu pid_t * __restrict pgroup) 394179838Sdavidxu{ 395179838Sdavidxu *pgroup = (*sa)->sa_pgroup; 396179838Sdavidxu return (0); 397179838Sdavidxu} 398179838Sdavidxu 399179838Sdavidxuint 400179838Sdavidxuposix_spawnattr_getschedparam(const posix_spawnattr_t * __restrict sa, 401179838Sdavidxu struct sched_param * __restrict schedparam) 402179838Sdavidxu{ 403179838Sdavidxu *schedparam = (*sa)->sa_schedparam; 404179838Sdavidxu return (0); 405179838Sdavidxu} 406179838Sdavidxu 407179838Sdavidxuint 408179838Sdavidxuposix_spawnattr_getschedpolicy(const posix_spawnattr_t * __restrict sa, 409179838Sdavidxu int * __restrict schedpolicy) 410179838Sdavidxu{ 411179838Sdavidxu *schedpolicy = (*sa)->sa_schedpolicy; 412179838Sdavidxu return (0); 413179838Sdavidxu} 414179838Sdavidxu 415179838Sdavidxuint 416179838Sdavidxuposix_spawnattr_getsigdefault(const posix_spawnattr_t * __restrict sa, 417179838Sdavidxu sigset_t * __restrict sigdefault) 418179838Sdavidxu{ 419179838Sdavidxu *sigdefault = (*sa)->sa_sigdefault; 420179838Sdavidxu return (0); 421179838Sdavidxu} 422179838Sdavidxu 423179838Sdavidxuint 424179838Sdavidxuposix_spawnattr_getsigmask(const posix_spawnattr_t * __restrict sa, 425179838Sdavidxu sigset_t * __restrict sigmask) 426179838Sdavidxu{ 427179838Sdavidxu *sigmask = (*sa)->sa_sigmask; 428179838Sdavidxu return (0); 429179838Sdavidxu} 430179838Sdavidxu 431179838Sdavidxuint 432179838Sdavidxuposix_spawnattr_setflags(posix_spawnattr_t *sa, short flags) 433179838Sdavidxu{ 434179838Sdavidxu (*sa)->sa_flags = flags; 435179838Sdavidxu return (0); 436179838Sdavidxu} 437179838Sdavidxu 438179838Sdavidxuint 439179838Sdavidxuposix_spawnattr_setpgroup(posix_spawnattr_t *sa, pid_t pgroup) 440179838Sdavidxu{ 441179838Sdavidxu (*sa)->sa_pgroup = pgroup; 442179838Sdavidxu return (0); 443179838Sdavidxu} 444179838Sdavidxu 445179838Sdavidxuint 446179838Sdavidxuposix_spawnattr_setschedparam(posix_spawnattr_t *sa __restrict, 447179838Sdavidxu const struct sched_param * __restrict schedparam) 448179838Sdavidxu{ 449179838Sdavidxu (*sa)->sa_schedparam = *schedparam; 450179838Sdavidxu return (0); 451179838Sdavidxu} 452179838Sdavidxu 453179838Sdavidxuint 454179838Sdavidxuposix_spawnattr_setschedpolicy(posix_spawnattr_t *sa, int schedpolicy) 455179838Sdavidxu{ 456179838Sdavidxu (*sa)->sa_schedpolicy = schedpolicy; 457179838Sdavidxu return (0); 458179838Sdavidxu} 459179838Sdavidxu 460179838Sdavidxuint 461179838Sdavidxuposix_spawnattr_setsigdefault(posix_spawnattr_t * __restrict sa, 462179838Sdavidxu const sigset_t * __restrict sigdefault) 463179838Sdavidxu{ 464179838Sdavidxu (*sa)->sa_sigdefault = *sigdefault; 465179838Sdavidxu return (0); 466179838Sdavidxu} 467179838Sdavidxu 468179838Sdavidxuint 469179838Sdavidxuposix_spawnattr_setsigmask(posix_spawnattr_t * __restrict sa, 470179838Sdavidxu const sigset_t * __restrict sigmask) 471179838Sdavidxu{ 472179838Sdavidxu (*sa)->sa_sigmask = *sigmask; 473179838Sdavidxu return (0); 474179838Sdavidxu} 475