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