|  | #include "sam.h" | 
|  | #include "parse.h" | 
|  |  | 
|  | extern	jmp_buf	mainloop; | 
|  |  | 
|  | char	errfile[64]; | 
|  | String	plan9cmd;	/* null terminated */ | 
|  | Buffer	plan9buf; | 
|  | void	checkerrs(void); | 
|  |  | 
|  | int | 
|  | plan9(File *f, int type, String *s, int nest) | 
|  | { | 
|  | long l; | 
|  | int m; | 
|  | int volatile pid; | 
|  | int fd; | 
|  | int retcode; | 
|  | int pipe1[2], pipe2[2]; | 
|  |  | 
|  | if(s->s[0]==0 && plan9cmd.s[0]==0) | 
|  | error(Enocmd); | 
|  | else if(s->s[0]) | 
|  | Strduplstr(&plan9cmd, s); | 
|  | if(downloaded){ | 
|  | samerr(errfile); | 
|  | remove(errfile); | 
|  | } | 
|  | if(type!='!' && pipe(pipe1)==-1) | 
|  | error(Epipe); | 
|  | if(type=='|') | 
|  | snarf(f, addr.r.p1, addr.r.p2, &plan9buf, 1); | 
|  | if((pid=fork()) == 0){ | 
|  | if(downloaded){	/* also put nasty fd's into errfile */ | 
|  | fd = create(errfile, 1, 0666L); | 
|  | if(fd < 0) | 
|  | fd = create("/dev/null", 1, 0666L); | 
|  | dup(fd, 2); | 
|  | close(fd); | 
|  | /* 2 now points at err file */ | 
|  | if(type == '>') | 
|  | dup(2, 1); | 
|  | else if(type=='!'){ | 
|  | dup(2, 1); | 
|  | fd = open("/dev/null", 0); | 
|  | dup(fd, 0); | 
|  | close(fd); | 
|  | } | 
|  | } | 
|  | if(type != '!') { | 
|  | if(type=='<' || type=='|') | 
|  | dup(pipe1[1], 1); | 
|  | else if(type == '>') | 
|  | dup(pipe1[0], 0); | 
|  | close(pipe1[0]); | 
|  | close(pipe1[1]); | 
|  | } | 
|  | if(type == '|'){ | 
|  | if(pipe(pipe2) == -1) | 
|  | exits("pipe"); | 
|  | if((pid = fork())==0){ | 
|  | /* | 
|  | * It's ok if we get SIGPIPE here | 
|  | */ | 
|  | close(pipe2[0]); | 
|  | io = pipe2[1]; | 
|  | if(retcode=!setjmp(mainloop)){	/* assignment = */ | 
|  | char *c; | 
|  | for(l = 0; l<plan9buf.nc; l+=m){ | 
|  | m = plan9buf.nc-l; | 
|  | if(m>BLOCKSIZE-1) | 
|  | m = BLOCKSIZE-1; | 
|  | bufread(&plan9buf, l, genbuf, m); | 
|  | genbuf[m] = 0; | 
|  | c = Strtoc(tmprstr(genbuf, m+1)); | 
|  | Write(pipe2[1], c, strlen(c)); | 
|  | free(c); | 
|  | } | 
|  | } | 
|  | exits(retcode? "error" : 0); | 
|  | } | 
|  | if(pid==-1){ | 
|  | fprint(2, "Can't fork?!\n"); | 
|  | exits("fork"); | 
|  | } | 
|  | dup(pipe2[0], 0); | 
|  | close(pipe2[0]); | 
|  | close(pipe2[1]); | 
|  | } | 
|  | if(type=='<'){ | 
|  | close(0);	/* so it won't read from terminal */ | 
|  | open("/dev/null", 0); | 
|  | } | 
|  | execl(SHPATH, SH, "-c", Strtoc(&plan9cmd), (char *)0); | 
|  | exits("exec"); | 
|  | } | 
|  | if(pid == -1) | 
|  | error(Efork); | 
|  | if(type=='<' || type=='|'){ | 
|  | int nulls; | 
|  | if(downloaded && addr.r.p1 != addr.r.p2) | 
|  | outTl(Hsnarflen, addr.r.p2-addr.r.p1); | 
|  | snarf(f, addr.r.p1, addr.r.p2, &snarfbuf, 0); | 
|  | logdelete(f, addr.r.p1, addr.r.p2); | 
|  | close(pipe1[1]); | 
|  | io = pipe1[0]; | 
|  | f->tdot.p1 = -1; | 
|  | f->ndot.r.p2 = addr.r.p2+readio(f, &nulls, 0, FALSE); | 
|  | f->ndot.r.p1 = addr.r.p2; | 
|  | closeio((Posn)-1); | 
|  | }else if(type=='>'){ | 
|  | close(pipe1[0]); | 
|  | io = pipe1[1]; | 
|  | bpipeok = 1; | 
|  | writeio(f); | 
|  | bpipeok = 0; | 
|  | closeio((Posn)-1); | 
|  | } | 
|  | retcode = waitfor(pid); | 
|  | if(type=='|' || type=='<') | 
|  | if(retcode!=0) | 
|  | warn(Wbadstatus); | 
|  | if(downloaded) | 
|  | checkerrs(); | 
|  | if(!nest) | 
|  | dprint("!\n"); | 
|  | return retcode; | 
|  | } | 
|  |  | 
|  | void | 
|  | checkerrs(void) | 
|  | { | 
|  | char buf[256]; | 
|  | int f, n, nl; | 
|  | char *p; | 
|  | long l; | 
|  |  | 
|  | if(statfile(errfile, 0, 0, 0, &l, 0) > 0 && l != 0){ | 
|  | if((f=open((char *)errfile, 0)) != -1){ | 
|  | if((n=read(f, buf, sizeof buf-1)) > 0){ | 
|  | for(nl=0,p=buf; nl<3 && p<&buf[n]; p++) | 
|  | if(*p=='\n') | 
|  | nl++; | 
|  | *p = 0; | 
|  | dprint("%s", buf); | 
|  | if(p-buf < l-1) | 
|  | dprint("(sam: more in %s)\n", errfile); | 
|  | } | 
|  | close(f); | 
|  | } | 
|  | }else | 
|  | remove((char *)errfile); | 
|  | } |