xref: /plan9/sys/src/cmd/rc/havefork.c (revision d3907fe5a68251e8b016f54f72acf8767ba044bb)
1dc5a79c1SDavid du Colombier #include "rc.h"
2dc5a79c1SDavid du Colombier #include "getflags.h"
3dc5a79c1SDavid du Colombier #include "exec.h"
4dc5a79c1SDavid du Colombier #include "io.h"
5dc5a79c1SDavid du Colombier #include "fns.h"
6dc5a79c1SDavid du Colombier 
7dc5a79c1SDavid du Colombier int havefork = 1;
8dc5a79c1SDavid du Colombier 
9dc5a79c1SDavid du Colombier void
10dc5a79c1SDavid du Colombier Xasync(void)
11dc5a79c1SDavid du Colombier {
12dc5a79c1SDavid du Colombier 	int null = open("/dev/null", 0);
13dc5a79c1SDavid du Colombier 	int pid;
14dc5a79c1SDavid du Colombier 	char npid[10];
15dc5a79c1SDavid du Colombier 	if(null<0){
16dc5a79c1SDavid du Colombier 		Xerror("Can't open /dev/null\n");
17dc5a79c1SDavid du Colombier 		return;
18dc5a79c1SDavid du Colombier 	}
1975ac14c9SDavid du Colombier 	switch(pid = rfork(RFFDG|RFPROC|RFNOTEG)){
20dc5a79c1SDavid du Colombier 	case -1:
21dc5a79c1SDavid du Colombier 		close(null);
22dc5a79c1SDavid du Colombier 		Xerror("try again");
23dc5a79c1SDavid du Colombier 		break;
24dc5a79c1SDavid du Colombier 	case 0:
25*d3907fe5SDavid du Colombier 		clearwaitpids();
26dc5a79c1SDavid du Colombier 		pushredir(ROPEN, null, 0);
27dc5a79c1SDavid du Colombier 		start(runq->code, runq->pc+1, runq->local);
28dc5a79c1SDavid du Colombier 		runq->ret = 0;
29dc5a79c1SDavid du Colombier 		break;
30dc5a79c1SDavid du Colombier 	default:
31*d3907fe5SDavid du Colombier 		addwaitpid(pid);
32dc5a79c1SDavid du Colombier 		close(null);
33dc5a79c1SDavid du Colombier 		runq->pc = runq->code[runq->pc].i;
34dc5a79c1SDavid du Colombier 		inttoascii(npid, pid);
35dc5a79c1SDavid du Colombier 		setvar("apid", newword(npid, (word *)0));
36dc5a79c1SDavid du Colombier 		break;
37dc5a79c1SDavid du Colombier 	}
38dc5a79c1SDavid du Colombier }
39dc5a79c1SDavid du Colombier 
40dc5a79c1SDavid du Colombier void
41dc5a79c1SDavid du Colombier Xpipe(void)
42dc5a79c1SDavid du Colombier {
43dc5a79c1SDavid du Colombier 	struct thread *p = runq;
44dc5a79c1SDavid du Colombier 	int pc = p->pc, forkid;
45dc5a79c1SDavid du Colombier 	int lfd = p->code[pc++].i;
46dc5a79c1SDavid du Colombier 	int rfd = p->code[pc++].i;
47dc5a79c1SDavid du Colombier 	int pfd[2];
48dc5a79c1SDavid du Colombier 	if(pipe(pfd)<0){
49dc5a79c1SDavid du Colombier 		Xerror("can't get pipe");
50dc5a79c1SDavid du Colombier 		return;
51dc5a79c1SDavid du Colombier 	}
52dc5a79c1SDavid du Colombier 	switch(forkid = fork()){
53dc5a79c1SDavid du Colombier 	case -1:
54dc5a79c1SDavid du Colombier 		Xerror("try again");
55dc5a79c1SDavid du Colombier 		break;
56dc5a79c1SDavid du Colombier 	case 0:
57*d3907fe5SDavid du Colombier 		clearwaitpids();
58dc5a79c1SDavid du Colombier 		start(p->code, pc+2, runq->local);
59dc5a79c1SDavid du Colombier 		runq->ret = 0;
60dc5a79c1SDavid du Colombier 		close(pfd[PRD]);
61dc5a79c1SDavid du Colombier 		pushredir(ROPEN, pfd[PWR], lfd);
62dc5a79c1SDavid du Colombier 		break;
63dc5a79c1SDavid du Colombier 	default:
64*d3907fe5SDavid du Colombier 		addwaitpid(forkid);
65dc5a79c1SDavid du Colombier 		start(p->code, p->code[pc].i, runq->local);
66dc5a79c1SDavid du Colombier 		close(pfd[PWR]);
67dc5a79c1SDavid du Colombier 		pushredir(ROPEN, pfd[PRD], rfd);
68dc5a79c1SDavid du Colombier 		p->pc = p->code[pc+1].i;
69dc5a79c1SDavid du Colombier 		p->pid = forkid;
70dc5a79c1SDavid du Colombier 		break;
71dc5a79c1SDavid du Colombier 	}
72dc5a79c1SDavid du Colombier }
73dc5a79c1SDavid du Colombier 
74dc5a79c1SDavid du Colombier /*
75dc5a79c1SDavid du Colombier  * Who should wait for the exit from the fork?
76dc5a79c1SDavid du Colombier  */
77dc5a79c1SDavid du Colombier void
78dc5a79c1SDavid du Colombier Xbackq(void)
79dc5a79c1SDavid du Colombier {
80dc5a79c1SDavid du Colombier 	char wd[8193];
81dc5a79c1SDavid du Colombier 	int c;
82dc5a79c1SDavid du Colombier 	char *s, *ewd=&wd[8192], *stop;
83dc5a79c1SDavid du Colombier 	struct io *f;
84dc5a79c1SDavid du Colombier 	var *ifs = vlook("ifs");
85dc5a79c1SDavid du Colombier 	word *v, *nextv;
86dc5a79c1SDavid du Colombier 	int pfd[2];
87dc5a79c1SDavid du Colombier 	int pid;
88dc5a79c1SDavid du Colombier 	stop = ifs->val?ifs->val->word:"";
89dc5a79c1SDavid du Colombier 	if(pipe(pfd)<0){
90dc5a79c1SDavid du Colombier 		Xerror("can't make pipe");
91dc5a79c1SDavid du Colombier 		return;
92dc5a79c1SDavid du Colombier 	}
93dc5a79c1SDavid du Colombier 	switch(pid = fork()){
94dc5a79c1SDavid du Colombier 	case -1:
95dc5a79c1SDavid du Colombier 		Xerror("try again");
96dc5a79c1SDavid du Colombier 		close(pfd[PRD]);
97dc5a79c1SDavid du Colombier 		close(pfd[PWR]);
98dc5a79c1SDavid du Colombier 		return;
99dc5a79c1SDavid du Colombier 	case 0:
100*d3907fe5SDavid du Colombier 		clearwaitpids();
101dc5a79c1SDavid du Colombier 		close(pfd[PRD]);
102dc5a79c1SDavid du Colombier 		start(runq->code, runq->pc+1, runq->local);
103dc5a79c1SDavid du Colombier 		pushredir(ROPEN, pfd[PWR], 1);
104dc5a79c1SDavid du Colombier 		return;
105dc5a79c1SDavid du Colombier 	default:
106*d3907fe5SDavid du Colombier 		addwaitpid(pid);
107dc5a79c1SDavid du Colombier 		close(pfd[PWR]);
108dc5a79c1SDavid du Colombier 		f = openfd(pfd[PRD]);
109dc5a79c1SDavid du Colombier 		s = wd;
110dc5a79c1SDavid du Colombier 		v = 0;
111dc5a79c1SDavid du Colombier 		while((c = rchr(f))!=EOF){
112dc5a79c1SDavid du Colombier 			if(strchr(stop, c) || s==ewd){
113dc5a79c1SDavid du Colombier 				if(s!=wd){
114dc5a79c1SDavid du Colombier 					*s='\0';
115dc5a79c1SDavid du Colombier 					v = newword(wd, v);
116dc5a79c1SDavid du Colombier 					s = wd;
117dc5a79c1SDavid du Colombier 				}
118dc5a79c1SDavid du Colombier 			}
119dc5a79c1SDavid du Colombier 			else *s++=c;
120dc5a79c1SDavid du Colombier 		}
121dc5a79c1SDavid du Colombier 		if(s!=wd){
122dc5a79c1SDavid du Colombier 			*s='\0';
123dc5a79c1SDavid du Colombier 			v = newword(wd, v);
124dc5a79c1SDavid du Colombier 		}
125dc5a79c1SDavid du Colombier 		closeio(f);
126dc5a79c1SDavid du Colombier 		Waitfor(pid, 0);
127dc5a79c1SDavid du Colombier 		/* v points to reversed arglist -- reverse it onto argv */
128dc5a79c1SDavid du Colombier 		while(v){
129dc5a79c1SDavid du Colombier 			nextv = v->next;
130dc5a79c1SDavid du Colombier 			v->next = runq->argv->words;
131dc5a79c1SDavid du Colombier 			runq->argv->words = v;
132dc5a79c1SDavid du Colombier 			v = nextv;
133dc5a79c1SDavid du Colombier 		}
134dc5a79c1SDavid du Colombier 		runq->pc = runq->code[runq->pc].i;
135dc5a79c1SDavid du Colombier 		return;
136dc5a79c1SDavid du Colombier 	}
137dc5a79c1SDavid du Colombier }
138dc5a79c1SDavid du Colombier 
139dc5a79c1SDavid du Colombier void
140dc5a79c1SDavid du Colombier Xpipefd(void)
141dc5a79c1SDavid du Colombier {
142dc5a79c1SDavid du Colombier 	struct thread *p = runq;
143*d3907fe5SDavid du Colombier 	int pc = p->pc, pid;
144dc5a79c1SDavid du Colombier 	char name[40];
145dc5a79c1SDavid du Colombier 	int pfd[2];
146dc5a79c1SDavid du Colombier 	int sidefd, mainfd;
147dc5a79c1SDavid du Colombier 	if(pipe(pfd)<0){
148dc5a79c1SDavid du Colombier 		Xerror("can't get pipe");
149dc5a79c1SDavid du Colombier 		return;
150dc5a79c1SDavid du Colombier 	}
151dc5a79c1SDavid du Colombier 	if(p->code[pc].i==READ){
152dc5a79c1SDavid du Colombier 		sidefd = pfd[PWR];
153dc5a79c1SDavid du Colombier 		mainfd = pfd[PRD];
154dc5a79c1SDavid du Colombier 	}
155dc5a79c1SDavid du Colombier 	else{
156dc5a79c1SDavid du Colombier 		sidefd = pfd[PRD];
157dc5a79c1SDavid du Colombier 		mainfd = pfd[PWR];
158dc5a79c1SDavid du Colombier 	}
159*d3907fe5SDavid du Colombier 	switch(pid = fork()){
160dc5a79c1SDavid du Colombier 	case -1:
161dc5a79c1SDavid du Colombier 		Xerror("try again");
162dc5a79c1SDavid du Colombier 		break;
163dc5a79c1SDavid du Colombier 	case 0:
164*d3907fe5SDavid du Colombier 		clearwaitpids();
165dc5a79c1SDavid du Colombier 		start(p->code, pc+2, runq->local);
166dc5a79c1SDavid du Colombier 		close(mainfd);
167dc5a79c1SDavid du Colombier 		pushredir(ROPEN, sidefd, p->code[pc].i==READ?1:0);
168dc5a79c1SDavid du Colombier 		runq->ret = 0;
169dc5a79c1SDavid du Colombier 		break;
170dc5a79c1SDavid du Colombier 	default:
171*d3907fe5SDavid du Colombier 		addwaitpid(pid);
172dc5a79c1SDavid du Colombier 		close(sidefd);
173dc5a79c1SDavid du Colombier 		pushredir(ROPEN, mainfd, mainfd);	/* isn't this a noop? */
174dc5a79c1SDavid du Colombier 		strcpy(name, Fdprefix);
175dc5a79c1SDavid du Colombier 		inttoascii(name+strlen(name), mainfd);
176dc5a79c1SDavid du Colombier 		pushword(name);
177dc5a79c1SDavid du Colombier 		p->pc = p->code[pc+1].i;
178dc5a79c1SDavid du Colombier 		break;
179dc5a79c1SDavid du Colombier 	}
180dc5a79c1SDavid du Colombier }
181dc5a79c1SDavid du Colombier 
182dc5a79c1SDavid du Colombier void
183dc5a79c1SDavid du Colombier Xsubshell(void)
184dc5a79c1SDavid du Colombier {
185dc5a79c1SDavid du Colombier 	int pid;
186dc5a79c1SDavid du Colombier 	switch(pid = fork()){
187dc5a79c1SDavid du Colombier 	case -1:
188dc5a79c1SDavid du Colombier 		Xerror("try again");
189dc5a79c1SDavid du Colombier 		break;
190dc5a79c1SDavid du Colombier 	case 0:
191*d3907fe5SDavid du Colombier 		clearwaitpids();
192dc5a79c1SDavid du Colombier 		start(runq->code, runq->pc+1, runq->local);
193dc5a79c1SDavid du Colombier 		runq->ret = 0;
194dc5a79c1SDavid du Colombier 		break;
195dc5a79c1SDavid du Colombier 	default:
196*d3907fe5SDavid du Colombier 		addwaitpid(pid);
197dc5a79c1SDavid du Colombier 		Waitfor(pid, 1);
198dc5a79c1SDavid du Colombier 		runq->pc = runq->code[runq->pc].i;
199dc5a79c1SDavid du Colombier 		break;
200dc5a79c1SDavid du Colombier 	}
201dc5a79c1SDavid du Colombier }
202dc5a79c1SDavid du Colombier 
203dc5a79c1SDavid du Colombier int
204dc5a79c1SDavid du Colombier execforkexec(void)
205dc5a79c1SDavid du Colombier {
206dc5a79c1SDavid du Colombier 	int pid;
207dc5a79c1SDavid du Colombier 	int n;
208dc5a79c1SDavid du Colombier 	char buf[ERRMAX];
209dc5a79c1SDavid du Colombier 
210dc5a79c1SDavid du Colombier 	switch(pid = fork()){
211dc5a79c1SDavid du Colombier 	case -1:
212dc5a79c1SDavid du Colombier 		return -1;
213dc5a79c1SDavid du Colombier 	case 0:
214*d3907fe5SDavid du Colombier 		clearwaitpids();
215dc5a79c1SDavid du Colombier 		pushword("exec");
216dc5a79c1SDavid du Colombier 		execexec();
217dc5a79c1SDavid du Colombier 		strcpy(buf, "can't exec: ");
218dc5a79c1SDavid du Colombier 		n = strlen(buf);
219dc5a79c1SDavid du Colombier 		errstr(buf+n, ERRMAX-n);
220dc5a79c1SDavid du Colombier 		Exit(buf);
221dc5a79c1SDavid du Colombier 	}
222*d3907fe5SDavid du Colombier 	addwaitpid(pid);
223dc5a79c1SDavid du Colombier 	return pid;
224dc5a79c1SDavid du Colombier }
225