#
/* send3.c */


/* This information is proprietary and is the property of Bell
   Telephone Laboratories, Incorporated.  Its reproduction or
   disclosure to others, either orally or in writing, is pro-
   hibited without written permission of Bell Laboratories. */


#define IDMOD send3

#define IDSTR "~|^`send3.c 1.10 4/22/76

#include "send.h"

doarg(ctx,n,s,eof)
struct context *ctx;
char *s;
int *eof;
{
	static int nsh;
	char *px,*avv,vv[LNX];
	int ndo,k,nv,vt,vx,pd[2];
	struct keywd *pk;
	register int i;
	register char *p;
	register struct context *x;
	avv=vv;
	x=ctx;
	if (abort)
	{
		if (x->sfd>0) unlink(x->stm);
		x->sfd=0; 
		return (1);
	};
	px=(p=s)+n;
	for (i=0;p<px;)
	{
		if ((k=0177&(*p++))=='\\')
		{
			if (p<px) k=0200|(*p++);
		};
		ss[i]=k;
		if (i<LNL) i++;
	};
	if (i>=LNL) i=LNL-1;
	px=(p=avv)+(nv=i);
	for (i=0;p<px;) *p++=0177&ss[i++];
	*p=0;
	vt=type(nv,ss,&vx);
	if (vt==TDOL)
	{
		if (x->sfd==0)
		{
			prf("%q/tmp/sh",x->stm);
			x->sfd=i=mktmp(x->stm,nsh++);
			if (i>0) inibf(&tbf,i);
		};
		if (x->sfd>0) putl(&tbf,nv-1,avv+1);
		return (0);
	};
	ndo=0;
	if (x->sfd)
	{
		if (x->sfd<0) {
			p="(create)"; 
			goto NS;
		};
		flush(&tbf);
		close(x->sfd);
		if (xpipe(pd)<0) {
			p="(pipe)"; 
			goto NS;
		};
		if ((i=tfork())==(-1))
		{
			p="(fork)";
NS: 
			k=diag(x,"cannot run shell",p,587);
			goto XS;
		};
		if (i==0)
		{
			close(0); 
			open("/dev/null",0);
			close(1); 
			dup(pd[1]);
			execl("/bin/sh","sh",x->stm,0);
			exit(040);
		};
		close(pd[1]);
		ndo=|dofile(pd[0],x->stm,x,TDOL);
		k=shex(x);
XS: 
		if (k && (i=open(x->stm,0))>=0)
		{
			inibf(&tbf,i);
			while ((i=getl(&tbf,ss))>=0) putl(&dbf,i,ss);
			close(tbf.fd);
		};
		if (x->sfd>0) unlink(x->stm);
		x->sfd=0;
	};
	switch (vt)
	{
	case TCOM: 
		break;
	case TEOF: 
		*eof=1; 
		break;
	case TINP: 
		ndo=|dofile(0,"-",x,vt); 
		break;
	case TTTY: 
		ndo=|dofile(dup(getty()),"+",x,vt); 
		break;
	case TMSG: 
		*px='\n'; 
		write(getty(),avv+1,nv); 
		break;
	case TPIN:
		*px='\n';
		if (tin) {
			write(getty(),avv+2,nv-1); 
			vt=TPTY;
		};
		*px=0;
		ndo=|dofile(0,avv,x,vt); 
		break;
	case TPTY:
		*px='\n';
		write(getty(),avv+2,nv-1);
		*px=0;
		ndo=|dofile(dup(getty()),avv,x,vt); 
		break;
	case TFMT:
		i=0; 
		ss[i++]='<';
		for (p=avv;p<px;) ss[i++]=(*p++);
		ss[i++]='>';
		if (exfm(i,ss,x->dsp)<0)
			diag(x,"default spec rejected",avv,588);
		ndo=|1; 
		break;
	case TSFL:
		for (p=avv+1;p<px;p++)
		{
			x->flg[i=F(*p)]=1;
			if (i==(F'f')) fold(1);
			if (i==(F'k'))
			{
				x->kw0=x->kw1=(x->ocx)->kw1;
				for (i=0;i<128;i++) kwx[i]=0;
			};
		};
		ndo=|1; 
		break;
	case TRFL:
		for (p=avv+1;p<px;p++)
		{
			x->flg[i=F(*p)]=0;
			if (i==(F'f')) fold(0);
			if (i==(F'k'))
				index(x->kw0=(x->ocx)->kw1,x->kw1);
		};
		ndo=|1; 
		break;
	case TVFL:
		for (p=avv+1;p<px;p++)
		{
			i=F(*p);
			x->flg[i]=k=(x->ocx)->flg[i];
			if (i==(F'f')) fold(k);
			if (i==(F'k'))
				index(x->kw0=(x->ocx)->kw0,x->kw1);
		};
		ndo=|1; 
		break;
	case TPKY:
		avv=+2; 
		nv=- 2;
		if (pk=gtky(x,nv,avv))
		{
			dfky(x,nv,avv,pk->nr,pk->rp); 
			break;
		};
		*px='=';
		write(getty(),avv,nv+1);
		px=(p=ss)+LNL;
		while (read(getty(),p,1)==1 && *p!='\n')
		{
			if (p<px) p++;
		};
		px=p; 
		p=ss;
		for (i=0;p<px;)
		{
			if ((k=0177&(*p++))=='\\')
			{
				if (p<px) k=0200|(*p++);
			};
			ss[i++]=k;
		};
		if ((k=hex(i,ss))>=0)
		{
			dfky(x,nv,avv,0,k); 
			break;
		};
		px=(p=ss)+i;
		while (p<px) *p++=0177&(*p);
		dfky(x,nv,avv,i,ss); 
		break;
	case TDHX:
		dfky(x,nv-4,avv,0,vx); 
		break;
	case TDKY:
		i=vx+1;
		dfky(x,vx,avv,nv-i,avv+i); 
		break;
	case TCHD:
		if (x->dfl==0)
		{
			svdir(x->dsv,NDR); 
			x->dfl++;
		};
		if (chdir(avv+vx)<0)
			diag(x,"cannot chdir",avv+vx,589);
		break;
	case TEXC:
		avv++; 
		nv--;
		if (xpipe(pd)<0) {
			p="(pipe)"; 
			goto NC;
		};
		if ((i=tfork())==(-1))
		{
			p="(fork)";
NC: 
			k=diag(x,"cannot run command",p,590);
			goto XC;
		};
		if (i==0)
		{
			close(0); 
			open("/dev/null",0);
			close(1); 
			dup(pd[1]);
			execl("/bin/sh","sh","-c",avv,0);
			exit(040);
		};
		close(pd[1]);
		ndo=|dofile(pd[0],avv,x,vt);
		k=shex(x);
XC: 
		if (k) putl(&dbf,nv,avv); 
		break;
	case TFIL:
		ndo=|dofile(open(avv,0),avv,x,vt);
	};
	return (ndo);
};

