16b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes/*	$NetBSD: popen.c,v 1.32 2012/06/25 22:32:43 abs Exp $	*/
26b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes
31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (c) 1988, 1993
51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	The Regents of the University of California.  All rights reserved.
61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * This code is derived from software written by Ken Arnold and
81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * published in UNIX Review, Vol. 6, No. 8.
91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Redistribution and use in source and binary forms, with or without
111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * modification, are permitted provided that the following conditions
121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * are met:
131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    documentation and/or other materials provided with the distribution.
181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 3. Neither the name of the University nor the names of its contributors
191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    may be used to endorse or promote products derived from this software
201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    without specific prior written permission.
211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * SUCH DAMAGE.
331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
356b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes#include <sys/cdefs.h>
366b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes#if defined(LIBC_SCCS) && !defined(lint)
376b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes#if 0
386b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughesstatic char sccsid[] = "@(#)popen.c	8.3 (Berkeley) 5/3/95";
396b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes#else
406b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes__RCSID("$NetBSD: popen.c,v 1.32 2012/06/25 22:32:43 abs Exp $");
416b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes#endif
426b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes#endif /* LIBC_SCCS and not lint */
436b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes
446b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes#include "namespace.h"
451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/param.h>
461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/wait.h>
476b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes#include <sys/socket.h>
481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
496b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes#include <assert.h>
501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <errno.h>
516b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes#include <paths.h>
526b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes#include <signal.h>
531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdio.h>
541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdlib.h>
551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <string.h>
566b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes#include <unistd.h>
576b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes#include <fcntl.h>
586b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes
596b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes#include "env.h"
606b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes#include "reentrant.h"
616b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes
626b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes#ifdef __weak_alias
636b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes__weak_alias(popen,_popen)
646b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes__weak_alias(pclose,_pclose)
656b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes#endif
661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic struct pid {
681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	struct pid *next;
691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	FILE *fp;
706b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes#ifdef _REENTRANT
716b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes	int fd;
726b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes#endif
731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	pid_t pid;
746b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes} *pidlist;
756b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes
766b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes#ifdef _REENTRANT
776b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughesstatic rwlock_t pidlist_lock = RWLOCK_INITIALIZER;
786b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes#endif
793884bfe9661955543ce203c60f9225bbdf33f6bbJP Abgrall
801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectFILE *
816b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughespopen(const char *command, const char *type)
821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
836b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes	struct pid *cur, *old;
841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	FILE *iop;
856b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes	const char * volatile xtype = type;
866b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes	int pdes[2], pid, serrno;
876b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes	volatile int twoway;
886b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes	int flags;
896b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes
906b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes	_DIAGASSERT(command != NULL);
916b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes	_DIAGASSERT(xtype != NULL);
926b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes
936b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes	flags = strchr(xtype, 'e') ? O_CLOEXEC : 0;
946b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes	if (strchr(xtype, '+')) {
956b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes		int stype = flags ? (SOCK_STREAM | SOCK_CLOEXEC) : SOCK_STREAM;
966b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes		twoway = 1;
976b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes		xtype = "r+";
986b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes		if (socketpair(AF_LOCAL, stype, 0, pdes) < 0)
996b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes			return NULL;
1006b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes	} else  {
1016b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes		twoway = 0;
1026b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes		xtype = strrchr(xtype, 'r') ? "r" : "w";
1036b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes		if (pipe2(pdes, flags) == -1)
1046b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes			return NULL;
1051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
1061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1076b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes	if ((cur = malloc(sizeof(struct pid))) == NULL) {
1086b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes		(void)close(pdes[0]);
1096b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes		(void)close(pdes[1]);
1106b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes		errno = ENOMEM;
1111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (NULL);
1121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
1131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1146b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes	(void)rwlock_rdlock(&pidlist_lock);
1156b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes	(void)__readlockenv();
1166b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes	switch (pid = vfork()) {
1171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case -1:			/* Error. */
1186b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes		serrno = errno;
1196b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes		(void)__unlockenv();
1206b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes		(void)rwlock_unlock(&pidlist_lock);
1216b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes		free(cur);
1221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		(void)close(pdes[0]);
1231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		(void)close(pdes[1]);
1246b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes		errno = serrno;
1251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (NULL);
1261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/* NOTREACHED */
1271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case 0:				/* Child. */
1286b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes		/* POSIX.2 B.3.2.2 "popen() shall ensure that any streams
1296b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes		   from previous popen() calls that remain open in the
1306b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes		   parent process are closed in the new child process. */
1316b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes		for (old = pidlist; old; old = old->next)
1326b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes#ifdef _REENTRANT
1336b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes			close(old->fd); /* don't allow a flush */
1346b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes#else
1356b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes			close(fileno(old->fp)); /* don't allow a flush */
1366b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes#endif
1376b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes
1386b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes		if (*xtype == 'r') {
1396b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes			(void)close(pdes[0]);
1403884bfe9661955543ce203c60f9225bbdf33f6bbJP Abgrall			if (pdes[1] != STDOUT_FILENO) {
1413884bfe9661955543ce203c60f9225bbdf33f6bbJP Abgrall				(void)dup2(pdes[1], STDOUT_FILENO);
1423884bfe9661955543ce203c60f9225bbdf33f6bbJP Abgrall				(void)close(pdes[1]);
1431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
1446b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes			if (twoway)
1456b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes				(void)dup2(STDOUT_FILENO, STDIN_FILENO);
1461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		} else {
1471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			(void)close(pdes[1]);
1481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (pdes[0] != STDIN_FILENO) {
1491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				(void)dup2(pdes[0], STDIN_FILENO);
1501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				(void)close(pdes[0]);
1511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
1521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
1536b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes
1546b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes		execl(_PATH_BSHELL, "sh", "-c", command, NULL);
1551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		_exit(127);
1561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/* NOTREACHED */
1571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
1586b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes	(void)__unlockenv();
1591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* Parent; assume fdopen can't fail. */
1616b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes	if (*xtype == 'r') {
1626b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes		iop = fdopen(pdes[0], xtype);
1636b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes#ifdef _REENTRANT
1646b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes		cur->fd = pdes[0];
1656b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes#endif
1661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		(void)close(pdes[1]);
1671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	} else {
1686b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes		iop = fdopen(pdes[1], xtype);
1696b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes#ifdef _REENTRANT
1706b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes		cur->fd = pdes[1];
1716b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes#endif
1721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		(void)close(pdes[0]);
1731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
1741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* Link into list of file descriptors. */
1761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	cur->fp = iop;
1771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	cur->pid =  pid;
1781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	cur->next = pidlist;
1791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	pidlist = cur;
1806b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes	(void)rwlock_unlock(&pidlist_lock);
1811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (iop);
1831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
1841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
1861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * pclose --
1871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Pclose returns -1 if stream is not associated with a `popened' command,
1881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	if already `pclosed', or waitpid returns an error.
1891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
1901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
1911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectpclose(FILE *iop)
1921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
1931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	struct pid *cur, *last;
1941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int pstat;
1951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	pid_t pid;
1961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1976b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes	_DIAGASSERT(iop != NULL);
1986b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes
1996b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes	rwlock_wrlock(&pidlist_lock);
2006b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes
2011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* Find the appropriate file pointer. */
2021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next)
2031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (cur->fp == iop)
2041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
2056b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes	if (cur == NULL) {
2066b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes		(void)rwlock_unlock(&pidlist_lock);
2071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
2086b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes	}
2091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	(void)fclose(iop);
2111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* Remove the entry from the linked list. */
2131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (last == NULL)
2141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		pidlist = cur->next;
2151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	else
2161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		last->next = cur->next;
2176b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes
2186b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes	(void)rwlock_unlock(&pidlist_lock);
2196b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes
2206b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes	do {
2216b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes		pid = waitpid(cur->pid, &pstat, 0);
2226b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes	} while (pid == -1 && errno == EINTR);
2236b3f49a5374305ce9690c3c5ca2aadc90f54c521Elliott Hughes
2241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	free(cur);
2251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (pid == -1 ? -1 : pstat);
2271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
228