havefork.c - 9base - revived minimalist port of Plan 9 userland to Unix
(HTM) git clone git://git.suckless.org/9base
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
havefork.c (4415B)
---
1 #include <u.h>
2 #include <signal.h>
3 #include "rc.h"
4 #include "getflags.h"
5 #include "exec.h"
6 #include "io.h"
7 #include "fns.h"
8
9 int havefork = 1;
10
11 void
12 Xasync(void)
13 {
14 int null = open("/dev/null", 0);
15 int pid;
16 char npid[10];
17 if(null<0){
18 Xerror("Can't open /dev/null\n");
19 return;
20 }
21 switch(pid = rfork(RFFDG|RFPROC|RFNOTEG)){
22 case -1:
23 close(null);
24 Xerror("try again");
25 break;
26 case 0:
27 clearwaitpids();
28 pushredir(ROPEN, null, 0);
29 start(runq->code, runq->pc+1, runq->local);
30 runq->ret = 0;
31 break;
32 default:
33 addwaitpid(pid);
34 close(null);
35 runq->pc = runq->code[runq->pc].i;
36 inttoascii(npid, pid);
37 setvar("apid", newword(npid, (word *)0));
38 break;
39 }
40 }
41
42 void
43 Xpipe(void)
44 {
45 struct thread *p = runq;
46 int pc = p->pc, forkid;
47 int lfd = p->code[pc++].i;
48 int rfd = p->code[pc++].i;
49 int pfd[2];
50 if(pipe(pfd)<0){
51 Xerror("can't get pipe");
52 return;
53 }
54 switch(forkid = fork()){
55 case -1:
56 Xerror("try again");
57 break;
58 case 0:
59 clearwaitpids();
60 start(p->code, pc+2, runq->local);
61 runq->ret = 0;
62 close(pfd[PRD]);
63 pushredir(ROPEN, pfd[PWR], lfd);
64 break;
65 default:
66 addwaitpid(forkid);
67 start(p->code, p->code[pc].i, runq->local);
68 close(pfd[PWR]);
69 pushredir(ROPEN, pfd[PRD], rfd);
70 p->pc = p->code[pc+1].i;
71 p->pid = forkid;
72 break;
73 }
74 }
75
76 /*
77 * Who should wait for the exit from the fork?
78 */
79 void
80 Xbackq(void)
81 {
82 struct thread *p = runq;
83 char wd[8193];
84 int c, n;
85 char *s, *ewd=&wd[8192], *stop, *q;
86 struct io *f;
87 var *ifs = vlook("ifs");
88 word *v, *nextv;
89 int pfd[2];
90 int pid;
91 Rune r;
92 stop = ifs->val?ifs->val->word:"";
93 if(pipe(pfd)<0){
94 Xerror("can't make pipe");
95 return;
96 }
97 switch(pid = fork()){
98 case -1:
99 Xerror("try again");
100 close(pfd[PRD]);
101 close(pfd[PWR]);
102 return;
103 case 0:
104 clearwaitpids();
105 close(pfd[PRD]);
106 start(runq->code, runq->pc+1, runq->local);
107 pushredir(ROPEN, pfd[PWR], 1);
108 return;
109 default:
110 addwaitpid(pid);
111 close(pfd[PWR]);
112 f = openfd(pfd[PRD]);
113 s = wd;
114 v = 0;
115 while((c = rchr(f))!=EOF){
116 if(s != ewd) {
117 *s++ = c;
118 for(q=stop; *q; q+=n) {
119 n = chartorune(&r, q);
120 if(s-wd >= n && memcmp(s-n, q, n) == 0) {
121 s -= n;
122 goto stop;
123 }
124 }
125 continue;
126 }
127 stop:
128 if(s != wd) {
129 *s = '\0';
130 v = newword(wd, v);
131 }
132 s = wd;
133 }
134 if(s!=wd){
135 *s='\0';
136 v = newword(wd, v);
137 }
138 closeio(f);
139 Waitfor(pid, 0);
140 /* v points to reversed arglist -- reverse it onto argv */
141 while(v){
142 nextv = v->next;
143 v->next = runq->argv->words;
144 runq->argv->words = v;
145 v = nextv;
146 }
147 p->pc = p->code[p->pc].i;
148 return;
149 }
150 }
151
152 void
153 Xpipefd(void)
154 {
155 struct thread *p = runq;
156 int pc = p->pc, pid;
157 char name[40];
158 int pfd[2];
159 struct { int sidefd, mainfd; } fd[2], *r, *w;
160
161 r = &fd[0];
162 w = &fd[1];
163 switch(p->code[pc].i){
164 case READ:
165 w = nil;
166 break;
167 case WRITE:
168 r = nil;
169 }
170
171 if(r){
172 if(pipe(pfd)<0){
173 Xerror("can't get pipe");
174 return;
175 }
176 r->sidefd = pfd[PWR];
177 r->mainfd = pfd[PRD];
178 }
179 if(w){
180 if(pipe(pfd)<0){
181 Xerror("can't get pipe");
182 return;
183 }
184 w->sidefd = pfd[PRD];
185 w->mainfd = pfd[PWR];
186 }
187 switch(pid = fork()){
188 case -1:
189 Xerror("try again");
190 break;
191 case 0:
192 clearwaitpids();
193 start(p->code, pc+2, runq->local);
194 if(r){
195 close(r->mainfd);
196 pushredir(ROPEN, r->sidefd, 1);
197 }
198 if(w){
199 close(w->mainfd);
200 pushredir(ROPEN, w->sidefd, 0);
201 }
202 runq->ret = 0;
203 break;
204 default:
205 addwaitpid(pid);
206 if(w){
207 close(w->sidefd);
208 pushredir(ROPEN, w->mainfd, w->mainfd); /* so that Xpopredir can close it later */
209 strcpy(name, Fdprefix);
210 inttoascii(name+strlen(name), w->mainfd);
211 pushword(name);
212 }
213 if(r){
214 close(r->sidefd);
215 pushredir(ROPEN, r->mainfd, r->mainfd);
216 strcpy(name, Fdprefix);
217 inttoascii(name+strlen(name), r->mainfd);
218 pushword(name);
219 }
220 p->pc = p->code[pc+1].i;
221 break;
222 }
223 }
224
225 void
226 Xsubshell(void)
227 {
228 int pid;
229 switch(pid = fork()){
230 case -1:
231 Xerror("try again");
232 break;
233 case 0:
234 clearwaitpids();
235 start(runq->code, runq->pc+1, runq->local);
236 runq->ret = 0;
237 break;
238 default:
239 addwaitpid(pid);
240 Waitfor(pid, 1);
241 runq->pc = runq->code[runq->pc].i;
242 break;
243 }
244 }
245
246 int
247 execforkexec(void)
248 {
249 int pid;
250 int n;
251 char buf[ERRMAX];
252
253 switch(pid = fork()){
254 case -1:
255 return -1;
256 case 0:
257 clearwaitpids();
258 pushword("exec");
259 execexec();
260 strcpy(buf, "can't exec: ");
261 n = strlen(buf);
262 errstr(buf+n, ERRMAX-n);
263 Exit(buf);
264 }
265 addwaitpid(pid);
266 return pid;
267 }