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