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