1 #include "rc.h" 2 #include "getflags.h" 3 #include "exec.h" 4 #include "io.h" 5 #include "fns.h" 6 #include <String.h> 7 8 int havefork = 1; 9 10 void 11 Xasync(void) 12 { 13 int null = open("/dev/null", 0); 14 int pid; 15 char npid[10]; 16 if(null<0){ 17 Xerror("Can't open /dev/null\n"); 18 return; 19 } 20 switch(pid = rfork(RFFDG|RFPROC|RFNOTEG)){ 21 case -1: 22 close(null); 23 Xerror("try again"); 24 break; 25 case 0: 26 clearwaitpids(); 27 pushredir(ROPEN, null, 0); 28 start(runq->code, runq->pc+1, runq->local); 29 runq->ret = 0; 30 break; 31 default: 32 addwaitpid(pid); 33 close(null); 34 runq->pc = runq->code[runq->pc].i; 35 inttoascii(npid, pid); 36 setvar("apid", newword(npid, (word *)0)); 37 break; 38 } 39 } 40 41 void 42 Xpipe(void) 43 { 44 struct thread *p = runq; 45 int pc = p->pc, forkid; 46 int lfd = p->code[pc++].i; 47 int rfd = p->code[pc++].i; 48 int pfd[2]; 49 if(pipe(pfd)<0){ 50 Xerror("can't get pipe"); 51 return; 52 } 53 switch(forkid = fork()){ 54 case -1: 55 Xerror("try again"); 56 break; 57 case 0: 58 clearwaitpids(); 59 start(p->code, pc+2, runq->local); 60 runq->ret = 0; 61 close(pfd[PRD]); 62 pushredir(ROPEN, pfd[PWR], lfd); 63 break; 64 default: 65 addwaitpid(forkid); 66 start(p->code, p->code[pc].i, runq->local); 67 close(pfd[PWR]); 68 pushredir(ROPEN, pfd[PRD], rfd); 69 p->pc = p->code[pc+1].i; 70 p->pid = forkid; 71 break; 72 } 73 } 74 75 /* 76 * Who should wait for the exit from the fork? 77 */ 78 79 void 80 Xbackq(void) 81 { 82 int n, pid; 83 int pfd[2]; 84 char *stop; 85 char utf[UTFmax+1]; 86 struct io *f; 87 var *ifs = vlook("ifs"); 88 word *v, *nextv; 89 Rune r; 90 String *word; 91 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 word = s_new(); 114 v = nil; 115 /* rutf requires at least UTFmax+1 bytes in utf */ 116 while((n = rutf(f, utf, &r)) != EOF){ 117 utf[n] = '\0'; 118 if(utfutf(stop, utf) == nil) 119 s_nappend(word, utf, n); 120 else 121 /* 122 * utf/r is an ifs rune (e.g., \t, \n), thus 123 * ends the current word, if any. 124 */ 125 if(s_len(word) > 0){ 126 v = newword(s_to_c(word), v); 127 s_reset(word); 128 } 129 } 130 if(s_len(word) > 0) 131 v = newword(s_to_c(word), v); 132 s_free(word); 133 closeio(f); 134 Waitfor(pid, 0); 135 /* v points to reversed arglist -- reverse it onto argv */ 136 while(v){ 137 nextv = v->next; 138 v->next = runq->argv->words; 139 runq->argv->words = v; 140 v = nextv; 141 } 142 runq->pc = runq->code[runq->pc].i; 143 return; 144 } 145 } 146 147 void 148 Xpipefd(void) 149 { 150 struct thread *p = runq; 151 int pc = p->pc, pid; 152 char name[40]; 153 int pfd[2]; 154 int sidefd, mainfd; 155 if(pipe(pfd)<0){ 156 Xerror("can't get pipe"); 157 return; 158 } 159 if(p->code[pc].i==READ){ 160 sidefd = pfd[PWR]; 161 mainfd = pfd[PRD]; 162 } 163 else{ 164 sidefd = pfd[PRD]; 165 mainfd = pfd[PWR]; 166 } 167 switch(pid = fork()){ 168 case -1: 169 Xerror("try again"); 170 break; 171 case 0: 172 clearwaitpids(); 173 start(p->code, pc+2, runq->local); 174 close(mainfd); 175 pushredir(ROPEN, sidefd, p->code[pc].i==READ?1:0); 176 runq->ret = 0; 177 break; 178 default: 179 addwaitpid(pid); 180 close(sidefd); 181 pushredir(ROPEN, mainfd, mainfd); /* isn't this a noop? */ 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