xref: /plan9-contrib/sys/src/cmd/rc/havefork.c (revision fbd2c77cf86542e8f8bf27bfe7d1dfc5f8f29c74)
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:
25d3907fe5SDavid 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:
31d3907fe5SDavid 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:
57d3907fe5SDavid 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:
64d3907fe5SDavid 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 
74276e7d6dSDavid du Colombier enum { Wordmax = 8192, };
75276e7d6dSDavid du Colombier 
76dc5a79c1SDavid du Colombier /*
77dc5a79c1SDavid du Colombier  * Who should wait for the exit from the fork?
78dc5a79c1SDavid du Colombier  */
79dc5a79c1SDavid du Colombier void
80dc5a79c1SDavid du Colombier Xbackq(void)
81dc5a79c1SDavid du Colombier {
82276e7d6dSDavid du Colombier 	int c, pid;
83276e7d6dSDavid du Colombier 	int pfd[2];
84276e7d6dSDavid du Colombier 	char wd[Wordmax + 1];
85276e7d6dSDavid du Colombier 	char *s, *ewd = &wd[Wordmax], *stop;
86dc5a79c1SDavid du Colombier 	struct io *f;
87dc5a79c1SDavid du Colombier 	var *ifs = vlook("ifs");
88dc5a79c1SDavid du Colombier 	word *v, *nextv;
89276e7d6dSDavid du Colombier 
90dc5a79c1SDavid du Colombier 	stop = ifs->val? ifs->val->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]);
111dc5a79c1SDavid du Colombier 		s = wd;
112dc5a79c1SDavid du Colombier 		v = 0;
113*fbd2c77cSDavid du Colombier 		/*
114*fbd2c77cSDavid du Colombier 		 * this isn't quite right for utf.  stop could have utf
115*fbd2c77cSDavid du Colombier 		 * in it, and we're processing the input as bytes, not
116*fbd2c77cSDavid du Colombier 		 * utf encodings of runes.  further, if we run out of
117*fbd2c77cSDavid du Colombier 		 * room in wd, we can chop in the middle of a utf encoding
118*fbd2c77cSDavid du Colombier 		 * (not to mention stepping on one of the bytes).
119*fbd2c77cSDavid du Colombier 		 * presotto's Strings seem like the right data structure here.
120*fbd2c77cSDavid du Colombier 		 */
121dc5a79c1SDavid du Colombier 		while((c = rchr(f))!=EOF){
122dc5a79c1SDavid du Colombier 			if(strchr(stop, c) || s==ewd){
123dc5a79c1SDavid du Colombier 				if(s!=wd){
124dc5a79c1SDavid du Colombier 					*s='\0';
125dc5a79c1SDavid du Colombier 					v = newword(wd, v);
126dc5a79c1SDavid du Colombier 					s = wd;
127dc5a79c1SDavid du Colombier 				}
128dc5a79c1SDavid du Colombier 			}
12999eb86a7SDavid du Colombier 			else *s++=c;
130dc5a79c1SDavid du Colombier 		}
131dc5a79c1SDavid du Colombier 		if(s!=wd){
132dc5a79c1SDavid du Colombier 			*s='\0';
133dc5a79c1SDavid du Colombier 			v = newword(wd, v);
134dc5a79c1SDavid du Colombier 		}
135dc5a79c1SDavid du Colombier 		closeio(f);
136dc5a79c1SDavid du Colombier 		Waitfor(pid, 0);
137dc5a79c1SDavid du Colombier 		/* v points to reversed arglist -- reverse it onto argv */
138dc5a79c1SDavid du Colombier 		while(v){
139dc5a79c1SDavid du Colombier 			nextv = v->next;
140dc5a79c1SDavid du Colombier 			v->next = runq->argv->words;
141dc5a79c1SDavid du Colombier 			runq->argv->words = v;
142dc5a79c1SDavid du Colombier 			v = nextv;
143dc5a79c1SDavid du Colombier 		}
144dc5a79c1SDavid du Colombier 		runq->pc = runq->code[runq->pc].i;
145dc5a79c1SDavid du Colombier 		return;
146dc5a79c1SDavid du Colombier 	}
147dc5a79c1SDavid du Colombier }
148dc5a79c1SDavid du Colombier 
149dc5a79c1SDavid du Colombier void
150dc5a79c1SDavid du Colombier Xpipefd(void)
151dc5a79c1SDavid du Colombier {
152dc5a79c1SDavid du Colombier 	struct thread *p = runq;
15399eb86a7SDavid du Colombier 	int pc = p->pc, pid;
154276e7d6dSDavid du Colombier 	char name[40];
15599eb86a7SDavid du Colombier 	int pfd[2];
15699eb86a7SDavid du Colombier 	int sidefd, mainfd;
157dc5a79c1SDavid du Colombier 	if(pipe(pfd)<0){
158dc5a79c1SDavid du Colombier 		Xerror("can't get pipe");
159dc5a79c1SDavid du Colombier 		return;
160dc5a79c1SDavid du Colombier 	}
161dc5a79c1SDavid du Colombier 	if(p->code[pc].i==READ){
162dc5a79c1SDavid du Colombier 		sidefd = pfd[PWR];
163dc5a79c1SDavid du Colombier 		mainfd = pfd[PRD];
164dc5a79c1SDavid du Colombier 	}
165dc5a79c1SDavid du Colombier 	else{
166dc5a79c1SDavid du Colombier 		sidefd = pfd[PRD];
167dc5a79c1SDavid du Colombier 		mainfd = pfd[PWR];
168dc5a79c1SDavid du Colombier 	}
169d3907fe5SDavid du Colombier 	switch(pid = fork()){
170dc5a79c1SDavid du Colombier 	case -1:
171dc5a79c1SDavid du Colombier 		Xerror("try again");
172dc5a79c1SDavid du Colombier 		break;
173dc5a79c1SDavid du Colombier 	case 0:
174d3907fe5SDavid du Colombier 		clearwaitpids();
175dc5a79c1SDavid du Colombier 		start(p->code, pc+2, runq->local);
176dc5a79c1SDavid du Colombier 		close(mainfd);
177dc5a79c1SDavid du Colombier 		pushredir(ROPEN, sidefd, p->code[pc].i==READ?1:0);
178dc5a79c1SDavid du Colombier 		runq->ret = 0;
179dc5a79c1SDavid du Colombier 		break;
180dc5a79c1SDavid du Colombier 	default:
181d3907fe5SDavid du Colombier 		addwaitpid(pid);
182dc5a79c1SDavid du Colombier 		close(sidefd);
183dc5a79c1SDavid du Colombier 		pushredir(ROPEN, mainfd, mainfd);	/* isn't this a noop? */
184dc5a79c1SDavid du Colombier 		strcpy(name, Fdprefix);
185dc5a79c1SDavid du Colombier 		inttoascii(name+strlen(name), mainfd);
186dc5a79c1SDavid du Colombier 		pushword(name);
187dc5a79c1SDavid du Colombier 		p->pc = p->code[pc+1].i;
188dc5a79c1SDavid du Colombier 		break;
189dc5a79c1SDavid du Colombier 	}
190dc5a79c1SDavid du Colombier }
191dc5a79c1SDavid du Colombier 
192dc5a79c1SDavid du Colombier void
193dc5a79c1SDavid du Colombier Xsubshell(void)
194dc5a79c1SDavid du Colombier {
195dc5a79c1SDavid du Colombier 	int pid;
196dc5a79c1SDavid du Colombier 	switch(pid = fork()){
197dc5a79c1SDavid du Colombier 	case -1:
198dc5a79c1SDavid du Colombier 		Xerror("try again");
199dc5a79c1SDavid du Colombier 		break;
200dc5a79c1SDavid du Colombier 	case 0:
201d3907fe5SDavid du Colombier 		clearwaitpids();
202dc5a79c1SDavid du Colombier 		start(runq->code, runq->pc+1, runq->local);
203dc5a79c1SDavid du Colombier 		runq->ret = 0;
204dc5a79c1SDavid du Colombier 		break;
205dc5a79c1SDavid du Colombier 	default:
206d3907fe5SDavid du Colombier 		addwaitpid(pid);
207dc5a79c1SDavid du Colombier 		Waitfor(pid, 1);
208dc5a79c1SDavid du Colombier 		runq->pc = runq->code[runq->pc].i;
209dc5a79c1SDavid du Colombier 		break;
210dc5a79c1SDavid du Colombier 	}
211dc5a79c1SDavid du Colombier }
212dc5a79c1SDavid du Colombier 
213dc5a79c1SDavid du Colombier int
214dc5a79c1SDavid du Colombier execforkexec(void)
215dc5a79c1SDavid du Colombier {
216dc5a79c1SDavid du Colombier 	int pid;
217dc5a79c1SDavid du Colombier 	int n;
218dc5a79c1SDavid du Colombier 	char buf[ERRMAX];
219dc5a79c1SDavid du Colombier 
220dc5a79c1SDavid du Colombier 	switch(pid = fork()){
221dc5a79c1SDavid du Colombier 	case -1:
222dc5a79c1SDavid du Colombier 		return -1;
223dc5a79c1SDavid du Colombier 	case 0:
224d3907fe5SDavid du Colombier 		clearwaitpids();
225dc5a79c1SDavid du Colombier 		pushword("exec");
226dc5a79c1SDavid du Colombier 		execexec();
227dc5a79c1SDavid du Colombier 		strcpy(buf, "can't exec: ");
228dc5a79c1SDavid du Colombier 		n = strlen(buf);
229dc5a79c1SDavid du Colombier 		errstr(buf+n, ERRMAX-n);
230dc5a79c1SDavid du Colombier 		Exit(buf);
231dc5a79c1SDavid du Colombier 	}
232d3907fe5SDavid du Colombier 	addwaitpid(pid);
233dc5a79c1SDavid du Colombier 	return pid;
234dc5a79c1SDavid du Colombier }
235