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