2.9BSD/usr/src/cmd/uucp/cico.c

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

#ifndef lint
static char sccsid[] = "@(#)cico.c	5.2 (Berkeley) 7/19/83";
#endif

#include "uucp.h"
#include <signal.h>
#include <setjmp.h>
#include <sys/types.h>
#ifdef	SYSIII
#include <termio.h>
#endif
#ifndef	SYSIII
#include <sgtty.h>
#endif


#ifdef UNET
#include <UNET/unetio.h>
#include <UNET/tcp.h>
static struct uiocstate ust;
#endif

jmp_buf Sjbuf;
	/*  call fail text  */
char *Stattext[] = {
	"",
	"BAD SYSTEM",
	"WRONG TIME",
	"SYSTEM LOCKED",
	"NO DEVICE",
	"DIAL FAILED",
	"LOGIN FAILED",
	"BAD SEQUENCE"
	};

int Role = 0;
	/*  call fail codes  */
int Stattype[] = {0, 0, 0, 0,
	SS_NODEVICE, SS_FAIL, SS_FAIL, SS_BADSEQ
	};


int Errorrate = 0;
#ifdef	SYSIII
struct termio Savettyb;
#endif
#ifndef	SYSIII
struct sgttyb Savettyb;
#endif

/*******
 *	cico - this program is used  to place a call to a
 *	remote machine, login, and copy files between the two machines.
 */

