rc

[fork] interactive rc shell
git clone https://hhvn.uk/rc
git clone git://hhvn.uk/rc
Log | Files | Refs | README | LICENSE

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 }