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