1*8a16b7a1SPedro F. Giffuni /*- 2*8a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 3*8a16b7a1SPedro F. Giffuni * 49b50d902SRodney W. Grimes * Copyright (c) 1980, 1993 59b50d902SRodney W. Grimes * The Regents of the University of California. All rights reserved. 69b50d902SRodney W. Grimes * 79b50d902SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 89b50d902SRodney W. Grimes * modification, are permitted provided that the following conditions 99b50d902SRodney W. Grimes * are met: 109b50d902SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 119b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 129b50d902SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 139b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 149b50d902SRodney W. Grimes * documentation and/or other materials provided with the distribution. 15fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 169b50d902SRodney W. Grimes * may be used to endorse or promote products derived from this software 179b50d902SRodney W. Grimes * without specific prior written permission. 189b50d902SRodney W. Grimes * 199b50d902SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 209b50d902SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 219b50d902SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 229b50d902SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 239b50d902SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 249b50d902SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 259b50d902SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 269b50d902SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 279b50d902SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 289b50d902SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 299b50d902SRodney W. Grimes * SUCH DAMAGE. 309b50d902SRodney W. Grimes */ 319b50d902SRodney W. Grimes 329b50d902SRodney W. Grimes #ifndef lint 330c3a8314SMike Heffner #if 0 349b50d902SRodney W. Grimes static char sccsid[] = "@(#)popen.c 8.1 (Berkeley) 6/6/93"; 350c3a8314SMike Heffner #endif 369b50d902SRodney W. Grimes #endif /* not lint */ 37e026a48cSDavid E. O'Brien #include <sys/cdefs.h> 38e026a48cSDavid E. O'Brien __FBSDID("$FreeBSD$"); 399b50d902SRodney W. Grimes 409b50d902SRodney W. Grimes #include "rcv.h" 419b50d902SRodney W. Grimes #include <sys/wait.h> 429b50d902SRodney W. Grimes #include <fcntl.h> 43b22a8699SPedro F. Giffuni #include <errno.h> 44b22a8699SPedro F. Giffuni #include <stdarg.h> 459b50d902SRodney W. Grimes #include "extern.h" 469b50d902SRodney W. Grimes 479b50d902SRodney W. Grimes #define READ 0 489b50d902SRodney W. Grimes #define WRITE 1 499b50d902SRodney W. Grimes 509b50d902SRodney W. Grimes struct fp { 519b50d902SRodney W. Grimes FILE *fp; 529b50d902SRodney W. Grimes int pipe; 53b22a8699SPedro F. Giffuni pid_t pid; 549b50d902SRodney W. Grimes struct fp *link; 559b50d902SRodney W. Grimes }; 569b50d902SRodney W. Grimes static struct fp *fp_head; 579b50d902SRodney W. Grimes 589b50d902SRodney W. Grimes struct child { 59b22a8699SPedro F. Giffuni pid_t pid; 609b50d902SRodney W. Grimes char done; 619b50d902SRodney W. Grimes char free; 620c3a8314SMike Heffner int status; 639b50d902SRodney W. Grimes struct child *link; 649b50d902SRodney W. Grimes }; 65b22a8699SPedro F. Giffuni static struct child *child, *child_freelist = NULL; 66b22a8699SPedro F. Giffuni 67d3cb5dedSWarner Losh static void delchild(struct child *); 68b22a8699SPedro F. Giffuni static pid_t file_pid(FILE *); 69b22a8699SPedro F. Giffuni static pid_t start_commandv(char *, sigset_t *, int, int, va_list); 709b50d902SRodney W. Grimes 719b50d902SRodney W. Grimes FILE * 726d8484b0SPhilippe Charnier Fopen(const char *path, const char *mode) 739b50d902SRodney W. Grimes { 749b50d902SRodney W. Grimes FILE *fp; 759b50d902SRodney W. Grimes 769ce73e90SMike Heffner if ((fp = fopen(path, mode)) != NULL) { 779b50d902SRodney W. Grimes register_file(fp, 0, 0); 789b50d902SRodney W. Grimes (void)fcntl(fileno(fp), F_SETFD, 1); 799b50d902SRodney W. Grimes } 809ce73e90SMike Heffner return (fp); 819b50d902SRodney W. Grimes } 829b50d902SRodney W. Grimes 839b50d902SRodney W. Grimes FILE * 846d8484b0SPhilippe Charnier Fdopen(int fd, const char *mode) 859b50d902SRodney W. Grimes { 869b50d902SRodney W. Grimes FILE *fp; 879b50d902SRodney W. Grimes 889b50d902SRodney W. Grimes if ((fp = fdopen(fd, mode)) != NULL) { 899b50d902SRodney W. Grimes register_file(fp, 0, 0); 909b50d902SRodney W. Grimes (void)fcntl(fileno(fp), F_SETFD, 1); 919b50d902SRodney W. Grimes } 929ce73e90SMike Heffner return (fp); 939b50d902SRodney W. Grimes } 949b50d902SRodney W. Grimes 959b50d902SRodney W. Grimes int 966d8484b0SPhilippe Charnier Fclose(FILE *fp) 979b50d902SRodney W. Grimes { 98b22a8699SPedro F. Giffuni 999b50d902SRodney W. Grimes unregister_file(fp); 1009ce73e90SMike Heffner return (fclose(fp)); 1019b50d902SRodney W. Grimes } 1029b50d902SRodney W. Grimes 1039b50d902SRodney W. Grimes FILE * 1046d8484b0SPhilippe Charnier Popen(char *cmd, const char *mode) 1059b50d902SRodney W. Grimes { 1069b50d902SRodney W. Grimes int p[2]; 1079b50d902SRodney W. Grimes int myside, hisside, fd0, fd1; 108b22a8699SPedro F. Giffuni pid_t pid; 109856f23edSMike Heffner sigset_t nset; 1109b50d902SRodney W. Grimes FILE *fp; 1119b50d902SRodney W. Grimes 1129b50d902SRodney W. Grimes if (pipe(p) < 0) 1139ce73e90SMike Heffner return (NULL); 1149b50d902SRodney W. Grimes (void)fcntl(p[READ], F_SETFD, 1); 1159b50d902SRodney W. Grimes (void)fcntl(p[WRITE], F_SETFD, 1); 1169b50d902SRodney W. Grimes if (*mode == 'r') { 1179b50d902SRodney W. Grimes myside = p[READ]; 118b22a8699SPedro F. Giffuni hisside = fd0 = fd1 = p[WRITE]; 1199b50d902SRodney W. Grimes } else { 1209b50d902SRodney W. Grimes myside = p[WRITE]; 1219b50d902SRodney W. Grimes hisside = fd0 = p[READ]; 1229b50d902SRodney W. Grimes fd1 = -1; 1239b50d902SRodney W. Grimes } 124856f23edSMike Heffner (void)sigemptyset(&nset); 125b22a8699SPedro F. Giffuni pid = start_command(value("SHELL"), &nset, fd0, fd1, "-c", cmd, NULL); 126b22a8699SPedro F. Giffuni if (pid < 0) { 1279ce73e90SMike Heffner (void)close(p[READ]); 1289ce73e90SMike Heffner (void)close(p[WRITE]); 1299ce73e90SMike Heffner return (NULL); 1309b50d902SRodney W. Grimes } 1319b50d902SRodney W. Grimes (void)close(hisside); 1329b50d902SRodney W. Grimes if ((fp = fdopen(myside, mode)) != NULL) 1339b50d902SRodney W. Grimes register_file(fp, 1, pid); 1349ce73e90SMike Heffner return (fp); 1359b50d902SRodney W. Grimes } 1369b50d902SRodney W. Grimes 1379b50d902SRodney W. Grimes int 1386d8484b0SPhilippe Charnier Pclose(FILE *ptr) 1399b50d902SRodney W. Grimes { 1409b50d902SRodney W. Grimes int i; 141856f23edSMike Heffner sigset_t nset, oset; 1429b50d902SRodney W. Grimes 1439b50d902SRodney W. Grimes i = file_pid(ptr); 1449b50d902SRodney W. Grimes unregister_file(ptr); 1459b50d902SRodney W. Grimes (void)fclose(ptr); 146856f23edSMike Heffner (void)sigemptyset(&nset); 147856f23edSMike Heffner (void)sigaddset(&nset, SIGINT); 148856f23edSMike Heffner (void)sigaddset(&nset, SIGHUP); 149856f23edSMike Heffner (void)sigprocmask(SIG_BLOCK, &nset, &oset); 1509b50d902SRodney W. Grimes i = wait_child(i); 151856f23edSMike Heffner (void)sigprocmask(SIG_SETMASK, &oset, NULL); 1529ce73e90SMike Heffner return (i); 1539b50d902SRodney W. Grimes } 1549b50d902SRodney W. Grimes 1559b50d902SRodney W. Grimes void 1566d8484b0SPhilippe Charnier close_all_files(void) 1579b50d902SRodney W. Grimes { 1589b50d902SRodney W. Grimes 1599ce73e90SMike Heffner while (fp_head != NULL) 1609b50d902SRodney W. Grimes if (fp_head->pipe) 1619b50d902SRodney W. Grimes (void)Pclose(fp_head->fp); 1629b50d902SRodney W. Grimes else 1639b50d902SRodney W. Grimes (void)Fclose(fp_head->fp); 1649b50d902SRodney W. Grimes } 1659b50d902SRodney W. Grimes 1669b50d902SRodney W. Grimes void 167b22a8699SPedro F. Giffuni register_file(FILE *fp, int pipe, pid_t pid) 1689b50d902SRodney W. Grimes { 1699b50d902SRodney W. Grimes struct fp *fpp; 1709b50d902SRodney W. Grimes 1719ce73e90SMike Heffner if ((fpp = malloc(sizeof(*fpp))) == NULL) 1720c3a8314SMike Heffner err(1, "Out of memory"); 1739b50d902SRodney W. Grimes fpp->fp = fp; 1749b50d902SRodney W. Grimes fpp->pipe = pipe; 1759b50d902SRodney W. Grimes fpp->pid = pid; 1769b50d902SRodney W. Grimes fpp->link = fp_head; 1779b50d902SRodney W. Grimes fp_head = fpp; 1789b50d902SRodney W. Grimes } 1799b50d902SRodney W. Grimes 1809b50d902SRodney W. Grimes void 1816d8484b0SPhilippe Charnier unregister_file(FILE *fp) 1829b50d902SRodney W. Grimes { 1839b50d902SRodney W. Grimes struct fp **pp, *p; 1849b50d902SRodney W. Grimes 1859ce73e90SMike Heffner for (pp = &fp_head; (p = *pp) != NULL; pp = &p->link) 1869b50d902SRodney W. Grimes if (p->fp == fp) { 1879b50d902SRodney W. Grimes *pp = p->link; 1889ce73e90SMike Heffner (void)free(p); 1899b50d902SRodney W. Grimes return; 1909b50d902SRodney W. Grimes } 1910c3a8314SMike Heffner errx(1, "Invalid file pointer"); 1920c3a8314SMike Heffner /*NOTREACHED*/ 1939b50d902SRodney W. Grimes } 1949b50d902SRodney W. Grimes 195b22a8699SPedro F. Giffuni pid_t 1966d8484b0SPhilippe Charnier file_pid(FILE *fp) 1979b50d902SRodney W. Grimes { 1989b50d902SRodney W. Grimes struct fp *p; 1999b50d902SRodney W. Grimes 2009ce73e90SMike Heffner for (p = fp_head; p != NULL; p = p->link) 2019b50d902SRodney W. Grimes if (p->fp == fp) 2029b50d902SRodney W. Grimes return (p->pid); 2030c3a8314SMike Heffner errx(1, "Invalid file pointer"); 2049b50d902SRodney W. Grimes /*NOTREACHED*/ 2059b50d902SRodney W. Grimes } 2069b50d902SRodney W. Grimes 2079b50d902SRodney W. Grimes /* 2089b50d902SRodney W. Grimes * Run a command without a shell, with optional arguments and splicing 209b22a8699SPedro F. Giffuni * of stdin (-1 means none) and stdout. The command name can be a sequence 210b22a8699SPedro F. Giffuni * of words. 2119b50d902SRodney W. Grimes * Signals must be handled by the caller. 212b22a8699SPedro F. Giffuni * "nset" contains the signals to ignore in the new process. 213b22a8699SPedro F. Giffuni * SIGINT is enabled unless it's in "nset". 2149b50d902SRodney W. Grimes */ 215b22a8699SPedro F. Giffuni static pid_t 216b22a8699SPedro F. Giffuni start_commandv(char *cmd, sigset_t *nset, int infd, int outfd, va_list args) 2179b50d902SRodney W. Grimes { 218b22a8699SPedro F. Giffuni pid_t pid; 2199b50d902SRodney W. Grimes 220db6b6910SBruce Evans if ((pid = fork()) < 0) { 2210c3a8314SMike Heffner warn("fork"); 2229ce73e90SMike Heffner return (-1); 2239b50d902SRodney W. Grimes } 2249b50d902SRodney W. Grimes if (pid == 0) { 2259b50d902SRodney W. Grimes char *argv[100]; 2269ce73e90SMike Heffner int i = getrawlist(cmd, argv, sizeof(argv) / sizeof(*argv)); 2279b50d902SRodney W. Grimes 228b22a8699SPedro F. Giffuni while ((argv[i++] = va_arg(args, char *))) 229b22a8699SPedro F. Giffuni ; 2309ce73e90SMike Heffner argv[i] = NULL; 231b22a8699SPedro F. Giffuni prepare_child(nset, infd, outfd); 2329b50d902SRodney W. Grimes execvp(argv[0], argv); 2330c3a8314SMike Heffner warn("%s", argv[0]); 2349b50d902SRodney W. Grimes _exit(1); 2359b50d902SRodney W. Grimes } 2369ce73e90SMike Heffner return (pid); 2379b50d902SRodney W. Grimes } 2389b50d902SRodney W. Grimes 239b22a8699SPedro F. Giffuni int 240b22a8699SPedro F. Giffuni run_command(char *cmd, sigset_t *nset, int infd, int outfd, ...) 241b22a8699SPedro F. Giffuni { 242b22a8699SPedro F. Giffuni pid_t pid; 243b22a8699SPedro F. Giffuni va_list args; 244b22a8699SPedro F. Giffuni 245b22a8699SPedro F. Giffuni va_start(args, outfd); 246b22a8699SPedro F. Giffuni pid = start_commandv(cmd, nset, infd, outfd, args); 247b22a8699SPedro F. Giffuni va_end(args); 248b22a8699SPedro F. Giffuni if (pid < 0) 249b22a8699SPedro F. Giffuni return -1; 250b22a8699SPedro F. Giffuni return wait_command(pid); 251b22a8699SPedro F. Giffuni } 252b22a8699SPedro F. Giffuni 253b22a8699SPedro F. Giffuni int 254b22a8699SPedro F. Giffuni start_command(char *cmd, sigset_t *nset, int infd, int outfd, ...) 255b22a8699SPedro F. Giffuni { 256b22a8699SPedro F. Giffuni va_list args; 257b22a8699SPedro F. Giffuni int r; 258b22a8699SPedro F. Giffuni 259b22a8699SPedro F. Giffuni va_start(args, outfd); 260b22a8699SPedro F. Giffuni r = start_commandv(cmd, nset, infd, outfd, args); 261b22a8699SPedro F. Giffuni va_end(args); 262b22a8699SPedro F. Giffuni return r; 263b22a8699SPedro F. Giffuni } 264b22a8699SPedro F. Giffuni 2659b50d902SRodney W. Grimes void 2666d8484b0SPhilippe Charnier prepare_child(sigset_t *nset, int infd, int outfd) 2679b50d902SRodney W. Grimes { 2689b50d902SRodney W. Grimes int i; 269856f23edSMike Heffner sigset_t eset; 2709b50d902SRodney W. Grimes 2719b50d902SRodney W. Grimes /* 2729b50d902SRodney W. Grimes * All file descriptors other than 0, 1, and 2 are supposed to be 2739b50d902SRodney W. Grimes * close-on-exec. 2749b50d902SRodney W. Grimes */ 2759b50d902SRodney W. Grimes if (infd >= 0) 2769b50d902SRodney W. Grimes dup2(infd, 0); 2779b50d902SRodney W. Grimes if (outfd >= 0) 2789b50d902SRodney W. Grimes dup2(outfd, 1); 279856f23edSMike Heffner for (i = 1; i < NSIG; i++) 280856f23edSMike Heffner if (nset != NULL && sigismember(nset, i)) 2819b50d902SRodney W. Grimes (void)signal(i, SIG_IGN); 282856f23edSMike Heffner if (nset == NULL || !sigismember(nset, SIGINT)) 2839b50d902SRodney W. Grimes (void)signal(SIGINT, SIG_DFL); 284856f23edSMike Heffner (void)sigemptyset(&eset); 285856f23edSMike Heffner (void)sigprocmask(SIG_SETMASK, &eset, NULL); 2869b50d902SRodney W. Grimes } 2879b50d902SRodney W. Grimes 2889b50d902SRodney W. Grimes int 289b22a8699SPedro F. Giffuni wait_command(pid_t pid) 2909b50d902SRodney W. Grimes { 2919b50d902SRodney W. Grimes 2929b50d902SRodney W. Grimes if (wait_child(pid) < 0) { 2939b50d902SRodney W. Grimes printf("Fatal error in process.\n"); 2949ce73e90SMike Heffner return (-1); 2959b50d902SRodney W. Grimes } 2969ce73e90SMike Heffner return (0); 2979b50d902SRodney W. Grimes } 2989b50d902SRodney W. Grimes 2999b50d902SRodney W. Grimes static struct child * 300b22a8699SPedro F. Giffuni findchild(pid_t pid, int dont_alloc) 3019b50d902SRodney W. Grimes { 3029ce73e90SMike Heffner struct child **cpp; 3039b50d902SRodney W. Grimes 3049b50d902SRodney W. Grimes for (cpp = &child; *cpp != NULL && (*cpp)->pid != pid; 3059b50d902SRodney W. Grimes cpp = &(*cpp)->link) 3069b50d902SRodney W. Grimes ; 3079b50d902SRodney W. Grimes if (*cpp == NULL) { 308b22a8699SPedro F. Giffuni if (dont_alloc) 309b22a8699SPedro F. Giffuni return(NULL); 310b22a8699SPedro F. Giffuni if (child_freelist) { 311b22a8699SPedro F. Giffuni *cpp = child_freelist; 312b22a8699SPedro F. Giffuni child_freelist = (*cpp)->link; 313b22a8699SPedro F. Giffuni } else { 3149ce73e90SMike Heffner *cpp = malloc(sizeof(struct child)); 3150c3a8314SMike Heffner if (*cpp == NULL) 316b22a8699SPedro F. Giffuni err(1, "malloc"); 317b22a8699SPedro F. Giffuni } 3189b50d902SRodney W. Grimes (*cpp)->pid = pid; 3199b50d902SRodney W. Grimes (*cpp)->done = (*cpp)->free = 0; 3209b50d902SRodney W. Grimes (*cpp)->link = NULL; 3219b50d902SRodney W. Grimes } 3229ce73e90SMike Heffner return (*cpp); 3239b50d902SRodney W. Grimes } 3249b50d902SRodney W. Grimes 3259b50d902SRodney W. Grimes static void 3266d8484b0SPhilippe Charnier delchild(struct child *cp) 3279b50d902SRodney W. Grimes { 3289ce73e90SMike Heffner struct child **cpp; 3299b50d902SRodney W. Grimes 3309b50d902SRodney W. Grimes for (cpp = &child; *cpp != cp; cpp = &(*cpp)->link) 3319b50d902SRodney W. Grimes ; 3329b50d902SRodney W. Grimes *cpp = cp->link; 333b22a8699SPedro F. Giffuni cp->link = child_freelist; 334b22a8699SPedro F. Giffuni child_freelist = cp; 3359b50d902SRodney W. Grimes } 3369b50d902SRodney W. Grimes 3379ce73e90SMike Heffner /*ARGSUSED*/ 3389b50d902SRodney W. Grimes void 3396d8484b0SPhilippe Charnier sigchild(int signo __unused) 3409b50d902SRodney W. Grimes { 341b22a8699SPedro F. Giffuni pid_t pid; 3420c3a8314SMike Heffner int status; 3439ce73e90SMike Heffner struct child *cp; 344b22a8699SPedro F. Giffuni int save_errno; 3459b50d902SRodney W. Grimes 346b22a8699SPedro F. Giffuni save_errno = errno; 347ed74b69cSKevin Lo while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { 348b22a8699SPedro F. Giffuni cp = findchild(pid, 1); 3491d1e1f63SXin LI if (cp == NULL) 3501d1e1f63SXin LI continue; 3519b50d902SRodney W. Grimes if (cp->free) 3529b50d902SRodney W. Grimes delchild(cp); 3539b50d902SRodney W. Grimes else { 3549b50d902SRodney W. Grimes cp->done = 1; 3559b50d902SRodney W. Grimes cp->status = status; 3569b50d902SRodney W. Grimes } 3579b50d902SRodney W. Grimes } 358b22a8699SPedro F. Giffuni errno = save_errno; 3599b50d902SRodney W. Grimes } 3609b50d902SRodney W. Grimes 3610c3a8314SMike Heffner int wait_status; 3629b50d902SRodney W. Grimes 3639b50d902SRodney W. Grimes /* 3649b50d902SRodney W. Grimes * Wait for a specific child to die. 3659b50d902SRodney W. Grimes */ 3669b50d902SRodney W. Grimes int 367b22a8699SPedro F. Giffuni wait_child(pid_t pid) 3689b50d902SRodney W. Grimes { 36935f8ab70SEitan Adler struct child *cp; 37092fa728bSPedro F. Giffuni sigset_t nset, oset; 37192fa728bSPedro F. Giffuni pid_t rv = 0; 3729b50d902SRodney W. Grimes 373856f23edSMike Heffner (void)sigemptyset(&nset); 374856f23edSMike Heffner (void)sigaddset(&nset, SIGCHLD); 375856f23edSMike Heffner (void)sigprocmask(SIG_BLOCK, &nset, &oset); 37692fa728bSPedro F. Giffuni /* 37792fa728bSPedro F. Giffuni * If we have not already waited on the pid (via sigchild) 37892fa728bSPedro F. Giffuni * wait on it now. Otherwise, use the wait status stashed 37992fa728bSPedro F. Giffuni * by sigchild. 38092fa728bSPedro F. Giffuni */ 381b22a8699SPedro F. Giffuni cp = findchild(pid, 1); 38292fa728bSPedro F. Giffuni if (cp == NULL || !cp->done) 38392fa728bSPedro F. Giffuni rv = waitpid(pid, &wait_status, 0); 38492fa728bSPedro F. Giffuni else 3859b50d902SRodney W. Grimes wait_status = cp->status; 38692fa728bSPedro F. Giffuni if (cp != NULL) 3879b50d902SRodney W. Grimes delchild(cp); 388856f23edSMike Heffner (void)sigprocmask(SIG_SETMASK, &oset, NULL); 38992fa728bSPedro F. Giffuni if (rv == -1 || (WIFEXITED(wait_status) && WEXITSTATUS(wait_status))) 39092fa728bSPedro F. Giffuni return -1; 39192fa728bSPedro F. Giffuni else 39292fa728bSPedro F. Giffuni return 0; 3939b50d902SRodney W. Grimes } 3949b50d902SRodney W. Grimes 3959b50d902SRodney W. Grimes /* 3969b50d902SRodney W. Grimes * Mark a child as don't care. 3979b50d902SRodney W. Grimes */ 3989b50d902SRodney W. Grimes void 399b22a8699SPedro F. Giffuni free_child(pid_t pid) 4009b50d902SRodney W. Grimes { 401b22a8699SPedro F. Giffuni struct child *cp; 402856f23edSMike Heffner sigset_t nset, oset; 4039b50d902SRodney W. Grimes 404856f23edSMike Heffner (void)sigemptyset(&nset); 405856f23edSMike Heffner (void)sigaddset(&nset, SIGCHLD); 406856f23edSMike Heffner (void)sigprocmask(SIG_BLOCK, &nset, &oset); 407b22a8699SPedro F. Giffuni if ((cp = findchild(pid, 0)) != NULL) { 4089b50d902SRodney W. Grimes if (cp->done) 4099b50d902SRodney W. Grimes delchild(cp); 4109b50d902SRodney W. Grimes else 4119b50d902SRodney W. Grimes cp->free = 1; 412b22a8699SPedro F. Giffuni } 413856f23edSMike Heffner (void)sigprocmask(SIG_SETMASK, &oset, NULL); 4149b50d902SRodney W. Grimes } 415