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