main(argc, argv)
register char *argv[];
{
	register int ret;
	int seq;
	int onesys = 0;
	char wkpre[NAMESIZE], file[NAMESIZE];
	char msg[BUFSIZ], *q;
	register char *p;
	extern onintr(), timeout(), setdebug();
	extern intrEXIT();
	extern char *pskip();
	char rflags[30];
	char *ttyn;
	int orig_uid = getuid();

	strcpy(Progname, "uucico");
	uucpname(Myname);

	/* Try to run as uucp -- rti!trt */
	setgid(getegid());
	setuid(geteuid());

	signal(SIGILL, intrEXIT);
	signal(SIGTRAP, intrEXIT);
	signal(SIGIOT, intrEXIT);
	signal(SIGEMT, intrEXIT);
	signal(SIGFPE, intrEXIT);
	signal(SIGBUS, intrEXIT);
	signal(SIGSEGV, intrEXIT);
	signal(SIGSYS, intrEXIT);
	signal(SIGINT, onintr);
	signal(SIGHUP, onintr);
	signal(SIGQUIT, onintr);
	signal(SIGTERM, onintr);
	signal(SIGPIPE, onintr);	/* 4.1a tcp-ip stupidity */
	signal(SIGFPE, setdebug);
	ret = guinfo(getuid(), User, msg);
	strcpy(Loginuser, User);
	ASSERT(ret == 0, "BAD UID ", "", ret);

	rflags[0] = '\0';
	umask(WFMASK);
	strcpy(Rmtname, Myname);
	Ifn = Ofn = -1;
	while(argc>1 && argv[1][0] == '-'){
		switch(argv[1][1]){
		case 'd':
			Spool = &argv[1][2];
			break;
#ifdef PROTODEBUG
		case 'E':
			Errorrate = atoi(&argv[1][2]);
			if (Errorrate <= 0)
				Errorrate = 100;
			break;
		case 'g':
			Pkdrvon = 1;
			break;
		case 'G':
			Pkdrvon = 1;
			strcat(rflags, " -g ");
			break;
#endif
		case 'r':
			Role = atoi(&argv[1][2]);
			break;
		case 's':
			sprintf(Rmtname, "%.7s", &argv[1][2]);
			if (Rmtname[0] != '\0')
				onesys = 1;
			break;
		case 'x':
			chkdebug(orig_uid);
			Debug = atoi(&argv[1][2]);
			if (Debug <= 0)
				Debug = 1;
			strcat(rflags, argv[1]);
			logent("ENABLED", "DEBUG");
			break;
		default:
			printf("unknown flag %s\n", argv[1]);
			break;
		}
		--argc;  argv++;
	}

	subchdir(Spool);
	strcpy(Wrkdir, Spool);

#ifdef	UNET
/*
 * Determine if we are on UNET
 */
	ret = ioctl(0, UIOCSTATE, &ust);
	if (ret == 0) {
		Unet = 1;
		DEBUG(4, "UNET connection -- ioctl-s disabled\n", "");
	}
#endif
	if (Role == SLAVE) {
		/* initial handshake */
		onesys = 1;
		if (!Unet) {
#ifdef	SYSIII
			ret = ioctl(0, TCGETA, &Savettyb);
			Savettyb.c_cflag = (Savettyb.c_cflag & ~CS8) | CS7;
			Savettyb.c_oflag |= OPOST;
			Savettyb.c_lflag |= (ISIG|ICANON|ECHO);
#endif
#ifndef	SYSIII
			ret = ioctl(0, TIOCGETP, &Savettyb);
			Savettyb.sg_flags |= ECHO;
			Savettyb.sg_flags &= ~RAW;
#endif
		}
		Ifn = 0;
		Ofn = 1;
		fixmode(Ifn);
		fclose(stderr);
		fopen(RMTDEBUG, "w");
		omsg('S', "here", Ofn);
		signal(SIGALRM, timeout);
		alarm(MAXMSGTIME);
		if (setjmp(Sjbuf)) {
			/* timed out */
			if (!Unet) {
#ifdef	SYSIII
				ret = ioctl(0, TCSETA, &Savettyb);
#endif
#ifndef	SYSIII
				ret = ioctl(0, TIOCSETP, &Savettyb);
#endif
			}
			exit(0);
		}
		for (;;) {
			ret = imsg(msg, Ifn);
			if (ret != 0) {
				alarm(0);
				if (!Unet) {
#ifdef	SYSIII
					ret = ioctl(0, TCSETA, &Savettyb);
#endif
#ifndef	SYSIII
					ret = ioctl(0, TIOCSETP, &Savettyb);
#endif
				}
				exit(0);
			}
			if (msg[0] == 'S')
				break;
		}
		alarm(0);
		q = &msg[1];
		p = pskip(q);
		sprintf(Rmtname, "%.7s", q);
		DEBUG(4, "sys-%s\n", Rmtname);
		if (mlock(Rmtname)) {
			omsg('R', "LCK", Ofn);
			cleanup(0);
		}
		else if (callback(Loginuser)) {
			signal(SIGINT, SIG_IGN);
			signal(SIGHUP, SIG_IGN);
			omsg('R', "CB", Ofn);
			logent("CALLBACK", "REQUIRED");
			/*  set up for call back  */
			systat(Rmtname, SS_CALLBACK, "CALL BACK");
			gename(CMDPRE, Rmtname, 'C', file);
			close(creat(subfile(file), 0666));
			xuucico(Rmtname);
			cleanup(0);
		}
		seq = 0;
		while (*p == '-') {
			q = pskip(p);
			switch(*(++p)) {
			case 'g':
				Pkdrvon = 1;
				break;
			case 'x':
				Debug = atoi(++p);
				if (Debug <= 0)
					Debug = 1;
				break;
			case 'Q':
				seq = atoi(++p);
				break;
			default:
				break;
			}
			p = q;
		}
		if (callok(Rmtname) == SS_BADSEQ) {
			logent("BADSEQ", "PREVIOUS");
			omsg('R', "BADSEQ", Ofn);
			cleanup(0);
		}
		if ((ret = gnxseq(Rmtname)) == seq) {
			omsg('R', "OK", Ofn);
			cmtseq();
		}
		else {
			systat(Rmtname, Stattype[7], Stattext[7]);
			logent("BAD SEQ", "HANDSHAKE FAILED");
			ulkseq();
			omsg('R', "BADSEQ", Ofn);
			cleanup(0);
		}
		ttyn = ttyname(Ifn);
		if (ttyn != NULL)
			chmod(ttyn, 0600);
	}
loop:
	if (!onesys) {
		ret = gnsys(Rmtname, Spool, CMDPRE);
		if (ret == FAIL)
			cleanup(100);
		if (ret == 0)
			cleanup(0);
	}
	else if (Role == MASTER && callok(Rmtname) != 0) {
		logent("SYSTEM STATUS", "CAN NOT CALL");
		cleanup(0);
	}

	sprintf(wkpre, "%c.%.7s", CMDPRE, Rmtname);

	if (Role == MASTER) {
		/*  master part */
		signal(SIGINT, SIG_IGN);
		signal(SIGHUP, SIG_IGN);
		signal(SIGQUIT, SIG_IGN);
		if (!iswrk(file, "chk", Spool, wkpre) && !onesys) {
			logent(Rmtname, "NO WORK");
			goto next;
		}
		if (Ifn != -1 && Role == MASTER) {
			write(Ofn, EOTMSG, strlen(EOTMSG));
			clsacu();
			close(Ofn);
			close(Ifn);
			Ifn = Ofn = -1;
			rmlock(CNULL);
			sleep(3);
		}
		sprintf(msg, "call to %s ", Rmtname);
		if (mlock(Rmtname) != 0) {
			logent(msg, "LOCKED");
			goto next;
		}
		Ofn = Ifn = conn(Rmtname);
		if (Ofn < 0) {
			logent(msg, "FAILED");
			systat(Rmtname, Stattype[-Ofn],
				Stattext[-Ofn]);
			goto next;
		}
		else {
			logent(msg, "SUCCEEDED");
		}
	
		if (setjmp(Sjbuf))
			goto next;
		signal(SIGALRM, timeout);
		alarm(2 * MAXMSGTIME);
		for (;;) {
			ret = imsg(msg, Ifn);
			if (ret != 0) {
				alarm(0);
				logent("imsg 1", "FAILED");
				goto next;
			}
			if (msg[0] == 'S')
				break;
		}
		alarm(MAXMSGTIME);
		seq = gnxseq(Rmtname);
		sprintf(msg, "%.7s -Q%d %s", Myname, seq, rflags);
		omsg('S', msg, Ofn);
		for (;;) {
			ret = imsg(msg, Ifn);
			DEBUG(4, "msg-%s\n", msg);
			if (ret != 0) {
				alarm(0);
				ulkseq();
				logent("imsg 2", "FAILED");
				goto next;
			}
			if (msg[0] == 'R')
				break;
		}
		alarm(0);
		if (msg[1] == 'B') {
			/* bad sequence */
			logent("BAD SEQ", "HANDSHAKE FAILED");
			systat(Rmtname, Stattype[7], Stattext[7]);
			ulkseq();
			goto next;
		}
		if (strcmp(&msg[1], "OK") != SAME)  {
			logent(&msg[1], "HANDSHAKE FAILED");
			ulkseq();
			goto next;
		}
		cmtseq();
	}
	DEBUG(1, " Rmtname %s, ", Rmtname);
	DEBUG(1, "Role %s,  ", Role ? "MASTER" : "SLAVE");
	DEBUG(1, "Ifn - %d, ", Ifn);
	DEBUG(1, "Loginuser - %s\n", Loginuser);

	alarm(MAXMSGTIME);
	if (setjmp(Sjbuf))
		goto Failure;
	ret = startup(Role);
	alarm(0);
	if (ret != SUCCESS) {
Failure:
		logent("startup", "FAILED");
		systat(Rmtname, SS_FAIL, "STARTUP");
		goto next;
	}
	else {
		logent("startup", "OK");
		systat(Rmtname, SS_INPROGRESS, "TALKING");
		ret = cntrl(Role, wkpre);
		DEBUG(1, "cntrl - %d\n", ret);
		signal(SIGINT, SIG_IGN);
		signal(SIGHUP, SIG_IGN);
		signal(SIGALRM, timeout);
		if (ret == 0) {
			logent("conversation complete", "OK");
			rmstat(Rmtname);

		}
		else {
			logent("conversation complete", "FAILED");
			systat(Rmtname, SS_FAIL, "CONVERSATION");
		}
		alarm(MAXMSGTIME);
		omsg('O', "OOOOO", Ofn);
		DEBUG(4, "send OO %d,", ret);
		if (!setjmp(Sjbuf)) {
			for (;;) {
				omsg('O', "OOOOO", Ofn);
				ret = imsg(msg, Ifn);
				if (ret != 0)
					break;
				if (msg[0] == 'O')
					break;
			}
		}
		alarm(0);
		clsacu();	/* rti!trt: is this needed? */
	}
next:
	if (!onesys) {
		goto loop;
	}
	cleanup(0);
}

