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 int 12 plan9(File *f, int type, String *s, int nest) 13 { 14 long l; 15 int m; 16 int pid, fd; 17 int retcode; 18 char *retmsg; 19 int pipe1[2], pipe2[2]; 20 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 here 64 */ 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), nil); 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 retmsg = waitfor(pid); 120 if(type=='|' || type=='<') 121 if(retmsg[0]!=0) 122 warn_s(Wbadstatus, retmsg); 123 if(downloaded) 124 checkerrs(); 125 if(!nest) 126 dprint("!\n"); 127 return retmsg[0] ? -1 : 0; 128 } 129 130 void 131 checkerrs(void) 132 { 133 char buf[256]; 134 int f, n, nl; 135 char *p; 136 long l; 137 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 }else 152 remove((char *)errfile); 153 } 154