Blob
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"9 int havefork = 1;11 void12 Xasync(void)13 {14 int null = open("/dev/null", 0);15 int pid;16 int tcpgrp, pgrp;17 char npid[10];19 if(null<0){20 Xerror("Can't open /dev/null\n");21 return;22 }23 switch(pid = rfork(RFFDG|RFPROC|RFNOTEG)){24 case -1:25 close(null);26 Xerror("try again");27 break;28 case 0:29 /*30 * Should make reads of tty fail, writes succeed.31 */32 signal(SIGTTIN, SIG_IGN);33 signal(SIGTTOU, SIG_IGN);35 pushredir(ROPEN, null, 0);36 start(runq->code, runq->pc+1, runq->local);37 runq->ret = 0;38 break;39 default:40 close(null);41 runq->pc = runq->code[runq->pc].i;42 inttoascii(npid, pid);43 setvar("apid", newword(npid, (word *)0));44 break;45 }46 }48 void49 Xpipe(void)50 {51 struct thread *p = runq;52 int pc = p->pc, forkid;53 int lfd = p->code[pc++].i;54 int rfd = p->code[pc++].i;55 int pfd[2];56 if(pipe(pfd)<0){57 Xerror("can't get pipe");58 return;59 }60 switch(forkid = fork()){61 case -1:62 Xerror("try again");63 break;64 case 0:65 start(p->code, pc+2, runq->local);66 runq->ret = 0;67 close(pfd[PRD]);68 pushredir(ROPEN, pfd[PWR], lfd);69 break;70 default:71 start(p->code, p->code[pc].i, runq->local);72 close(pfd[PWR]);73 pushredir(ROPEN, pfd[PRD], rfd);74 p->pc = p->code[pc+1].i;75 p->pid = forkid;76 break;77 }78 }80 /*81 * Who should wait for the exit from the fork?82 */83 void84 Xbackq(void)85 {86 char wd[8193];87 int c;88 char *s, *ewd=&wd[8192], *stop;89 struct io *f;90 var *ifs = vlook("ifs");91 word *v, *nextv;92 int pfd[2];93 int pid;94 stop = ifs->val?ifs->val->word:"";95 if(pipe(pfd)<0){96 Xerror("can't make pipe");97 return;98 }99 switch(pid = fork()){100 case -1:101 Xerror("try again");102 close(pfd[PRD]);103 close(pfd[PWR]);104 return;105 case 0:106 close(pfd[PRD]);107 start(runq->code, runq->pc+1, runq->local);108 pushredir(ROPEN, pfd[PWR], 1);109 return;110 default:111 close(pfd[PWR]);112 f = openfd(pfd[PRD]);113 s = wd;114 v = 0;115 while((c = rchr(f))!=EOF){116 if(strchr(stop, c) || s==ewd){117 if(s!=wd){118 *s='\0';119 v = newword(wd, v);120 s = wd;121 }122 }123 else *s++=c;124 }125 if(s!=wd){126 *s='\0';127 v = newword(wd, v);128 }129 closeio(f);130 Waitfor(pid, 0);131 /* v points to reversed arglist -- reverse it onto argv */132 while(v){133 nextv = v->next;134 v->next = runq->argv->words;135 runq->argv->words = v;136 v = nextv;137 }138 runq->pc = runq->code[runq->pc].i;139 return;140 }141 }143 void144 Xpipefd(void)145 {146 struct thread *p = runq;147 int pc = p->pc;148 char name[40];149 int pfd[2];150 int sidefd, mainfd;151 if(pipe(pfd)<0){152 Xerror("can't get pipe");153 return;154 }155 if(p->code[pc].i==READ){156 sidefd = pfd[PWR];157 mainfd = pfd[PRD];158 }159 else{160 sidefd = pfd[PRD];161 mainfd = pfd[PWR];162 }163 switch(fork()){164 case -1:165 Xerror("try again");166 break;167 case 0:168 start(p->code, pc+2, runq->local);169 close(mainfd);170 pushredir(ROPEN, sidefd, p->code[pc].i==READ?1:0);171 runq->ret = 0;172 break;173 default:174 close(sidefd);175 pushredir(ROPEN, mainfd, mainfd); /* isn't this a noop? */176 strcpy(name, Fdprefix);177 inttoascii(name+strlen(name), mainfd);178 pushword(name);179 p->pc = p->code[pc+1].i;180 break;181 }182 }184 void185 Xsubshell(void)186 {187 int pid;188 switch(pid = fork()){189 case -1:190 Xerror("try again");191 break;192 case 0:193 start(runq->code, runq->pc+1, runq->local);194 runq->ret = 0;195 break;196 default:197 Waitfor(pid, 1);198 runq->pc = runq->code[runq->pc].i;199 break;200 }201 }203 int204 execforkexec(void)205 {206 int pid;207 int n;208 char buf[ERRMAX];210 switch(pid = fork()){211 case -1:212 return -1;213 case 0:214 pushword("exec");215 execexec();216 strcpy(buf, "can't exec: ");217 n = strlen(buf);218 errstr(buf+n, ERRMAX-n);219 Exit(buf);220 }221 return pid;222 }