posix_spawn.c revision 179838
1179838Sdavidxu/*- 2179838Sdavidxu * Copyright (c) 2008 Ed Schouten <ed@80386.nl> 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 179838 2008-06-17 06:26:29Z 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 signal masks/defaults */ 96179838Sdavidxu if (sa->sa_flags & POSIX_SPAWN_SETSIGMASK) { 97179838Sdavidxu _sigprocmask(SIG_SETMASK, &sa->sa_sigmask, NULL); 98179838Sdavidxu } 99179838Sdavidxu 100179838Sdavidxu if (sa->sa_flags & POSIX_SPAWN_SETSIGDEF) { 101179838Sdavidxu for (i = 1; i <= _SIG_MAXSIG; i++) { 102179838Sdavidxu if (sigismember(&sa->sa_sigdefault, i)) 103179838Sdavidxu if (_sigaction(i, &sigact, NULL) != 0) 104179838Sdavidxu return (errno); 105179838Sdavidxu } 106179838Sdavidxu } 107179838Sdavidxu 108179838Sdavidxu /* Reset user ID's */ 109179838Sdavidxu if (sa->sa_flags & POSIX_SPAWN_RESETIDS) { 110179838Sdavidxu if (setegid(getgid()) != 0) 111179838Sdavidxu return (errno); 112179838Sdavidxu if (seteuid(getuid()) != 0) 113179838Sdavidxu return (errno); 114179838Sdavidxu } 115179838Sdavidxu 116179838Sdavidxu /* Set process group */ 117179838Sdavidxu if (sa->sa_flags & POSIX_SPAWN_SETPGROUP) { 118179838Sdavidxu if (setpgid(0, sa->sa_pgroup) != 0) 119179838Sdavidxu return (errno); 120179838Sdavidxu } 121179838Sdavidxu 122179838Sdavidxu /* Set scheduler policy */ 123179838Sdavidxu if (sa->sa_flags & POSIX_SPAWN_SETSCHEDULER) { 124179838Sdavidxu if (sched_setscheduler(0, sa->sa_schedpolicy, 125179838Sdavidxu &sa->sa_schedparam) != 0) 126179838Sdavidxu return (errno); 127179838Sdavidxu } else if (sa->sa_flags & POSIX_SPAWN_SETSCHEDPARAM) { 128179838Sdavidxu if (sched_setparam(0, &sa->sa_schedparam) != 0) 129179838Sdavidxu return (errno); 130179838Sdavidxu } 131179838Sdavidxu return (0); 132179838Sdavidxu} 133179838Sdavidxu 134179838Sdavidxustatic int 135179838Sdavidxuprocess_file_actions_entry(posix_spawn_file_actions_entry_t *fae) 136179838Sdavidxu{ 137179838Sdavidxu int fd; 138179838Sdavidxu 139179838Sdavidxu switch (fae->fae_action) { 140179838Sdavidxu case FAE_OPEN: 141179838Sdavidxu /* Perform an open(), make it use the right fd */ 142179838Sdavidxu fd = _open(fae->fae_path, fae->fae_oflag, fae->fae_mode); 143179838Sdavidxu if (fd < 0) 144179838Sdavidxu return (errno); 145179838Sdavidxu if (fd != fae->fae_fildes) { 146179838Sdavidxu if (_dup2(fd, fae->fae_fildes) == -1) 147179838Sdavidxu return (errno); 148179838Sdavidxu if (_close(fd) != 0) { 149179838Sdavidxu if (errno == EBADF) 150179838Sdavidxu return (EBADF); 151179838Sdavidxu } 152179838Sdavidxu } 153179838Sdavidxu if (_fcntl(fae->fae_fildes, F_SETFD, 0) == -1) 154179838Sdavidxu return (errno); 155179838Sdavidxu break; 156179838Sdavidxu case FAE_DUP2: 157179838Sdavidxu /* Perform a dup2() */ 158179838Sdavidxu if (_dup2(fae->fae_fildes, fae->fae_newfildes) == -1) 159179838Sdavidxu return (errno); 160179838Sdavidxu if (_fcntl(fae->fae_newfildes, F_SETFD, 0) == -1) 161179838Sdavidxu return (errno); 162179838Sdavidxu break; 163179838Sdavidxu case FAE_CLOSE: 164179838Sdavidxu /* Perform a close() */ 165179838Sdavidxu if (_close(fae->fae_fildes) != 0) { 166179838Sdavidxu if (errno == EBADF) 167179838Sdavidxu return (EBADF); 168179838Sdavidxu } 169179838Sdavidxu break; 170179838Sdavidxu } 171179838Sdavidxu return (0); 172179838Sdavidxu} 173179838Sdavidxu 174179838Sdavidxustatic int 175179838Sdavidxuprocess_file_actions(const posix_spawn_file_actions_t fa) 176179838Sdavidxu{ 177179838Sdavidxu posix_spawn_file_actions_entry_t *fae; 178179838Sdavidxu int error; 179179838Sdavidxu 180179838Sdavidxu /* Replay all file descriptor modifications */ 181179838Sdavidxu STAILQ_FOREACH(fae, &fa->fa_list, fae_list) { 182179838Sdavidxu error = process_file_actions_entry(fae); 183179838Sdavidxu if (error) 184179838Sdavidxu return (error); 185179838Sdavidxu } 186179838Sdavidxu return (0); 187179838Sdavidxu} 188179838Sdavidxu 189179838Sdavidxustatic int 190179838Sdavidxudo_posix_spawn(pid_t *pid, const char *path, 191179838Sdavidxu const posix_spawn_file_actions_t *fa, 192179838Sdavidxu const posix_spawnattr_t *sa, 193179838Sdavidxu char * const argv[], char * const envp[], int use_env_path) 194179838Sdavidxu{ 195179838Sdavidxu pid_t p; 196179838Sdavidxu volatile int error = 0; 197179838Sdavidxu 198179838Sdavidxu p = vfork(); 199179838Sdavidxu switch (p) { 200179838Sdavidxu case -1: 201179838Sdavidxu return (errno); 202179838Sdavidxu case 0: 203179838Sdavidxu if (sa != NULL) { 204179838Sdavidxu error = process_spawnattr(*sa); 205179838Sdavidxu if (error) 206179838Sdavidxu _exit(127); 207179838Sdavidxu } 208179838Sdavidxu if (fa != NULL) { 209179838Sdavidxu error = process_file_actions(*fa); 210179838Sdavidxu if (error) 211179838Sdavidxu _exit(127); 212179838Sdavidxu } 213179838Sdavidxu if (use_env_path) 214179838Sdavidxu execvpe(path, argv, envp != NULL ? envp : environ); 215179838Sdavidxu else 216179838Sdavidxu _execve(path, argv, envp != NULL ? envp : environ); 217179838Sdavidxu error = errno; 218179838Sdavidxu _exit(127); 219179838Sdavidxu default: 220179838Sdavidxu if (pid != NULL) 221179838Sdavidxu *pid = p; 222179838Sdavidxu return (error); 223179838Sdavidxu } 224179838Sdavidxu} 225179838Sdavidxu 226179838Sdavidxuint 227179838Sdavidxuposix_spawn(pid_t *pid, const char *path, 228179838Sdavidxu const posix_spawn_file_actions_t *fa, 229179838Sdavidxu const posix_spawnattr_t *sa, 230179838Sdavidxu char * const argv[], char * const envp[]) 231179838Sdavidxu{ 232179838Sdavidxu return do_posix_spawn(pid, path, fa, sa, argv, envp, 0); 233179838Sdavidxu} 234179838Sdavidxu 235179838Sdavidxuint 236179838Sdavidxuposix_spawnp(pid_t *pid, const char *path, 237179838Sdavidxu const posix_spawn_file_actions_t *fa, 238179838Sdavidxu const posix_spawnattr_t *sa, 239179838Sdavidxu char * const argv[], char * const envp[]) 240179838Sdavidxu{ 241179838Sdavidxu return do_posix_spawn(pid, path, fa, sa, argv, envp, 1); 242179838Sdavidxu} 243179838Sdavidxu 244179838Sdavidxu/* 245179838Sdavidxu * File descriptor actions 246179838Sdavidxu */ 247179838Sdavidxu 248179838Sdavidxuint 249179838Sdavidxuposix_spawn_file_actions_init(posix_spawn_file_actions_t *ret) 250179838Sdavidxu{ 251179838Sdavidxu posix_spawn_file_actions_t fa; 252179838Sdavidxu 253179838Sdavidxu fa = malloc(sizeof(struct __posix_spawn_file_actions)); 254179838Sdavidxu if (fa == NULL) 255179838Sdavidxu return (-1); 256179838Sdavidxu 257179838Sdavidxu STAILQ_INIT(&fa->fa_list); 258179838Sdavidxu *ret = fa; 259179838Sdavidxu return (0); 260179838Sdavidxu} 261179838Sdavidxu 262179838Sdavidxuint 263179838Sdavidxuposix_spawn_file_actions_destroy(posix_spawn_file_actions_t *fa) 264179838Sdavidxu{ 265179838Sdavidxu posix_spawn_file_actions_entry_t *fae; 266179838Sdavidxu 267179838Sdavidxu while ((fae = STAILQ_FIRST(&(*fa)->fa_list)) != NULL) { 268179838Sdavidxu /* Remove file action entry from the queue */ 269179838Sdavidxu STAILQ_REMOVE_HEAD(&(*fa)->fa_list, fae_list); 270179838Sdavidxu 271179838Sdavidxu /* Deallocate file action entry */ 272179838Sdavidxu if (fae->fae_action == FAE_OPEN) 273179838Sdavidxu free(fae->fae_path); 274179838Sdavidxu free(fae); 275179838Sdavidxu } 276179838Sdavidxu 277179838Sdavidxu free(*fa); 278179838Sdavidxu return (0); 279179838Sdavidxu} 280179838Sdavidxu 281179838Sdavidxuint 282179838Sdavidxuposix_spawn_file_actions_addopen(posix_spawn_file_actions_t * __restrict fa, 283179838Sdavidxu int fildes, const char * __restrict path, int oflag, mode_t mode) 284179838Sdavidxu{ 285179838Sdavidxu posix_spawn_file_actions_entry_t *fae; 286179838Sdavidxu int error; 287179838Sdavidxu 288179838Sdavidxu if (fildes < 0) 289179838Sdavidxu return (EBADF); 290179838Sdavidxu 291179838Sdavidxu /* Allocate object */ 292179838Sdavidxu fae = malloc(sizeof(posix_spawn_file_actions_entry_t)); 293179838Sdavidxu if (fae == NULL) 294179838Sdavidxu return (errno); 295179838Sdavidxu 296179838Sdavidxu /* Set values and store in queue */ 297179838Sdavidxu fae->fae_action = FAE_OPEN; 298179838Sdavidxu fae->fae_path = strdup(path); 299179838Sdavidxu if (fae->fae_path == NULL) { 300179838Sdavidxu error = errno; 301179838Sdavidxu free(fae); 302179838Sdavidxu return (error); 303179838Sdavidxu } 304179838Sdavidxu fae->fae_fildes = fildes; 305179838Sdavidxu fae->fae_oflag = oflag; 306179838Sdavidxu fae->fae_mode = mode; 307179838Sdavidxu 308179838Sdavidxu STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list); 309179838Sdavidxu return (0); 310179838Sdavidxu} 311179838Sdavidxu 312179838Sdavidxuint 313179838Sdavidxuposix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *fa, 314179838Sdavidxu int fildes, int newfildes) 315179838Sdavidxu{ 316179838Sdavidxu posix_spawn_file_actions_entry_t *fae; 317179838Sdavidxu 318179838Sdavidxu if (fildes < 0 || newfildes < 0) 319179838Sdavidxu return (EBADF); 320179838Sdavidxu 321179838Sdavidxu /* Allocate object */ 322179838Sdavidxu fae = malloc(sizeof(posix_spawn_file_actions_entry_t)); 323179838Sdavidxu if (fae == NULL) 324179838Sdavidxu return (errno); 325179838Sdavidxu 326179838Sdavidxu /* Set values and store in queue */ 327179838Sdavidxu fae->fae_action = FAE_DUP2; 328179838Sdavidxu fae->fae_fildes = fildes; 329179838Sdavidxu fae->fae_newfildes = newfildes; 330179838Sdavidxu 331179838Sdavidxu STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list); 332179838Sdavidxu return (0); 333179838Sdavidxu} 334179838Sdavidxu 335179838Sdavidxuint posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *fa, 336179838Sdavidxu int fildes) 337179838Sdavidxu{ 338179838Sdavidxu posix_spawn_file_actions_entry_t *fae; 339179838Sdavidxu 340179838Sdavidxu if (fildes < 0) 341179838Sdavidxu return (EBADF); 342179838Sdavidxu 343179838Sdavidxu /* Allocate object */ 344179838Sdavidxu fae = malloc(sizeof(posix_spawn_file_actions_entry_t)); 345179838Sdavidxu if (fae == NULL) 346179838Sdavidxu return (errno); 347179838Sdavidxu 348179838Sdavidxu /* Set values and store in queue */ 349179838Sdavidxu fae->fae_action = FAE_CLOSE; 350179838Sdavidxu fae->fae_fildes = fildes; 351179838Sdavidxu 352179838Sdavidxu STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list); 353179838Sdavidxu return (0); 354179838Sdavidxu} 355179838Sdavidxu 356179838Sdavidxu/* 357179838Sdavidxu * Spawn attributes 358179838Sdavidxu */ 359179838Sdavidxu 360179838Sdavidxuint 361179838Sdavidxuposix_spawnattr_init(posix_spawnattr_t *ret) 362179838Sdavidxu{ 363179838Sdavidxu posix_spawnattr_t sa; 364179838Sdavidxu 365179838Sdavidxu sa = calloc(1, sizeof(struct __posix_spawnattr)); 366179838Sdavidxu if (sa == NULL) 367179838Sdavidxu return (errno); 368179838Sdavidxu 369179838Sdavidxu /* Set defaults as specified by POSIX, cleared above */ 370179838Sdavidxu *ret = sa; 371179838Sdavidxu return (0); 372179838Sdavidxu} 373179838Sdavidxu 374179838Sdavidxuint 375179838Sdavidxuposix_spawnattr_destroy(posix_spawnattr_t *sa) 376179838Sdavidxu{ 377179838Sdavidxu free(*sa); 378179838Sdavidxu return (0); 379179838Sdavidxu} 380179838Sdavidxu 381179838Sdavidxuint 382179838Sdavidxuposix_spawnattr_getflags(const posix_spawnattr_t * __restrict sa, 383179838Sdavidxu short * __restrict flags) 384179838Sdavidxu{ 385179838Sdavidxu *flags = (*sa)->sa_flags; 386179838Sdavidxu return (0); 387179838Sdavidxu} 388179838Sdavidxu 389179838Sdavidxuint 390179838Sdavidxuposix_spawnattr_getpgroup(const posix_spawnattr_t * __restrict sa, 391179838Sdavidxu pid_t * __restrict pgroup) 392179838Sdavidxu{ 393179838Sdavidxu *pgroup = (*sa)->sa_pgroup; 394179838Sdavidxu return (0); 395179838Sdavidxu} 396179838Sdavidxu 397179838Sdavidxuint 398179838Sdavidxuposix_spawnattr_getschedparam(const posix_spawnattr_t * __restrict sa, 399179838Sdavidxu struct sched_param * __restrict schedparam) 400179838Sdavidxu{ 401179838Sdavidxu *schedparam = (*sa)->sa_schedparam; 402179838Sdavidxu return (0); 403179838Sdavidxu} 404179838Sdavidxu 405179838Sdavidxuint 406179838Sdavidxuposix_spawnattr_getschedpolicy(const posix_spawnattr_t * __restrict sa, 407179838Sdavidxu int * __restrict schedpolicy) 408179838Sdavidxu{ 409179838Sdavidxu *schedpolicy = (*sa)->sa_schedpolicy; 410179838Sdavidxu return (0); 411179838Sdavidxu} 412179838Sdavidxu 413179838Sdavidxuint 414179838Sdavidxuposix_spawnattr_getsigdefault(const posix_spawnattr_t * __restrict sa, 415179838Sdavidxu sigset_t * __restrict sigdefault) 416179838Sdavidxu{ 417179838Sdavidxu *sigdefault = (*sa)->sa_sigdefault; 418179838Sdavidxu return (0); 419179838Sdavidxu} 420179838Sdavidxu 421179838Sdavidxuint 422179838Sdavidxuposix_spawnattr_getsigmask(const posix_spawnattr_t * __restrict sa, 423179838Sdavidxu sigset_t * __restrict sigmask) 424179838Sdavidxu{ 425179838Sdavidxu *sigmask = (*sa)->sa_sigmask; 426179838Sdavidxu return (0); 427179838Sdavidxu} 428179838Sdavidxu 429179838Sdavidxuint 430179838Sdavidxuposix_spawnattr_setflags(posix_spawnattr_t *sa, short flags) 431179838Sdavidxu{ 432179838Sdavidxu (*sa)->sa_flags = flags; 433179838Sdavidxu return (0); 434179838Sdavidxu} 435179838Sdavidxu 436179838Sdavidxuint 437179838Sdavidxuposix_spawnattr_setpgroup(posix_spawnattr_t *sa, pid_t pgroup) 438179838Sdavidxu{ 439179838Sdavidxu (*sa)->sa_pgroup = pgroup; 440179838Sdavidxu return (0); 441179838Sdavidxu} 442179838Sdavidxu 443179838Sdavidxuint 444179838Sdavidxuposix_spawnattr_setschedparam(posix_spawnattr_t *sa __restrict, 445179838Sdavidxu const struct sched_param * __restrict schedparam) 446179838Sdavidxu{ 447179838Sdavidxu (*sa)->sa_schedparam = *schedparam; 448179838Sdavidxu return (0); 449179838Sdavidxu} 450179838Sdavidxu 451179838Sdavidxuint 452179838Sdavidxuposix_spawnattr_setschedpolicy(posix_spawnattr_t *sa, int schedpolicy) 453179838Sdavidxu{ 454179838Sdavidxu (*sa)->sa_schedpolicy = schedpolicy; 455179838Sdavidxu return (0); 456179838Sdavidxu} 457179838Sdavidxu 458179838Sdavidxuint 459179838Sdavidxuposix_spawnattr_setsigdefault(posix_spawnattr_t * __restrict sa, 460179838Sdavidxu const sigset_t * __restrict sigdefault) 461179838Sdavidxu{ 462179838Sdavidxu (*sa)->sa_sigdefault = *sigdefault; 463179838Sdavidxu return (0); 464179838Sdavidxu} 465179838Sdavidxu 466179838Sdavidxuint 467179838Sdavidxuposix_spawnattr_setsigmask(posix_spawnattr_t * __restrict sa, 468179838Sdavidxu const sigset_t * __restrict sigmask) 469179838Sdavidxu{ 470179838Sdavidxu (*sa)->sa_sigmask = *sigmask; 471179838Sdavidxu return (0); 472179838Sdavidxu} 473