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