File:  [Research Unix] / researchv9 / jtools / src / pads / host / term.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:21:59 2018 UTC (8 years, 1 month ago) by root
Branches: belllabs, MAIN
CVS tags: researchv9-SUN3_old, researchv9-SUN3, HEAD
researchv9-SUN3(old)

#include <ctype.h>
#include <pads.pri>
#include <CC/sys/types.h>
#include <CC/sys/stat.h>
#ifdef BSD
#include <sys/socket.h>
#endif BSD
SRCFILE("term.c")

void Pick( char *s, Action a, long o )
{
	Index ix;

	trace("Pick(%d,%d)", a, o);
	ix = ICache->place(Item(s, a, o));
	R->pktstart( P_PICK );
	R->sendshort( ix.sht() );
	R->pktend();
}

char *JerqTERM[] = {	"/usr/jerq/bin/32ld /usr/jerq/mbin/pads.m",
			"5620", "jerq", "JERQ", "Jerq", "DMD", "DMD5620",
			0 };

char *BlitTERM[] = {	"/usr/blit/bin/68ld /usr/blit/mbin/pads.m",
			"blit", "BLIT", "Blit",
			0 };

char *XTERM[] = {	"pads",
			"xterm", "sun",
			0 };

char **MapTERM[] = { JerqTERM, BlitTERM, XTERM, 0 };

int pipe(int[2]), fork(), _exit(int);
#ifdef BSD
int socketpair(int,int,int,int[2]);
#endif BSD

char *PadsInit(char *loadcmd)
{
	trace( "PadsInit(%s)", loadcmd );
	if( !loadcmd ){
		char *getenv(char*), *TERM = getenv("TERM"), ***map, **term;
		loadcmd = MapTERM[0][0];
		for( map = MapTERM; TERM && *map; ++map )
			for( term = *map, ++term; *term; ++term )
				if( !strcmp(TERM, *term) )
					loadcmd = **map;
	}
	if( loadcmd == XTERM[0] ){
		int afildes[2], pid;
#ifdef BSD
		if( socketpair(AF_UNIX, SOCK_STREAM, 0, afildes)==-1 )
#else
		if( pipe(afildes)==-1 )
#endif BSD
			return "can't open pipe\n";
		if( (pid=fork())==0 ){
			dup2(afildes[0], 0);
			dup2(afildes[0], 1);
			close(afildes[0]);
			close(afildes[1]);
			execlp(loadcmd, "pads", (char *)0);
			_exit(1);
		}
		if(pid==-1)
			return "terminal fork failed";
		close(afildes[0]);
		R = new Remote(afildes[1]);
	}
	else {
		if ( system(loadcmd) ) return "terminal download failed";
		R = new Remote("/dev/tty");
	}
	R->pktstart(P_VERSION); R->sendlong(PADS_VERSION); R->pktend();
	R->pktstart(P_BUSY); R->pktend();
	ICache = new ItemCache;
	CCache = new CarteCache;
	close(2);
	return 0;
}

char *PadsTermInit(char *machine)
{
	char *loadcmd =  XTERM[0];
	int afildes[2], pid;
#ifdef BSD
	if( socketpair(AF_UNIX, SOCK_STREAM, 0, afildes)==-1 )
#else
	if( pipe(afildes)==-1 )
#endif BSD
		return "can't open pipe\n";
	if( (pid=fork())==0 ){
		dup2(afildes[0], 0);
		dup2(afildes[0], 1);
		close(afildes[0]);
		close(afildes[1]);
		execlp(loadcmd, "pads", (char *)0);
		_exit(1);
	}
	if(pid==-1)
		return "terminal fork failed";
	dup2(afildes[1], 0);
	dup2(afildes[1], 1);
	dup2(afildes[1], 2);
	close(afildes[0]);
	close(afildes[1]);
	execlp("rsh", machine, "exec /usr/jerq/bin/pi -R", 0);
	exit(127);
	return 0;
}

void PadsRemInit()
{
	R = new Remote(0);
	R->pktstart(P_VERSION); R->sendlong(PADS_VERSION); R->pktend();
	R->pktstart(P_BUSY); R->pktend();
	ICache = new ItemCache;
	CCache = new CarteCache;
}

char *TapTo;
void WireTap(PRINTF_ARGS)
{
	static int fd = -1;
	static long t0;
	struct stat s;
	char *ctime(long*);
	long t, time(long*);

	if( !TapTo ) return;
	t = time(0);
	if( ::stat("/usr/jerq/lib/.logpads", &s) || ctime(&t)[23]!='6' )
		goto BailOut;
	if( t0 )
		t -= t0;
	else
		t0 = t;
	char buf[256];
	sprintf(buf, "%x:", t);
	sprintf(buf+strlen(buf), PRINTF_COPY);
	if( fd < 0 ){
		if( ::stat(TapTo, &s) )
			creat(TapTo, 0777); 
		fd = open(TapTo, 1);
	}
#define PILOGSIZE 32000
	if( fd<0
	 || fstat(fd, &s)
	 || s.st_size > PILOGSIZE )
			goto BailOut;
	lseek(fd, s.st_size, 0);
	write(fd, buf, strlen(buf));
	return;
BailOut:
	TapTo = 0;
}

