plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

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 }