V9/jtools/src/sam/unix.c

Compare this file to the similar file:
Show the results in this format:

#include "sam.h"
#include "parse.h"
#ifdef SUN
/* a hack to get around redef of ushort in sys/types.h .
   this depends on non-use of ushort in this file */
#define ushort USHORT
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <setjmp.h>

extern	jmp_buf	mainloop;

uchar	errfile[64];
String	unixcmd;	/* null terminated */

Unix(f, type, s, nest)
	register File *f;
	register type;
	register String *s;
{
	register pid, rpid;
	int (*onbpipe)();
	int retcode;
	int pipe1[2], pipe2[2];
	if(s->s[0]==0 && unixcmd.s[0]==0)
		error(Enocmd);
	else if(s->s[0])
		strdupstr(&unixcmd, s);
	if(downloaded){
		strcpy(errfile, (uchar *)home);
		strcat((char *)errfile, "/sam.err");
	}else
		strcpy(errfile, (uchar *)"/dev/tty");
	if(type!='!' && pipe(pipe1)==-1)
			error(Epipe);
	unlink((char *)errfile);
	if((pid=fork()) == 0){
		if(downloaded){	/* also put nasty fd's into errfile */
			int fd=creat((char *)errfile, 0666);
			if(fd<0)
				fd=creat("/dev/null", 0666);
#ifdef	V8
			close(3);	/* v8 /dev/tty */
			open("/dev/null", 2);
#endif
			close(2);
			dup(fd);
			close(fd);
			/* 2 now points at err file */
			close(1);
			if(type == '>')
				dup(2);
			else if(type=='!'){
				dup(2);
				fd=open("/dev/null", 0);
				close(0);
				dup(fd);
				close(fd);
			}
		}
		if(type!='!') {
			if(type=='<' || type=='|'){
				close(1);
				dup(pipe1[1]);
			}else if(type == '>'){
				close(0);
				dup(pipe1[0]);
			}
			close(pipe1[0]);
			close(pipe1[1]);
		}
		if(type=='|'){
			if(pipe(pipe2)==-1)
				exit(1);
			if((pid=fork())==0){
				/*
				 * It's ok if we get SIGPIPE here
				 */
				close(pipe2[0]);
				io=pipe2[1];
				if(retcode=!setjmp(mainloop))	/* assignment = */
					(void)writeio(f);
				exit(retcode);
			}
			if(pid==-1){
				fprint(2, "Can't fork?!\n");
				exit(1);
			}
			close(0);
			dup(pipe2[0]);
			close(pipe2[0]);
			close(pipe2[1]);
		}
		Dclosefd();
		if(type=='<'){
			close(0);	/* so it won't read from terminal */
			open("/dev/null", 0);
		}
		execlp("sh", "sh", "-c", unixcmd.s, (char *)0);
		exit(-1);
	}
	if(pid==-1)
		error(Efork);
	if(type=='<' || type=='|'){
		if(downloaded)
			outTl(Hsnarflen, addr.r.p2-addr.r.p1);
		snarf(f, addr.r.p1, addr.r.p2);
		Fdelete(f, addr.r.p1, addr.r.p2);
		close(pipe1[1]);
		io=pipe1[0];
		f->dot.r.p2=addr.r.p2+readio(f, (int *)0, 0);
		f->dot.r.p1=addr.r.p2;
		closeio((Posn)-1);
	}else if(type=='>'){
		onbpipe = signal(SIGPIPE, SIG_IGN);
		close(pipe1[0]);
		io=pipe1[1];
		(void)writeio(f);
		closeio((Posn)-1);
		signal(SIGPIPE, onbpipe);
	}
	do; while ((rpid = wait(&retcode)) != pid && rpid != -1);
	retcode=(retcode>>8)&0377;
	if(type=='|' || type=='<')
		if(retcode!=0)
			warn(Wbadstatus);
	checkerrs();
	if(!nest)
		dprint("!\n");
}
checkerrs(){
	struct stat statb;
	char buf[256];
	register f;
	register n, nl;
	register char *p;
	if(stat((char *)errfile, &statb)==0 && statb.st_size){
		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 < statb.st_size-1)
					dprint("(sam: more in %s)\n", errfile);
			}
			close(f);
		}
	}else
		unlink((char *)errfile);
}