1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *          Copyright (c) 1985-2011 AT&T Intellectual Property          *
5 *                      and is licensed under the                       *
6 *                 Eclipse Public License, Version 1.0                  *
7 *                    by AT&T Intellectual Property                     *
8 *                                                                      *
9 *                A copy of the License is available at                 *
10 *          http://www.eclipse.org/org/documents/epl-v10.html           *
11 *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
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 
35 NoN(waitpid)
36 
37 #else
38 
39 #if _lib_wait4
40 
41 struct rusage;
42 
43 extern int	wait4(int, int*, int, struct rusage*);
44 
45 pid_t
46 waitpid(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 
57 extern 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 
65 extern int		wait2(int*, int);
66 
67 #else
68 
69 #include <sig.h>
70 
71 #define wait3(s,f,u)	wait(s)
72 
73 static int	caught;
74 
75 static void
76 catch(sig)
77 int	sig;
78 {
79 	NoP(sig);
80 	caught = 1;
81 }
82 
83 #endif
84 
85 #endif
86 
87 #include <error.h>
88 
89 struct zombie
90 {
91 	struct zombie*	next;
92 	int		status;
93 	pid_t		pid;
94 };
95 
96 pid_t
97 waitpid(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