1 #include "lib.h" 2 #include <stdlib.h> 3 #include <sys/wait.h> 4 #include <sys/time.h> 5 #include <sys/resource.h> 6 #include <sys/stat.h> 7 #include <unistd.h> 8 #include <string.h> 9 #include <errno.h> 10 #include <stdio.h> 11 #include "sys9.h" 12 #include "dir.h" 13 14 /* 15 * status not yet collected for processes that have exited 16 */ 17 typedef struct Waited Waited; 18 struct Waited { 19 Waitmsg* msg; 20 Waited* next; 21 }; 22 static Waited *wd; 23 24 static Waitmsg * 25 lookpid(int pid) 26 { 27 Waited **wl, *w; 28 Waitmsg *msg; 29 30 for(wl = &wd; (w = *wl) != nil; wl = &w->next) 31 if(pid <= 0 || w->msg->pid == pid){ 32 msg = w->msg; 33 *wl = w->next; 34 free(w); 35 return msg; 36 } 37 return 0; 38 } 39 40 static void 41 addpid(Waitmsg *msg) 42 { 43 Waited *w; 44 45 w = malloc(sizeof(*w)); 46 if(w == nil){ 47 /* lost it; what can we do? */ 48 free(msg); 49 return; 50 } 51 w->msg = msg; 52 w->next = wd; 53 wd = w; 54 } 55 56 static int 57 waitstatus(Waitmsg *w) 58 { 59 int r, t; 60 char *bp, *ep; 61 62 r = 0; 63 t = 0; 64 if(w->msg[0]){ 65 /* message is 'prog pid:string' */ 66 bp = w->msg; 67 while(*bp){ 68 if(*bp++ == ':') 69 break; 70 } 71 if(*bp == 0) 72 bp = w->msg; 73 r = strtol(bp, &ep, 10); 74 if(*ep == 0){ 75 if(r < 0 || r >= 256) 76 r = 1; 77 }else{ 78 t = _stringsig(bp); 79 if(t == 0) 80 r = 1; 81 } 82 } 83 return (r<<8) | t; 84 } 85 86 static void 87 waitresource(struct rusage *ru, Waitmsg *w) 88 { 89 memset(ru, 0, sizeof(*ru)); 90 ru->ru_utime.tv_sec = w->time[0]/1000; 91 ru->ru_utime.tv_usec = (w->time[0]%1000)*1000; 92 ru->ru_stime.tv_sec = w->time[1]/1000; 93 ru->ru_stime.tv_usec = (w->time[1]%1000)*1000; 94 } 95 96 pid_t 97 wait(int *status) 98 { 99 return wait4(-1, status, 0, nil); 100 } 101 102 pid_t 103 waitpid(pid_t wpid, int *status, int options) 104 { 105 return wait4(wpid, status, options, nil); 106 } 107 108 pid_t 109 wait3(int *status, int options, struct rusage *res) 110 { 111 return wait4(-1, status, options, res); 112 } 113 114 pid_t 115 wait4(pid_t wpid, int *status, int options, struct rusage *res) 116 { 117 char pname[50]; 118 Dir *d; 119 Waitmsg *w; 120 121 w = lookpid(wpid); 122 if(w == nil){ 123 if(options & WNOHANG){ 124 snprintf(pname, sizeof(pname), "/proc/%d/wait", getpid()); 125 d = _dirstat(pname); 126 if(d != nil && d->length == 0){ 127 free(d); 128 return 0; 129 } 130 free(d); 131 } 132 for(;;){ 133 w = _WAIT(); 134 if(w == nil){ 135 _syserrno(); 136 return -1; 137 } 138 if(wpid <= 0 || w->pid == wpid) 139 break; 140 addpid(w); 141 } 142 } 143 if(res != nil) 144 waitresource(res, w); 145 if(status != nil) 146 *status = waitstatus(w); 147 wpid = w->pid; 148 free(w); 149 return wpid; 150 } 151