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 enum { Wordmax = 8192, }; 75 76 /* 77 * Who should wait for the exit from the fork? 78 */ 79 void 80 Xbackq(void) 81 { 82 int c, pid; 83 int pfd[2]; 84 char wd[Wordmax + 1]; 85 char *s, *ewd = &wd[Wordmax], *stop; 86 struct io *f; 87 var *ifs = vlook("ifs"); 88 word *v, *nextv; 89 90 stop = ifs->val? ifs->val->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 s = wd; 112 v = 0; 113 /* 114 * this isn't quite right for utf. stop could have utf 115 * in it, and we're processing the input as bytes, not 116 * utf encodings of runes. further, if we run out of 117 * room in wd, we can chop in the middle of a utf encoding 118 * (not to mention stepping on one of the bytes). 119 * presotto's Strings seem like the right data structure here. 120 */ 121 while((c = rchr(f))!=EOF){ 122 if(strchr(stop, c) || s==ewd){ 123 if(s!=wd){ 124 *s='\0'; 125 v = newword(wd, v); 126 s = wd; 127 } 128 } 129 else *s++=c; 130 } 131 if(s!=wd){ 132 *s='\0'; 133 v = newword(wd, v); 134 } 135 closeio(f); 136 Waitfor(pid, 0); 137 /* v points to reversed arglist -- reverse it onto argv */ 138 while(v){ 139 nextv = v->next; 140 v->next = runq->argv->words; 141 runq->argv->words = v; 142 v = nextv; 143 } 144 runq->pc = runq->code[runq->pc].i; 145 return; 146 } 147 } 148 149 void 150 Xpipefd(void) 151 { 152 struct thread *p = runq; 153 int pc = p->pc, pid; 154 char name[40]; 155 int pfd[2]; 156 int sidefd, mainfd; 157 if(pipe(pfd)<0){ 158 Xerror("can't get pipe"); 159 return; 160 } 161 if(p->code[pc].i==READ){ 162 sidefd = pfd[PWR]; 163 mainfd = pfd[PRD]; 164 } 165 else{ 166 sidefd = pfd[PRD]; 167 mainfd = pfd[PWR]; 168 } 169 switch(pid = fork()){ 170 case -1: 171 Xerror("try again"); 172 break; 173 case 0: 174 clearwaitpids(); 175 start(p->code, pc+2, runq->local); 176 close(mainfd); 177 pushredir(ROPEN, sidefd, p->code[pc].i==READ?1:0); 178 runq->ret = 0; 179 break; 180 default: 181 addwaitpid(pid); 182 close(sidefd); 183 pushredir(ROPEN, mainfd, mainfd); /* isn't this a noop? */ 184 strcpy(name, Fdprefix); 185 inttoascii(name+strlen(name), mainfd); 186 pushword(name); 187 p->pc = p->code[pc+1].i; 188 break; 189 } 190 } 191 192 void 193 Xsubshell(void) 194 { 195 int pid; 196 switch(pid = fork()){ 197 case -1: 198 Xerror("try again"); 199 break; 200 case 0: 201 clearwaitpids(); 202 start(runq->code, runq->pc+1, runq->local); 203 runq->ret = 0; 204 break; 205 default: 206 addwaitpid(pid); 207 Waitfor(pid, 1); 208 runq->pc = runq->code[runq->pc].i; 209 break; 210 } 211 } 212 213 int 214 execforkexec(void) 215 { 216 int pid; 217 int n; 218 char buf[ERRMAX]; 219 220 switch(pid = fork()){ 221 case -1: 222 return -1; 223 case 0: 224 clearwaitpids(); 225 pushword("exec"); 226 execexec(); 227 strcpy(buf, "can't exec: "); 228 n = strlen(buf); 229 errstr(buf+n, ERRMAX-n); 230 Exit(buf); 231 } 232 addwaitpid(pid); 233 return pid; 234 } 235