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