shell.c (3288B)
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 } 21 22 int 23 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]; 31 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 here 76 */ 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 } 141 142 void 143 checkerrs(void) 144 { 145 char buf[BLOCKSIZE-10]; 146 int f, n, nl; 147 char *p; 148 long l; 149 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 }else 164 remove(errfile); 165 }