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 }