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 #include "rcv.h"
339b50d902SRodney W. Grimes #include <sys/wait.h>
349b50d902SRodney W. Grimes #include <fcntl.h>
35b22a8699SPedro F. Giffuni #include <errno.h>
36b22a8699SPedro F. Giffuni #include <stdarg.h>
379b50d902SRodney W. Grimes #include "extern.h"
389b50d902SRodney W. Grimes
399b50d902SRodney W. Grimes #define READ 0
409b50d902SRodney W. Grimes #define WRITE 1
419b50d902SRodney W. Grimes
429b50d902SRodney W. Grimes struct fp {
439b50d902SRodney W. Grimes FILE *fp;
449b50d902SRodney W. Grimes int pipe;
45b22a8699SPedro F. Giffuni pid_t pid;
469b50d902SRodney W. Grimes struct fp *link;
479b50d902SRodney W. Grimes };
489b50d902SRodney W. Grimes static struct fp *fp_head;
499b50d902SRodney W. Grimes
509b50d902SRodney W. Grimes struct child {
51b22a8699SPedro F. Giffuni pid_t pid;
529b50d902SRodney W. Grimes char done;
539b50d902SRodney W. Grimes char free;
540c3a8314SMike Heffner int status;
559b50d902SRodney W. Grimes struct child *link;
569b50d902SRodney W. Grimes };
57b22a8699SPedro F. Giffuni static struct child *child, *child_freelist = NULL;
58b22a8699SPedro F. Giffuni
59d3cb5dedSWarner Losh static void delchild(struct child *);
60b22a8699SPedro F. Giffuni static pid_t file_pid(FILE *);
61b22a8699SPedro F. Giffuni static pid_t start_commandv(char *, sigset_t *, int, int, va_list);
629b50d902SRodney W. Grimes
639b50d902SRodney W. Grimes FILE *
Fopen(const char * path,const char * mode)646d8484b0SPhilippe Charnier Fopen(const char *path, const char *mode)
659b50d902SRodney W. Grimes {
669b50d902SRodney W. Grimes FILE *fp;
679b50d902SRodney W. Grimes
689ce73e90SMike Heffner if ((fp = fopen(path, mode)) != NULL) {
699b50d902SRodney W. Grimes register_file(fp, 0, 0);
709b50d902SRodney W. Grimes (void)fcntl(fileno(fp), F_SETFD, 1);
719b50d902SRodney W. Grimes }
729ce73e90SMike Heffner return (fp);
739b50d902SRodney W. Grimes }
749b50d902SRodney W. Grimes
759b50d902SRodney W. Grimes FILE *
Fdopen(int fd,const char * mode)766d8484b0SPhilippe Charnier Fdopen(int fd, const char *mode)
779b50d902SRodney W. Grimes {
789b50d902SRodney W. Grimes FILE *fp;
799b50d902SRodney W. Grimes
809b50d902SRodney W. Grimes if ((fp = fdopen(fd, mode)) != NULL) {
819b50d902SRodney W. Grimes register_file(fp, 0, 0);
829b50d902SRodney W. Grimes (void)fcntl(fileno(fp), F_SETFD, 1);
839b50d902SRodney W. Grimes }
849ce73e90SMike Heffner return (fp);
859b50d902SRodney W. Grimes }
869b50d902SRodney W. Grimes
879b50d902SRodney W. Grimes int
Fclose(FILE * fp)886d8484b0SPhilippe Charnier Fclose(FILE *fp)
899b50d902SRodney W. Grimes {
90b22a8699SPedro F. Giffuni
919b50d902SRodney W. Grimes unregister_file(fp);
929ce73e90SMike Heffner return (fclose(fp));
939b50d902SRodney W. Grimes }
949b50d902SRodney W. Grimes
959b50d902SRodney W. Grimes FILE *
Popen(char * cmd,const char * mode)966d8484b0SPhilippe Charnier Popen(char *cmd, const char *mode)
979b50d902SRodney W. Grimes {
989b50d902SRodney W. Grimes int p[2];
999b50d902SRodney W. Grimes int myside, hisside, fd0, fd1;
100b22a8699SPedro F. Giffuni pid_t pid;
101856f23edSMike Heffner sigset_t nset;
1029b50d902SRodney W. Grimes FILE *fp;
1039b50d902SRodney W. Grimes
1049b50d902SRodney W. Grimes if (pipe(p) < 0)
1059ce73e90SMike Heffner return (NULL);
1069b50d902SRodney W. Grimes (void)fcntl(p[READ], F_SETFD, 1);
1079b50d902SRodney W. Grimes (void)fcntl(p[WRITE], F_SETFD, 1);
1089b50d902SRodney W. Grimes if (*mode == 'r') {
1099b50d902SRodney W. Grimes myside = p[READ];
110b22a8699SPedro F. Giffuni hisside = fd0 = fd1 = p[WRITE];
1119b50d902SRodney W. Grimes } else {
1129b50d902SRodney W. Grimes myside = p[WRITE];
1139b50d902SRodney W. Grimes hisside = fd0 = p[READ];
1149b50d902SRodney W. Grimes fd1 = -1;
1159b50d902SRodney W. Grimes }
116856f23edSMike Heffner (void)sigemptyset(&nset);
117b22a8699SPedro F. Giffuni pid = start_command(value("SHELL"), &nset, fd0, fd1, "-c", cmd, NULL);
118b22a8699SPedro F. Giffuni if (pid < 0) {
1199ce73e90SMike Heffner (void)close(p[READ]);
1209ce73e90SMike Heffner (void)close(p[WRITE]);
1219ce73e90SMike Heffner return (NULL);
1229b50d902SRodney W. Grimes }
1239b50d902SRodney W. Grimes (void)close(hisside);
1249b50d902SRodney W. Grimes if ((fp = fdopen(myside, mode)) != NULL)
1259b50d902SRodney W. Grimes register_file(fp, 1, pid);
1269ce73e90SMike Heffner return (fp);
1279b50d902SRodney W. Grimes }
1289b50d902SRodney W. Grimes
1299b50d902SRodney W. Grimes int
Pclose(FILE * ptr)1306d8484b0SPhilippe Charnier Pclose(FILE *ptr)
1319b50d902SRodney W. Grimes {
1329b50d902SRodney W. Grimes int i;
133856f23edSMike Heffner sigset_t nset, oset;
1349b50d902SRodney W. Grimes
1359b50d902SRodney W. Grimes i = file_pid(ptr);
1369b50d902SRodney W. Grimes unregister_file(ptr);
1379b50d902SRodney W. Grimes (void)fclose(ptr);
138856f23edSMike Heffner (void)sigemptyset(&nset);
139856f23edSMike Heffner (void)sigaddset(&nset, SIGINT);
140856f23edSMike Heffner (void)sigaddset(&nset, SIGHUP);
141856f23edSMike Heffner (void)sigprocmask(SIG_BLOCK, &nset, &oset);
1429b50d902SRodney W. Grimes i = wait_child(i);
143856f23edSMike Heffner (void)sigprocmask(SIG_SETMASK, &oset, NULL);
1449ce73e90SMike Heffner return (i);
1459b50d902SRodney W. Grimes }
1469b50d902SRodney W. Grimes
1479b50d902SRodney W. Grimes void
close_all_files(void)1486d8484b0SPhilippe Charnier close_all_files(void)
1499b50d902SRodney W. Grimes {
1509b50d902SRodney W. Grimes
1519ce73e90SMike Heffner while (fp_head != NULL)
1529b50d902SRodney W. Grimes if (fp_head->pipe)
1539b50d902SRodney W. Grimes (void)Pclose(fp_head->fp);
1549b50d902SRodney W. Grimes else
1559b50d902SRodney W. Grimes (void)Fclose(fp_head->fp);
1569b50d902SRodney W. Grimes }
1579b50d902SRodney W. Grimes
1589b50d902SRodney W. Grimes void
register_file(FILE * fp,int pipe,pid_t pid)159b22a8699SPedro F. Giffuni register_file(FILE *fp, int pipe, pid_t pid)
1609b50d902SRodney W. Grimes {
1619b50d902SRodney W. Grimes struct fp *fpp;
1629b50d902SRodney W. Grimes
1639ce73e90SMike Heffner if ((fpp = malloc(sizeof(*fpp))) == NULL)
1640c3a8314SMike Heffner err(1, "Out of memory");
1659b50d902SRodney W. Grimes fpp->fp = fp;
1669b50d902SRodney W. Grimes fpp->pipe = pipe;
1679b50d902SRodney W. Grimes fpp->pid = pid;
1689b50d902SRodney W. Grimes fpp->link = fp_head;
1699b50d902SRodney W. Grimes fp_head = fpp;
1709b50d902SRodney W. Grimes }
1719b50d902SRodney W. Grimes
1729b50d902SRodney W. Grimes void
unregister_file(FILE * fp)1736d8484b0SPhilippe Charnier unregister_file(FILE *fp)
1749b50d902SRodney W. Grimes {
1759b50d902SRodney W. Grimes struct fp **pp, *p;
1769b50d902SRodney W. Grimes
1779ce73e90SMike Heffner for (pp = &fp_head; (p = *pp) != NULL; pp = &p->link)
1789b50d902SRodney W. Grimes if (p->fp == fp) {
1799b50d902SRodney W. Grimes *pp = p->link;
1809ce73e90SMike Heffner (void)free(p);
1819b50d902SRodney W. Grimes return;
1829b50d902SRodney W. Grimes }
1830c3a8314SMike Heffner errx(1, "Invalid file pointer");
1840c3a8314SMike Heffner /*NOTREACHED*/
1859b50d902SRodney W. Grimes }
1869b50d902SRodney W. Grimes
187b22a8699SPedro F. Giffuni pid_t
file_pid(FILE * fp)1886d8484b0SPhilippe Charnier file_pid(FILE *fp)
1899b50d902SRodney W. Grimes {
1909b50d902SRodney W. Grimes struct fp *p;
1919b50d902SRodney W. Grimes
1929ce73e90SMike Heffner for (p = fp_head; p != NULL; p = p->link)
1939b50d902SRodney W. Grimes if (p->fp == fp)
1949b50d902SRodney W. Grimes return (p->pid);
1950c3a8314SMike Heffner errx(1, "Invalid file pointer");
1969b50d902SRodney W. Grimes /*NOTREACHED*/
1979b50d902SRodney W. Grimes }
1989b50d902SRodney W. Grimes
1999b50d902SRodney W. Grimes /*
2009b50d902SRodney W. Grimes * Run a command without a shell, with optional arguments and splicing
201b22a8699SPedro F. Giffuni * of stdin (-1 means none) and stdout. The command name can be a sequence
202b22a8699SPedro F. Giffuni * of words.
2039b50d902SRodney W. Grimes * Signals must be handled by the caller.
204b22a8699SPedro F. Giffuni * "nset" contains the signals to ignore in the new process.
205b22a8699SPedro F. Giffuni * SIGINT is enabled unless it's in "nset".
2069b50d902SRodney W. Grimes */
207b22a8699SPedro F. Giffuni static pid_t
start_commandv(char * cmd,sigset_t * nset,int infd,int outfd,va_list args)208b22a8699SPedro F. Giffuni start_commandv(char *cmd, sigset_t *nset, int infd, int outfd, va_list args)
2099b50d902SRodney W. Grimes {
210b22a8699SPedro F. Giffuni pid_t pid;
2119b50d902SRodney W. Grimes
212db6b6910SBruce Evans if ((pid = fork()) < 0) {
2130c3a8314SMike Heffner warn("fork");
2149ce73e90SMike Heffner return (-1);
2159b50d902SRodney W. Grimes }
2169b50d902SRodney W. Grimes if (pid == 0) {
2179b50d902SRodney W. Grimes char *argv[100];
2189ce73e90SMike Heffner int i = getrawlist(cmd, argv, sizeof(argv) / sizeof(*argv));
2199b50d902SRodney W. Grimes
220b22a8699SPedro F. Giffuni while ((argv[i++] = va_arg(args, char *)))
221b22a8699SPedro F. Giffuni ;
2229ce73e90SMike Heffner argv[i] = NULL;
223b22a8699SPedro F. Giffuni prepare_child(nset, infd, outfd);
2249b50d902SRodney W. Grimes execvp(argv[0], argv);
2250c3a8314SMike Heffner warn("%s", argv[0]);
2269b50d902SRodney W. Grimes _exit(1);
2279b50d902SRodney W. Grimes }
2289ce73e90SMike Heffner return (pid);
2299b50d902SRodney W. Grimes }
2309b50d902SRodney W. Grimes
231b22a8699SPedro F. Giffuni int
run_command(char * cmd,sigset_t * nset,int infd,int outfd,...)232b22a8699SPedro F. Giffuni run_command(char *cmd, sigset_t *nset, int infd, int outfd, ...)
233b22a8699SPedro F. Giffuni {
234b22a8699SPedro F. Giffuni pid_t pid;
235b22a8699SPedro F. Giffuni va_list args;
236b22a8699SPedro F. Giffuni
237b22a8699SPedro F. Giffuni va_start(args, outfd);
238b22a8699SPedro F. Giffuni pid = start_commandv(cmd, nset, infd, outfd, args);
239b22a8699SPedro F. Giffuni va_end(args);
240b22a8699SPedro F. Giffuni if (pid < 0)
241b22a8699SPedro F. Giffuni return -1;
242b22a8699SPedro F. Giffuni return wait_command(pid);
243b22a8699SPedro F. Giffuni }
244b22a8699SPedro F. Giffuni
245b22a8699SPedro F. Giffuni int
start_command(char * cmd,sigset_t * nset,int infd,int outfd,...)246b22a8699SPedro F. Giffuni start_command(char *cmd, sigset_t *nset, int infd, int outfd, ...)
247b22a8699SPedro F. Giffuni {
248b22a8699SPedro F. Giffuni va_list args;
249b22a8699SPedro F. Giffuni int r;
250b22a8699SPedro F. Giffuni
251b22a8699SPedro F. Giffuni va_start(args, outfd);
252b22a8699SPedro F. Giffuni r = start_commandv(cmd, nset, infd, outfd, args);
253b22a8699SPedro F. Giffuni va_end(args);
254b22a8699SPedro F. Giffuni return r;
255b22a8699SPedro F. Giffuni }
256b22a8699SPedro F. Giffuni
2579b50d902SRodney W. Grimes void
prepare_child(sigset_t * nset,int infd,int outfd)2586d8484b0SPhilippe Charnier prepare_child(sigset_t *nset, int infd, int outfd)
2599b50d902SRodney W. Grimes {
2609b50d902SRodney W. Grimes int i;
261856f23edSMike Heffner sigset_t eset;
2629b50d902SRodney W. Grimes
2639b50d902SRodney W. Grimes /*
2649b50d902SRodney W. Grimes * All file descriptors other than 0, 1, and 2 are supposed to be
2659b50d902SRodney W. Grimes * close-on-exec.
2669b50d902SRodney W. Grimes */
2679b50d902SRodney W. Grimes if (infd >= 0)
2689b50d902SRodney W. Grimes dup2(infd, 0);
2699b50d902SRodney W. Grimes if (outfd >= 0)
2709b50d902SRodney W. Grimes dup2(outfd, 1);
271856f23edSMike Heffner for (i = 1; i < NSIG; i++)
272856f23edSMike Heffner if (nset != NULL && sigismember(nset, i))
2739b50d902SRodney W. Grimes (void)signal(i, SIG_IGN);
274856f23edSMike Heffner if (nset == NULL || !sigismember(nset, SIGINT))
2759b50d902SRodney W. Grimes (void)signal(SIGINT, SIG_DFL);
276856f23edSMike Heffner (void)sigemptyset(&eset);
277856f23edSMike Heffner (void)sigprocmask(SIG_SETMASK, &eset, NULL);
2789b50d902SRodney W. Grimes }
2799b50d902SRodney W. Grimes
2809b50d902SRodney W. Grimes int
wait_command(pid_t pid)281b22a8699SPedro F. Giffuni wait_command(pid_t pid)
2829b50d902SRodney W. Grimes {
2839b50d902SRodney W. Grimes
2849b50d902SRodney W. Grimes if (wait_child(pid) < 0) {
2859b50d902SRodney W. Grimes printf("Fatal error in process.\n");
2869ce73e90SMike Heffner return (-1);
2879b50d902SRodney W. Grimes }
2889ce73e90SMike Heffner return (0);
2899b50d902SRodney W. Grimes }
2909b50d902SRodney W. Grimes
2919b50d902SRodney W. Grimes static struct child *
findchild(pid_t pid,int dont_alloc)292b22a8699SPedro F. Giffuni findchild(pid_t pid, int dont_alloc)
2939b50d902SRodney W. Grimes {
2949ce73e90SMike Heffner struct child **cpp;
2959b50d902SRodney W. Grimes
2969b50d902SRodney W. Grimes for (cpp = &child; *cpp != NULL && (*cpp)->pid != pid;
2979b50d902SRodney W. Grimes cpp = &(*cpp)->link)
2989b50d902SRodney W. Grimes ;
2999b50d902SRodney W. Grimes if (*cpp == NULL) {
300b22a8699SPedro F. Giffuni if (dont_alloc)
301b22a8699SPedro F. Giffuni return(NULL);
302b22a8699SPedro F. Giffuni if (child_freelist) {
303b22a8699SPedro F. Giffuni *cpp = child_freelist;
304b22a8699SPedro F. Giffuni child_freelist = (*cpp)->link;
305b22a8699SPedro F. Giffuni } else {
3069ce73e90SMike Heffner *cpp = malloc(sizeof(struct child));
3070c3a8314SMike Heffner if (*cpp == NULL)
308b22a8699SPedro F. Giffuni err(1, "malloc");
309b22a8699SPedro F. Giffuni }
3109b50d902SRodney W. Grimes (*cpp)->pid = pid;
3119b50d902SRodney W. Grimes (*cpp)->done = (*cpp)->free = 0;
3129b50d902SRodney W. Grimes (*cpp)->link = NULL;
3139b50d902SRodney W. Grimes }
3149ce73e90SMike Heffner return (*cpp);
3159b50d902SRodney W. Grimes }
3169b50d902SRodney W. Grimes
3179b50d902SRodney W. Grimes static void
delchild(struct child * cp)3186d8484b0SPhilippe Charnier delchild(struct child *cp)
3199b50d902SRodney W. Grimes {
3209ce73e90SMike Heffner struct child **cpp;
3219b50d902SRodney W. Grimes
3229b50d902SRodney W. Grimes for (cpp = &child; *cpp != cp; cpp = &(*cpp)->link)
3239b50d902SRodney W. Grimes ;
3249b50d902SRodney W. Grimes *cpp = cp->link;
325b22a8699SPedro F. Giffuni cp->link = child_freelist;
326b22a8699SPedro F. Giffuni child_freelist = cp;
3279b50d902SRodney W. Grimes }
3289b50d902SRodney W. Grimes
3299ce73e90SMike Heffner /*ARGSUSED*/
3309b50d902SRodney W. Grimes void
sigchild(int signo __unused)3316d8484b0SPhilippe Charnier sigchild(int signo __unused)
3329b50d902SRodney W. Grimes {
333b22a8699SPedro F. Giffuni pid_t pid;
3340c3a8314SMike Heffner int status;
3359ce73e90SMike Heffner struct child *cp;
336b22a8699SPedro F. Giffuni int save_errno;
3379b50d902SRodney W. Grimes
338b22a8699SPedro F. Giffuni save_errno = errno;
339ed74b69cSKevin Lo while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
340b22a8699SPedro F. Giffuni cp = findchild(pid, 1);
3411d1e1f63SXin LI if (cp == NULL)
3421d1e1f63SXin LI continue;
3439b50d902SRodney W. Grimes if (cp->free)
3449b50d902SRodney W. Grimes delchild(cp);
3459b50d902SRodney W. Grimes else {
3469b50d902SRodney W. Grimes cp->done = 1;
3479b50d902SRodney W. Grimes cp->status = status;
3489b50d902SRodney W. Grimes }
3499b50d902SRodney W. Grimes }
350b22a8699SPedro F. Giffuni errno = save_errno;
3519b50d902SRodney W. Grimes }
3529b50d902SRodney W. Grimes
3530c3a8314SMike Heffner int wait_status;
3549b50d902SRodney W. Grimes
3559b50d902SRodney W. Grimes /*
3569b50d902SRodney W. Grimes * Wait for a specific child to die.
3579b50d902SRodney W. Grimes */
3589b50d902SRodney W. Grimes int
wait_child(pid_t pid)359b22a8699SPedro F. Giffuni wait_child(pid_t pid)
3609b50d902SRodney W. Grimes {
36135f8ab70SEitan Adler struct child *cp;
36292fa728bSPedro F. Giffuni sigset_t nset, oset;
36392fa728bSPedro F. Giffuni pid_t rv = 0;
3649b50d902SRodney W. Grimes
365856f23edSMike Heffner (void)sigemptyset(&nset);
366856f23edSMike Heffner (void)sigaddset(&nset, SIGCHLD);
367856f23edSMike Heffner (void)sigprocmask(SIG_BLOCK, &nset, &oset);
36892fa728bSPedro F. Giffuni /*
36992fa728bSPedro F. Giffuni * If we have not already waited on the pid (via sigchild)
37092fa728bSPedro F. Giffuni * wait on it now. Otherwise, use the wait status stashed
37192fa728bSPedro F. Giffuni * by sigchild.
37292fa728bSPedro F. Giffuni */
373b22a8699SPedro F. Giffuni cp = findchild(pid, 1);
37492fa728bSPedro F. Giffuni if (cp == NULL || !cp->done)
37592fa728bSPedro F. Giffuni rv = waitpid(pid, &wait_status, 0);
37692fa728bSPedro F. Giffuni else
3779b50d902SRodney W. Grimes wait_status = cp->status;
37892fa728bSPedro F. Giffuni if (cp != NULL)
3799b50d902SRodney W. Grimes delchild(cp);
380856f23edSMike Heffner (void)sigprocmask(SIG_SETMASK, &oset, NULL);
38192fa728bSPedro F. Giffuni if (rv == -1 || (WIFEXITED(wait_status) && WEXITSTATUS(wait_status)))
38292fa728bSPedro F. Giffuni return -1;
38392fa728bSPedro F. Giffuni else
38492fa728bSPedro F. Giffuni return 0;
3859b50d902SRodney W. Grimes }
3869b50d902SRodney W. Grimes
3879b50d902SRodney W. Grimes /*
3889b50d902SRodney W. Grimes * Mark a child as don't care.
3899b50d902SRodney W. Grimes */
3909b50d902SRodney W. Grimes void
free_child(pid_t pid)391b22a8699SPedro F. Giffuni free_child(pid_t pid)
3929b50d902SRodney W. Grimes {
393b22a8699SPedro F. Giffuni struct child *cp;
394856f23edSMike Heffner sigset_t nset, oset;
3959b50d902SRodney W. Grimes
396856f23edSMike Heffner (void)sigemptyset(&nset);
397856f23edSMike Heffner (void)sigaddset(&nset, SIGCHLD);
398856f23edSMike Heffner (void)sigprocmask(SIG_BLOCK, &nset, &oset);
399b22a8699SPedro F. Giffuni if ((cp = findchild(pid, 0)) != NULL) {
4009b50d902SRodney W. Grimes if (cp->done)
4019b50d902SRodney W. Grimes delchild(cp);
4029b50d902SRodney W. Grimes else
4039b50d902SRodney W. Grimes cp->free = 1;
404b22a8699SPedro F. Giffuni }
405856f23edSMike Heffner (void)sigprocmask(SIG_SETMASK, &oset, NULL);
4069b50d902SRodney W. Grimes }
407