URI: 
       havefork.c - 9base - revived minimalist port of Plan 9 userland to Unix
  HTML git clone git://git.suckless.org/9base
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       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 }