Ultrix-3.1/src/cmd/uucp/cico.c

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


/**********************************************************************
 *   Copyright (c) Digital Equipment Corporation 1984, 1985, 1986.    *
 *   All Rights Reserved. 					      *
 *   Reference "/usr/src/COPYRIGHT" for applicable restrictions.      *
 **********************************************************************/

#ifndef lint
static char sccsid[] = "@(#)cico.c	3.0 (decvax!larry) 4/22/86";
#endif

/*******
 *	cico - this program is used  to place a call to a
 *	remote machine, login, and copy files between the two machines.
 *	The following options are available:
 *	  -r# : if #==0 operate in slave mode,  if #==1 operate in master mode
 *	  -X# : debugging output from packet level code (pk0.c pk1.c),  0<X<10
 *	  -x# : debugging output from all other routines, 0<x<10
 *	  -sNAME :  start transfer to specified system NAME, if NAME is null
 *		    then start a general poll to all systems that have work.
 *
 *	decvax!larry -  add callcheck() routine to check if remote machine
 *			is using its valid login id.
 * 	decvax!larry -  cleanup code - unnecessary close()'s.
 *		     -  uustat messages added.
 *		     -  cleanup() modified to call clsacu()
 *		     -  intrEXIT() cleans up LCK files.
 *
 */


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


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

int Role = 0;

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


extern int errno;
int Errorrate = 0;
#ifdef	SYSIII
struct termio Savettyb;
#else
struct sgttyb Savettyb;
#endif


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

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


	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(SIGPIPE, onintr);
	signal(SIGINT, onintr);
	signal(SIGHUP, onintr);
	signal(SIGQUIT, onintr);
	signal(SIGTERM, onintr);
	ret = guinfo(getuid(), User, msg);
	ASSERT(ret == 0, "BAD UID ", "", ret);
	strcpy(Loginuser, User);

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

	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':
			Pkdebug = atoi(&argv[1][2]);
			if (Pkdebug <= 0)
				Pkdebug = 1;
			strcat(rflags, argv[1]);
			break;
		case 'x':
			chkdebug(orig_uid);
			Debug = atoi(&argv[1][2]);
			if (Debug <= 0)
				Debug = 1;
			strcat(rflags, argv[1]);
			break;
		case 'f':
			force++;
			break;
		default:
			printf("unknown flag %s\n", argv[1]);
			break;
		}
		--argc;  argv++;
	}


	if (Role == SLAVE) {
		/* initial handshake */
		onesys = 1;
#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);
#else
		ret = ioctl(0, TIOCGETP, &Savettyb);
		Savettyb.sg_flags |= ECHO;
		Savettyb.sg_flags &= ~RAW;
#endif
		Ifn = 0;
		Ofn = 1;
		fixmode(Ifn);
#ifdef NEWLDISC
		ldisc = HCLDISC;
		DEBUG(4,"Switching to new line discipline\n","");
		if ((ret = ioctl(Ifn,TIOCSETD,&ldisc)) < 0) 
			ASSERT_NOFAIL(ret != -1 ,"CAN NOT SWITCH_I LDISC","errno", errno);
		if ((ret = ioctl(Ofn,TIOCSETD,&ldisc)) < 0) 
			ASSERT_NOFAIL(ret != -1 ,"CAN NOT SWITCH_O LDISC","errno", errno);
#endif
		omsg('S', "here", Ofn);
		signal(SIGALRM, timeout);
		alarm(MAXMSGTIME);
		if (setjmp(Sjbuf)) {
			/* timed out */
#ifdef	SYSIII
			ret = ioctl(0, TCSETA, &Savettyb);
#else
			ret = ioctl(0, TIOCSETP, &Savettyb);
#endif
	DEBUG(4,"TIMEOUT\n","");
/* should not exit without closing acus ?
			exit(0);
*/
			cleanup(0);
		}
		for (;;) {
			ret = imsg(msg, Ifn);
			if (ret != 0) {
		DEBUG(4,"Bad return from imsg, ret=%d\n", ret);
				alarm(0);
#ifdef	SYSIII
				ret = ioctl(0, TCSETA, &Savettyb);
#else
				ret = ioctl(0, TIOCSETP, &Savettyb);
#endif
/*
				exit(0);
*/
				cleanup(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);
		}
		sprintf(Spool, "%s/sys/%s", SPOOL, Rmtname);
		ret = callcheck(Loginuser, Rmtname);
		if (ret==1) {
			signal(SIGINT, SIG_IGN);
			signal(SIGHUP, SIG_IGN);
			omsg('R', "CB", Ofn);
			logent("CALLBACK", "REQUIRED");
			/* point Spool to per system spool directory */
			mkspname(Rmtname);
			/*  set up for call back  */
			subchdir(Spool);
			strcpy(Wrkdir, Spool);
			systat(Rmtname, SS_CALLBACK, "CALL BACK");
			gename(CMDPRE, Rmtname, 'C', file);
			close(creat(subfile(file), 0666));
			xuucico(Rmtname);
			cleanup(0);
		}
		else if (ret==2) {
			logent("LOGIN VS MACHINE", "FAILED");
			systat(Rmtname, SS_BADLOGIN, "LOGIN/MACHINE");
			omsg('R', "LOGIN", Ofn);
			cleanup(0);
		     }
		mkspname(Rmtname);  /* determine Spool directory */
		subchdir(Spool);
		fclose(stderr);
		fopen(RMTDEBUG, "w");
		strcpy(Wrkdir, Spool);
		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 'X':
				Pkdebug = atoi(++p);
				if (Pkdebug <= 0)
					Pkdebug = 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, SS_HANDSHAKE, "HANDSHAKE FAILED");
			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, CMDPRE);
		if (ret == FAIL)
			cleanup(100);
		if (ret == 0)
			cleanup(0);
	}
	else if (!force && Role == MASTER && callok(Rmtname) != 0) {
		logent("SYSTEM STATUS", "CAN NOT CALL");
		cleanup(0);
	}

	sprintf(wkpre, "%c.%.7s", CMDPRE, Rmtname);
	mkspname(Rmtname); 
	subchdir(Spool);
	strcpy(Wrkdir, Spool);

	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();
