wait.c (1990B)
1 #include "rc.h" 2 3 #include <errno.h> 4 5 #include "wait.h" 6 7 bool forked = FALSE; 8 9 typedef struct Pid Pid; 10 11 static struct Pid { 12 pid_t pid; 13 int stat; 14 bool alive; 15 Pid *n; 16 } *plist = NULL; 17 18 extern pid_t rc_fork() { 19 Pid *new; 20 struct Pid *p, *q; 21 pid_t pid = fork(); 22 23 switch (pid) { 24 case -1: 25 uerror("fork"); 26 rc_error(NULL); 27 /* NOTREACHED */ 28 case 0: 29 forked = TRUE; 30 sigchk(); 31 p = plist; q = 0; 32 while (p) { 33 if (q) efree(q); 34 q = p; 35 p = p->n; 36 } 37 if (q) efree(q); 38 plist = 0; 39 return 0; 40 default: 41 new = enew(Pid); 42 new->pid = pid; 43 new->alive = TRUE; 44 new->n = plist; 45 plist = new; 46 return pid; 47 } 48 } 49 50 extern pid_t rc_wait4(pid_t pid, int *stat, bool nointr) { 51 Pid **p, *r; 52 53 /* Find the child on the list. */ 54 for (p = &plist; *p; p = &(*p)->n) 55 if ((*p)->pid == pid || (pid == -1 && !(*p)->alive)) 56 break; 57 58 /* Uh-oh, not there. */ 59 if (pid != -1 && *p == NULL) { 60 errno = ECHILD; /* no children */ 61 uerror("wait"); 62 *stat = 0x100; /* exit(1) */ 63 return -1; 64 } 65 66 /* If it's still alive, wait() for it. */ 67 while (*p == NULL || (*p)->alive) { 68 int ret; 69 Pid **q; 70 71 ret = rc_wait(stat); 72 73 if (ret < 0) { 74 if (errno == ECHILD) 75 panic("lost child"); 76 if (nointr) 77 continue; 78 else 79 return ret; 80 } 81 82 for (q = &plist; *q; q = &(*q)->n) 83 if ((*q)->pid == ret) { 84 if (pid == -1) 85 p = q; 86 (*q)->alive = FALSE; 87 (*q)->stat = *stat; 88 break; 89 } 90 } 91 r = *p; 92 pid = r->pid; 93 *stat = r->stat; 94 *p = r->n; /* remove element from list */ 95 efree(r); 96 return pid; 97 } 98 99 extern List *sgetapids() { 100 List *r; 101 Pid *p; 102 for (r = NULL, p = plist; p != NULL; p = p->n) { 103 List *q; 104 if (!p->alive) 105 continue; 106 q = nnew(List); 107 q->w = nprint("%d", p->pid); 108 q->m = NULL; 109 q->n = r; 110 r = q; 111 } 112 return r; 113 } 114 115 extern void waitforall() { 116 int stat; 117 118 while (plist != NULL) { 119 pid_t pid = rc_wait4(-1, &stat, FALSE); 120 if (pid > 0) 121 setstatus(pid, stat); 122 else { 123 set(FALSE); 124 if (errno == EINTR) 125 return; 126 } 127 sigchk(); 128 } 129 }