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