/*
	clsacu should close Dnf which is == Ofn == Ifn.
			close(Ofn);
			close(Ifn);
*/
			Ifn = Ofn = -1;
			rmlock(CNULL);
			sleep(3);
		}
		sprintf(msg, "call to %s ", Rmtname);
		if (mlock(Rmtname) != 0) {
			logent(msg, "LOCKED");
			systat(Rmtname, SS_OK, "STILL TALKING");
			goto next;
		}
		Ofn = Ifn = conn(Rmtname);
		if (Ofn < 0) {
			logent(msg, "FAILED");
			UB_SST(-Ofn);
			systat(Rmtname, Stattype[-Ofn],
				Stattext[-Ofn]);
			clsacu();	
			goto next;
		}
		else {
			logent(msg, "SUCCEEDED");
			systat(Rmtname, SS_CONN_OK, "CONNECT SUCCEEDED");
			UB_SST(ub_ok);
		}
	
		if (setjmp(Sjbuf)) {
			systat(Rmtname, SS_BADCONNECT, "CONNECT TIMEOUT");
			DEBUG(4," timeout-Ofn=%d\n",Ofn);
			goto next;
		}
		signal(SIGALRM, timeout);
		alarm(2 * MAXMSGTIME);
		for (;;) {
			ret = imsg(msg, Ifn);
			if (ret != 0) {
				alarm(0);
				systat(Rmtname, SS_OK, "NO START CHAR");
				goto next;
			}
			if (msg[0] == 'S')
				break;
		}
		alarm(MAXMSGTIME);
		seq = gnxseq(Rmtname);
		sprintf(msg, "%.7s -Q%d %s", Myname, seq, rflags);
