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* 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