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 }22 int23 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];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 here76 */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 }142 void143 checkerrs(void)144 {145 char buf[BLOCKSIZE-10];146 int f, n, nl;147 char *p;148 long l;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 }else164 remove(errfile);165 }