int BothValid(PadRcv *p, PadRcv *o)
{
	return p && o;
}

void TermAction(PadRcv *parent, PadRcv *obj, int pick)
{
	Item *item;
	Index ix(R->rcvshort());

	trace( "TermAction(%d,%d,%d)", parent, obj, pick );
	if( ix.null() ) return;
	item = ICache->take(ix);
	if( !BothValid(parent,obj)
	 || (pick && !obj->accept(item->action)) )
		return;
	Action a = item->action;
	long faddr, ixorf = (int) a;			// yuk: can't say
	if( ixorf & (~127) )				// &(obj->*item->action)
		faddr = ixorf;				//
	else						//
		faddr = ((long**) obj)[1][ixorf-1];	//
	WireTap("%x->%x(%x)\n", obj, faddr, item->opand);
	if( item->action ) (obj->*item->action)(item->opand, 0, 0);
}

char *DoKbd(PadRcv *obj, char *buf)
{
	WireTap("%x->%x(%x) %s\n", obj, &obj->kbd, strlen(buf), buf);
	char *e = obj->kbd(buf);
	if( e ) PadsWarn("%s", e);
	return e;
}

void Shell()
{
	char cmd[256];
	R->rcvstring(cmd);
	FILE *fp = Popen(cmd, "w");
	for( long lines = R->rcvlong(); lines>0; --lines ){
		char data[256];
		if( fp ) fprintf(fp, "%s\n", R->rcvstring(data));
	}
	if( !fp ){
		PadsWarn("cannot write to pipe");
		return;
	}
	int x = Pclose(fp);
	if( x ) PadsWarn( "exit(%d): %s", x, cmd );
}

void ShKbd(PadRcv *obj, char *cmd)
{
	trace( "ShKbd(%d,%s)", obj, buf );
	FILE *fp = Popen(cmd, "r");
	if( !fp ){
		PadsWarn("cannot read from pipe");
		return;
	}
	char buf[256];
	while( fgets(buf, sizeof buf, fp) ){
		buf[strlen(buf)-1] = 0;
		if( DoKbd(obj, buf) ) break;
	}
	int x = Pclose(fp);
	if( x ) PadsWarn( "exit(%d): %s", x, cmd );
}

void Kbd(PadRcv *parent, PadRcv *obj)
{
	char buf[256];
	R->rcvstring(buf);
	trace( "Kbd %d %s", obj, buf );
	if( !BothValid(parent,obj) ) return;
	if( !strcmp( buf, "?" ) ){
		char *h = obj->help();
		PadsWarn( "%s", (h && *h) ? h : "error: null help string" );
	} else if( buf[0] == '<' ){
		ShKbd(obj, buf+1);
	} else
		DoKbd(obj, buf);
}

void TermServe()
{
	Protocol p;
	long n, to, pick = 0;

	trace("TermServe()");
	R->writesize = 0;
	R->pktstart(P_IDLE); R->pktend();	/* flush */
	p = (Protocol) R->get();
	if( p == P_PICK ) {
		pick = 1;
		p = (Protocol) R->get();
	}
	PadRcv *par = R->rcvobj();
	PadRcv *obj = R->rcvobj();
	if( p != P_CYCLE ) { R->writesize = 0; R->pktstart(P_BUSY); R->pktend(); }
	switch( (int) p ){
		case P_ACTION:
			TermAction(par, obj, pick);
			break;
		case P_KBDSTR:
			Kbd(par, obj);
			break;
		case P_SHELL:
			Shell();
			break;
		case P_NUMERIC:
		case P_CYCLE:
		case P_USERCLOSE:
		case P_USERCUT:
			n = R->rcvshort();
			if( !BothValid(par,obj) ) return;
			switch( (int) p ){
			case P_NUMERIC:
				WireTap("%x->%x(%x)\n", obj, &obj->numeric, n);
				obj->numeric(n);	break;
			case P_CYCLE:
				obj->cycle();		break;
			case P_USERCLOSE:
				WireTap("%x->%x(0)\n", obj, &obj->userclose);
				obj->userclose();	break;
			case P_USERCUT	:
				WireTap("%x->%x(0)\n", obj, &obj->usercut);
				obj->usercut();		break;
			default: R->err();
			}
			break;
		case P_LINEREQ:
			n = R->rcvlong();
			to = R->rcvlong();
			trace("P_LINEREQ %d %d %d", p, n, to);
			if( !BothValid(par,obj) ) return;
//			WireTap("%x->%x(%x)", obj, &obj->linereq, to-n+1);
			while( n <= to )
				obj->linereq((long) n++, 0);
			break;
		default:
			R->err();
	}
}

void PadsServe(long n)
{
	if( n ){
		while( n-->0 ) TermServe();
	} else {
		for( ;; )  TermServe();
	}
}

void PadsWarn(PRINTF_ARGS)
{
	char t[256];
	sprintf( t, PRINTF_COPY );
	R->pktstart( P_HELPSTR );
	R->sendstring( t );
	R->pktend();
}

void PadsError(PRINTF_ARGS)
{
	char t[256];
	sprintf(t, PRINTF_COPY);
	int fd = open("/dev/tty", 1);
	write(fd, "  ", 2);
	write(fd, t, strlen(t));
	abort();
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.