haventfork.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
       ---
       haventfork.c (3436B)
       ---
            1 #include "rc.h"
            2 #include "getflags.h"
            3 #include "exec.h"
            4 #include "io.h"
            5 #include "fns.h"
            6 
            7 int havefork = 0;
            8 
            9 static char **
           10 rcargv(char *s)
           11 {
           12         int argc;
           13         char **argv;
           14         word *p;
           15 
           16         p = vlook("*")->val;
           17         argv = malloc((count(p)+6)*sizeof(char*));
           18         argc = 0;
           19         argv[argc++] = argv0;
           20         if(flag['e'])
           21                 argv[argc++] = "-Se";
           22         else
           23                 argv[argc++] = "-S";
           24         argv[argc++] = "-c";
           25         argv[argc++] = s;
           26         for(p = vlook("*")->val; p; p = p->next)
           27                 argv[argc++] = p->word;
           28         argv[argc] = 0;
           29         return argv;
           30 }
           31 
           32 void
           33 Xasync(void)
           34 {
           35         uint pid;
           36         char buf[20], **argv;
           37 
           38         Updenv();
           39 
           40         argv = rcargv(runq->code[runq->pc].s);
           41         pid = ForkExecute(argv0, argv, -1, 1, 2);
           42         free(argv);
           43 
           44         if(pid == 0) {
           45                 Xerror("proc failed");
           46                 return;
           47         }
           48 
           49         runq->pc++;
           50         sprint(buf, "%d", pid);
           51         setvar("apid", newword(buf, (word *)0));
           52 }
           53 
           54 char*
           55 erealloc(char *p, long n)
           56 {
           57         p = realloc(p, n);                /* botch, should be Realloc */
           58         if(p==0)
           59                 panic("Can't realloc %d bytes\n", n);
           60         return p;
           61 }
           62 
           63 enum { Stralloc = 100, };
           64 
           65 void
           66 Xbackq(void)
           67 {
           68         char **argv;
           69         int c, l;
           70         char *s, *wd, *ewd, *stop;
           71         struct io *f;
           72         var *ifs = vlook("ifs");
           73         word *v, *nextv;
           74         int pfd[2];
           75         int pid;
           76 
           77         stop = ifs->val?ifs->val->word:"";
           78         if(pipe(pfd)<0){
           79                 Xerror("can't make pipe");
           80                 return;
           81         }
           82 
           83         Updenv();
           84 
           85         argv = rcargv(runq->code[runq->pc].s);
           86         pid = ForkExecute(argv0, argv, -1, pfd[1], 2);
           87         free(argv);
           88 
           89         close(pfd[1]);
           90 
           91         if(pid == 0) {
           92                 Xerror("proc failed");
           93                 close(pfd[0]);
           94                 return;
           95         }
           96 
           97         f = openfd(pfd[0]);
           98                 s = wd = ewd = 0;
           99         v = 0;
          100         while((c=rchr(f))!=EOF){
          101                 if(s==ewd){
          102                         l = s-wd;
          103                         wd = erealloc(wd, l+Stralloc);
          104                         ewd = wd+l+Stralloc-1;
          105                         s = wd+l;
          106                 }
          107                 if(strchr(stop, c)){
          108                         if(s!=wd){
          109                                 *s='\0';
          110                                 v = newword(wd, v);
          111                                 s = wd;
          112                         }
          113                 }
          114                 else *s++=c;
          115         }
          116         if(s!=wd){
          117                 *s='\0';
          118                 v=newword(wd, v);
          119         }
          120         if(wd)
          121                 efree(wd);
          122         closeio(f);
          123         Waitfor(pid, 1);
          124         /* v points to reversed arglist -- reverse it onto argv */
          125         while(v){
          126                 nextv=v->next;
          127                 v->next=runq->argv->words;
          128                 runq->argv->words=v;
          129                 v=nextv;
          130         }
          131         runq->pc++;
          132 }
          133 
          134 void
          135 Xpipe(void)
          136 {
          137         thread *p=runq;
          138         int pc=p->pc, pid;
          139         int rfd=p->code[pc+1].i;
          140         int pfd[2];
          141         char **argv;
          142 
          143         if(pipe(pfd)<0){
          144                 Xerror1("can't get pipe");
          145                 return;
          146         }
          147 
          148         Updenv();
          149 
          150         argv = rcargv(runq->code[pc+2].s);
          151         pid = ForkExecute(argv0, argv, 0, pfd[1], 2);
          152         free(argv);
          153         close(pfd[1]);
          154 
          155         if(pid == 0) {
          156                 Xerror("proc failed");
          157                 close(pfd[0]);
          158                 return;
          159         }
          160 
          161         start(p->code, pc+4, runq->local);
          162         pushredir(ROPEN, pfd[0], rfd);
          163         p->pc=p->code[pc+3].i;
          164         p->pid=pid;
          165 }
          166 
          167 void
          168 Xpipefd(void)
          169 {
          170         Abort();
          171 }
          172 
          173 void
          174 Xsubshell(void)
          175 {
          176         char **argv;
          177         int pid;
          178 
          179         Updenv();
          180 
          181         argv = rcargv(runq->code[runq->pc].s);
          182         pid = ForkExecute(argv0, argv, -1, 1, 2);
          183         free(argv);
          184 
          185         if(pid < 0) {
          186                 Xerror("proc failed");
          187                 return;
          188         }
          189 
          190         Waitfor(pid, 1);
          191         runq->pc++;
          192 }
          193 
          194 /*
          195  *  start a process running the cmd on the stack and return its pid.
          196  */
          197 int
          198 execforkexec(void)
          199 {
          200         char **argv;
          201         char file[1024];
          202         int nc;
          203         word *path;
          204         int pid;
          205 
          206         if(runq->argv->words==0)
          207                 return -1;
          208         argv = mkargv(runq->argv->words);
          209 
          210         for(path = searchpath(runq->argv->words->word);path;path = path->next){
          211                 nc = strlen(path->word);
          212                 if(nc < sizeof file - 1){        /* 1 for / */
          213                         strcpy(file, path->word);
          214                         if(file[0]){
          215                                 strcat(file, "/");
          216                                 nc++;
          217                         }
          218                         if(nc+strlen(argv[1])<sizeof(file)){
          219                                 strcat(file, argv[1]);
          220                                 pid = ForkExecute(file, argv+1, mapfd(0), mapfd(1), mapfd(2));
          221                                 if(pid >= 0){
          222                                         free(argv);
          223                                         return pid;
          224                                 }
          225                         }
          226                 }
          227         }
          228         free(argv);
          229         return -1;
          230 }