xref: /plan9-contrib/sys/src/cmd/rc/havefork.c (revision dbee78772299b06484db59f95f481ad96b19f995)
1dc5a79c1SDavid du Colombier #include "rc.h"
2dc5a79c1SDavid du Colombier #include "exec.h"
3dc5a79c1SDavid du Colombier #include "io.h"
4dc5a79c1SDavid du Colombier #include "fns.h"
5dc5a79c1SDavid du Colombier 
6dc5a79c1SDavid du Colombier int havefork = 1;
7dc5a79c1SDavid du Colombier 
8dc5a79c1SDavid du Colombier void
9dc5a79c1SDavid du Colombier Xasync(void)
10dc5a79c1SDavid du Colombier {
11dc5a79c1SDavid du Colombier 	int null = open("/dev/null", 0);
12dc5a79c1SDavid du Colombier 	int pid;
13dc5a79c1SDavid du Colombier 	char npid[10];
14dc5a79c1SDavid du Colombier 	if(null<0){
15dc5a79c1SDavid du Colombier 		Xerror("Can't open /dev/null\n");
16dc5a79c1SDavid du Colombier 		return;
17dc5a79c1SDavid du Colombier 	}
1875ac14c9SDavid du Colombier 	switch(pid = rfork(RFFDG|RFPROC|RFNOTEG)){
19dc5a79c1SDavid du Colombier 	case -1:
20dc5a79c1SDavid du Colombier 		close(null);
21dc5a79c1SDavid du Colombier 		Xerror("try again");
22dc5a79c1SDavid du Colombier 		break;
23dc5a79c1SDavid du Colombier 	case 0:
24d3907fe5SDavid du Colombier 		clearwaitpids();
25dc5a79c1SDavid du Colombier 		pushredir(ROPEN, null, 0);
26dc5a79c1SDavid du Colombier 		start(runq->code, runq->pc+1, runq->local);
27dc5a79c1SDavid du Colombier 		runq->ret = 0;
28dc5a79c1SDavid du Colombier 		break;
29dc5a79c1SDavid du Colombier 	default:
30d3907fe5SDavid du Colombier 		addwaitpid(pid);
31dc5a79c1SDavid du Colombier 		close(null);
32dc5a79c1SDavid du Colombier 		runq->pc = runq->code[runq->pc].i;
33dc5a79c1SDavid du Colombier 		inttoascii(npid, pid);
34dc5a79c1SDavid du Colombier 		setvar("apid", newword(npid, (word *)0));
35dc5a79c1SDavid du Colombier 		break;
36dc5a79c1SDavid du Colombier 	}
37dc5a79c1SDavid du Colombier }
38dc5a79c1SDavid du Colombier 
39dc5a79c1SDavid du Colombier void
40dc5a79c1SDavid du Colombier Xpipe(void)
41dc5a79c1SDavid du Colombier {
42dc5a79c1SDavid du Colombier 	struct thread *p = runq;
43dc5a79c1SDavid du Colombier 	int pc = p->pc, forkid;
44dc5a79c1SDavid du Colombier 	int lfd = p->code[pc++].i;
45dc5a79c1SDavid du Colombier 	int rfd = p->code[pc++].i;
46dc5a79c1SDavid du Colombier 	int pfd[2];
47dc5a79c1SDavid du Colombier 	if(pipe(pfd)<0){
48dc5a79c1SDavid du Colombier 		Xerror("can't get pipe");
49dc5a79c1SDavid du Colombier 		return;
50dc5a79c1SDavid du Colombier 	}
51dc5a79c1SDavid du Colombier 	switch(forkid = fork()){
52dc5a79c1SDavid du Colombier 	case -1:
53dc5a79c1SDavid du Colombier 		Xerror("try again");
54dc5a79c1SDavid du Colombier 		break;
55dc5a79c1SDavid du Colombier 	case 0:
56d3907fe5SDavid du Colombier 		clearwaitpids();
57dc5a79c1SDavid du Colombier 		start(p->code, pc+2, runq->local);
58dc5a79c1SDavid du Colombier 		runq->ret = 0;
59dc5a79c1SDavid du Colombier 		close(pfd[PRD]);
60dc5a79c1SDavid du Colombier 		pushredir(ROPEN, pfd[PWR], lfd);
61dc5a79c1SDavid du Colombier 		break;
62dc5a79c1SDavid du Colombier 	default:
63d3907fe5SDavid du Colombier 		addwaitpid(forkid);
64dc5a79c1SDavid du Colombier 		start(p->code, p->code[pc].i, runq->local);
65dc5a79c1SDavid du Colombier 		close(pfd[PWR]);
66dc5a79c1SDavid du Colombier 		pushredir(ROPEN, pfd[PRD], rfd);
67dc5a79c1SDavid du Colombier 		p->pc = p->code[pc+1].i;
68dc5a79c1SDavid du Colombier 		p->pid = forkid;
69dc5a79c1SDavid du Colombier 		break;
70dc5a79c1SDavid du Colombier 	}
71dc5a79c1SDavid du Colombier }
72dc5a79c1SDavid du Colombier 
73dc5a79c1SDavid du Colombier /*
74dc5a79c1SDavid du Colombier  * Who should wait for the exit from the fork?
75dc5a79c1SDavid du Colombier  */
768cc1c73aSDavid du Colombier 
77dc5a79c1SDavid du Colombier void
78dc5a79c1SDavid du Colombier Xbackq(void)
79dc5a79c1SDavid du Colombier {
808cc1c73aSDavid du Colombier 	int n, pid;
81276e7d6dSDavid du Colombier 	int pfd[2];
828cc1c73aSDavid du Colombier 	char *stop;
838cc1c73aSDavid du Colombier 	char utf[UTFmax+1];
84c6df1444SDavid du Colombier 	io *f, *wd;
85dc5a79c1SDavid du Colombier 	word *v, *nextv;
868cc1c73aSDavid du Colombier 	Rune r;
87276e7d6dSDavid du Colombier 
88*dbee7877SDavid du Colombier  	stop = "";
89*dbee7877SDavid du Colombier  	if(runq->argv && runq->argv->words)
90*dbee7877SDavid du Colombier  		stop = runq->argv->words->word;
91dc5a79c1SDavid du Colombier 	if(pipe(pfd)<0){
92dc5a79c1SDavid du Colombier 		Xerror("can't make pipe");
93dc5a79c1SDavid du Colombier 		return;
94dc5a79c1SDavid du Colombier 	}
95dc5a79c1SDavid du Colombier 	switch(pid = fork()){
96dc5a79c1SDavid du Colombier 	case -1:
97dc5a79c1SDavid du Colombier 		Xerror("try again");
98dc5a79c1SDavid du Colombier 		close(pfd[PRD]);
99dc5a79c1SDavid du Colombier 		close(pfd[PWR]);
100dc5a79c1SDavid du Colombier 		return;
101dc5a79c1SDavid du Colombier 	case 0:
102d3907fe5SDavid du Colombier 		clearwaitpids();
103dc5a79c1SDavid du Colombier 		close(pfd[PRD]);
104dc5a79c1SDavid du Colombier 		start(runq->code, runq->pc+1, runq->local);
105dc5a79c1SDavid du Colombier 		pushredir(ROPEN, pfd[PWR], 1);
106dc5a79c1SDavid du Colombier 		return;
107dc5a79c1SDavid du Colombier 	default:
108d3907fe5SDavid du Colombier 		addwaitpid(pid);
109dc5a79c1SDavid du Colombier 		close(pfd[PWR]);
110dc5a79c1SDavid du Colombier 		f = openfd(pfd[PRD]);
111c6df1444SDavid du Colombier 		wd = openstr();
1128cc1c73aSDavid du Colombier 		v = nil;
1138cc1c73aSDavid du Colombier 		/* rutf requires at least UTFmax+1 bytes in utf */
1148cc1c73aSDavid du Colombier 		while((n = rutf(f, utf, &r)) != EOF){
1158cc1c73aSDavid du Colombier 			utf[n] = '\0';
1168cc1c73aSDavid du Colombier 			if(utfutf(stop, utf) == nil)
117c6df1444SDavid du Colombier 				pstr(wd, utf);	/* append utf to word */
1188cc1c73aSDavid du Colombier 			else
119fbd2c77cSDavid du Colombier 				/*
1208cc1c73aSDavid du Colombier 				 * utf/r is an ifs rune (e.g., \t, \n), thus
1218cc1c73aSDavid du Colombier 				 * ends the current word, if any.
122fbd2c77cSDavid du Colombier 				 */
123c6df1444SDavid du Colombier 				if(*(char *)wd->strp != '\0'){
124c6df1444SDavid du Colombier 					v = newword((char *)wd->strp, v);
125c6df1444SDavid du Colombier 					rewind(wd);
126dc5a79c1SDavid du Colombier 				}
127dc5a79c1SDavid du Colombier 		}
128c6df1444SDavid du Colombier 		if(*(char *)wd->strp != '\0')
129c6df1444SDavid du Colombier 			v = newword((char *)wd->strp, v);
130c6df1444SDavid du Colombier 		closeio(wd);
131dc5a79c1SDavid du Colombier 		closeio(f);
132dc5a79c1SDavid du Colombier 		Waitfor(pid, 0);
133*dbee7877SDavid du Colombier 		poplist();	/* ditch split in "stop" */
134dc5a79c1SDavid du Colombier 		/* v points to reversed arglist -- reverse it onto argv */
135dc5a79c1SDavid du Colombier 		while(v){
136dc5a79c1SDavid du Colombier 			nextv = v->next;
137dc5a79c1SDavid du Colombier 			v->next = runq->argv->words;
138dc5a79c1SDavid du Colombier 			runq->argv->words = v;
139dc5a79c1SDavid du Colombier 			v = nextv;
140dc5a79c1SDavid du Colombier 		}
141dc5a79c1SDavid du Colombier 		runq->pc = runq->code[runq->pc].i;
142dc5a79c1SDavid du Colombier 		return;
143dc5a79c1SDavid du Colombier 	}
144dc5a79c1SDavid du Colombier }
145dc5a79c1SDavid du Colombier 
146dc5a79c1SDavid du Colombier void
147dc5a79c1SDavid du Colombier Xpipefd(void)
148dc5a79c1SDavid du Colombier {
149dc5a79c1SDavid du Colombier 	struct thread *p = runq;
15099eb86a7SDavid du Colombier 	int pc = p->pc, pid;
151276e7d6dSDavid du Colombier 	char name[40];
15299eb86a7SDavid du Colombier 	int pfd[2];
15399eb86a7SDavid du Colombier 	int sidefd, mainfd;
154dc5a79c1SDavid du Colombier 	if(pipe(pfd)<0){
155dc5a79c1SDavid du Colombier 		Xerror("can't get pipe");
156dc5a79c1SDavid du Colombier 		return;
157dc5a79c1SDavid du Colombier 	}
158dc5a79c1SDavid du Colombier 	if(p->code[pc].i==READ){
159dc5a79c1SDavid du Colombier 		sidefd = pfd[PWR];
160dc5a79c1SDavid du Colombier 		mainfd = pfd[PRD];
161dc5a79c1SDavid du Colombier 	}
162dc5a79c1SDavid du Colombier 	else{
163dc5a79c1SDavid du Colombier 		sidefd = pfd[PRD];
164dc5a79c1SDavid du Colombier 		mainfd = pfd[PWR];
165dc5a79c1SDavid du Colombier 	}
166d3907fe5SDavid du Colombier 	switch(pid = fork()){
167dc5a79c1SDavid du Colombier 	case -1:
168dc5a79c1SDavid du Colombier 		Xerror("try again");
169dc5a79c1SDavid du Colombier 		break;
170dc5a79c1SDavid du Colombier 	case 0:
171d3907fe5SDavid du Colombier 		clearwaitpids();
172dc5a79c1SDavid du Colombier 		start(p->code, pc+2, runq->local);
173dc5a79c1SDavid du Colombier 		close(mainfd);
174dc5a79c1SDavid du Colombier 		pushredir(ROPEN, sidefd, p->code[pc].i==READ?1:0);
175dc5a79c1SDavid du Colombier 		runq->ret = 0;
176dc5a79c1SDavid du Colombier 		break;
177dc5a79c1SDavid du Colombier 	default:
178d3907fe5SDavid du Colombier 		addwaitpid(pid);
179dc5a79c1SDavid du Colombier 		close(sidefd);
180dc5a79c1SDavid du Colombier 		pushredir(ROPEN, mainfd, mainfd);	/* isn't this a noop? */
181dc5a79c1SDavid du Colombier 		strcpy(name, Fdprefix);
182dc5a79c1SDavid du Colombier 		inttoascii(name+strlen(name), mainfd);
183dc5a79c1SDavid du Colombier 		pushword(name);
184dc5a79c1SDavid du Colombier 		p->pc = p->code[pc+1].i;
185dc5a79c1SDavid du Colombier 		break;
186dc5a79c1SDavid du Colombier 	}
187dc5a79c1SDavid du Colombier }
188dc5a79c1SDavid du Colombier 
189dc5a79c1SDavid du Colombier void
190dc5a79c1SDavid du Colombier Xsubshell(void)
191dc5a79c1SDavid du Colombier {
192dc5a79c1SDavid du Colombier 	int pid;
193dc5a79c1SDavid du Colombier 	switch(pid = fork()){
194dc5a79c1SDavid du Colombier 	case -1:
195dc5a79c1SDavid du Colombier 		Xerror("try again");
196dc5a79c1SDavid du Colombier 		break;
197dc5a79c1SDavid du Colombier 	case 0:
198d3907fe5SDavid du Colombier 		clearwaitpids();
199dc5a79c1SDavid du Colombier 		start(runq->code, runq->pc+1, runq->local);
200dc5a79c1SDavid du Colombier 		runq->ret = 0;
201dc5a79c1SDavid du Colombier 		break;
202dc5a79c1SDavid du Colombier 	default:
203d3907fe5SDavid du Colombier 		addwaitpid(pid);
204dc5a79c1SDavid du Colombier 		Waitfor(pid, 1);
205dc5a79c1SDavid du Colombier 		runq->pc = runq->code[runq->pc].i;
206dc5a79c1SDavid du Colombier 		break;
207dc5a79c1SDavid du Colombier 	}
208dc5a79c1SDavid du Colombier }
209dc5a79c1SDavid du Colombier 
210dc5a79c1SDavid du Colombier int
211dc5a79c1SDavid du Colombier execforkexec(void)
212dc5a79c1SDavid du Colombier {
213dc5a79c1SDavid du Colombier 	int pid;
214dc5a79c1SDavid du Colombier 	int n;
215dc5a79c1SDavid du Colombier 	char buf[ERRMAX];
216dc5a79c1SDavid du Colombier 
217dc5a79c1SDavid du Colombier 	switch(pid = fork()){
218dc5a79c1SDavid du Colombier 	case -1:
219dc5a79c1SDavid du Colombier 		return -1;
220dc5a79c1SDavid du Colombier 	case 0:
221d3907fe5SDavid du Colombier 		clearwaitpids();
222dc5a79c1SDavid du Colombier 		pushword("exec");
223dc5a79c1SDavid du Colombier 		execexec();
224dc5a79c1SDavid du Colombier 		strcpy(buf, "can't exec: ");
225dc5a79c1SDavid du Colombier 		n = strlen(buf);
226dc5a79c1SDavid du Colombier 		errstr(buf+n, ERRMAX-n);
227dc5a79c1SDavid du Colombier 		Exit(buf);
228dc5a79c1SDavid du Colombier 	}
229d3907fe5SDavid du Colombier 	addwaitpid(pid);
230dc5a79c1SDavid du Colombier 	return pid;
231dc5a79c1SDavid du Colombier }
232