#ifndef	SYSIII
struct sgttyb Hupvec;
#endif

/***
 *	cleanup(code)	cleanup and exit with "code" status
 *	int code;
 */

cleanup(code)
register int code;
{
	register int ret;
	register char *ttyn;

	signal(SIGINT, SIG_IGN);
	signal(SIGHUP, SIG_IGN);
	rmlock(CNULL);
	clsacu();
	logcls();
	if (Role == SLAVE) {
		if (!Unet) {
#ifdef	SYSIII
			Savettyb.c_cflag |= HUPCL;
			ret = ioctl(0, TCSETA, &Savettyb);
#endif
#ifndef	SYSIII
			/* rti!trt:  use more robust hang up sequence */
			ret = ioctl(0, TIOCHPCL, STBNULL);
			ret = ioctl(0, TIOCGETP, &Hupvec);
			Hupvec.sg_ispeed = B0;
			Hupvec.sg_ospeed = B0;
			ret = ioctl(0, TIOCSETP, &Hupvec);
			sleep(2);
			ret = ioctl(0, TIOCSETP, &Savettyb);
#endif
			DEBUG(4, "ret ioctl - %d\n", ret);
		}
		ttyn = ttyname(Ifn);
		if (ttyn != NULL)
			chmod(ttyn, 0600);
	}
	if (Ofn != -1) {
		if (Role == MASTER)
			write(Ofn, EOTMSG, strlen(EOTMSG));
		close(Ifn);
		close(Ofn);
	}
	DEBUG(1, "exit code %d\n", code);
	if (code == 0)
		xuuxqt();
	exit(code);
}

