#
#include <sys/types.h>
#include <sys/stat.h>

struct stat statb;

/* rjeqer */
/* setuid=rje */


/* 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. */


/* modified by HY
   1.) after linking into hasp dir and locking stat file, but before
       modifying and unlockingg stat file, rjeqer2 is invoked, which
      does a chgrp bin and chmod 440 of the file. rjeqer2 (haspqer2) is
runnable only by hasp.
   2.) cleanup() now does an unlock().
   3.) if rjeqer is invoked as "-", then it wont delete the origg. file,
      used with rjestat -.
   4.) If invoked as "--", will not run rjeqer2, either.
*/
rjeqer() {
	return ("~|^`rjeqer.c 1.5 4/23/76");
};

char who[8] ;

char statf[40],lockf[40];

char *fil,*ofil,*dir;

char *nseq,*xmt;

int dev,siz;

int delete; /* on if orig. file is to be deleted (default) */
int ppid;

main(ac,av)
char *av[];
{
	int c,qid,sds,sb[18];
	char bf[60];
	register int t;
	register char *p,*q;
	char *sptr;
	int forkid, forkrc;
#ifdef	DEBUG
	int	sigpip();
#endif

	if (av[0][0] == '-')
		delete = 0;
	else
	    delete = 1;
	nseq="001";
	xmt="xmit000";
	if (ac!=3)
	{
		prf("Argument count! (598)\n"); 
		exit(~0);
	};
	fil=av[1];
	p = dir = av[2];
	while(*++p);
	while(*--p != '/');
	q = who;
	while(*q++ = *++p);
	stat(dir,&statb);
	dev = statb.st_dev;
	qid = statb.st_uid;
	cat(4,statf,dir,"/",who,"stat");
	cat(4,lockf,dir,"/",who,"lock");
	if (stat(fil,&statb)<0)
	{
		prf("Cannot access %s. (598)\n",fil); 
		exit(~0);
	};
	if ((0555 & statb.st_mode) != 0444)
	{
		prf("Mode of %s improper. (598)\n",fil); 
		exit(~0);
	};
	if (statb.st_uid == qid && getuid() != qid)
	{
		prf("Violates %s protection. (598)\n",who); 
		exit(~0);
	};
	signal(1,1);
	signal(2,1);
	signal(3,1);
	siz = (statb.st_size + 511) >> 9;
	if (statb.st_dev != dev)
	{
		ofil=fil; 
		fil=0; 
		fil=copy(ofil);
		if (delete) {
			if (unlink(ofil)!=(-1)) ofil=0;
		} 
		else { 
			ofil = 0; 
			delete = 1; 
		} 
	}
	if (fsfree(dev,sb)>=0 && sb[0]<1500 && sb[0]<(siz+500))
	{
		prf("Cannot queue - only %d blocks free on file system ",sb[0]+siz);
		for (p=dir;*p;prc(*p++))
		{
			if (p>dir && *p=='/') break;
		};
		prf(". (597)\n");
		cleanup(~0);
	};
	for (;;)
	{
		if (lock()<0)
		{
			err("enduring lockout"); 
			continue;
		};
		close(0);
		if ((sds=open(statf,2))<0 || read(sds,xmt+4,3)!=3)
		{
			err("stat file error"); 
			continue;
		};
		p=xmt+7; 
		*p=0;
		c=1;
		for (q=nseq+2;q>=nseq;q--)
		{
			t=(*--p);
			if (t<'0' || t>'9') break;
			t=+c; 
			c=0;
			if (t>'9') {
				t='0'; 
				c=1;
			};
			*q=t;
		};
		if (q>=nseq)
		{
			err("stat file corrupted"); 
			continue;
		};
		cat(3,bf,dir,"/",xmt);
		if (link(fil,bf)<0)
		{
			err("cannot link into xmit slot"); 
			continue;
		};
		break;
	};
	if (av[0][1] == '-')
		goto nofork;
	for (t = 0;t < 10;t++) {
		forkid = fork();
		if (forkid == -1) {
			sleep(2);
			continue;
		}
		goto forkok;
	}
	prf("Can't fork rjeqer2.\n");
	cleanup(~0);
forkok:
	if (forkid != 0) {
		while((ppid = wait(&forkrc)) != -1 && ppid != forkid);
		if(ppid == -1){
			kill(forkid, 9);
			prf("Fork error.\n");
			cleanup(~0);
		}
		if (forkrc != 0) {
			prf("rjeqer2 failed (%s, %d).\n", bf, forkrc);
			cleanup(~0);
		}
	} 
	else {
		execl("/usr/hasp/haspqer2","rjeqer2",bf,0);
		exit(-1);
	}
nofork:
	lseek(sds,(long)(0),0);
	write(sds,nseq,3);
	unlock();
	cat(3,bf,dir,"/info/logx",xmt+4);
	if ((t=creat(bf,0644))>=0)
	{
		q = logtty();
		p=prf("%q%s|%d|%s|%s\n",bf,logname(),getuid(),logtty(),q);
		write(t,bf,p-bf);
	};
	prf("Queued as %s/%s.\n",dir,xmt);
	cleanup(0);
};

