1/***********************************************************************
2*                                                                      *
3*               This software is part of the ast package               *
4*          Copyright (c) 1985-2010 AT&T Intellectual Property          *
5*                      and is licensed under the                       *
6*                  Common Public License, Version 1.0                  *
7*                    by AT&T Intellectual Property                     *
8*                                                                      *
9*                A copy of the License is available at                 *
10*            http://www.opensource.org/licenses/cpl1.0.txt             *
11*         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12*                                                                      *
13*              Information and Software Systems Research               *
14*                            AT&T Research                             *
15*                           Florham Park NJ                            *
16*                                                                      *
17*                 Glenn Fowler <gsf@research.att.com>                  *
18*                  David Korn <dgk@research.att.com>                   *
19*                   Phong Vo <kpv@research.att.com>                    *
20*                                                                      *
21***********************************************************************/
22#pragma prototyped
23/*
24 * POSIX waitpid()
25 *
26 * pid < -1 WUNTRACED may not be fully supported
27 * process group specifics ignored by non-{waitpid,wait4}
28 */
29
30#include <ast.h>
31#include <wait.h>
32
33#if _lib_waitpid
34
35NoN(waitpid)
36
37#else
38
39#if _lib_wait4
40
41struct rusage;
42
43extern int	wait4(int, int*, int, struct rusage*);
44
45pid_t
46waitpid(pid_t pid, int* status, int flags)
47{
48	return(wait4(pid, status, flags, NiL));
49}
50
51#else
52
53#undef	SIGCLD
54
55#if _lib_wait3
56
57extern int		wait3(int*, int, struct rusage*);
58
59#else
60
61#if _lib_wait2
62
63#define wait3(s,f,u)	wait2(s,f)
64
65extern int		wait2(int*, int);
66
67#else
68
69#include <sig.h>
70
71#define wait3(s,f,u)	wait(s)
72
73static int	caught;
74
75static void
76catch(sig)
77int	sig;
78{
79	NoP(sig);
80	caught = 1;
81}
82
83#endif
84
85#endif
86
87#include <error.h>
88
89struct zombie
90{
91	struct zombie*	next;
92	int		status;
93	pid_t		pid;
94};
95
96pid_t
97waitpid(pid_t pid, int* status, int flags)
98{
99	register struct zombie*	zp;
100	register struct zombie*	pp;
101	register int		p;
102	int			s;
103#if !_lib_wait2 && !_lib_wait3
104#if !defined(SIGCLD)
105	int			n;
106	int			oerrno;
107#endif
108	Sig_handler_t		handler;
109#endif
110
111	static struct zombie*	zombies;
112
113	pp = 0;
114	zp = zombies;
115	while (zp)
116	{
117		if (zp->pid >= 0 && (zp->pid == pid || pid <= 0))
118		{
119			if (pp) pp->next = zp->next;
120			else zombies = zp->next;
121			if (status) *status = zp->status;
122			pid = zp->pid;
123			free(zp);
124			return(pid);
125		}
126	}
127	if (pid > 0 && kill(pid, 0) < 0) return(-1);
128	for (;;)
129	{
130#if !_lib_wait2 && !_lib_wait3
131#if !defined(SIGCLD)
132		oerrno = errno;
133#endif
134		if (flags & WNOHANG)
135		{
136			caught = 0;
137#if defined(SIGCLD)
138			handler = signal(SIGCLD, catch);
139			if (!caught)
140			{
141				signal(SIGCLD, handler);
142				return(0);
143			}
144#else
145#if defined(SIGALRM)
146			handler = signal(SIGALRM, catch);
147			n = alarm(1);
148#endif
149#endif
150		}
151#endif
152		p = wait3(&s, flags, NiL);
153#if !_lib_wait3
154#if !_lib_wait2
155#if defined(SIGCLD)
156		if (flags & WNOHANG) signal(SIGCLD, handler);
157#else
158#if defined(SIGALRM)
159		if (flags & WNOHANG)
160		{
161			if (n == 0 && !caught || n == 1) alarm(n);
162			else if (n > 1) alarm(n - caught);
163			signal(SIGALRM, handler);
164		}
165		if (p == -1 && errno == EINTR)
166		{
167			errno = oerrno;
168			p = 0;
169			s = 0;
170		}
171#endif
172#endif
173#else
174		if (p == -1 && errno == EINVAL && (flags & ~WNOHANG))
175			p = wait3(&s, flags & WNOHANG, NiL);
176#endif
177#endif
178		if (p <= 0)
179		{
180			if (p == 0 && status) *status = s;
181			return(p);
182		}
183		if (pid <= 0 || p == pid)
184		{
185			if (status) *status = s;
186			return(p);
187		}
188		if (!(zp = newof(0, struct zombie, 1, 0))) return(-1);
189		zp->pid = p;
190		zp->status = s;
191		zp->next = zombies;
192		zombies = zp;
193	}
194	/*NOTREACHED*/
195}
196
197#endif
198
199#endif
200