shell.c - 9base - revived minimalist port of Plan 9 userland to Unix
 (HTM) git clone git://git.suckless.org/9base
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       shell.c (3288B)
       ---
            1 #include "sam.h"
            2 #include "parse.h"
            3 
            4 extern        jmp_buf        mainloop;
            5 
            6 char        errfile[64];
            7 String        plan9cmd;        /* null terminated */
            8 Buffer        plan9buf;
            9 void        checkerrs(void);
           10 
           11 void
           12 setname(File *f)
           13 {
           14         char buf[1024];
           15         if(f)
           16                 snprint(buf, sizeof buf, "%.*S", f->name.n, f->name.s);
           17         else
           18                 buf[0] = 0;
           19         putenv("samfile", buf);
           20 }
           21 
           22 int
           23 plan9(File *f, int type, String *s, int nest)
           24 {
           25         long l;
           26         int m;
           27         int volatile pid;
           28         int fd;
           29         int retcode;
           30         int pipe1[2], pipe2[2];
           31 
           32         if(s->s[0]==0 && plan9cmd.s[0]==0)
           33                 error(Enocmd);
           34         else if(s->s[0])
           35                 Strduplstr(&plan9cmd, s);
           36         if(downloaded){
           37                 samerr(errfile);
           38                 remove(errfile);
           39         }
           40         if(type!='!' && pipe(pipe1)==-1)
           41                 error(Epipe);
           42         if(type=='|')
           43                 snarf(f, addr.r.p1, addr.r.p2, &plan9buf, 1);
           44         if((pid=fork()) == 0){
           45                 setname(f);
           46                 if(downloaded){        /* also put nasty fd's into errfile */
           47                         fd = create(errfile, 1, 0666L);
           48                         if(fd < 0)
           49                                 fd = create("/dev/null", 1, 0666L);
           50                         dup(fd, 2);
           51                         close(fd);
           52                         /* 2 now points at err file */
           53                         if(type == '>')
           54                                 dup(2, 1);
           55                         else if(type=='!'){
           56                                 dup(2, 1);
           57                                 fd = open("/dev/null", 0);
           58                                 dup(fd, 0);
           59                                 close(fd);
           60                         }
           61                 }
           62                 if(type != '!') {
           63                         if(type=='<' || type=='|')
           64                                 dup(pipe1[1], 1);
           65                         else if(type == '>')
           66                                 dup(pipe1[0], 0);
           67                         close(pipe1[0]);
           68                         close(pipe1[1]);
           69                 }
           70                 if(type == '|'){
           71                         if(pipe(pipe2) == -1)
           72                                 exits("pipe");
           73                         if((pid = fork())==0){
           74                                 /*
           75                                  * It's ok if we get SIGPIPE here
           76                                  */
           77                                 close(pipe2[0]);
           78                                 io = pipe2[1];
           79                                 if(retcode=!setjmp(mainloop)){        /* assignment = */
           80                                         char *c;
           81                                         for(l = 0; l<plan9buf.nc; l+=m){
           82                                                 m = plan9buf.nc-l;
           83                                                 if(m>BLOCKSIZE-1)
           84                                                         m = BLOCKSIZE-1;
           85                                                 bufread(&plan9buf, l, genbuf, m);
           86                                                 genbuf[m] = 0;
           87                                                 c = Strtoc(tmprstr(genbuf, m+1));
           88                                                 Write(pipe2[1], c, strlen(c));
           89                                                 free(c);
           90                                         }
           91                                 }
           92                                 exits(retcode? "error" : 0);
           93                         }
           94                         if(pid==-1){
           95                                 fprint(2, "Can't fork?!\n");
           96                                 exits("fork");
           97                         }
           98                         dup(pipe2[0], 0);
           99                         close(pipe2[0]);
          100                         close(pipe2[1]);
          101                 }
          102                 if(type=='<'){
          103                         close(0);        /* so it won't read from terminal */
          104                         open("/dev/null", 0);
          105                 }
          106                 execl(SHPATH, SH, "-c", Strtoc(&plan9cmd), (char *)0);
          107                 exits("exec");
          108         }
          109         if(pid == -1)
          110                 error(Efork);
          111         if(type=='<' || type=='|'){
          112                 int nulls;
          113                 if(downloaded && addr.r.p1 != addr.r.p2)
          114                         outTl(Hsnarflen, addr.r.p2-addr.r.p1);
          115                 snarf(f, addr.r.p1, addr.r.p2, &snarfbuf, 0);
          116                 logdelete(f, addr.r.p1, addr.r.p2);
          117                 close(pipe1[1]);
          118                 io = pipe1[0];
          119                 f->tdot.p1 = -1;
          120                 f->ndot.r.p2 = addr.r.p2+readio(f, &nulls, 0, FALSE);
          121                 f->ndot.r.p1 = addr.r.p2;
          122                 closeio((Posn)-1);
          123         }else if(type=='>'){
          124                 close(pipe1[0]);
          125                 io = pipe1[1];
          126                 bpipeok = 1;
          127                 writeio(f);
          128                 bpipeok = 0;
          129                 closeio((Posn)-1);
          130         }
          131         retcode = waitfor(pid);
          132         if(type=='|' || type=='<')
          133                 if(retcode!=0)
          134                         warn(Wbadstatus);
          135         if(downloaded)
          136                 checkerrs();
          137         if(!nest)
          138                 dprint("!\n");
          139         return retcode;
          140 }
          141 
          142 void
          143 checkerrs(void)
          144 {
          145         char buf[BLOCKSIZE-10];
          146         int f, n, nl;
          147         char *p;
          148         long l;
          149 
          150         if(statfile(errfile, 0, 0, 0, &l, 0) > 0 && l != 0){
          151                 if((f=open(errfile, 0)) != -1){
          152                         if((n=read(f, buf, sizeof buf-1)) > 0){
          153                                 for(nl=0,p=buf; nl<25 && p<&buf[n]; p++)
          154                                         if(*p=='\n')
          155                                                 nl++;
          156                                 *p = 0;
          157                                 dprint("%s", buf);
          158                                 if(p-buf < l-1)
          159                                         dprint("(sam: more in %s)\n", errfile);
          160                         }
          161                         close(f);
          162                 }
          163         }else
          164                 remove(errfile);
          165 }