+
+struct child {
+ int pid;
+ char done;
+ char free;
+ union wait status;
+ struct child *link;
+};
+static struct child *child;
+
+struct child *
+findchild(pid)
+ int pid;
+{
+ register struct child **cpp;
+
+ for (cpp = &child; *cpp != NULL && (*cpp)->pid != pid;
+ cpp = &(*cpp)->link)
+ ;
+ if (*cpp == NULL) {
+ *cpp = (struct child *) malloc(sizeof (struct child));
+ (*cpp)->pid = pid;
+ (*cpp)->done = (*cpp)->free = 0;
+ (*cpp)->link = NULL;
+ }
+ return *cpp;
+}
+
+delchild(cp)
+ register struct child *cp;
+{
+ register struct child **cpp;
+
+ for (cpp = &child; *cpp != cp; cpp = &(*cpp)->link)
+ ;
+ *cpp = cp->link;
+ free((char *) cp);
+}
+
+sigchild()
+{
+ int pid;
+ union wait status;
+ register struct child *cp;
+
+ while ((pid = wait3(&status, WNOHANG, (struct timeval *)0)) > 0) {
+ cp = findchild(pid);
+ if (cp->free)
+ delchild(cp);
+ else {
+ cp->done = 1;
+ cp->status = status;
+ }
+ }
+}
+
+union wait wait_status;
+
+/*
+ * Wait for a specific child to die.
+ */
+wait_child(pid)
+ int pid;
+{
+ int mask = sigblock(sigmask(SIGCHLD));
+ register struct child *cp = findchild(pid);
+
+ while (!cp->done)
+ sigpause(mask);
+ wait_status = cp->status;
+ delchild(cp);
+ sigsetmask(mask);
+ return wait_status.w_status ? -1 : 0;
+}
+
+/*
+ * Mark a child as don't care.
+ */
+free_child(pid)
+ int pid;
+{
+ int mask = sigblock(sigmask(SIGCHLD));
+ register struct child *cp = findchild(pid);
+
+ if (cp->done)
+ delchild(cp);
+ else
+ cp->free = 1;
+ sigsetmask(mask);
+}