Commit Diff


commit - bd1b0cc17e58f8135fa0888cdb2d4fac61f85bce
commit + 4b241872ef56389e6bcf4ab602cd52989cf3151d
blob - f6454787f278e661eeea049ad9f583cbfd7ec07b
blob + c4d201dcb9ba4a37913d86d3b5cc0995da9e3095
--- src/cmd/rc/fns.h
+++ src/cmd/rc/fns.h
@@ -22,6 +22,7 @@ void	Updenv(void);
 void	Vinit(void);
 int	Waitfor(int, int);
 long	Write(int, char*, long);
+void	addwaitpid(int);
 int	advance(void);
 int	back(int);
 void	cleanhere(char*);
@@ -30,10 +31,12 @@ int	compile(tree*);
 char *	list2str(word*);
 int	count(word*);
 void	deglob(char*);
+void	delwaitpid(int);
 void	dotrap(void);
 void	freenodes(void);
 void	freewords(word*);
 void	globlist(void);
+int	havewaitpid(int);
 int	idchr(int);
 void	inttoascii(char*, long);
 void	kinit(void);
@@ -41,6 +44,7 @@ int	mapfd(int);
 int	match(char*, char*, int);
 int	matchfn(char*, char*);
 char**	mkargv(word*);
+void	clearwaitpids(void);
 void	panic(char*, int);
 void	pathinit(void);
 void	poplist(void);
blob - e81046d619af2a1a121e2d43c44a659860b46174
blob + 45419f0d17e69478529635479c006b3f18f0dbc2
--- src/cmd/rc/havefork.c
+++ src/cmd/rc/havefork.c
@@ -1,3 +1,9 @@
+#include <u.h>
+#include <signal.h>
+#if defined(PLAN9PORT) && defined(__sun__)
+#	define BSD_COMP	/* sigh.  for TIOCNOTTY */
+#endif
+#include <sys/ioctl.h>
 #include "rc.h"
 #include "getflags.h"
 #include "exec.h"
