shell.c (3301B)
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 void 12 setname(File *f) 13 { 14 char buf[1024]; 15 if(f) 16 snprint(buf, sizeof buf, "%.*S", f->name.n, f->name.s); 17 else 18 buf[0] = 0; 19 putenv("samfile", buf); 20 putenv("%", buf); // like acme 21 } 22 23 int 24 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]; 32 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 here 77 */ 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 } 142 143 void 144 checkerrs(void) 145 { 146 char buf[BLOCKSIZE-10]; 147 int f, n, nl; 148 char *p; 149 long l; 150 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 }else 165 remove(errfile); 166 }