type(n,s,xp)
char *s;
int *xp;
{
	char *px;
	register int i,t;
	register char *p;
	i=s[0];
	if (n<=0) return (TCOM);
	if (n==1)
	{
		if (i=='.') return (TEOF);
		if (i=='-') return (TINP);
		if (i=='+') return (TTTY);
	};
	if (n>=2 && s[1]==':')
	{
		if (i=='-') return (TPIN);
		if (i=='+') return (TPTY);
		if (i=='=') return (TPKY);
	};
	if (i==':')
	{
		if (n>=2 && s[n-1]==':') return (TFMT);
		return (TMSG);
	};
	if (i=='!')
	{
		if (mtch(7,s,"!chdir "))
		{
			for (i=7;i<n && s[i]==' ';i++);
			for (t=i;t<n && s[t]!=';';t++);
			if (t>=n) {
				*xp=i; 
				return (TCHD);
			};
		};
		return (TEXC);
	};
	if (i=='$') return (TDOL);
	if (i=='~') return (TCOM);
	if (i=='-' || i=='+' || i=='=')
	{
		px=(p=s)+n;
		while (++p<px)
		{
			if ((t=(*p))>=0140) t=& 0137;
			if (t<'A' || t>'Z') break;
		};
		if (p==px)
		{
			if (i=='-') return (TSFL);
			if (i=='+') return (TRFL);
			if (i=='=') return (TVFL);
		};
	};
	p=s+n;
	while (--p>=s && *p!='=');
	i=p-s;
	if (i>=0)
	{
		t=i+1;
		t=hex(n-t,s+t);
		if (t>=0) {
			*xp=t; 
			return (TDHX);
		};
		*xp=i; 
		return (TDKY);
	};
	for (i=0;i<NHST;i++)
	{
		t=host[i].hcnt;
		if (n==t && mtch(t,s,host[i].hnam)!=0)
		{
			if (nhst<0) nhst=i;
			return (TCOM);
		};
	};
	return (TFIL);
};

hex(n,s)
char *s;
{
	register int i,h;
	register char *p;
	p=s;
	if (n!=3 || *p++!='^') return (-1);
	h=0;
	i=(*p++);
	if (i>=0140) i=& 0137;
	if (i>='0' && i<='9') h=+(i-'0');
	else if (i>='A' && i<='F') h=+(i+10-'A');
	else return (-1);
	h=<<4;
	i=(*p++);
	if (i>=0140) i=& 0137;
	if (i>='0' && i<='9') h=+(i-'0');
	else if (i>='A' && i<='F') h=+(i+10-'A');
	else return (-1);
	return (h);
};

/*end*/
