xref: /onnv-gate/usr/src/lib/libast/common/comp/waitpid.c (revision 12068:08a39a083754)
14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*12068SRoger.Faulkner@Oracle.COM *          Copyright (c) 1985-2010 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
78462SApril.Chin@Sun.COM *                    by AT&T Intellectual Property                     *
84887Schin *                                                                      *
94887Schin *                A copy of the License is available at                 *
104887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
114887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
124887Schin *                                                                      *
134887Schin *              Information and Software Systems Research               *
144887Schin *                            AT&T Research                             *
154887Schin *                           Florham Park NJ                            *
164887Schin *                                                                      *
174887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
184887Schin *                  David Korn <dgk@research.att.com>                   *
194887Schin *                   Phong Vo <kpv@research.att.com>                    *
204887Schin *                                                                      *
214887Schin ***********************************************************************/
224887Schin #pragma prototyped
234887Schin /*
244887Schin  * POSIX waitpid()
254887Schin  *
264887Schin  * pid < -1 WUNTRACED may not be fully supported
274887Schin  * process group specifics ignored by non-{waitpid,wait4}
284887Schin  */
294887Schin 
304887Schin #include <ast.h>
314887Schin #include <wait.h>
324887Schin 
334887Schin #if _lib_waitpid
344887Schin 
354887Schin NoN(waitpid)
364887Schin 
374887Schin #else
384887Schin 
394887Schin #if _lib_wait4
404887Schin 
414887Schin struct rusage;
424887Schin 
434887Schin extern int	wait4(int, int*, int, struct rusage*);
444887Schin 
454887Schin pid_t
464887Schin waitpid(pid_t pid, int* status, int flags)
474887Schin {
484887Schin 	return(wait4(pid, status, flags, NiL));
494887Schin }
504887Schin 
514887Schin #else
524887Schin 
534887Schin #undef	SIGCLD
544887Schin 
554887Schin #if _lib_wait3
564887Schin 
574887Schin extern int		wait3(int*, int, struct rusage*);
584887Schin 
594887Schin #else
604887Schin 
614887Schin #if _lib_wait2
624887Schin 
634887Schin #define wait3(s,f,u)	wait2(s,f)
644887Schin 
654887Schin extern int		wait2(int*, int);
664887Schin 
674887Schin #else
684887Schin 
694887Schin #include <sig.h>
704887Schin 
714887Schin #define wait3(s,f,u)	wait(s)
724887Schin 
734887Schin static int	caught;
744887Schin 
754887Schin static void
764887Schin catch(sig)
774887Schin int	sig;
784887Schin {
794887Schin 	NoP(sig);
804887Schin 	caught = 1;
814887Schin }
824887Schin 
834887Schin #endif
844887Schin 
854887Schin #endif
864887Schin 
874887Schin #include <error.h>
884887Schin 
894887Schin struct zombie
904887Schin {
914887Schin 	struct zombie*	next;
924887Schin 	int		status;
934887Schin 	pid_t		pid;
944887Schin };
954887Schin 
964887Schin pid_t
974887Schin waitpid(pid_t pid, int* status, int flags)
984887Schin {
994887Schin 	register struct zombie*	zp;
1004887Schin 	register struct zombie*	pp;
1014887Schin 	register int		p;
1024887Schin 	int			s;
1034887Schin #if !_lib_wait2 && !_lib_wait3
1044887Schin #if !defined(SIGCLD)
1054887Schin 	int			n;
1064887Schin 	int			oerrno;
1074887Schin #endif
1084887Schin 	Sig_handler_t		handler;
1094887Schin #endif
1104887Schin 
1114887Schin 	static struct zombie*	zombies;
1124887Schin 
1134887Schin 	pp = 0;
1144887Schin 	zp = zombies;
1154887Schin 	while (zp)
1164887Schin 	{
1174887Schin 		if (zp->pid >= 0 && (zp->pid == pid || pid <= 0))
1184887Schin 		{
1194887Schin 			if (pp) pp->next = zp->next;
1204887Schin 			else zombies = zp->next;
1214887Schin 			if (status) *status = zp->status;
1224887Schin 			pid = zp->pid;
1234887Schin 			free(zp);
1244887Schin 			return(pid);
1254887Schin 		}
1264887Schin 	}
1274887Schin 	if (pid > 0 && kill(pid, 0) < 0) return(-1);
1284887Schin 	for (;;)
1294887Schin 	{
1304887Schin #if !_lib_wait2 && !_lib_wait3
1314887Schin #if !defined(SIGCLD)
1324887Schin 		oerrno = errno;
1334887Schin #endif
1344887Schin 		if (flags & WNOHANG)
1354887Schin 		{
1364887Schin 			caught = 0;
1374887Schin #if defined(SIGCLD)
1384887Schin 			handler = signal(SIGCLD, catch);
1394887Schin 			if (!caught)
1404887Schin 			{
1414887Schin 				signal(SIGCLD, handler);
1424887Schin 				return(0);
1434887Schin 			}
1444887Schin #else
1454887Schin #if defined(SIGALRM)
1464887Schin 			handler = signal(SIGALRM, catch);
1474887Schin 			n = alarm(1);
1484887Schin #endif
1494887Schin #endif
1504887Schin 		}
1514887Schin #endif
1524887Schin 		p = wait3(&s, flags, NiL);
1534887Schin #if !_lib_wait3
1544887Schin #if !_lib_wait2
1554887Schin #if defined(SIGCLD)
1564887Schin 		if (flags & WNOHANG) signal(SIGCLD, handler);
1574887Schin #else
1584887Schin #if defined(SIGALRM)
1594887Schin 		if (flags & WNOHANG)
1604887Schin 		{
1614887Schin 			if (n == 0 && !caught || n == 1) alarm(n);
1624887Schin 			else if (n > 1) alarm(n - caught);
1634887Schin 			signal(SIGALRM, handler);
1644887Schin 		}
1654887Schin 		if (p == -1 && errno == EINTR)
1664887Schin 		{
1674887Schin 			errno = oerrno;
1684887Schin 			p = 0;
1694887Schin 			s = 0;
1704887Schin 		}
1714887Schin #endif
1724887Schin #endif
1734887Schin #else
1744887Schin 		if (p == -1 && errno == EINVAL && (flags & ~WNOHANG))
1754887Schin 			p = wait3(&s, flags & WNOHANG, NiL);
1764887Schin #endif
1774887Schin #endif
1784887Schin 		if (p <= 0)
1794887Schin 		{
1804887Schin 			if (p == 0 && status) *status = s;
1814887Schin 			return(p);
1824887Schin 		}
1834887Schin 		if (pid <= 0 || p == pid)
1844887Schin 		{
1854887Schin 			if (status) *status = s;
1864887Schin 			return(p);
1874887Schin 		}
1884887Schin 		if (!(zp = newof(0, struct zombie, 1, 0))) return(-1);
1894887Schin 		zp->pid = p;
1904887Schin 		zp->status = s;
1914887Schin 		zp->next = zombies;
1924887Schin 		zombies = zp;
1934887Schin 	}
1944887Schin 	/*NOTREACHED*/
1954887Schin }
1964887Schin 
1974887Schin #endif
1984887Schin 
1994887Schin #endif
200