xref: /csrg-svn/usr.bin/uucp/uucico/cico.c (revision 17767)
113639Ssam #ifndef lint
2*17767Sralph static char sccsid[] = "@(#)cico.c	5.5 (Berkeley) 01/22/85";
313639Ssam #endif
413639Ssam 
513639Ssam #include "uucp.h"
613639Ssam #include <signal.h>
713639Ssam #include <setjmp.h>
813639Ssam #include <sys/types.h>
9*17767Sralph #ifdef	USG
1013639Ssam #include <termio.h>
1113639Ssam #endif
12*17767Sralph #ifndef	USG
1313639Ssam #include <sgtty.h>
1413639Ssam #endif
15*17767Sralph #ifdef BSDTCP
16*17767Sralph #include <netdb.h>
17*17767Sralph #include <netinet/in.h>
18*17767Sralph #include <sys/socket.h>
19*17767Sralph #endif BSDTCP
20*17767Sralph #include <sys/stat.h>
21*17767Sralph #include "uust.h"
22*17767Sralph #include "uusub.h"
2313639Ssam 
24*17767Sralph jmp_buf Sjbuf;
25*17767Sralph jmp_buf Pipebuf;
2613639Ssam 
27*17767Sralph /*  call fail text  */
2813639Ssam char *Stattext[] = {
2913639Ssam 	"",
3013639Ssam 	"BAD SYSTEM",
31*17767Sralph 	"WRONG TIME TO CALL",
3213639Ssam 	"SYSTEM LOCKED",
3313639Ssam 	"NO DEVICE",
3413639Ssam 	"DIAL FAILED",
3513639Ssam 	"LOGIN FAILED",
3613639Ssam 	"BAD SEQUENCE"
37*17767Sralph };
3813639Ssam 
39*17767Sralph /*  call fail codes  */
40*17767Sralph int Stattype[] = {
41*17767Sralph 	0,
42*17767Sralph 	0,
43*17767Sralph 	SS_WRONGTIME,
44*17767Sralph 	0,
45*17767Sralph 	SS_NODEVICE,
46*17767Sralph 	SS_FAIL,
47*17767Sralph 	SS_FAIL,
48*17767Sralph 	SS_BADSEQ
49*17767Sralph };
5013639Ssam 
5113639Ssam 
5213639Ssam int Errorrate = 0;
53*17767Sralph int ReverseRole = 0;
54*17767Sralph int StdErrIsTty = 0;
55*17767Sralph int Role = SLAVE;
56*17767Sralph int onesys = 0;
57*17767Sralph extern int LocalOnly;
58*17767Sralph extern char MaxGrade;
59*17767Sralph 
60*17767Sralph #ifdef	USG
6113639Ssam struct termio Savettyb;
6213639Ssam #endif
63*17767Sralph #ifndef	USG
6413639Ssam struct sgttyb Savettyb;
6513639Ssam #endif
6613639Ssam 
6713639Ssam /*******
6813639Ssam  *	cico - this program is used  to place a call to a
6913639Ssam  *	remote machine, login, and copy files between the two machines.
7013639Ssam  */
7113639Ssam 
7213639Ssam main(argc, argv)
7313639Ssam register char *argv[];
7413639Ssam {
7513639Ssam 	register int ret;
7613639Ssam 	int seq;
7713639Ssam 	char wkpre[NAMESIZE], file[NAMESIZE];
78*17767Sralph 	char msg[MAXFULLNAME], *q, **alias;
7913639Ssam 	register char *p;
8013639Ssam 	extern onintr(), timeout(), setdebug();
8113639Ssam 	extern char *pskip();
8213639Ssam 	char rflags[30];
8313639Ssam 	char *ttyn;
84*17767Sralph #if defined(VMS) && defined(BSDTCP)
85*17767Sralph 	u_long Hostnumber = 0;
86*17767Sralph #endif VMS && BSDTCP
8713639Ssam 
8813639Ssam 	strcpy(Progname, "uucico");
8913639Ssam 	uucpname(Myname);
9013639Ssam 
9113639Ssam 	signal(SIGINT, onintr);
9213639Ssam 	signal(SIGHUP, onintr);
9313639Ssam 	signal(SIGQUIT, onintr);
9413639Ssam 	signal(SIGTERM, onintr);
9513639Ssam 	signal(SIGPIPE, onintr);	/* 4.1a tcp-ip stupidity */
9613639Ssam 	signal(SIGFPE, setdebug);
9713639Ssam 	ret = guinfo(getuid(), User, msg);
9813639Ssam 	strcpy(Loginuser, User);
99*17767Sralph 	ASSERT(ret == 0, "BAD UID", CNULL, ret);
10013639Ssam 
101*17767Sralph #ifdef BSD4_2
102*17767Sralph 	setlinebuf(stderr);
103*17767Sralph #endif
10413639Ssam 	rflags[0] = '\0';
10513639Ssam 	umask(WFMASK);
10613639Ssam 	strcpy(Rmtname, Myname);
10713639Ssam 	Ifn = Ofn = -1;
10813639Ssam 	while(argc>1 && argv[1][0] == '-'){
10913639Ssam 		switch(argv[1][1]){
11013639Ssam 		case 'd':
11113639Ssam 			Spool = &argv[1][2];
11213639Ssam 			break;
11313639Ssam 		case 'g':
114*17767Sralph 			MaxGrade = argv[1][2];
11513639Ssam 			break;
11613639Ssam 		case 'r':
11713639Ssam 			Role = atoi(&argv[1][2]);
11813639Ssam 			break;
119*17767Sralph 		case 'R':
120*17767Sralph 			ReverseRole++;
121*17767Sralph 			Role = MASTER;
122*17767Sralph 			break;
12313639Ssam 		case 's':
12413639Ssam 			sprintf(Rmtname, "%.7s", &argv[1][2]);
12513639Ssam 			if (Rmtname[0] != '\0')
12613639Ssam 				onesys = 1;
12713639Ssam 			break;
12813639Ssam 		case 'x':
129*17767Sralph 			chkdebug();
13013639Ssam 			Debug = atoi(&argv[1][2]);
13113639Ssam 			if (Debug <= 0)
13213639Ssam 				Debug = 1;
13313639Ssam 			strcat(rflags, argv[1]);
13413639Ssam 			logent("ENABLED", "DEBUG");
13513639Ssam 			break;
136*17767Sralph 		case 'L':	/* local calls only */
137*17767Sralph 			LocalOnly++;
138*17767Sralph 			break;
139*17767Sralph #if defined(VMS) && defined(BSDTCP)
140*17767Sralph 		case 'h':
141*17767Sralph 			Hostnumber = inet_addr(&argv[1][2]);
142*17767Sralph 			break;
143*17767Sralph #endif VMS && BSDTCP
14413639Ssam 		default:
145*17767Sralph 			printf("unknown flag %s (ignored)\n", argv[1]);
14613639Ssam 			break;
14713639Ssam 		}
14813639Ssam 		--argc;  argv++;
14913639Ssam 	}
15013639Ssam 
151*17767Sralph 	while (argc > 1) {
152*17767Sralph 		printf("unknown argument %s (ignored)\n", argv[1]);
153*17767Sralph 		--argc; argv++;
154*17767Sralph 	}
155*17767Sralph 
156*17767Sralph 	/* Try to run as uucp -- rti!trt */
157*17767Sralph 	setgid(getegid());
158*17767Sralph 	setuid(geteuid());
159*17767Sralph #ifdef	TIOCNOTTY
160*17767Sralph 	/*
161*17767Sralph 	 * detach uucico from controlling terminal
162*17767Sralph 	 * to defend against rlogind sending us a SIGKILL (!!!)
163*17767Sralph 	 */
164*17767Sralph 	if (Role == MASTER && (ret = open("/dev/tty", 2)) >= 0) {
165*17767Sralph 		ioctl(ret, TIOCNOTTY, STBNULL);
166*17767Sralph 		close(ret);
167*17767Sralph 	}
168*17767Sralph #endif TIOCNOTTY
169*17767Sralph #ifdef BSD4_2
170*17767Sralph 	if (getpgrp(0) == 0) { /*We have no controlling terminal */
171*17767Sralph 		setpgrp(0, getpid());
172*17767Sralph 	}
173*17767Sralph #endif BSD4_2
174*17767Sralph 
175*17767Sralph 	ret = subchdir(Spool);
176*17767Sralph 	ASSERT(ret >= 0, "CHDIR FAILED", Spool, ret);
17713639Ssam 	strcpy(Wrkdir, Spool);
17813639Ssam 
17913639Ssam 	if (Role == SLAVE) {
180*17767Sralph 		/* check for /etc/nologin */
181*17767Sralph 		ultouch();	/* sets nologinflag as a side effect */
182*17767Sralph 		if (nologinflag) {
183*17767Sralph 			logent(NOLOGIN, "UUCICO SHUTDOWN");
184*17767Sralph 			if (Debug)
185*17767Sralph 				logent("DEBUGGING", "continuing anyway");
186*17767Sralph 			else
187*17767Sralph 				cleanup(1);
188*17767Sralph 		}
189*17767Sralph #ifdef	TCPIP
190*17767Sralph 		/*
191*17767Sralph 		 * Determine if we are on TCPIP
192*17767Sralph 		 */
193*17767Sralph 		if (isatty(0) ==  0) {
194*17767Sralph 			IsTcpIp = 1;
195*17767Sralph 			DEBUG(4, "TCPIP connection -- ioctl-s disabled\n", CNULL);
196*17767Sralph 		}
197*17767Sralph #endif TCPIP
19813639Ssam 		/* initial handshake */
19913639Ssam 		onesys = 1;
200*17767Sralph 		if (!IsTcpIp) {
201*17767Sralph #ifdef	USG
20213639Ssam 			ret = ioctl(0, TCGETA, &Savettyb);
20313639Ssam 			Savettyb.c_cflag = (Savettyb.c_cflag & ~CS8) | CS7;
20413639Ssam 			Savettyb.c_oflag |= OPOST;
20513639Ssam 			Savettyb.c_lflag |= (ISIG|ICANON|ECHO);
206*17767Sralph #else !USG
20713639Ssam 			ret = ioctl(0, TIOCGETP, &Savettyb);
20813639Ssam 			Savettyb.sg_flags |= ECHO;
20913639Ssam 			Savettyb.sg_flags &= ~RAW;
210*17767Sralph #endif !USG
21113639Ssam 		}
21213639Ssam 		Ifn = 0;
21313639Ssam 		Ofn = 1;
21413639Ssam 		fixmode(Ifn);
215*17767Sralph 		sprintf(file,"%s/%d", RMTDEBUG, getpid());
216*17767Sralph #ifdef VMS
217*17767Sralph 		/* hold the version number down */
218*17767Sralph 		unlink(file);
219*17767Sralph #endif
220*17767Sralph 		freopen(file, "w", stderr);
221*17767Sralph #ifdef BSD4_2
222*17767Sralph 		setlinebuf(stderr);
223*17767Sralph #else  !BSD4_2
224*17767Sralph 		setbuf(stderr, NULL);
225*17767Sralph #endif !BSD4_2
226*17767Sralph 		sprintf(msg, "here=%s", Myname);
227*17767Sralph 		omsg('S', msg, Ofn);
22813639Ssam 		signal(SIGALRM, timeout);
22913639Ssam 		alarm(MAXMSGTIME);
23013639Ssam 		if (setjmp(Sjbuf)) {
23113639Ssam 			/* timed out */
232*17767Sralph 			if (!IsTcpIp) {
233*17767Sralph #ifdef	USG
23413639Ssam 				ret = ioctl(0, TCSETA, &Savettyb);
23513639Ssam #endif
236*17767Sralph #ifndef	USG
23713639Ssam 				ret = ioctl(0, TIOCSETP, &Savettyb);
23813639Ssam #endif
23913639Ssam 			}
240*17767Sralph 			cleanup(0);
24113639Ssam 		}
24213639Ssam 		for (;;) {
24313639Ssam 			ret = imsg(msg, Ifn);
24413639Ssam 			if (ret != 0) {
24513639Ssam 				alarm(0);
246*17767Sralph 				if (!IsTcpIp) {
247*17767Sralph #ifdef	USG
24813639Ssam 					ret = ioctl(0, TCSETA, &Savettyb);
24913639Ssam #endif
250*17767Sralph #ifndef	USG
25113639Ssam 					ret = ioctl(0, TIOCSETP, &Savettyb);
25213639Ssam #endif
25313639Ssam 				}
254*17767Sralph 				cleanup(0);
25513639Ssam 			}
25613639Ssam 			if (msg[0] == 'S')
25713639Ssam 				break;
25813639Ssam 		}
25913639Ssam 		alarm(0);
26013639Ssam 		q = &msg[1];
26113639Ssam 		p = pskip(q);
26213639Ssam 		sprintf(Rmtname, "%.7s", q);
263*17767Sralph 		sprintf(wkpre,"%s/%s", RMTDEBUG, Rmtname);
264*17767Sralph 		unlink(wkpre);
265*17767Sralph 		if (link(file, wkpre) == 0)
266*17767Sralph 			unlink(file);
26713639Ssam 		DEBUG(4, "sys-%s\n", Rmtname);
268*17767Sralph #ifdef BSDTCP
269*17767Sralph 		/* we must make sure they are really who they say they
270*17767Sralph 		 * are. We compare the hostnumber with the number in the hosts
271*17767Sralph 		 * table for the site they claim to be.
272*17767Sralph 		 */
273*17767Sralph 		if (IsTcpIp) {
274*17767Sralph 			struct hostent *hp;
275*17767Sralph 			char *cpnt, *inet_ntoa();
276*17767Sralph 			int fromlen;
277*17767Sralph 			struct sockaddr_in from;
278*17767Sralph 
279*17767Sralph #ifndef	VMS
280*17767Sralph 			fromlen = sizeof(from);
281*17767Sralph 			if (getpeername(0, &from, &fromlen) < 0) {
282*17767Sralph 				logent(Rmtname, "NOT A TCP CONNECTION");
283*17767Sralph 				omsg('R', "NOT TCP", Ofn);
284*17767Sralph 				cleanup(0);
285*17767Sralph 			}
286*17767Sralph #else	VMS
287*17767Sralph 			from.sin_addr.s_addr = Hostnumber;
288*17767Sralph 			from.sin_family = AF_INET;
289*17767Sralph #endif	VMS
290*17767Sralph 			hp = gethostbyaddr(&from.sin_addr,
291*17767Sralph 				sizeof (struct in_addr), from.sin_family);
292*17767Sralph 			if (hp == 0) {
293*17767Sralph 				/* security break or just old host table? */
294*17767Sralph 				logent(Rmtname, "UNKNOWN IP-HOST Name =");
295*17767Sralph 				cpnt = inet_ntoa(from.sin_addr),
296*17767Sralph 				logent(cpnt, "UNKNOWN IP-HOST Number =");
297*17767Sralph 				sprintf(wkpre, "%s/%s isn't in my host table",
298*17767Sralph 					Rmtname, cpnt);
299*17767Sralph 				omsg('R' ,wkpre ,Ofn);
300*17767Sralph 				cleanup(0);
301*17767Sralph 			}
302*17767Sralph 			if (Debug>99)
303*17767Sralph 				logent(Rmtname,"Request from IP-Host name =");
304*17767Sralph 			/* The following is to determine if the name given us by
305*17767Sralph 			 * the Remote uucico matches any of the names(aliases)
306*17767Sralph 			 * given its network number (remote machine) in our
307*17767Sralph 			 * host table.
308*17767Sralph 			 */
309*17767Sralph 			if (strncmp(q, hp->h_name, 7) == 0) {
310*17767Sralph 				if (Debug > 99)
311*17767Sralph 					logent(q,"Found in host Tables");
312*17767Sralph 			} else { /* Scan The host aliases */
313*17767Sralph 				for(alias=hp->h_aliases; *alias!=0 &&
314*17767Sralph 				    strncmp(q, *alias, 7) != 0; ++alias)
315*17767Sralph 					;
316*17767Sralph 				if (strncmp(q, *alias, 7) != 0) {
317*17767Sralph 					logent(q, "FORGED HOSTNAME");
318*17767Sralph 					logent(inet_ntoa(from.sin_addr), "ORIGINATED AT");
319*17767Sralph 					omsg('R',"You're not who you claim to be");
320*17767Sralph 					cleanup(0);
321*17767Sralph 				}
322*17767Sralph #ifdef DEBUG
323*17767Sralph 				if (Debug> 99)
324*17767Sralph 					logent(q,"Found in host Tables");
325*17767Sralph #endif
326*17767Sralph 			}
327*17767Sralph 		}
328*17767Sralph #endif	BSDTCP
329*17767Sralph 
330*17767Sralph #ifdef	NOSTRANGERS
331*17767Sralph 		/* If we don't know them, we won't talk to them... */
332*17767Sralph 		if (versys(Rmtname)) {
333*17767Sralph 			logent(Rmtname, "UNKNOWN HOST");
334*17767Sralph 			omsg('R', "You are unknown to me", Ofn);
335*17767Sralph 			cleanup(0);
336*17767Sralph 		}
337*17767Sralph #endif	NOSTRANGERS
33813639Ssam 		if (mlock(Rmtname)) {
33913639Ssam 			omsg('R', "LCK", Ofn);
34013639Ssam 			cleanup(0);
34113639Ssam 		}
34213639Ssam 		else if (callback(Loginuser)) {
34313639Ssam 			signal(SIGINT, SIG_IGN);
34413639Ssam 			signal(SIGHUP, SIG_IGN);
34513639Ssam 			omsg('R', "CB", Ofn);
34613639Ssam 			logent("CALLBACK", "REQUIRED");
34713639Ssam 			/*  set up for call back  */
348*17767Sralph 			systat(Rmtname, SS_CALLBACK, "CALLING BACK");
34913639Ssam 			gename(CMDPRE, Rmtname, 'C', file);
35013639Ssam 			close(creat(subfile(file), 0666));
35113639Ssam 			xuucico(Rmtname);
35213639Ssam 			cleanup(0);
35313639Ssam 		}
35413639Ssam 		seq = 0;
35513639Ssam 		while (*p == '-') {
35613639Ssam 			q = pskip(p);
35713639Ssam 			switch(*(++p)) {
35813639Ssam 			case 'x':
35913639Ssam 				Debug = atoi(++p);
36013639Ssam 				if (Debug <= 0)
36113639Ssam 					Debug = 1;
36213639Ssam 				break;
36313639Ssam 			case 'Q':
36413639Ssam 				seq = atoi(++p);
36513639Ssam 				break;
36613639Ssam 			default:
36713639Ssam 				break;
36813639Ssam 			}
36913639Ssam 			p = q;
37013639Ssam 		}
37113639Ssam 		if (callok(Rmtname) == SS_BADSEQ) {
37213639Ssam 			logent("BADSEQ", "PREVIOUS");
37313639Ssam 			omsg('R', "BADSEQ", Ofn);
37413639Ssam 			cleanup(0);
37513639Ssam 		}
376*17767Sralph #ifdef GNXSEQ
37713639Ssam 		if ((ret = gnxseq(Rmtname)) == seq) {
37813639Ssam 			omsg('R', "OK", Ofn);
37913639Ssam 			cmtseq();
380*17767Sralph 		} else {
381*17767Sralph #else !GNXSEQ
382*17767Sralph 		if (seq == 0)
383*17767Sralph 			omsg('R', "OK", Ofn);
38413639Ssam 		else {
385*17767Sralph #endif !GNXSEQ
38613639Ssam 			systat(Rmtname, Stattype[7], Stattext[7]);
387*17767Sralph 			logent("BAD SEQ", "HANDSHAKE FAIL");
388*17767Sralph #ifdef GNXSEQ
38913639Ssam 			ulkseq();
390*17767Sralph #endif GNXSEQ
39113639Ssam 			omsg('R', "BADSEQ", Ofn);
39213639Ssam 			cleanup(0);
39313639Ssam 		}
39413639Ssam 		ttyn = ttyname(Ifn);
39513639Ssam 		if (ttyn != NULL)
39613639Ssam 			chmod(ttyn, 0600);
397*17767Sralph 	} else { /* Role == MASTER */
398*17767Sralph 		struct stat stbuf;
399*17767Sralph 		if (isatty(fileno(stderr)) || (fstat(fileno(stderr),&stbuf) == 0
400*17767Sralph 		    && stbuf.st_mode&S_IFREG) )
401*17767Sralph 			StdErrIsTty =  1;
402*17767Sralph 		setdebug(0);
40313639Ssam 	}
404*17767Sralph 
40513639Ssam loop:
406*17767Sralph 	if(setjmp(Pipebuf)) {	/* come here on SIGPIPE	*/
407*17767Sralph 		clsacu();
408*17767Sralph 		close(Ofn);
409*17767Sralph 		close(Ifn);
410*17767Sralph 		Ifn = Ofn = -1;
411*17767Sralph 		rmlock(CNULL);
412*17767Sralph 		sleep(3);
413*17767Sralph 	}
41413639Ssam 	if (!onesys) {
415*17767Sralph 		struct stat sbuf;
416*17767Sralph 
417*17767Sralph 		if (!StdErrIsTty) {
418*17767Sralph 			sprintf(file, "%s/%s", RMTDEBUG, Rmtname);
419*17767Sralph 			if (stat(file, &sbuf) == 0 && sbuf.st_size == 0)
420*17767Sralph 				unlink(file);
421*17767Sralph 		}
42213639Ssam 		ret = gnsys(Rmtname, Spool, CMDPRE);
423*17767Sralph 		setdebug(0);
42413639Ssam 		if (ret == FAIL)
42513639Ssam 			cleanup(100);
42613639Ssam 		if (ret == 0)
42713639Ssam 			cleanup(0);
428*17767Sralph 	} else if (Role == MASTER && callok(Rmtname) != 0) {
42913639Ssam 		logent("SYSTEM STATUS", "CAN NOT CALL");
43013639Ssam 		cleanup(0);
43113639Ssam 	}
43213639Ssam 
43313639Ssam 	sprintf(wkpre, "%c.%.7s", CMDPRE, Rmtname);
43413639Ssam 
435*17767Sralph 	signal(SIGINT, SIG_IGN);
436*17767Sralph 	signal(SIGQUIT, SIG_IGN);
43713639Ssam 	if (Role == MASTER) {
438*17767Sralph 		/* check for /etc/nologin */
439*17767Sralph 		ultouch();	/* sets nologinflag as a side effect */
440*17767Sralph 		if (nologinflag) {
441*17767Sralph 			logent(NOLOGIN, "UUCICO SHUTDOWN");
442*17767Sralph 			if (Debug)
443*17767Sralph 				logent("DEBUGGING", "continuing anyway");
444*17767Sralph 			else
445*17767Sralph 				cleanup(1);
446*17767Sralph 		}
44713639Ssam 		/*  master part */
44813639Ssam 		signal(SIGHUP, SIG_IGN);
44913639Ssam 		if (!iswrk(file, "chk", Spool, wkpre) && !onesys) {
45013639Ssam 			logent(Rmtname, "NO WORK");
45113639Ssam 			goto next;
45213639Ssam 		}
45313639Ssam 		if (Ifn != -1 && Role == MASTER) {
45413639Ssam 			write(Ofn, EOTMSG, strlen(EOTMSG));
45513639Ssam 			clsacu();
45613639Ssam 			close(Ofn);
45713639Ssam 			close(Ifn);
45813639Ssam 			Ifn = Ofn = -1;
45913639Ssam 			rmlock(CNULL);
46013639Ssam 			sleep(3);
46113639Ssam 		}
46213639Ssam 		sprintf(msg, "call to %s ", Rmtname);
46313639Ssam 		if (mlock(Rmtname) != 0) {
46413639Ssam 			logent(msg, "LOCKED");
465*17767Sralph 			US_SST(us_s_lock);
46613639Ssam 			goto next;
46713639Ssam 		}
46813639Ssam 		Ofn = Ifn = conn(Rmtname);
46913639Ssam 		if (Ofn < 0) {
470*17767Sralph 			if (Ofn != CF_TIME)
471*17767Sralph 				logent(msg, _FAILED);
472*17767Sralph 			/* avoid excessive 'wrong time' info */
473*17767Sralph 			if (Stattype[-Ofn] != SS_WRONGTIME || argv[0][0] != 'U'){
474*17767Sralph 				systat(Rmtname, Stattype[-Ofn], Stattext[-Ofn]);
475*17767Sralph 				US_SST(-Ofn);
476*17767Sralph 				UB_SST(-Ofn);
477*17767Sralph 			}
47813639Ssam 			goto next;
479*17767Sralph 		} else {
48013639Ssam 			logent(msg, "SUCCEEDED");
481*17767Sralph 			US_SST(us_s_cok);
482*17767Sralph 			UB_SST(ub_ok);
48313639Ssam 		}
484*17767Sralph #ifdef	TCPIP
485*17767Sralph 		/*
486*17767Sralph 		 * Determine if we are on TCPIP
487*17767Sralph 		 */
488*17767Sralph 		if (isatty(Ifn) ==  0) {
489*17767Sralph 			IsTcpIp = 1;
490*17767Sralph 			DEBUG(4, "TCPIP connection -- ioctl-s disabled\n", CNULL);
491*17767Sralph 		}
492*17767Sralph #endif
493*17767Sralph 
49413639Ssam 		if (setjmp(Sjbuf))
49513639Ssam 			goto next;
49613639Ssam 		signal(SIGALRM, timeout);
49713639Ssam 		alarm(2 * MAXMSGTIME);
49813639Ssam 		for (;;) {
49913639Ssam 			ret = imsg(msg, Ifn);
50013639Ssam 			if (ret != 0) {
50113639Ssam 				alarm(0);
502*17767Sralph 				logent("imsg 1", _FAILED);
503*17767Sralph 				goto Failure;
50413639Ssam 			}
50513639Ssam 			if (msg[0] == 'S')
50613639Ssam 				break;
50713639Ssam 		}
50813639Ssam 		alarm(MAXMSGTIME);
509*17767Sralph #ifdef GNXSEQ
51013639Ssam 		seq = gnxseq(Rmtname);
511*17767Sralph #else !GNXSEQ
512*17767Sralph 		seq = 0;
513*17767Sralph #endif !GNXSEQ
51413639Ssam 		sprintf(msg, "%.7s -Q%d %s", Myname, seq, rflags);
51513639Ssam 		omsg('S', msg, Ofn);
51613639Ssam 		for (;;) {
51713639Ssam 			ret = imsg(msg, Ifn);
51813639Ssam 			DEBUG(4, "msg-%s\n", msg);
519*17767Sralph 			if (ret != SUCCESS) {
52013639Ssam 				alarm(0);
521*17767Sralph #ifdef GNXSEQ
52213639Ssam 				ulkseq();
523*17767Sralph #endif GNXSEQ
524*17767Sralph 				logent("imsg 2", _FAILED);
525*17767Sralph 				goto Failure;
52613639Ssam 			}
52713639Ssam 			if (msg[0] == 'R')
52813639Ssam 				break;
52913639Ssam 		}
53013639Ssam 		alarm(0);
53113639Ssam 		if (msg[1] == 'B') {
53213639Ssam 			/* bad sequence */
533*17767Sralph 			logent("BAD SEQ", "HANDSHAKE FAIL");
534*17767Sralph 			US_SST(us_s_hand);
535*17767Sralph 			systat(Rmtname, SS_BADSEQ, Stattext[SS_BADSEQ]);
536*17767Sralph #ifdef GNXSEQ
53713639Ssam 			ulkseq();
538*17767Sralph #endif GNXSEQ
53913639Ssam 			goto next;
54013639Ssam 		}
54113639Ssam 		if (strcmp(&msg[1], "OK") != SAME)  {
542*17767Sralph 			logent(&msg[1], "HANDSHAKE FAIL");
543*17767Sralph 			US_SST(us_s_hand);
544*17767Sralph #ifdef GNXSEQ
54513639Ssam 			ulkseq();
546*17767Sralph #endif GNXSEQ
547*17767Sralph 			systat(Rmtname, SS_INPROGRESS,
548*17767Sralph 				strcmp(&msg[1], "CB") == SAME?
549*17767Sralph 				"AWAITING CALLBACK": "HANDSHAKE FAIL");
55013639Ssam 			goto next;
55113639Ssam 		}
552*17767Sralph #ifdef GNXSEQ
55313639Ssam 		cmtseq();
554*17767Sralph #endif GNXSEQ
55513639Ssam 	}
556*17767Sralph 	DEBUG(1, "Rmtname %s, ", Rmtname);
55713639Ssam 	DEBUG(1, "Role %s,  ", Role ? "MASTER" : "SLAVE");
55813639Ssam 	DEBUG(1, "Ifn - %d, ", Ifn);
55913639Ssam 	DEBUG(1, "Loginuser - %s\n", Loginuser);
56013639Ssam 
56113639Ssam 	alarm(MAXMSGTIME);
56213639Ssam 	if (setjmp(Sjbuf))
56313639Ssam 		goto Failure;
56413639Ssam 	ret = startup(Role);
56513639Ssam 	alarm(0);
56613639Ssam 	if (ret != SUCCESS) {
567*17767Sralph 		logent("startup", _FAILED);
56813639Ssam Failure:
569*17767Sralph 		US_SST(us_s_start);
570*17767Sralph 		systat(Rmtname, SS_FAIL, "STARTUP FAILED");
57113639Ssam 		goto next;
572*17767Sralph 	} else {
57313639Ssam 		logent("startup", "OK");
574*17767Sralph 		US_SST(us_s_gress);
57513639Ssam 		systat(Rmtname, SS_INPROGRESS, "TALKING");
57613639Ssam 		ret = cntrl(Role, wkpre);
57713639Ssam 		DEBUG(1, "cntrl - %d\n", ret);
57813639Ssam 		signal(SIGINT, SIG_IGN);
57913639Ssam 		signal(SIGHUP, SIG_IGN);
58013639Ssam 		signal(SIGALRM, timeout);
581*17767Sralph 		if (ret == SUCCESS) {
58213639Ssam 			logent("conversation complete", "OK");
583*17767Sralph 			US_SST(us_s_ok);
58413639Ssam 			rmstat(Rmtname);
58513639Ssam 
586*17767Sralph 		} else {
587*17767Sralph 			logent("conversation complete", _FAILED);
588*17767Sralph 			US_SST(us_s_cf);
589*17767Sralph 			systat(Rmtname, SS_FAIL, "CONVERSATION FAILED");
59013639Ssam 		}
59113639Ssam 		alarm(MAXMSGTIME);
59213639Ssam 		DEBUG(4, "send OO %d,", ret);
59313639Ssam 		if (!setjmp(Sjbuf)) {
59413639Ssam 			for (;;) {
59513639Ssam 				omsg('O', "OOOOO", Ofn);
59613639Ssam 				ret = imsg(msg, Ifn);
59713639Ssam 				if (ret != 0)
59813639Ssam 					break;
59913639Ssam 				if (msg[0] == 'O')
60013639Ssam 					break;
60113639Ssam 			}
60213639Ssam 		}
60313639Ssam 		alarm(0);
604*17767Sralph 		clsacu();
605*17767Sralph 		rmlock(CNULL);
60613639Ssam 	}
60713639Ssam next:
60813639Ssam 	if (!onesys) {
60913639Ssam 		goto loop;
61013639Ssam 	}
61113639Ssam 	cleanup(0);
61213639Ssam }
61313639Ssam 
614*17767Sralph #ifndef	USG
61513639Ssam struct sgttyb Hupvec;
61613639Ssam #endif
61713639Ssam 
61813639Ssam /***
61913639Ssam  *	cleanup(code)	cleanup and exit with "code" status
62013639Ssam  *	int code;
62113639Ssam  */
62213639Ssam 
62313639Ssam cleanup(code)
62413639Ssam register int code;
62513639Ssam {
62613639Ssam 	register int ret;
62713639Ssam 	register char *ttyn;
628*17767Sralph 	char bfr[BUFSIZ];
629*17767Sralph 	struct stat sbuf;
63013639Ssam 
63113639Ssam 	signal(SIGINT, SIG_IGN);
63213639Ssam 	signal(SIGHUP, SIG_IGN);
63313639Ssam 	rmlock(CNULL);
63413639Ssam 	clsacu();
63513639Ssam 	logcls();
63613639Ssam 	if (Role == SLAVE) {
637*17767Sralph 		if (!IsTcpIp) {
638*17767Sralph #ifdef USG
63913639Ssam 			Savettyb.c_cflag |= HUPCL;
64013639Ssam 			ret = ioctl(0, TCSETA, &Savettyb);
641*17767Sralph #else !USG
64213639Ssam 			ret = ioctl(0, TIOCHPCL, STBNULL);
64313639Ssam 			ret = ioctl(0, TIOCGETP, &Hupvec);
64413639Ssam 			Hupvec.sg_ispeed = B0;
64513639Ssam 			Hupvec.sg_ospeed = B0;
64613639Ssam 			ret = ioctl(0, TIOCSETP, &Hupvec);
64713639Ssam 			sleep(2);
64813639Ssam 			ret = ioctl(0, TIOCSETP, &Savettyb);
649*17767Sralph 			/* make *sure* exclusive access is off */
650*17767Sralph 			ret = ioctl(0, TIOCNXCL, STBNULL);
651*17767Sralph #endif !USG
65213639Ssam 			DEBUG(4, "ret ioctl - %d\n", ret);
65313639Ssam 		}
65413639Ssam 		ttyn = ttyname(Ifn);
65513639Ssam 		if (ttyn != NULL)
65613639Ssam 			chmod(ttyn, 0600);
65713639Ssam 	}
65813639Ssam 	if (Ofn != -1) {
65913639Ssam 		if (Role == MASTER)
66013639Ssam 			write(Ofn, EOTMSG, strlen(EOTMSG));
66113639Ssam 		close(Ifn);
66213639Ssam 		close(Ofn);
66313639Ssam 	}
66413639Ssam 	if (code == 0)
66513639Ssam 		xuuxqt();
666*17767Sralph 	else
667*17767Sralph 		DEBUG(1, "exit code %d\n", code);
668*17767Sralph 	sprintf(bfr, "%s/%s", RMTDEBUG, Rmtname);
669*17767Sralph 	if (stat(bfr, &sbuf) == 0 && sbuf.st_size == 0)
670*17767Sralph 		unlink(bfr);
671*17767Sralph 	sprintf(bfr, "%s/%d", RMTDEBUG, getpid());
672*17767Sralph 	unlink(bfr);
67313639Ssam 	exit(code);
67413639Ssam }
67513639Ssam 
67613639Ssam /***
67713639Ssam  *	onintr(inter)	interrupt - remove locks and exit
67813639Ssam  */
67913639Ssam 
68013639Ssam onintr(inter)
68113639Ssam register int inter;
68213639Ssam {
68313639Ssam 	char str[30];
68413639Ssam 	signal(inter, SIG_IGN);
68513639Ssam 	sprintf(str, "SIGNAL %d", inter);
68613639Ssam 	logent(str, "CAUGHT");
687*17767Sralph 	US_SST(us_s_intr);
688*17767Sralph 	if (*Rmtname && strcmp(Rmtname, Myname))
689*17767Sralph 		systat(Rmtname, SS_FAIL, str);
690*17767Sralph 	if (inter == SIGPIPE && !onesys)
691*17767Sralph 		longjmp(Pipebuf, 1);
69213639Ssam 	cleanup(inter);
69313639Ssam }
69413639Ssam 
69513639Ssam /*
69613639Ssam  * Catch a special signal
69713639Ssam  * (SIGFPE, ugh), and toggle debugging between 0 and 30.
69813639Ssam  * Handy for looking in on long running uucicos.
69913639Ssam  */
700*17767Sralph setdebug(code)
701*17767Sralph int code;
70213639Ssam {
703*17767Sralph 	char buf[BUFSIZ];
704*17767Sralph 
705*17767Sralph 	if (!StdErrIsTty) {
706*17767Sralph 		sprintf(buf,"%s/%s", RMTDEBUG, Rmtname);
707*17767Sralph 		unlink(buf);
708*17767Sralph 		freopen(buf, "w", stderr);
709*17767Sralph #ifdef BSD4_2
710*17767Sralph 		setlinebuf(stderr);
711*17767Sralph #else  !BSD4_2
712*17767Sralph 		setbuf(stderr, NULL);
713*17767Sralph #endif !BSD4_2
714*17767Sralph 	}
715*17767Sralph 	if (code) {
716*17767Sralph 		if (Debug == 0)
717*17767Sralph 			Debug = 30;
718*17767Sralph 		else
719*17767Sralph 			Debug = 0;
720*17767Sralph 	}
72113639Ssam }
72213639Ssam 
72313639Ssam 
72413639Ssam /***
72513639Ssam  *	fixmode(tty)	fix kill/echo/raw on line
72613639Ssam  *
72713639Ssam  *	return codes:  none
72813639Ssam  */
72913639Ssam 
73013639Ssam fixmode(tty)
73113639Ssam register int tty;
73213639Ssam {
733*17767Sralph #ifdef	USG
73413639Ssam 	struct termio ttbuf;
73513639Ssam #endif
736*17767Sralph #ifndef	USG
73713639Ssam 	struct sgttyb ttbuf;
73813639Ssam #endif
73913639Ssam 	register int ret;
74013639Ssam 
741*17767Sralph 	if (IsTcpIp)
74213639Ssam 		return;
743*17767Sralph #ifdef	USG
744*17767Sralph 	ret = ioctl(tty, TCGETA, &ttbuf);
74513639Ssam 	ttbuf.c_iflag = ttbuf.c_oflag = ttbuf.c_lflag = (ushort)0;
74613639Ssam 	ttbuf.c_cflag &= (CBAUD);
74713639Ssam 	ttbuf.c_cflag |= (CS8|CREAD);
74813639Ssam 	ttbuf.c_cc[VMIN] = 6;
74913639Ssam 	ttbuf.c_cc[VTIME] = 1;
75013639Ssam 	ret = ioctl(tty, TCSETA, &ttbuf);
75113639Ssam #endif
752*17767Sralph #ifndef	USG
75313639Ssam 	ioctl(tty, TIOCGETP, &ttbuf);
75413639Ssam 	ttbuf.sg_flags = (ANYP | RAW);
75513639Ssam 	ret = ioctl(tty, TIOCSETP, &ttbuf);
75613639Ssam #endif
757*17767Sralph /*	ASSERT(ret >= 0, "STTY FAILED", CNULL, ret); */
758*17767Sralph #ifndef	USG
759*17767Sralph 	ret = ioctl(tty, TIOCEXCL, STBNULL);
76013639Ssam #endif
76113639Ssam }
76213639Ssam 
76313639Ssam 
76413639Ssam /***
76513639Ssam  *	timeout()	catch SIGALRM routine
76613639Ssam  */
76713639Ssam 
76813639Ssam timeout()
76913639Ssam {
77013639Ssam 	logent(Rmtname, "TIMEOUT");
771*17767Sralph 	if (*Rmtname && strcmp(Rmtname, Myname)) {
772*17767Sralph 		US_SST(us_s_tmot);
773*17767Sralph 		systat(Rmtname, SS_FAIL, "TIMEOUT");
774*17767Sralph 	}
77513639Ssam 	longjmp(Sjbuf, 1);
77613639Ssam }
77713639Ssam 
77813639Ssam static char *
77913639Ssam pskip(p)
78013639Ssam register char *p;
78113639Ssam {
782*17767Sralph 	while(*p && *p != ' ')
78313639Ssam 		++p;
784*17767Sralph 	if(*p)
785*17767Sralph 		*p++ = 0;
786*17767Sralph 	return p;
78713639Ssam }
788