1 #include "lib.h" 2 #include <stdlib.h> 3 #include <sys/wait.h> 4 #include <sys/stat.h> 5 #include <unistd.h> 6 #include <errno.h> 7 #include <stdio.h> 8 #include "sys9.h" 9 10 /* 11 ** PID cache 12 */ 13 typedef struct wdesc wdesc; 14 struct wdesc { 15 pid_t w_pid; 16 Waitmsg *w_msg; 17 wdesc *w_next; 18 }; 19 static wdesc *wd = 0; 20 21 static Waitmsg * 22 lookpid (pid_t pid) { 23 wdesc **wp0 = &wd, *wp; 24 Waitmsg *msg; 25 26 if (pid == -1) { 27 if (wd == 0) 28 return 0; 29 pid = wd->w_pid; 30 } 31 for (wp = wd; wp; wp = wp->w_next) { 32 if (wp->w_pid == pid) { 33 msg = wp->w_msg; 34 *wp0 = wp->w_next; 35 free (wp); 36 return msg; 37 } 38 wp0 = &(wp->w_next); 39 } 40 return 0; 41 } 42 43 static void 44 addpid (Waitmsg *msg) { 45 wdesc *wp = malloc (sizeof (wdesc)); 46 47 wp->w_msg = msg; 48 wp->w_pid = msg->pid; 49 wp->w_next = wd; 50 wd = wp; 51 } 52 53 pid_t 54 wait (int *status) { 55 return wait4(-1, status, 0, 0); 56 } 57 58 pid_t 59 waitpid (pid_t wpid, int *status, int options) { 60 return wait4(wpid, status, options, 0); 61 } 62 63 pid_t 64 wait3 (int *status, int options, Waitmsg *waitmsg) { 65 return wait4(-1, status, options, waitmsg); 66 } 67 68 pid_t 69 wait4 (pid_t wpid, int *status, int options, Waitmsg *waitmsg) { 70 Waitmsg *w; 71 72 if (options & WNOHANG) { 73 char pname[128]; 74 int i; 75 struct stat buf; 76 77 snprintf (pname, sizeof (pname), "/proc/%d/wait", getpid()); 78 i = stat (pname, &buf); 79 if (i >= 0 && buf.st_size == 0) 80 return 0; 81 } 82 if (w = lookpid (wpid)) { 83 waitmsg = w; 84 wpid = w->pid; 85 return wpid; 86 } 87 w = _WAIT(); 88 while (w) { 89 if (wpid <= 0) { 90 waitmsg = w; 91 wpid = w->pid; 92 return wpid; 93 } 94 if (w->pid == wpid) { 95 if (status) { 96 int r = 0; 97 int t = 0; 98 char *bp, *ep; 99 100 if (w->msg[0]) { 101 /* message is 'prog pid:string' */ 102 bp = w->msg; 103 while (*bp) { 104 if (*bp++ == ':') 105 break; 106 } 107 if (*bp == 0) 108 bp = w->msg; 109 r = strtol (bp, &ep, 10); 110 if (*ep == 0) { 111 if (r < 0 || r >= 256) 112 r = 1; 113 } else { 114 t = _stringsig (bp); 115 if (t == 0) 116 r = 1; 117 } 118 } 119 *status = (r << 8) | t; 120 } 121 waitmsg = w; 122 wpid = w->pid; 123 return wpid; 124 } else { 125 addpid (w); 126 } 127 w = _WAIT(); 128 } 129 if (w == 0) { 130 _syserrno (); 131 } 132 } 133