/***
 *	onintr(inter)	interrupt - remove locks and exit
 */

onintr(inter)
register int inter;
{
	char str[30];
	signal(inter, SIG_IGN);
	sprintf(str, "SIGNAL %d", inter);
	logent(str, "CAUGHT");
	systat(Rmtname, SS_FAIL, str);
	cleanup(inter);
}

/* changed to single version of intrEXIT.  Is this okay? rti!trt */
intrEXIT(signo)
int signo;
{
	signal(signo, SIG_DFL);
	setgid(getgid());
	setuid(getuid());
	abort();
}
/*
 * Catch a special signal
 * (SIGFPE, ugh), and toggle debugging between 0 and 30.
 * Handy for looking in on long running uucicos.
 */
setdebug()
{
	if (Debug < 30)
		Debug = 30;
	else
		Debug = 0;
}


/***
 *	fixmode(tty)	fix kill/echo/raw on line
 *
 *	return codes:  none
 */

fixmode(tty)
register int tty;
{
#ifdef	SYSIII
	struct termio ttbuf;
#endif
#ifndef	SYSIII
	struct sgttyb ttbuf;
#endif
	register int ret;

	if (Unet)
		return;
#ifdef	SYSIII
	ioctl(tty, TCGETA, &ttbuf);
	ttbuf.c_iflag = ttbuf.c_oflag = ttbuf.c_lflag = (ushort)0;
	ttbuf.c_cflag &= (CBAUD);
	ttbuf.c_cflag |= (CS8|CREAD);
	ttbuf.c_cc[VMIN] = 6;
	ttbuf.c_cc[VTIME] = 1;
	ret = ioctl(tty, TCSETA, &ttbuf);
#endif
#ifndef	SYSIII
	ioctl(tty, TIOCGETP, &ttbuf);
	ttbuf.sg_flags = (ANYP | RAW);
	ret = ioctl(tty, TIOCSETP, &ttbuf);
#endif
	ASSERT(ret >= 0, "STTY FAILED", "", ret);
#ifndef	SYSIII
	ioctl(tty, TIOCEXCL, STBNULL);
#endif
}


/***
 *	timeout()	catch SIGALRM routine
 */

timeout()
{
	logent(Rmtname, "TIMEOUT");
	systat(Rmtname, SS_FAIL, "TIMEOUT");
	longjmp(Sjbuf, 1);
}

static char *
pskip(p)
register char *p;
{
	while( *p && *p != ' ' )
		++p;
	if( *p ) *p++ = 0;
	return(p);
}