@@ -10,6 +16,7 @@ void
 Xasync(void)
 {
 	int null = open("/dev/null", 0);
+	int tty;
 	int pid;
 	char npid[10];
 	if(null<0){
@@ -22,11 +29,39 @@ Xasync(void)
 		Xerror("try again");
 		break;
 	case 0:
-		pushredir(ROPEN, null, 0);
+		clearwaitpids();
+		/*
+		 * I don't know what the right thing to do here is,
+		 * so this is all experimentally determined.
+		 * If we just dup /dev/null onto 0, then running
+		 * ssh foo & will reopen /dev/tty, try to read a password,
+		 * get a signal, and repeat, in a tight loop, forever.
+		 * Arguably this is a bug in ssh (it behaves the same
+		 * way under bash as under rc) but I'm fixing it here 
+		 * anyway.  If we dissociate the process from the tty,
+		 * then it won't be able to open /dev/tty ever again.
+		 * The SIG_IGN on SIGTTOU makes writing the tty
+		 * (via fd 1 or 2, for example) succeed even though 
+		 * our pgrp is not the terminal's controlling pgrp.
+		 */
+		if((tty = open("/dev/tty", OREAD)) >= 0){
+			/*
+			 * Should make reads of tty fail, writes succeed.
+			 */
+			signal(SIGTTIN, SIG_IGN);
+			signal(SIGTTOU, SIG_IGN);
+			ioctl(tty, TIOCNOTTY);
+			close(tty);
+		}
+		if(isatty(0))
+			pushredir(ROPEN, null, 0);
+		else
+			close(null);
 		start(runq->code, runq->pc+1, runq->local);
 		runq->ret = 0;
 		break;
 	default:
+		addwaitpid(pid);
 		close(null);
 		runq->pc = runq->code[runq->pc].i;
 		inttoascii(npid, pid);
@@ -52,12 +87,14 @@ Xpipe(void)
 		Xerror("try again");
 		break;
 	case 0:
+		clearwaitpids();
 		start(p->code, pc+2, runq->local);
 		runq->ret = 0;
 		close(pfd[PRD]);
 		pushredir(ROPEN, pfd[PWR], lfd);
 		break;
 	default:
+		addwaitpid(forkid);
 		start(p->code, p->code[pc].i, runq->local);
 		close(pfd[PWR]);
 		pushredir(ROPEN, pfd[PRD], rfd);
@@ -93,11 +130,13 @@ Xbackq(void)
 		close(pfd[PWR]);
 		return;
 	case 0:
+		clearwaitpids();
 		close(pfd[PRD]);
 		start(runq->code, runq->pc+1, runq->local);
 		pushredir(ROPEN, pfd[PWR], 1);
 		return;
 	default:
+		addwaitpid(pid);
 		close(pfd[PWR]);
 		f = openfd(pfd[PRD]);
 		s = wd;
@@ -134,7 +173,7 @@ void
 Xpipefd(void)
 {
 	struct thread *p = runq;
-	int pc = p->pc;
+	int pc = p->pc, pid;
 	char name[40];
 	int pfd[2];
 	int sidefd, mainfd;
@@ -150,17 +189,19 @@ Xpipefd(void)
 		sidefd = pfd[PRD];
 		mainfd = pfd[PWR];
 	}
-	switch(fork()){
+	switch(pid = fork()){
 	case -1:
 		Xerror("try again");
 		break;
 	case 0:
+		clearwaitpids();
 		start(p->code, pc+2, runq->local);
 		close(mainfd);
 		pushredir(ROPEN, sidefd, p->code[pc].i==READ?1:0);
 		runq->ret = 0;
 		break;
 	default:
+		addwaitpid(pid);
 		close(sidefd);
 		pushredir(ROPEN, mainfd, mainfd);	/* isn't this a noop? */
 		strcpy(name, Fdprefix);
@@ -180,10 +221,12 @@ Xsubshell(void)
 		Xerror("try again");
 		break;
 	case 0:
+		clearwaitpids();
 		start(runq->code, runq->pc+1, runq->local);
 		runq->ret = 0;
 		break;
 	default:
+		addwaitpid(pid);
 		Waitfor(pid, 1);
 		runq->pc = runq->code[runq->pc].i;
 		break;
@@ -201,6 +244,7 @@ execforkexec(void)
 	case -1:
 		return -1;
 	case 0:
+		clearwaitpids();
 		pushword("exec");
 		execexec();
 		strcpy(buf, "can't exec: ");
@@ -208,5 +252,6 @@ execforkexec(void)
 		errstr(buf+n, ERRMAX-n);
 		Exit(buf);
 	}
+	addwaitpid(pid);
 	return pid;
 }
blob - 29e2272bb5eed053eefbcb88e55c236d1d6729c9 (mode 644)
blob + /dev/null
--- src/cmd/rc/havep9p.c
+++ /dev/null
@@ -1,246 +0,0 @@
-#include <u.h>
-#include <signal.h>
-#if defined(PLAN9PORT) && defined(__sun__)
-#	define BSD_COMP	/* sigh.  for TIOCNOTTY */
-#endif
-#include <sys/ioctl.h>
-#include "rc.h"
-#include "getflags.h"
-#include "exec.h"
-#include "io.h"
-#include "fns.h"
-
-int havefork = 1;
-
-void
-Xasync(void)
-{
-	int null=open("/dev/null", 0);
-	int tty;
-	int pid;
-	char npid[10];
-	if(null<0){
-		Xerror("Can't open /dev/null\n");
-		return;
-	}
-	switch(pid=rfork(RFFDG|RFPROC|RFNOTEG)){
-	case -1:
-		close(null);
-		Xerror("try again");
-		break;
-	case 0:
-		/*
-		 * I don't know what the right thing to do here is,
-		 * so this is all experimentally determined.
-		 * If we just dup /dev/null onto 0, then running
-		 * ssh foo & will reopen /dev/tty, try to read a password,
-		 * get a signal, and repeat, in a tight loop, forever.
-		 * Arguably this is a bug in ssh (it behaves the same
-		 * way under bash as under rc) but I'm fixing it here 
-		 * anyway.  If we dissociate the process from the tty,
-		 * then it won't be able to open /dev/tty ever again.
-		 * The SIG_IGN on SIGTTOU makes writing the tty
-		 * (via fd 1 or 2, for example) succeed even though 
-		 * our pgrp is not the terminal's controlling pgrp.
-		 */
-		if((tty=open("/dev/tty", OREAD)) >= 0){
-			/*
-			 * Should make reads of tty fail, writes succeed.
-			 */
-			signal(SIGTTIN, SIG_IGN);
-			signal(SIGTTOU, SIG_IGN);
-			ioctl(tty, TIOCNOTTY);
-			close(tty);
-		}
-		if(isatty(0))
-			pushredir(ROPEN, null, 0);
-		else
-			close(null);
-		start(runq->code, runq->pc+1, runq->local);
-		runq->ret=0;
-		break;
-	default:
-		close(null);
-		runq->pc=runq->code[runq->pc].i;
-		inttoascii(npid, pid);
-		setvar("apid", newword(npid, (word *)0));
-		break;
-	}
-}
-
-void
-Xpipe(void)
-{
-	struct thread *p = runq;
-	int pc = p->pc, forkid;
-	int lfd = p->code[pc++].i;
-	int rfd = p->code[pc++].i;
-	int pfd[2];
-
-	if(pipe(pfd)<0){
-		Xerror("can't get pipe");
-		return;
-	}
-	switch(forkid=fork()){
-	case -1:
-		Xerror("try again");
-		break;
-	case 0:
-		start(p->code, pc+2, runq->local);
-		runq->ret=0;
-		close(pfd[PRD]);
-		pushredir(ROPEN, pfd[PWR], lfd);
-		break;
-	default:
-		start(p->code, p->code[pc].i, runq->local);
-		close(pfd[PWR]);
-		pushredir(ROPEN, pfd[PRD], rfd);
-		p->pc=p->code[pc+1].i;
-		p->pid=forkid;
-		break;
-	}
-}
-
-void
-Xbackq(void)
-{
-	char wd[8193];
-	int c;
-	char *s, *ewd = &wd[8192], *stop;
-	struct io *f;
-	var *ifs = vlook("ifs");
-	word *v, *nextv;
-	int pfd[2];
-	int pid;
-
-	stop = ifs->val?ifs->val->word:"";
-	if(pipe(pfd)<0){
-		Xerror("can't make pipe");
-		return;
-	}
-	switch(pid = fork()){
-	case -1: Xerror("try again");
-		close(pfd[PRD]);
-		close(pfd[PWR]);
-		return;
-	case 0:
-		close(pfd[PRD]);
-		start(runq->code, runq->pc+1, runq->local);
-		pushredir(ROPEN, pfd[PWR], 1);
-		return;
-	default:
-		close(pfd[PWR]);
-		f=openfd(pfd[PRD]);
-		s=wd;
-		v=0;
-		while((c=rchr(f))!=EOF){
-			if(strchr(stop, c) || s==ewd){
-				if(s!=wd){
-					*s='\0';
-					v=newword(wd, v);
-					s=wd;
-				}
-			}
-			else *s++=c;
-		}
-		if(s!=wd){
-			*s='\0';
-			v=newword(wd, v);
-		}
-		closeio(f);
-		Waitfor(pid, 0);
-		/* v points to reversed arglist -- reverse it onto argv */
-		while(v){
-			nextv=v->next;
-			v->next=runq->argv->words;
-			runq->argv->words=v;
-			v=nextv;
-		}
-		runq->pc=runq->code[runq->pc].i;
-		return;
-	}
-}
-
-/*
- * Who should wait for the exit from the fork?
- */
-void
-Xpipefd(void)
-{
-	struct thread *p=runq;
-	int pc=p->pc;
-	char name[40];
-	int pfd[2];
-	int sidefd, mainfd;
-	if(pipe(pfd)<0){
-		Xerror("can't get pipe");
-		return;
-	}
-	if(p->code[pc].i==READ){
-		sidefd=pfd[PWR];
-		mainfd=pfd[PRD];
-	}
-	else{
-		sidefd=pfd[PRD];
-		mainfd=pfd[PWR];
-	}
-	switch(fork()){
-	case -1:
-		Xerror("try again");
-		break;
-	case 0:
-		start(p->code, pc+2, runq->local);
-		close(mainfd);
-		pushredir(ROPEN, sidefd, p->code[pc].i==READ?1:0);
-		runq->ret=0;
-		break;
-	default:
-		close(sidefd);
-		pushredir(ROPEN, mainfd, mainfd);	/* isn't this a noop? */
-		strcpy(name, Fdprefix);
-		inttoascii(name+strlen(name), mainfd);
-		pushword(name);
-		p->pc=p->code[pc+1].i;
-		break;
-	}
-}
-
-void
-Xsubshell(void)
-{
-	int pid;
-	switch(pid=fork()){
-	case -1:
-		Xerror("try again");
-		break;
-	case 0:
-		start(runq->code, runq->pc+1, runq->local);
-		runq->ret=0;
-		break;
-	default:
-		Waitfor(pid, 1);
-		runq->pc=runq->code[runq->pc].i;
-		break;
-	}
-}
-
-int
-execforkexec(void)
-{
-	int pid;
-	int n;
-	char buf[ERRMAX];
-
-	switch(pid = fork()){
-	case -1:
-		return -1;
-	case 0:
-		pushword("exec");
-		execexec();
-		strcpy(buf, "can't exec: ");
-		n = strlen(buf);
-		errstr(buf+n, ERRMAX-n);
-		Exit(buf);
-	}
-	return pid;
-}
blob - d1144e8584acc60cd8fee5fb043154a762aee9b6
blob + 79b407f88d0790e0cf76ebd14c4ebe4214fccd8c
--- src/cmd/rc/mkfile
+++ src/cmd/rc/mkfile
@@ -20,7 +20,7 @@ OFILES=\
 	var.$O\
 	y.tab.$O\
 	plan9ish.$O\
-	havep9p.$O\
+	havefork.$O\
 
 HFILES=\
 	rc.h\
blob - 1e8965361ba393d4cf0ea90ba5a283db29e2a46d
blob + da9d8679e6794bb6c9040291681aa800139090ac
--- src/cmd/rc/plan9ish.c
+++ src/cmd/rc/plan9ish.c
@@ -199,7 +199,10 @@ int Waitfor(int pid, int unused0){
 	Waitmsg *w;
 	char errbuf[ERRMAX];
 
+	if(pid >= 0 && !havewaitpid(pid))
+		return 0;
 	while((w = wait()) != nil){
+		delwaitpid(w->pid);
 		if(w->pid==pid){
 			if(strncmp(w->msg, "signal: ", 8) == 0)
 				fprint(mapfd(2), "%d: %s\n", w->pid, w->msg);
@@ -217,7 +220,7 @@ int Waitfor(int pid, int unused0){
 		free(w);
 	}
 
-	errstr(errbuf, sizeof errbuf);
+	rerrstr(errbuf, sizeof errbuf);
 	if(strcmp(errbuf, "interrupted")==0) return -1;
 	return 0;
 }
@@ -558,4 +561,44 @@ exitcode(char *msg)
 	if(n == 0)
 		n = 1;
 	return n;
+}
+
+int *waitpids;
+int nwaitpids;
+
+void
+addwaitpid(int pid)
+{
+	waitpids = realloc(waitpids, (nwaitpids+1)*sizeof waitpids[0]);
+	if(waitpids == 0)
+		panic("Can't realloc %d waitpids", nwaitpids+1);
+	waitpids[nwaitpids++] = pid;
 }
+
+void
+delwaitpid(int pid)
+{
+	int r, w;
+	
+	for(r=w=0; r<nwaitpids; r++)
+		if(waitpids[r] != pid)
+			waitpids[w++] = waitpids[r];
+	nwaitpids = w;
+}
+
+void
+clearwaitpids(void)
+{
+	nwaitpids = 0;
+}
+
+int
+havewaitpid(int pid)
+{
+	int i;
+	
+	for(i=0; i<nwaitpids; i++)
+		if(waitpids[i] == pid)
+			return 1;
+	return 0;
+}