copy(s)
char *s;
{
	static char f[50];
	int ids,ods,sb[18];
	char bf[512];
	register int t;
	register char *p;
	if ((ids=open(s,0))<0)
	{
		prf("Cannot open %s for copy. (598)\n",s); 
		exit(~0);
	};
	prf("%q%s/pool/qtm%d",f,dir,getpid());
	for (;;)
	{
		if (fsfree(dev,sb)>=0)
		{
			if (sb[0]<(siz+1200) || sb[1]<50)
			{
				err("not enough space to copy"); 
				continue;
			};
		};
		lseek(ids,(long)(0),0);
		if ((t=creat(p=f,0444))<0)
		{
			unlink(p);
			if ((t=creat(p,0444))<0) unlink(p);
		};
		if ((ods=t)<0)
		{
			err("cannot create copy"); 
			continue;
		};
		p=bf;
		while ((t=read(ids,p,512))>0)
		{
			if (write(ods,p,t)!=t) break;
		};
		close(ids);
		close(ods);
		if (t!=0)
		{
			unlink(f); 
			err("read/write error during copy"); 
			continue;
		};
		break;
	};
	chown(f, getuid(), 0);
	return (f);
};

err(s)
char *s;
{
	int x,abrt();
	register int t;
	register char *p;
	unlock();
	prf("%sqer: %s. Try again? (599)  ",who,s);
	signal(1,abrt);
	signal(2,abrt);
	t=0; 
	p=(&x);
	if (read(2,p,1)==1)
	{
		t=0137&(*p);
		while (*p!='\n' && read(2,p,1)==1);
	};
	signal(1,1);
	signal(2,1);
	if (t!='Y') cleanup(~0);
};

abrt()
{
	signal(1,1); 
	signal(2,1); 
	cleanup(~0);
};

cleanup(c)
{
	setuid(getuid());
	if (delete)
		if (fil) unlink(fil);
	if (ofil) unlink(ofil);
	unlock();
	exit(c);
};

#define ENFILE 23

int lox;

lock()
{
	extern int errno;
	int sb[20];
	register int i,t,sf;
	for (sf=t=0;(i=creat(lockf,0))<0;t++)
	{
		if (errno==ENFILE) unlink(lockf);
		if (sf==0 && stat(lockf,&statb)>=0) sf=t+1;
		if (t<sf+20) {
			sleep(2); 
			continue;
		};
		if (sf != 0 && stat(lockf, &statb) >= 0 && statb.st_mtime == statb.st_atime)
		{
			unlink(lockf); 
			sf=t=0; 
			continue;
		};
		return (-1);
	};
	close(i); 
	lox=1;
	return (0);
};

unlock()
{
	if (lox) {
		unlink(lockf); 
		lox=0;
	};
};

char *prfq;

prf(s,a)
char *s;
{
	register int c,*aa;
	register char *p;
	p=s;
	aa=(&a);
	while (c=(*p++))
	{
		if (c!='%') {
			prc(c); 
			continue;
		};
		if ((c=(*p++))==0) break;
		if (c=='c') prc(*aa++);
		if (c=='d') prd(*aa++);
		if (c=='o') pro(*aa++);
		if (c=='s') prs(*aa++);
		if (c=='t') prt(*aa++);
		if (c=='q') prfq=(*aa++);
	};
	if (p=prfq) *p=prfq=0;
	return (p);
};

prc(c)
{
	register char *q;
	if (q=prfq)
	{
		*q++=c; 
		prfq=q; 
		return;
	};
	write(2,&c,1);
};

prd(n)
{
	register int m,k;
	if ((m=n)<0) {
		prc('-'); 
		m=(-m);
	};
	if (k=m/10) prd(k);
	prc('0'+m%10);
};

pro(n)
{
	register int k;
	if (k=017777&(n>>3)) pro(k);
	prc('0'+(7&n));
};

prs(s)
char *s;
{
	register int i;
	register char *p;
	p=s;
	while (i=(*p++)) prc(i);
};

prt(v)
int v[];
{
	register char *p;
	p=ctime(v)+11;
	*(p+8)=0;
	prs(p);
};

notejohn(s)
char *s;
{
	int fd;
	fd=open("/dev/ttyK",1);
	write(fd,s,strlen(s));
	write(fd, "\n\n",2);
	close(fd);
}

#ifdef	DEBUG
sigpip()
{
	prf("Signal 13 received.\n");
	signal(13, sigpip);
	return;
}
#endif
