xref: /plan9/sys/src/cmd/sam/shell.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
13e12c5d1SDavid du Colombier #include "sam.h"
23e12c5d1SDavid du Colombier #include "parse.h"
33e12c5d1SDavid du Colombier 
43e12c5d1SDavid du Colombier extern	jmp_buf	mainloop;
53e12c5d1SDavid du Colombier 
63e12c5d1SDavid du Colombier char	errfile[64];
73e12c5d1SDavid du Colombier String	plan9cmd;	/* null terminated */
83e12c5d1SDavid du Colombier Buffer	*plan9buf;
93e12c5d1SDavid du Colombier void	checkerrs(void);
103e12c5d1SDavid du Colombier 
11*219b2ee8SDavid du Colombier int
123e12c5d1SDavid du Colombier plan9(File *f, int type, String *s, int nest)
133e12c5d1SDavid du Colombier {
143e12c5d1SDavid du Colombier 	long l;
153e12c5d1SDavid du Colombier 	int m;
163e12c5d1SDavid du Colombier 	int pid, fd;
173e12c5d1SDavid du Colombier 	int retcode;
183e12c5d1SDavid du Colombier 	int pipe1[2], pipe2[2];
193e12c5d1SDavid du Colombier 
203e12c5d1SDavid du Colombier 	if(s->s[0]==0 && plan9cmd.s[0]==0)
213e12c5d1SDavid du Colombier 		error(Enocmd);
223e12c5d1SDavid du Colombier 	else if(s->s[0])
233e12c5d1SDavid du Colombier 		Strduplstr(&plan9cmd, s);
243e12c5d1SDavid du Colombier 	if(downloaded)
253e12c5d1SDavid du Colombier 		samerr(errfile);
263e12c5d1SDavid du Colombier 	else
273e12c5d1SDavid du Colombier 		strcpy(errfile, "/dev/tty");
283e12c5d1SDavid du Colombier 	if(type!='!' && pipe(pipe1)==-1)
293e12c5d1SDavid du Colombier 		error(Epipe);
303e12c5d1SDavid du Colombier 	if(type=='|')
313e12c5d1SDavid du Colombier 		snarf(f, addr.r.p1, addr.r.p2, plan9buf, 1);
323e12c5d1SDavid du Colombier 	if(downloaded)
333e12c5d1SDavid du Colombier 		remove(errfile);
343e12c5d1SDavid du Colombier 	if((pid=fork()) == 0){
353e12c5d1SDavid du Colombier 		if(downloaded){	/* also put nasty fd's into errfile */
363e12c5d1SDavid du Colombier 			fd = create(errfile, 1, 0666L);
373e12c5d1SDavid du Colombier 			if(fd < 0)
383e12c5d1SDavid du Colombier 				fd = create("/dev/null", 1, 0666L);
393e12c5d1SDavid du Colombier 			dup(fd, 2);
403e12c5d1SDavid du Colombier 			close(fd);
413e12c5d1SDavid du Colombier 			/* 2 now points at err file */
423e12c5d1SDavid du Colombier 			if(type == '>')
433e12c5d1SDavid du Colombier 				dup(2, 1);
443e12c5d1SDavid du Colombier 			else if(type=='!'){
453e12c5d1SDavid du Colombier 				dup(2, 1);
463e12c5d1SDavid du Colombier 				fd = open("/dev/null", 0);
473e12c5d1SDavid du Colombier 				dup(fd, 0);
483e12c5d1SDavid du Colombier 				close(fd);
493e12c5d1SDavid du Colombier 			}
503e12c5d1SDavid du Colombier 		}
513e12c5d1SDavid du Colombier 		if(type != '!') {
523e12c5d1SDavid du Colombier 			if(type=='<' || type=='|')
533e12c5d1SDavid du Colombier 				dup(pipe1[1], 1);
543e12c5d1SDavid du Colombier 			else if(type == '>')
553e12c5d1SDavid du Colombier 				dup(pipe1[0], 0);
563e12c5d1SDavid du Colombier 			close(pipe1[0]);
573e12c5d1SDavid du Colombier 			close(pipe1[1]);
583e12c5d1SDavid du Colombier 		}
593e12c5d1SDavid du Colombier 		if(type == '|'){
603e12c5d1SDavid du Colombier 			if(pipe(pipe2) == -1)
613e12c5d1SDavid du Colombier 				exits("pipe");
623e12c5d1SDavid du Colombier 			if((pid = fork())==0){
633e12c5d1SDavid du Colombier 				/*
643e12c5d1SDavid du Colombier 				 * It's ok if we get SIGPIPE here
653e12c5d1SDavid du Colombier 				 */
663e12c5d1SDavid du Colombier 				close(pipe2[0]);
673e12c5d1SDavid du Colombier 				io = pipe2[1];
683e12c5d1SDavid du Colombier 				if(retcode=!setjmp(mainloop)){	/* assignment = */
693e12c5d1SDavid du Colombier 					char *c;
703e12c5d1SDavid du Colombier 					for(l = 0; l<plan9buf->nrunes; l+=m){
713e12c5d1SDavid du Colombier 						m = plan9buf->nrunes-l;
723e12c5d1SDavid du Colombier 						if(m>BLOCKSIZE-1)
733e12c5d1SDavid du Colombier 							m = BLOCKSIZE-1;
743e12c5d1SDavid du Colombier 						Bread(plan9buf, genbuf, m, l);
753e12c5d1SDavid du Colombier 						genbuf[m] = 0;
763e12c5d1SDavid du Colombier 						c = Strtoc(tmprstr(genbuf, m+1));
773e12c5d1SDavid du Colombier 						Write(pipe2[1], c, strlen(c));
783e12c5d1SDavid du Colombier 						free(c);
793e12c5d1SDavid du Colombier 					}
803e12c5d1SDavid du Colombier 				}
813e12c5d1SDavid du Colombier 				exits(retcode? "error" : 0);
823e12c5d1SDavid du Colombier 			}
833e12c5d1SDavid du Colombier 			if(pid==-1){
843e12c5d1SDavid du Colombier 				fprint(2, "Can't fork?!\n");
853e12c5d1SDavid du Colombier 				exits("fork");
863e12c5d1SDavid du Colombier 			}
873e12c5d1SDavid du Colombier 			dup(pipe2[0], 0);
883e12c5d1SDavid du Colombier 			close(pipe2[0]);
893e12c5d1SDavid du Colombier 			close(pipe2[1]);
903e12c5d1SDavid du Colombier 		}
913e12c5d1SDavid du Colombier 		if(type=='<'){
923e12c5d1SDavid du Colombier 			close(0);	/* so it won't read from terminal */
933e12c5d1SDavid du Colombier 			open("/dev/null", 0);
943e12c5d1SDavid du Colombier 		}
953e12c5d1SDavid du Colombier 		execl(SHPATH, SH, "-c", Strtoc(&plan9cmd), (char *)0);
963e12c5d1SDavid du Colombier 		exits("exec");
973e12c5d1SDavid du Colombier 	}
983e12c5d1SDavid du Colombier 	if(pid == -1)
993e12c5d1SDavid du Colombier 		error(Efork);
1003e12c5d1SDavid du Colombier 	if(type=='<' || type=='|'){
1013e12c5d1SDavid du Colombier 		int nulls;
102*219b2ee8SDavid du Colombier 		if(downloaded && addr.r.p1 != addr.r.p2)
1033e12c5d1SDavid du Colombier 			outTl(Hsnarflen, addr.r.p2-addr.r.p1);
1043e12c5d1SDavid du Colombier 		snarf(f, addr.r.p1, addr.r.p2, snarfbuf, 0);
1053e12c5d1SDavid du Colombier 		Fdelete(f, addr.r.p1, addr.r.p2);
1063e12c5d1SDavid du Colombier 		close(pipe1[1]);
1073e12c5d1SDavid du Colombier 		io = pipe1[0];
1083e12c5d1SDavid du Colombier 		f->tdot.p1 = -1;
1093e12c5d1SDavid du Colombier 		f->ndot.r.p2 = addr.r.p2+readio(f, &nulls, 0);
1103e12c5d1SDavid du Colombier 		f->ndot.r.p1 = addr.r.p2;
1113e12c5d1SDavid du Colombier 		closeio((Posn)-1);
1123e12c5d1SDavid du Colombier 	}else if(type=='>'){
1133e12c5d1SDavid du Colombier 		close(pipe1[0]);
1143e12c5d1SDavid du Colombier 		io = pipe1[1];
1153e12c5d1SDavid du Colombier 		bpipeok = 1;
1163e12c5d1SDavid du Colombier 		writeio(f);
1173e12c5d1SDavid du Colombier 		bpipeok = 0;
1183e12c5d1SDavid du Colombier 		closeio((Posn)-1);
1193e12c5d1SDavid du Colombier 	}
1203e12c5d1SDavid du Colombier 	retcode = waitfor(pid);
1213e12c5d1SDavid du Colombier 	if(type=='|' || type=='<')
1223e12c5d1SDavid du Colombier 		if(retcode!=0)
1233e12c5d1SDavid du Colombier 			warn(Wbadstatus);
1243e12c5d1SDavid du Colombier 	if(downloaded)
1253e12c5d1SDavid du Colombier 		checkerrs();
1263e12c5d1SDavid du Colombier 	if(!nest)
1273e12c5d1SDavid du Colombier 		dprint("!\n");
128*219b2ee8SDavid du Colombier 	return retcode;
1293e12c5d1SDavid du Colombier }
1303e12c5d1SDavid du Colombier 
1313e12c5d1SDavid du Colombier void
1323e12c5d1SDavid du Colombier checkerrs(void)
1333e12c5d1SDavid du Colombier {
1343e12c5d1SDavid du Colombier 	char buf[256];
1353e12c5d1SDavid du Colombier 	int f, n, nl;
1363e12c5d1SDavid du Colombier 	char *p;
1373e12c5d1SDavid du Colombier 	long l;
1383e12c5d1SDavid du Colombier 
139*219b2ee8SDavid du Colombier 	if(statfile(errfile, 0, 0, 0, &l, 0) > 0 && l != 0){
1403e12c5d1SDavid du Colombier 		if((f=open((char *)errfile, 0)) != -1){
1413e12c5d1SDavid du Colombier 			if((n=read(f, buf, sizeof buf-1)) > 0){
1423e12c5d1SDavid du Colombier 				for(nl=0,p=buf; nl<3 && p<&buf[n]; p++)
1433e12c5d1SDavid du Colombier 					if(*p=='\n')
1443e12c5d1SDavid du Colombier 						nl++;
1453e12c5d1SDavid du Colombier 				*p = 0;
1463e12c5d1SDavid du Colombier 				dprint("%s", buf);
1473e12c5d1SDavid du Colombier 				if(p-buf < l-1)
1483e12c5d1SDavid du Colombier 					dprint("(sam: more in %s)\n", errfile);
1493e12c5d1SDavid du Colombier 			}
1503e12c5d1SDavid du Colombier 			close(f);
1513e12c5d1SDavid du Colombier 		}
1523e12c5d1SDavid du Colombier 	}else
1533e12c5d1SDavid du Colombier 		remove((char *)errfile);
1543e12c5d1SDavid du Colombier }
155