191 lines · 3.8 KB · C
RawDownload
#include "sam.h"#include "parse.h" extern	jmp_buf	mainloop; char	errfile[64];String	plan9cmd;	/* null terminated */Buffer	plan9buf;void	checkerrs(void);Buffer	cmdbuf;int	cmdbufpos; static voidupdateenv(File *f){	static int fd = -1;	int n;	char buf[64], *p, *e;		if(f == nil){		putenv("%", "");		putenv("%dot", "");		return;	} 	p = Strtoc(&f->name);	putenv("%", p);	free(p);		p = buf;	e = buf+sizeof(buf);	p = seprint(p, e, "%lud", 1+nlcount(f, 0, f->dot.r.p1));	p = seprint(p+1, e, "%lud", f->dot.r.p1);	p = seprint(p+1, e, "%lud", f->dot.r.p2);	n = p - buf;	if(fd == -1)	if((fd = create("/env/%dot", OWRITE, 0666)) < 0)		fprint(2, "updateenv create: %r\n");	if(write(fd, buf, n) != n)		fprint(2, "updateenv write: %r\n");} intplan9(File *f, int type, String *s, int nest){	long l;	int m;	int pid, fd;	char *retmsg;	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=='|' || 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 == '>')				dup(pipe1[0], 0);			else				dup(pipe1[1], 1);			close(pipe1[0]);			close(pipe1[1]);		}		if(type == '|' || 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(setjmp(mainloop))					exits("error"); 				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(nil);			}			if(pid==-1){				fprint(2, "Can't fork?!\n");				exits("fork");			}			dup(pipe2[0], 0);			close(pipe2[0]);			close(pipe2[1]);		}		if(type=='<' || type=='^'){			close(0);	/* so it won't read from terminal */			open("/dev/null", 0);		}		updateenv(f);		execl(SHPATH, SH, "-c", Strtoc(&plan9cmd), nil);		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);	}else if(type == '^' || type == '_'){		int nulls;		close(pipe1[1]);		bufload(&cmdbuf, cmdbufpos, pipe1[0], &nulls);		close(pipe1[0]);	}	retmsg = waitfor(pid);	if(type=='|' || type=='<' || type=='_' || type=='^')		if(retmsg[0]!=0)			warn_s(Wbadstatus, retmsg);	if(downloaded)		checkerrs();	if(!nest)		dprint("!\n");	return retmsg[0] ? -1 : 0;} voidcheckerrs(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);}