9base

revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log | Files | Refs | README | LICENSE

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 }