xref: /plan9/sys/src/cmd/mk/run.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
13e12c5d1SDavid du Colombier #include	"mk.h"
23e12c5d1SDavid du Colombier 
33e12c5d1SDavid du Colombier typedef struct Event
43e12c5d1SDavid du Colombier {
53e12c5d1SDavid du Colombier 	int pid;
63e12c5d1SDavid du Colombier 	Job *job;
73e12c5d1SDavid du Colombier } Event;
83e12c5d1SDavid du Colombier static Event *events;
93e12c5d1SDavid du Colombier static int nevents, nrunning;
103e12c5d1SDavid du Colombier typedef struct Process
113e12c5d1SDavid du Colombier {
123e12c5d1SDavid du Colombier 	int pid;
133e12c5d1SDavid du Colombier 	int status;
143e12c5d1SDavid du Colombier 	struct Process *b, *f;
153e12c5d1SDavid du Colombier } Process;
163e12c5d1SDavid du Colombier static Process *phead, *pfree;
173e12c5d1SDavid du Colombier static void sched(void);
183e12c5d1SDavid du Colombier static void pnew(int, int), pdelete(Process *);
193e12c5d1SDavid du Colombier static Envy *envy;
203e12c5d1SDavid du Colombier static int special;
213e12c5d1SDavid du Colombier #define	ENVQUANTA	10
223e12c5d1SDavid du Colombier static int envsize;
233e12c5d1SDavid du Colombier static int nextv;
243e12c5d1SDavid du Colombier 
253e12c5d1SDavid du Colombier static int pidslot(int);
263e12c5d1SDavid du Colombier 
273e12c5d1SDavid du Colombier int
283e12c5d1SDavid du Colombier Execl(char *p, char *a, ...)
293e12c5d1SDavid du Colombier {
303e12c5d1SDavid du Colombier 	if (envy)
31*219b2ee8SDavid du Colombier 		exportenv(envy, nextv);
323e12c5d1SDavid du Colombier 	exec(p, &a);
333e12c5d1SDavid du Colombier 	return -1;
343e12c5d1SDavid du Colombier }
353e12c5d1SDavid du Colombier 
363e12c5d1SDavid du Colombier void
373e12c5d1SDavid du Colombier run(Job *j)
383e12c5d1SDavid du Colombier {
393e12c5d1SDavid du Colombier 	Job *jj;
403e12c5d1SDavid du Colombier 
413e12c5d1SDavid du Colombier 	if(jobs){
423e12c5d1SDavid du Colombier 		for(jj = jobs; jj->next; jj = jj->next)
433e12c5d1SDavid du Colombier 			;
443e12c5d1SDavid du Colombier 		jj->next = j;
453e12c5d1SDavid du Colombier 	} else
463e12c5d1SDavid du Colombier 		jobs = j;
473e12c5d1SDavid du Colombier 	j->next = 0;
483e12c5d1SDavid du Colombier 	/* this code also in waitup after parse redirect */
493e12c5d1SDavid du Colombier 	if(nrunning < nproclimit)
503e12c5d1SDavid du Colombier 		sched();
513e12c5d1SDavid du Colombier }
523e12c5d1SDavid du Colombier 
533e12c5d1SDavid du Colombier static void
543e12c5d1SDavid du Colombier sched(void)
553e12c5d1SDavid du Colombier {
563e12c5d1SDavid du Colombier 	Job *j;
573e12c5d1SDavid du Colombier 	Bufblock *buf;
583e12c5d1SDavid du Colombier 	int slot, pip[2], pid;
593e12c5d1SDavid du Colombier 	Node *n;
603e12c5d1SDavid du Colombier 
613e12c5d1SDavid du Colombier 	if(jobs == 0){
62*219b2ee8SDavid du Colombier 		usage();
633e12c5d1SDavid du Colombier 		return;
643e12c5d1SDavid du Colombier 	}
653e12c5d1SDavid du Colombier 	j = jobs;
663e12c5d1SDavid du Colombier 	jobs = j->next;
673e12c5d1SDavid du Colombier 	if(DEBUG(D_EXEC))
683e12c5d1SDavid du Colombier 		fprint(1, "firing up job for target %s\n", wtos(j->t));
693e12c5d1SDavid du Colombier 	slot = nextslot();
703e12c5d1SDavid du Colombier 	events[slot].job = j;
713e12c5d1SDavid du Colombier 	dovars(j, slot);
723e12c5d1SDavid du Colombier 	buf = newbuf();
733e12c5d1SDavid du Colombier 	shprint(j->r->recipe, envy, buf);
743e12c5d1SDavid du Colombier 	if(!tflag && (nflag || !(j->r->attr&QUIET)))
753e12c5d1SDavid du Colombier 		Bwrite(&stdout, buf->start, (long)strlen(buf->start));
763e12c5d1SDavid du Colombier 	freebuf(buf);
773e12c5d1SDavid du Colombier 	if(nflag||tflag){
783e12c5d1SDavid du Colombier 		for(n = j->n; n; n = n->next){
793e12c5d1SDavid du Colombier 			if(tflag){
803e12c5d1SDavid du Colombier 				if(!(n->flags&VIRTUAL))
813e12c5d1SDavid du Colombier 					touch(n->name);
823e12c5d1SDavid du Colombier 				else if(explain)
833e12c5d1SDavid du Colombier 					Bprint(&stdout, "no touch of virtual '%s'\n", n->name);
843e12c5d1SDavid du Colombier 			}
853e12c5d1SDavid du Colombier 			n->time = time((long *)0);
863e12c5d1SDavid du Colombier 			MADESET(n, MADE);
873e12c5d1SDavid du Colombier 		}
883e12c5d1SDavid du Colombier 	} else {
893e12c5d1SDavid du Colombier /*Bprint(&stdout, "recipe='%s'\n", j->r->recipe);/**/
903e12c5d1SDavid du Colombier 		Bflush(&stdout);
913e12c5d1SDavid du Colombier 		if(j->r->attr&RED){
923e12c5d1SDavid du Colombier 			if(pipe(pip) < 0){
933e12c5d1SDavid du Colombier 				perror("pipe");
943e12c5d1SDavid du Colombier 				Exit();
953e12c5d1SDavid du Colombier 			}
963e12c5d1SDavid du Colombier 		}
973e12c5d1SDavid du Colombier 		if((pid = rfork(RFPROC|RFFDG|RFENVG)) < 0){
983e12c5d1SDavid du Colombier 			perror("mk rfork");
993e12c5d1SDavid du Colombier 			Exit();
1003e12c5d1SDavid du Colombier 		}
1013e12c5d1SDavid du Colombier 		if(pid == 0){
1023e12c5d1SDavid du Colombier 			if(j->r->attr&RED){
1033e12c5d1SDavid du Colombier 				close(pip[0]);
104*219b2ee8SDavid du Colombier 				dup(pip[1], 1);
1053e12c5d1SDavid du Colombier 				close(pip[1]);
1063e12c5d1SDavid du Colombier 			}
1073e12c5d1SDavid du Colombier 			if(pipe(pip) < 0){
1083e12c5d1SDavid du Colombier 				perror("pipe-i");
1093e12c5d1SDavid du Colombier 				Exit();
1103e12c5d1SDavid du Colombier 			}
1113e12c5d1SDavid du Colombier 			if((pid = fork()) < 0){
1123e12c5d1SDavid du Colombier 				perror("mk fork");
1133e12c5d1SDavid du Colombier 				Exit();
1143e12c5d1SDavid du Colombier 			}
1153e12c5d1SDavid du Colombier 			if(pid != 0){
1163e12c5d1SDavid du Colombier 				close(pip[1]);
117*219b2ee8SDavid du Colombier 				dup(pip[0], 0);
1183e12c5d1SDavid du Colombier 				close(pip[0]);
1193e12c5d1SDavid du Colombier 				if(j->r->attr&NOMINUSE)
1203e12c5d1SDavid du Colombier 
1213e12c5d1SDavid du Colombier 					Execl(shell, shellname, "-I", (char *)0);
1223e12c5d1SDavid du Colombier 				else
1233e12c5d1SDavid du Colombier 					Execl(shell, shellname, "-eI", (char *)0);
1243e12c5d1SDavid du Colombier 				perror(shell);
125*219b2ee8SDavid du Colombier 				_exits("exec");
1263e12c5d1SDavid du Colombier 			} else {
1273e12c5d1SDavid du Colombier 				int k;
1283e12c5d1SDavid du Colombier 				char *s, *send;
1293e12c5d1SDavid du Colombier 
1303e12c5d1SDavid du Colombier 				close(pip[0]);
1313e12c5d1SDavid du Colombier 				s = j->r->recipe;
1323e12c5d1SDavid du Colombier 				send = s+strlen(s);
1333e12c5d1SDavid du Colombier 				while(s < send){
1343e12c5d1SDavid du Colombier 					if((k = write(pip[1], s, send-s)) < 0)
1353e12c5d1SDavid du Colombier 						break;
1363e12c5d1SDavid du Colombier 					s += k;
1373e12c5d1SDavid du Colombier 				}
138*219b2ee8SDavid du Colombier 				_exits(0);
1393e12c5d1SDavid du Colombier 			}
1403e12c5d1SDavid du Colombier 		}
141*219b2ee8SDavid du Colombier 		usage();
1423e12c5d1SDavid du Colombier 		nrunning++;
1433e12c5d1SDavid du Colombier 		if(j->r->attr&RED)
1443e12c5d1SDavid du Colombier 			close(pip[1]), j->fd = pip[0];
1453e12c5d1SDavid du Colombier 		else
1463e12c5d1SDavid du Colombier 			j->fd = -1;
1473e12c5d1SDavid du Colombier 		if(DEBUG(D_EXEC))
1483e12c5d1SDavid du Colombier 			fprint(1, "pid for target %s = %d\n", wtos(j->t), pid);
1493e12c5d1SDavid du Colombier 		events[slot].pid = pid;
1503e12c5d1SDavid du Colombier 	}
1513e12c5d1SDavid du Colombier }
1523e12c5d1SDavid du Colombier 
1533e12c5d1SDavid du Colombier int
1543e12c5d1SDavid du Colombier waitup(int echildok, int *retstatus)
1553e12c5d1SDavid du Colombier {
1563e12c5d1SDavid du Colombier 	int pid;
1573e12c5d1SDavid du Colombier 	int slot;
1583e12c5d1SDavid du Colombier 	Symtab *s;
1593e12c5d1SDavid du Colombier 	Word *w;
1603e12c5d1SDavid du Colombier 	Job *j;
161*219b2ee8SDavid du Colombier 	char buf[ERRLEN];
1623e12c5d1SDavid du Colombier 	Bufblock *bp;
1633e12c5d1SDavid du Colombier 	int uarg = 0;
1643e12c5d1SDavid du Colombier 	int done;
1653e12c5d1SDavid du Colombier 	Node *n;
1663e12c5d1SDavid du Colombier 	Process *p;
167*219b2ee8SDavid du Colombier 	extern int runerrs;
1683e12c5d1SDavid du Colombier 
1693e12c5d1SDavid du Colombier 	/* first check against the proces slist */
1703e12c5d1SDavid du Colombier 	if(retstatus)
1713e12c5d1SDavid du Colombier 		for(p = phead; p; p = p->f)
1723e12c5d1SDavid du Colombier 			if(p->pid == *retstatus){
1733e12c5d1SDavid du Colombier 				*retstatus = p->status;
1743e12c5d1SDavid du Colombier 				pdelete(p);
1753e12c5d1SDavid du Colombier 				return(-1);
1763e12c5d1SDavid du Colombier 			}
1773e12c5d1SDavid du Colombier again:		/* rogue processes */
178*219b2ee8SDavid du Colombier 	if((pid = waitfor(buf)) < 0){
1793e12c5d1SDavid du Colombier 		if(echildok > 0)
1803e12c5d1SDavid du Colombier 			return(1);
1813e12c5d1SDavid du Colombier 		else {
1823e12c5d1SDavid du Colombier 			fprint(2, "mk: (waitup %d) ", echildok);
1833e12c5d1SDavid du Colombier 			perror("mk wait");
1843e12c5d1SDavid du Colombier 			Exit();
1853e12c5d1SDavid du Colombier 		}
1863e12c5d1SDavid du Colombier 	}
1873e12c5d1SDavid du Colombier 	if(DEBUG(D_EXEC))
188*219b2ee8SDavid du Colombier 		fprint(1, "waitup got pid=%d, status=%s\n", pid, buf);
1893e12c5d1SDavid du Colombier 	if(retstatus && (pid == *retstatus)){
190*219b2ee8SDavid du Colombier 		*retstatus = buf[0]? 1:0;
1913e12c5d1SDavid du Colombier 		return(-1);
1923e12c5d1SDavid du Colombier 	}
1933e12c5d1SDavid du Colombier 	slot = pidslot(pid);
1943e12c5d1SDavid du Colombier 	if(slot < 0){
1953e12c5d1SDavid du Colombier 		if(DEBUG(D_EXEC))
1963e12c5d1SDavid du Colombier 			fprint(2, "mk: wait returned unexpected process %d\n", pid);
197*219b2ee8SDavid du Colombier 		pnew(pid, buf[0]? 1:0);
1983e12c5d1SDavid du Colombier 		goto again;
1993e12c5d1SDavid du Colombier 	}
2003e12c5d1SDavid du Colombier 	j = events[slot].job;
201*219b2ee8SDavid du Colombier 	usage();
2023e12c5d1SDavid du Colombier 	nrunning--;
2033e12c5d1SDavid du Colombier 	events[slot].pid = -1;
204*219b2ee8SDavid du Colombier 	if(buf[0]){
2053e12c5d1SDavid du Colombier 		dovars(j, slot);
2063e12c5d1SDavid du Colombier 		bp = newbuf();
2073e12c5d1SDavid du Colombier 		shprint(j->r->recipe, envy, bp);
2083e12c5d1SDavid du Colombier 		front(bp->start);
209*219b2ee8SDavid du Colombier 		fprint(2, "mk: %s: exit status=%s", bp->start, buf);
2103e12c5d1SDavid du Colombier 		freebuf(bp);
2113e12c5d1SDavid du Colombier 		for(n = j->n, done = 0; n; n = n->next)
2123e12c5d1SDavid du Colombier 			if(n->flags&DELETE){
2133e12c5d1SDavid du Colombier 				if(done++ == 0)
2143e12c5d1SDavid du Colombier 					fprint(2, ", deleting");
2153e12c5d1SDavid du Colombier 				fprint(2, " '%s'", n->name);
2163e12c5d1SDavid du Colombier 			}
2173e12c5d1SDavid du Colombier 		fprint(2, "\n");
2183e12c5d1SDavid du Colombier 		for(n = j->n, done = 0; n; n = n->next)
2193e12c5d1SDavid du Colombier 			if(n->flags&DELETE){
2203e12c5d1SDavid du Colombier 				if(done++ == 0)
2213e12c5d1SDavid du Colombier 					/*Fflush(2)*/;
2223e12c5d1SDavid du Colombier 				delete(n->name);
2233e12c5d1SDavid du Colombier 			}
2243e12c5d1SDavid du Colombier 		if(kflag){
2253e12c5d1SDavid du Colombier 			runerrs++;
2263e12c5d1SDavid du Colombier 			uarg = 1;
2273e12c5d1SDavid du Colombier 		} else {
2283e12c5d1SDavid du Colombier 			jobs = 0;
2293e12c5d1SDavid du Colombier 			Exit();
2303e12c5d1SDavid du Colombier 		}
2313e12c5d1SDavid du Colombier 	}
2323e12c5d1SDavid du Colombier 	if(j->fd >= 0){
2333e12c5d1SDavid du Colombier 		sprint(buf, "process %d", pid);
2343e12c5d1SDavid du Colombier 		parse(buf, j->fd, 0, 0);
2353e12c5d1SDavid du Colombier 		execinit();	/* reread environ */
2363e12c5d1SDavid du Colombier 		nproc();
2373e12c5d1SDavid du Colombier 		while(jobs && (nrunning < nproclimit))
2383e12c5d1SDavid du Colombier 			sched();
2393e12c5d1SDavid du Colombier 	}
2403e12c5d1SDavid du Colombier 	for(w = j->t; w; w = w->next){
2413e12c5d1SDavid du Colombier 		if((s = symlook(w->s, S_NODE, (char *)0)) == 0)
2423e12c5d1SDavid du Colombier 			continue;	/* not interested in this node */
2433e12c5d1SDavid du Colombier 		update(uarg, (Node *)s->value);
2443e12c5d1SDavid du Colombier 	}
2453e12c5d1SDavid du Colombier 	if(nrunning < nproclimit)
2463e12c5d1SDavid du Colombier 		sched();
2473e12c5d1SDavid du Colombier 	return(0);
2483e12c5d1SDavid du Colombier }
2493e12c5d1SDavid du Colombier 
2503e12c5d1SDavid du Colombier enum {
2513e12c5d1SDavid du Colombier 	TARGET,
2523e12c5d1SDavid du Colombier 	STEM,
2533e12c5d1SDavid du Colombier 	PREREQ,
2543e12c5d1SDavid du Colombier 	PID,
2553e12c5d1SDavid du Colombier 	NPROC,
2563e12c5d1SDavid du Colombier 	NEWPREREQ,
2573e12c5d1SDavid du Colombier 	ALLTARGET,
2583e12c5d1SDavid du Colombier 	STEM0,
2593e12c5d1SDavid du Colombier 	STEM1,
2603e12c5d1SDavid du Colombier 	STEM2,
2613e12c5d1SDavid du Colombier 	STEM3,
2623e12c5d1SDavid du Colombier 	STEM4,
2633e12c5d1SDavid du Colombier 	STEM5,
2643e12c5d1SDavid du Colombier 	STEM6,
2653e12c5d1SDavid du Colombier 	STEM7,
2663e12c5d1SDavid du Colombier 	STEM8,
2673e12c5d1SDavid du Colombier 	STEM9,
2683e12c5d1SDavid du Colombier };
2693e12c5d1SDavid du Colombier 
2703e12c5d1SDavid du Colombier struct Myenv {
2713e12c5d1SDavid du Colombier 	char *name;
2723e12c5d1SDavid du Colombier 	Word w;
2733e12c5d1SDavid du Colombier } myenv[] =
2743e12c5d1SDavid du Colombier {
2753e12c5d1SDavid du Colombier 	[TARGET]	"target",	{"",0},		/* really sleazy */
2763e12c5d1SDavid du Colombier 	[STEM]		"stem",		{"",0},
2773e12c5d1SDavid du Colombier 	[PREREQ]	"prereq",	{"",0},
2783e12c5d1SDavid du Colombier 	[PID]		"pid",		{"",0},
2793e12c5d1SDavid du Colombier 	[NPROC]		"nproc",	{"",0},
2803e12c5d1SDavid du Colombier 	[NEWPREREQ]	"newprereq",	{"",0},
2813e12c5d1SDavid du Colombier 	[ALLTARGET]	"alltarget",	{"",0},
2823e12c5d1SDavid du Colombier 	[STEM0]		"stem0",	{"",0},	/* retain order of rest */
2833e12c5d1SDavid du Colombier 	[STEM1]		"stem1",	{"",0},
2843e12c5d1SDavid du Colombier 	[STEM2]		"stem2",	{"",0},
2853e12c5d1SDavid du Colombier 	[STEM3]		"stem3",	{"",0},
2863e12c5d1SDavid du Colombier 	[STEM4]		"stem4",	{"",0},
2873e12c5d1SDavid du Colombier 	[STEM5]		"stem5",	{"",0},
2883e12c5d1SDavid du Colombier 	[STEM6]		"stem6",	{"",0},
2893e12c5d1SDavid du Colombier 	[STEM7]		"stem7",	{"",0},
2903e12c5d1SDavid du Colombier 	[STEM8]		"stem8",	{"",0},
2913e12c5d1SDavid du Colombier 	[STEM9]		"stem9",	{"",0},
2923e12c5d1SDavid du Colombier 			0,		{0,0},
2933e12c5d1SDavid du Colombier };
2943e12c5d1SDavid du Colombier 
2953e12c5d1SDavid du Colombier void
2963e12c5d1SDavid du Colombier execinit(void)
2973e12c5d1SDavid du Colombier {
2983e12c5d1SDavid du Colombier 	struct Myenv *mp;
2993e12c5d1SDavid du Colombier 
3003e12c5d1SDavid du Colombier 	nextv = 0;		/* fill env from beginning */
3013e12c5d1SDavid du Colombier 	vardump();
3023e12c5d1SDavid du Colombier 	special = nextv-1;	/* pointer to last original env*/
3033e12c5d1SDavid du Colombier 	for (mp = myenv; mp->name; mp++)
3043e12c5d1SDavid du Colombier 		symlook(mp->name, S_WESET, "");
3053e12c5d1SDavid du Colombier }
3063e12c5d1SDavid du Colombier 
3073e12c5d1SDavid du Colombier int
3083e12c5d1SDavid du Colombier internalvar(char *name, Word *w)
3093e12c5d1SDavid du Colombier {
3103e12c5d1SDavid du Colombier 	struct Myenv *mp;
3113e12c5d1SDavid du Colombier 
3123e12c5d1SDavid du Colombier 	for (mp = myenv; mp->name; mp++)
3133e12c5d1SDavid du Colombier 		if (strcmp(name, mp->name) == 0) {
3143e12c5d1SDavid du Colombier 			mp->w.s = w->s;
3153e12c5d1SDavid du Colombier 			mp->w.next = w->next;
3163e12c5d1SDavid du Colombier 			return 1;
3173e12c5d1SDavid du Colombier 		}
3183e12c5d1SDavid du Colombier 	return 0;
3193e12c5d1SDavid du Colombier }
3203e12c5d1SDavid du Colombier 
3213e12c5d1SDavid du Colombier void
3223e12c5d1SDavid du Colombier dovars(Job *j, int slot)
3233e12c5d1SDavid du Colombier {
3243e12c5d1SDavid du Colombier 	int c;
3253e12c5d1SDavid du Colombier 	char *s;
3263e12c5d1SDavid du Colombier 	struct Myenv *mp;
3273e12c5d1SDavid du Colombier 	int i;
3283e12c5d1SDavid du Colombier 	char buf[20];
3293e12c5d1SDavid du Colombier 
3303e12c5d1SDavid du Colombier 	nextv = special;
3313e12c5d1SDavid du Colombier 	envinsert(myenv[TARGET].name, j->t);
3323e12c5d1SDavid du Colombier 	envinsert(myenv[STEM].name, &myenv[STEM].w);
3333e12c5d1SDavid du Colombier 	if(j->r->attr&REGEXP) {			/* memory leak */
3343e12c5d1SDavid du Colombier 		if (j->match[1].sp && j->match[1].ep) {
3353e12c5d1SDavid du Colombier 			s = j->match[1].ep+1;
3363e12c5d1SDavid du Colombier 			c = *s;
337*219b2ee8SDavid du Colombier 			*s = 0;
3383e12c5d1SDavid du Colombier 			myenv[STEM].w.s = strdup(j->match[1].sp);
3393e12c5d1SDavid du Colombier 			*s = c;
3403e12c5d1SDavid du Colombier 		} else
3413e12c5d1SDavid du Colombier 			myenv[STEM].w.s = "";
3423e12c5d1SDavid du Colombier 	} else
3433e12c5d1SDavid du Colombier 		myenv[STEM].w.s = j->stem;
3443e12c5d1SDavid du Colombier 	envinsert(myenv[PREREQ].name, j->p);
3453e12c5d1SDavid du Colombier 	sprint(buf, "%d", getpid());
3463e12c5d1SDavid du Colombier 	myenv[PID].w.s = strdup(buf);		/* memory leak */
3473e12c5d1SDavid du Colombier 	envinsert(myenv[PID].name, &myenv[PID].w);
3483e12c5d1SDavid du Colombier 	sprint(buf, "%d", slot);
3493e12c5d1SDavid du Colombier 	myenv[NPROC].w.s = strdup(buf);		/* memory leak */
3503e12c5d1SDavid du Colombier 	envinsert(myenv[NPROC].name, &myenv[NPROC].w);
3513e12c5d1SDavid du Colombier 	envinsert(myenv[NEWPREREQ].name, j->np);
3523e12c5d1SDavid du Colombier 	envinsert(myenv[ALLTARGET].name, j->at);
3533e12c5d1SDavid du Colombier 	mp = &myenv[STEM0];		/* careful - assumed order*/
3543e12c5d1SDavid du Colombier 	for(i = 0; i <= 9; i++){
3553e12c5d1SDavid du Colombier 		if((j->r->attr&REGEXP) && j->match[i].sp && j->match[i].ep) {
3563e12c5d1SDavid du Colombier 			s = j->match[i].ep;
3573e12c5d1SDavid du Colombier 			c = *s;
3583e12c5d1SDavid du Colombier 			*s = 0;
3593e12c5d1SDavid du Colombier 			mp->w.s = strdup(j->match[i].sp);	/*leak*/
3603e12c5d1SDavid du Colombier 			*s = c;
3613e12c5d1SDavid du Colombier 			envinsert(mp->name, &mp->w);
3623e12c5d1SDavid du Colombier 		} else
3633e12c5d1SDavid du Colombier 			envinsert(mp->name, 0);
3643e12c5d1SDavid du Colombier 		mp++;
3653e12c5d1SDavid du Colombier 	}
3663e12c5d1SDavid du Colombier 	envinsert(0, 0);
3673e12c5d1SDavid du Colombier }
3683e12c5d1SDavid du Colombier 
3693e12c5d1SDavid du Colombier void
3703e12c5d1SDavid du Colombier nproc(void)
3713e12c5d1SDavid du Colombier {
3723e12c5d1SDavid du Colombier 	Symtab *sym;
3733e12c5d1SDavid du Colombier 	Word *w;
3743e12c5d1SDavid du Colombier 
3753e12c5d1SDavid du Colombier 	if(sym = symlook("NPROC", S_VAR, (char *)0)) {
3763e12c5d1SDavid du Colombier 		w = (Word *) sym->value;
3773e12c5d1SDavid du Colombier 		if (w && w->s && w->s[0])
3783e12c5d1SDavid du Colombier 			nproclimit = atoi(w->s);
3793e12c5d1SDavid du Colombier 	}
3803e12c5d1SDavid du Colombier 	if(nproclimit < 1)
3813e12c5d1SDavid du Colombier 		nproclimit = 1;
3823e12c5d1SDavid du Colombier 	if(DEBUG(D_EXEC))
3833e12c5d1SDavid du Colombier 		fprint(1, "nprocs = %d\n", nproclimit);
3843e12c5d1SDavid du Colombier 	if(nproclimit > nevents){
3853e12c5d1SDavid du Colombier 		if(nevents)
3863e12c5d1SDavid du Colombier 			events = (Event *)Realloc((char *)events, nproclimit*sizeof(Event));
3873e12c5d1SDavid du Colombier 		else
3883e12c5d1SDavid du Colombier 			events = (Event *)Malloc(nproclimit*sizeof(Event));
3893e12c5d1SDavid du Colombier 		while(nevents < nproclimit)
3903e12c5d1SDavid du Colombier 			events[nevents++].pid = 0;
3913e12c5d1SDavid du Colombier 	}
3923e12c5d1SDavid du Colombier }
3933e12c5d1SDavid du Colombier 
3943e12c5d1SDavid du Colombier int
3953e12c5d1SDavid du Colombier nextslot(void)
3963e12c5d1SDavid du Colombier {
3973e12c5d1SDavid du Colombier 	int i;
3983e12c5d1SDavid du Colombier 
3993e12c5d1SDavid du Colombier 	for(i = 0; i < nproclimit; i++)
4003e12c5d1SDavid du Colombier 		if(events[i].pid <= 0) return i;
4013e12c5d1SDavid du Colombier 	assert("out of slots!!", 0);
4023e12c5d1SDavid du Colombier 	return 0;	/* cyntax */
4033e12c5d1SDavid du Colombier }
4043e12c5d1SDavid du Colombier 
4053e12c5d1SDavid du Colombier int
4063e12c5d1SDavid du Colombier pidslot(int pid)
4073e12c5d1SDavid du Colombier {
4083e12c5d1SDavid du Colombier 	int i;
4093e12c5d1SDavid du Colombier 
4103e12c5d1SDavid du Colombier 	for(i = 0; i < nevents; i++)
4113e12c5d1SDavid du Colombier 		if(events[i].pid == pid) return(i);
4123e12c5d1SDavid du Colombier 	if(DEBUG(D_EXEC))
4133e12c5d1SDavid du Colombier 		fprint(2, "mk: wait returned unexpected process %d\n", pid);
4143e12c5d1SDavid du Colombier 	return(-1);
4153e12c5d1SDavid du Colombier }
4163e12c5d1SDavid du Colombier 
4173e12c5d1SDavid du Colombier 
4183e12c5d1SDavid du Colombier static void
4193e12c5d1SDavid du Colombier pnew(int pid, int status)
4203e12c5d1SDavid du Colombier {
4213e12c5d1SDavid du Colombier 	Process *p;
4223e12c5d1SDavid du Colombier 
4233e12c5d1SDavid du Colombier 	if(pfree){
4243e12c5d1SDavid du Colombier 		p = pfree;
4253e12c5d1SDavid du Colombier 		pfree = p->f;
4263e12c5d1SDavid du Colombier 	} else
4273e12c5d1SDavid du Colombier 		p = (Process *)Malloc(sizeof(Process));
4283e12c5d1SDavid du Colombier 	p->pid = pid;
4293e12c5d1SDavid du Colombier 	p->status = status;
4303e12c5d1SDavid du Colombier 	p->f = phead;
4313e12c5d1SDavid du Colombier 	phead = p;
4323e12c5d1SDavid du Colombier 	if(p->f)
4333e12c5d1SDavid du Colombier 		p->f->b = p;
4343e12c5d1SDavid du Colombier 	p->b = 0;
4353e12c5d1SDavid du Colombier }
4363e12c5d1SDavid du Colombier 
4373e12c5d1SDavid du Colombier static void
4383e12c5d1SDavid du Colombier pdelete(Process *p)
4393e12c5d1SDavid du Colombier {
4403e12c5d1SDavid du Colombier 	if(p->f)
4413e12c5d1SDavid du Colombier 		p->f->b = p->b;
4423e12c5d1SDavid du Colombier 	if(p->b)
4433e12c5d1SDavid du Colombier 		p->b->f = p->f;
4443e12c5d1SDavid du Colombier 	else
4453e12c5d1SDavid du Colombier 		phead = p->f;
4463e12c5d1SDavid du Colombier 	p->f = pfree;
4473e12c5d1SDavid du Colombier 	pfree = p;
4483e12c5d1SDavid du Colombier }
4493e12c5d1SDavid du Colombier 
4503e12c5d1SDavid du Colombier void
4513e12c5d1SDavid du Colombier killchildren(char *msg)
4523e12c5d1SDavid du Colombier {
4533e12c5d1SDavid du Colombier 	Process *p;
4543e12c5d1SDavid du Colombier 
455*219b2ee8SDavid du Colombier 	for(p = phead; p; p = p->f)
456*219b2ee8SDavid du Colombier 		expunge(p->pid, msg);
4573e12c5d1SDavid du Colombier }
458*219b2ee8SDavid du Colombier 
459*219b2ee8SDavid du Colombier int
460*219b2ee8SDavid du Colombier notifyf(void *a, char *msg)
461*219b2ee8SDavid du Colombier {
462*219b2ee8SDavid du Colombier 	static int nnote;
463*219b2ee8SDavid du Colombier 
464*219b2ee8SDavid du Colombier 	USED(a);
465*219b2ee8SDavid du Colombier 	if(++nnote > 100){	/* until andrew fixes his program */
466*219b2ee8SDavid du Colombier 		fprint(2, "mk: too many notes\n");
467*219b2ee8SDavid du Colombier 		notify(0);
468*219b2ee8SDavid du Colombier 		abort();
4693e12c5d1SDavid du Colombier 	}
470*219b2ee8SDavid du Colombier 	if(strcmp(msg, "interrupt")!=0 && strcmp(msg, "hangup")!=0)
471*219b2ee8SDavid du Colombier 		return 0;
472*219b2ee8SDavid du Colombier 	kflag = 1;	/* to make sure waitup doesn't exit */
473*219b2ee8SDavid du Colombier 	jobs = 0;	/* make sure no more get scheduled */
474*219b2ee8SDavid du Colombier 	killchildren(msg);
475*219b2ee8SDavid du Colombier 	while(waitup(1, (int *)0) == 0)
476*219b2ee8SDavid du Colombier 		;
477*219b2ee8SDavid du Colombier 	Bprint(&stdout, "mk: %s\n", msg);
478*219b2ee8SDavid du Colombier 	Exit();
479*219b2ee8SDavid du Colombier 	return -1;
4803e12c5d1SDavid du Colombier }
4813e12c5d1SDavid du Colombier /*
4823e12c5d1SDavid du Colombier  *	execute a shell command capturing the output into the buffer.
4833e12c5d1SDavid du Colombier  */
4843e12c5d1SDavid du Colombier void
4853e12c5d1SDavid du Colombier rcexec(char *cstart, char *cend, Bufblock *buf)
4863e12c5d1SDavid du Colombier {
4873e12c5d1SDavid du Colombier 	int childin[2], childout[2], pid;
4883e12c5d1SDavid du Colombier 	int tot, n;
4893e12c5d1SDavid du Colombier 
4903e12c5d1SDavid du Colombier 	Bflush(&stdout);
4913e12c5d1SDavid du Colombier 	if(pipe(childin) < 0){
4923e12c5d1SDavid du Colombier 		SYNERR(-1); perror("pipe1");
4933e12c5d1SDavid du Colombier 		Exit();
4943e12c5d1SDavid du Colombier 	}
4953e12c5d1SDavid du Colombier 	if(pipe(childout) < 0){
4963e12c5d1SDavid du Colombier 		SYNERR(-1); perror("pipe2");
4973e12c5d1SDavid du Colombier 		Exit();
4983e12c5d1SDavid du Colombier 	}
4993e12c5d1SDavid du Colombier 	if((pid = rfork(RFPROC|RFFDG|RFENVG)) < 0){
5003e12c5d1SDavid du Colombier 		SYNERR(-1); perror("fork");
5013e12c5d1SDavid du Colombier 		Exit();
5023e12c5d1SDavid du Colombier 	}
5033e12c5d1SDavid du Colombier 	if(pid){	/* parent */
5043e12c5d1SDavid du Colombier 		close(childin[0]);
5053e12c5d1SDavid du Colombier 		close(childout[1]);
5063e12c5d1SDavid du Colombier 		if(cstart < cend)
5073e12c5d1SDavid du Colombier 			write(childin[1], cstart, cend-cstart+1);
5083e12c5d1SDavid du Colombier 		close(childin[1]);
5093e12c5d1SDavid du Colombier 		tot = n = 0;
5103e12c5d1SDavid du Colombier 		do {
5113e12c5d1SDavid du Colombier 			tot += n;
5123e12c5d1SDavid du Colombier 			buf->current += n;
5133e12c5d1SDavid du Colombier 			if (buf->current >= buf->end)
5143e12c5d1SDavid du Colombier 				growbuf(buf);
5153e12c5d1SDavid du Colombier 		} while((n = read(childout[0], buf->current, buf->end-buf->current)) > 0);
5163e12c5d1SDavid du Colombier 		if (tot && buf->current[-1] == '\n')
5173e12c5d1SDavid du Colombier 			buf->current--;
5183e12c5d1SDavid du Colombier 		close(childout[0]);
5193e12c5d1SDavid du Colombier 	} else {
520*219b2ee8SDavid du Colombier 		dup(childin[0], 0);
521*219b2ee8SDavid du Colombier 		dup(childout[1], 1);
5223e12c5d1SDavid du Colombier 		close(childin[0]);
5233e12c5d1SDavid du Colombier 		close(childin[1]);
5243e12c5d1SDavid du Colombier 		close(childout[0]);
5253e12c5d1SDavid du Colombier 		close(childout[1]);
526*219b2ee8SDavid du Colombier 		Execl(shell, shellname, "-I", (char *)0);
5273e12c5d1SDavid du Colombier 		perror(shell);
528*219b2ee8SDavid du Colombier 		_exits("exec");
5293e12c5d1SDavid du Colombier 	}
5303e12c5d1SDavid du Colombier }
5313e12c5d1SDavid du Colombier 
5323e12c5d1SDavid du Colombier void
5333e12c5d1SDavid du Colombier envinsert(char *name, Word *value)
5343e12c5d1SDavid du Colombier {
5353e12c5d1SDavid du Colombier 	if (nextv >= envsize) {
5363e12c5d1SDavid du Colombier 		envsize += ENVQUANTA;
5373e12c5d1SDavid du Colombier 		envy = (Envy *) Realloc((char *) envy, envsize*sizeof(Envy));
5383e12c5d1SDavid du Colombier 	}
5393e12c5d1SDavid du Colombier 	envy[nextv].name = name;
5403e12c5d1SDavid du Colombier 	envy[nextv++].values = value;
5413e12c5d1SDavid du Colombier }
542*219b2ee8SDavid du Colombier 
543*219b2ee8SDavid du Colombier static long tslot[1000];
544*219b2ee8SDavid du Colombier static long tick;
545*219b2ee8SDavid du Colombier 
546*219b2ee8SDavid du Colombier void
547*219b2ee8SDavid du Colombier usage(void)
548*219b2ee8SDavid du Colombier {
549*219b2ee8SDavid du Colombier 	long t;
550*219b2ee8SDavid du Colombier 
551*219b2ee8SDavid du Colombier 	time(&t);
552*219b2ee8SDavid du Colombier 	if(tick)
553*219b2ee8SDavid du Colombier 		tslot[nrunning] += (t-tick);
554*219b2ee8SDavid du Colombier 	tick = t;
555*219b2ee8SDavid du Colombier }
556*219b2ee8SDavid du Colombier 
557*219b2ee8SDavid du Colombier void
558*219b2ee8SDavid du Colombier prusage(void)
559*219b2ee8SDavid du Colombier {
560*219b2ee8SDavid du Colombier 	int i;
561*219b2ee8SDavid du Colombier 
562*219b2ee8SDavid du Colombier 	usage();
563*219b2ee8SDavid du Colombier 	for(i = 0; i <= nevents; i++)
564*219b2ee8SDavid du Colombier 		fprint(1, "%d: %ld\n", i, tslot[i]);
565*219b2ee8SDavid du Colombier }
566