#ifdef NEWLDISC
		ldisc = HCLDISC;
		DEBUG(4,"Switching to new line discipline\n","");
/*  Ifn == Ofn  therefore only have to switch one
		if ((ret = ioctl(Ifn,TIOCSETD,&ldisc)) < 0) 
			ASSERT_NOFAIL(ret != -1 ,"CAN NOT SWITCH1 LDISC","errno", errno);
*/
		if ((ret = ioctl(Ofn,TIOCSETD,&ldisc)) < 0) 
			ASSERT_NOFAIL(ret != -1 ,"CAN NOT SWITCH2 LDISC","errno", errno);
#endif
		omsg('S', msg, Ofn);
		for (;;) {
			ret = imsg(msg, Ifn);
			DEBUG(4, "msg-%s\n", msg);
			if (ret != 0) {
				alarm(0);
				ulkseq();
				systat(Rmtname, SS_OK, " NO RECEIVE ACK");
				goto next;
			}
			if (msg[0] == 'R')
				break;
		}
		alarm(0);
		if (msg[1] == 'B') {
			/* bad sequence */
			logent("BAD SEQ", "HANDSHAKE FAILED");
			systat(Rmtname, SS_BADSEQ, "BAD SEQUENCE");
			ulkseq();
			goto next;
		}
		if (strcmp(&msg[1], "OK") != SAME)  {
			logent(&msg[1], "HANDSHAKE FAILED");
			systat(Rmtname, SS_OK, "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 FAILED");
		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) {
			systat(Rmtname, SS_OK, "CONVERSATION FINI");
#ifdef ULTRIX
			US_SST(us_s_ok);
#endif
			logent("conversation complete", "OK");
		}
		else {
			logent("conversation complete", "FAILED");
			systat(Rmtname, SS_OK, "CONVERSATION FAILED");
		}
		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);
	}
next:
	/* just to make sure everything is closed */
/*
	logcls();
	for(i=3; i<20; i++)
		close(i);
*/
	if (!onesys) {
		goto loop;
	}
	cleanup(0);
}


#ifndef	SYSIII
struct sgttyb Hupvec;
#endif

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

cleanup(code)
int code;
{
	int ret;
	char *ttyn;
	char msg[75];

	signal(SIGINT, SIG_IGN);
	signal(SIGHUP, SIG_IGN);
	rmlock(CNULL);
	logcls();
	if (Role == SLAVE) {
#ifdef	SYSIII
		Savettyb.c_cflag |= HUPCL;
		ret = ioctl(0, TCSETA, &Savettyb);
#else
		/* 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 (Role == MASTER) {
			DEBUG(5,"about to close acu\n", "");
			if (Ofn != -1) 
				write(Ofn, EOTMSG, strlen(EOTMSG));
			/* acu may be open but not connected */
			clsacu();
		} else 
			if (Ofn != -1) {
				close(Ifn);
				close(Ofn);
			}
	
	DEBUG(1, "exit code %d\n", code);
	if (code == 0)
		xuuxqt();
	else {
		sprintf(msg, "ABORTED (%d)", code);
		systat(Rmtname, SS_OK, msg);
	}
	exit(code);
}

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

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

/* changed to single version of intrEXIT.  Is this okay? rti!trt */
intrEXIT(signo)
int signo;
{
	char sig[30];
	sprintf(sig, " signal: %d", signo);
	logent(sig, "intrEXIT");
	signal(signo, SIG_DFL);
	setuid(getuid());
	cleanup(signo);
/*
	abort();
*/
}

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

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

#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);
#else
	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
	return;
}


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

timeout()
{
	DEBUG(1, "timeout - %s\n", Rmtname);
	logent(Rmtname, "TIMEOUT");
	longjmp(Sjbuf, 1);
}

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