xref: /csrg-svn/usr.bin/uucp/uucico/conn.c (revision 33562)
113642Ssam 
223596Sbloom #include <signal.h>
313642Ssam #include "uucp.h"
413642Ssam #include <setjmp.h>
513642Ssam #include <ctype.h>
613642Ssam #include <errno.h>
717834Sralph #ifdef	USG
813642Ssam #include <termio.h>
913642Ssam #include <fcntl.h>
1013642Ssam #endif
1117834Sralph #ifndef	USG
1213642Ssam #include <sgtty.h>
1313642Ssam #endif
1417834Sralph #ifdef BSD4_2
1517834Sralph #include <sys/time.h>
1617834Sralph #else
1717834Sralph #include <time.h>
1817834Sralph #endif
1913642Ssam 
2013642Ssam #define MAXC 1000
2113642Ssam 
2213642Ssam extern jmp_buf Sjbuf;
2317834Sralph jmp_buf Cjbuf;
2418619Sralph extern int errno, onesys;
2517834Sralph extern char *sys_errlist[];
2618619Sralph extern char MaxGrade, DefMaxGrade;
2713642Ssam 
2813642Ssam /* Parity control during login procedure */
2913642Ssam #define	P_ZERO	0
3013642Ssam #define	P_ONE	1
3113642Ssam #define	P_EVEN	2
3213642Ssam #define	P_ODD	3
3317834Sralph 
3417834Sralph #define ABORT -2
3517834Sralph 
3617834Sralph char 	*AbortOn = NULL;
3713642Ssam char	par_tab[128];	/* must be power of two */
3817834Sralph int	linebaudrate;	/* used for the sleep test in pk1.c */
3913642Ssam int next_fd = -1;	/* predicted fd to close interrupted opens */
4025705Sbloom 
4125705Sbloom char *PCP = "PCP";	/* PC Pursuit device type */
4225127Sbloom /*
4325127Sbloom  *	catch alarm routine for "expect".
4413642Ssam  */
4513642Ssam alarmtr()
4613642Ssam {
4713642Ssam 	signal(SIGALRM, alarmtr);
4813642Ssam 	if (next_fd >= 0) {
4913642Ssam 		if (close(next_fd))
5013642Ssam 			logent("FAIL", "ACU LINE CLOSE");
5113642Ssam 		next_fd = -1;
5213642Ssam 	}
5313642Ssam 	longjmp(Sjbuf, 1);
5413642Ssam }
5513642Ssam 
5625705Sbloom /* This template is for seismo to call ihnp4
5725705Sbloom  * the 3 lines marked ---> will be overwritten for the appropriate city
5825705Sbloom  */
5925705Sbloom #define PCP_BAUD	3
6025705Sbloom #define PCP_PHONE	4
61*33562Srick #define PCP_CITY	14
62*33562Srick #define PCP_PASSWORD	16
63*33562Srick #define PCP_RPHONE	20
64*33562Srick #define NPCFIELDS	23
6525705Sbloom 
6625705Sbloom static char *PCFlds[] = {
6725705Sbloom 	"PC-PURSUIT",
6825705Sbloom 	"Any",
6925705Sbloom 	"ACU",
7025705Sbloom 	"1200",
71*33562Srick 	CNULL,
72*33562Srick 	CNULL,
73*33562Srick 	"P_ZERO",	/* Telenet insists on zero parity */
7425705Sbloom 	"ABORT",
75*33562Srick 	"BUSY",		/* Abort on Busy Signal */
76*33562Srick 	CNULL,
77*33562Srick 	"\\d\\d\\r\\d\\r",	/* Get telenet's attention */
78*33562Srick 	"TERMINAL=~3-\r-TERM~3-\r-TERM~5", 	/* Terminal type ? */
79*33562Srick 	"\\r",
80*33562Srick 	"@",		/* telenet's prompt */
81*33562Srick 	"D/DCWAS/21,telenetloginstring", /* overwritten later */
82*33562Srick 	"PASSWORD",
83*33562Srick 	CNULL,		/* telenet password */
84*33562Srick 	"CONNECTED",	/* We're now talking to a Hayes in the remote city */
85*33562Srick 	"ATZ",		/* Reset it */
86*33562Srick 	"OK",
87*33562Srick 	"ATDT6907171", /* overwritten */
88*33562Srick 	"CONNECT",
89*33562Srick 	"\\d\\r",		/* We're in !*/
90*33562Srick 	CNULL,
9125705Sbloom };
9225705Sbloom 
93*33562Srick static char PCP_brand[25];
9425705Sbloom 
9518619Sralph /*
9618619Sralph  *	place a telephone call to system and login, etc.
9713642Ssam  *
9813642Ssam  *	return codes:
9913642Ssam  *		CF_SYSTEM: don't know system
10013642Ssam  *		CF_TIME: wrong time to call
10113642Ssam  *		CF_DIAL: call failed
10213642Ssam  *		CF_NODEV: no devices available to place call
10313642Ssam  *		CF_LOGIN: login/password dialog failed
10413642Ssam  *
10513642Ssam  *		>0  - file no.  -  connect ok
10613642Ssam  */
10713642Ssam 
10813642Ssam int Dcf = -1;
10917834Sralph char *Flds[MAXC/10];
11025966Sbloom char LineType[10];
11117834Sralph extern int LocalOnly;
11213642Ssam 
11313642Ssam conn(system)
11413642Ssam char *system;
11513642Ssam {
11625705Sbloom 	int nf;
11718619Sralph 	char info[MAXC], wkpre[NAMESIZE], file[NAMESIZE];
11813642Ssam 	register FILE *fsys;
11913642Ssam 	int fcode = 0;
12013642Ssam 
12113642Ssam 	nf = 0;
12213642Ssam 
12313642Ssam 	fsys = fopen(SYSFILE, "r");
12413642Ssam 	ASSERT(fsys != NULL, "CAN'T OPEN", SYSFILE, 0);
12513642Ssam 
12617834Sralph 	DEBUG(4, "finds (%s) called\n", system);
12725127Sbloom keeplooking:
12817834Sralph 	while((nf = finds(fsys, system, info, Flds)) > 0) {
12925966Sbloom 		strncpy(LineType, Flds[F_LINE], 10);
13017834Sralph 		if (LocalOnly) {
13125966Sbloom 			if (strcmp("TCP", LineType)
13225966Sbloom 				&& strcmp("DIR", LineType)
13325966Sbloom 				&& strcmp("LOCAL", LineType) ) {
13425705Sbloom 					fcode = CF_TIME;
13525705Sbloom 					continue;
13625705Sbloom 			}
13717834Sralph 		}
13823596Sbloom 		sprintf(wkpre, "%c.%.*s", CMDPRE, SYSNSIZE, Rmtname);
13918619Sralph 		if (!onesys && MaxGrade != DefMaxGrade &&
14025705Sbloom 			!iswrk(file, "chk", Spool, wkpre))  {
14125705Sbloom 				fcode = CF_TIME;
14225705Sbloom 				continue;
14325705Sbloom 		}
14425705Sbloom 		/* For GTE's PC Pursuit */
14525966Sbloom 		if (snccmp(LineType, PCP) == SAME) {
14625705Sbloom 			FILE *dfp;
14725705Sbloom 			int status;
14825705Sbloom 			static struct Devices dev;
149*33562Srick 
15025705Sbloom 			dfp = fopen(DEVFILE, "r");
15125705Sbloom 			ASSERT(dfp != NULL, "Can't open", DEVFILE, 0);
15225705Sbloom 			while ((status=rddev(dfp, &dev)) != FAIL
15325705Sbloom 				&& strcmp(PCP, dev.D_type) != SAME)
15425705Sbloom 					;
15525705Sbloom 			fclose(dfp);
15625705Sbloom 			if (status == FAIL)
15725705Sbloom 				continue;
15825705Sbloom 			if (mlock(PCP) == FAIL) {
15925705Sbloom 				fcode = CF_NODEV;
16025705Sbloom 				logent("DEVICE", "NO");
16125705Sbloom 				continue;
16225705Sbloom 			}
16325705Sbloom 			PCFlds[PCP_BAUD] = dev.D_class;
16425705Sbloom 			PCFlds[PCP_PHONE] = dev.D_calldev;
165*33562Srick 			sprintf(PCFlds[PCP_CITY], "c d/%s%s,%s",
166*33562Srick 				Flds[F_CLASS],
167*33562Srick 				index(Flds[F_CLASS], '/') == NULL ? "/12" : "",
168*33562Srick 				dev.D_arg[D_CHAT]);
169*33562Srick 			PCFlds[PCP_PASSWORD] = dev.D_line;
170*33562Srick 			strncpy(&PCFlds[PCP_RPHONE][4], Flds[F_PHONE], 7);
17125705Sbloom 			strncpy(PCP_brand, dev.D_brand, sizeof(PCP_brand));
172*33562Srick 			if ((fcode = getto(PCFlds)) < 0) {
173*33562Srick 				rmlock(PCP);
17425705Sbloom 				continue;
175*33562Srick 			}
17625705Sbloom 			Dcf = fcode;
17725705Sbloom 			fcode = login(NPCFIELDS, PCFlds, Dcf);
178*33562Srick 			if (fcode == SUCCESS)
179*33562Srick 				break;
180*33562Srick 			fcode = CF_DIAL;
181*33562Srick 			rmlock(PCP);
182*33562Srick 			/* end PC Pursuit */
183*33562Srick 		} else if ((fcode = getto(Flds)) > 0)  {
184*33562Srick 			Dcf = fcode;
18513642Ssam 			break;
186*33562Srick 		}
18713642Ssam 	}
18813642Ssam 
18925127Sbloom 	if (nf <= 0) {
19025127Sbloom 		fclose(fsys);
19117834Sralph 		return fcode ? fcode : nf;
19225127Sbloom 	}
19313642Ssam 
19425705Sbloom 
19525705Sbloom 	if (fcode >= 0) {
19625705Sbloom 		DEBUG(4, "login %s\n", "called");
197*33562Srick 		fcode = login(nf, Flds, Dcf); }
19825705Sbloom 	if (fcode < 0) {
19913642Ssam 		clsacu();
20025705Sbloom 		if (fcode == ABORT) {
20125127Sbloom 			fcode = CF_DIAL;
20225127Sbloom 			goto  keeplooking;
20325127Sbloom 		} else {
20425127Sbloom 			fclose(fsys);
20523596Sbloom 			return CF_LOGIN;
20625127Sbloom 		}
20713642Ssam 	}
20825127Sbloom 	fclose(fsys);
20925705Sbloom 	fioclex(Dcf);
21025705Sbloom 	return Dcf;
21113642Ssam }
21213642Ssam 
21325127Sbloom /*
21425127Sbloom  *	connect to remote machine
21513642Ssam  *
21613642Ssam  *	return codes:
21713642Ssam  *		>0  -  file number - ok
21813642Ssam  *		FAIL  -  failed
21913642Ssam  */
22013642Ssam 
22113642Ssam getto(flds)
22213642Ssam register char *flds[];
22313642Ssam {
22413642Ssam 	register struct condev *cd;
22513642Ssam 	int nulldev(), diropn();
22625127Sbloom 	char *line;
22713642Ssam 
22817834Sralph 	DEBUG(4, "getto: call no. %s ", flds[F_PHONE]);
22913642Ssam 	DEBUG(4, "for sys %s\n", flds[F_NAME]);
23013642Ssam 
23125127Sbloom 	if (snccmp(flds[F_LINE], "LOCAL") == SAME)
23225127Sbloom 		line = "ACU";
23325127Sbloom 	else
23425127Sbloom 		line = flds[F_LINE];
23525127Sbloom #ifdef DIALINOUT
23625127Sbloom 	if (snccmp(line, "ACU") != SAME)
23725127Sbloom 		reenable();
23825127Sbloom #endif DIALINOUT
23913642Ssam 	CU_end = nulldev;
24025705Sbloom 	if (snccmp(line, PCP) == SAME) {
24125705Sbloom 		for(cd = condevs; cd->CU_meth != NULL; cd++) {
24225705Sbloom 			if (snccmp(PCP_brand, cd->CU_brand) == SAME) {
24325705Sbloom 				CU_end = cd->CU_clos;
24425705Sbloom 				return diropn(flds);
24525705Sbloom 			}
24613642Ssam 		}
24725705Sbloom 		logent(PCP_brand, "UNSUPPORTED ACU TYPE");
24825705Sbloom 	} else {
24925705Sbloom 		for (cd = condevs; cd->CU_meth != NULL; cd++) {
25025705Sbloom 			if (snccmp(cd->CU_meth, line) == SAME) {
25125705Sbloom 				DEBUG(4, "Using %s to call\n", cd->CU_meth);
25225705Sbloom 				return (*(cd->CU_gen))(flds);
25325705Sbloom 			}
25425705Sbloom 		}
25525705Sbloom 		DEBUG(1, "Can't find %s, assuming DIR\n", flds[F_LINE]);
25613642Ssam 	}
25717834Sralph 	return diropn(flds);	/* search failed, so use direct */
25817834Sralph }
25913642Ssam 
26025127Sbloom /*
26125127Sbloom  *	close call unit
26213642Ssam  *
26313642Ssam  *	return codes:  none
26413642Ssam  */
26513642Ssam 
26613642Ssam int (*CU_end)() = nulldev;
26713642Ssam clsacu()
26813642Ssam {
26917834Sralph 	/* make *sure* Dcf is no longer exclusive.
27017834Sralph 	 * Otherwise dual call-in/call-out modems could get stuck.
27117834Sralph 	 * Unfortunately, doing this here is not ideal, but it is the
27217834Sralph 	 * easiest place to put the call.
27317834Sralph 	 * Hopefully everyone honors the LCK protocol, of course
27417834Sralph 	 */
27525705Sbloom #ifdef	TIOCNXCL
27623596Sbloom 	if (!IsTcpIp && Dcf >= 0 && ioctl(Dcf, TIOCNXCL, STBNULL) < 0)
27723596Sbloom 		DEBUG(5, "clsacu ioctl %s\n", sys_errlist[errno]);
27817834Sralph #endif
27917834Sralph 	if  (setjmp(Sjbuf))
28017834Sralph 		logent(Rmtname, "CLOSE TIMEOUT");
28117834Sralph 	else {
28217834Sralph 		signal(SIGALRM, alarmtr);
28317834Sralph 		alarm(20);
28417834Sralph 		(*(CU_end))(Dcf);
28517834Sralph 		alarm(0);
28617834Sralph 	}
28713642Ssam 	if (close(Dcf) == 0) {
28813642Ssam 		DEBUG(4, "fd %d NOT CLOSED by CU_clos\n", Dcf);
28913642Ssam 		logent("clsacu", "NOT CLOSED by CU_clos");
29013642Ssam 	}
29113642Ssam 	Dcf = -1;
29213642Ssam 	CU_end = nulldev;
29313642Ssam }
29413642Ssam 
29525127Sbloom /*
29625127Sbloom  *	expand phone number for given prefix and number
29713642Ssam  */
29813642Ssam 
29913642Ssam exphone(in, out)
30013642Ssam register char *in, *out;
30113642Ssam {
30213642Ssam 	FILE *fn;
30313642Ssam 	char pre[MAXPH], npart[MAXPH], tpre[MAXPH], p[MAXPH];
30413642Ssam 	char buf[BUFSIZ];
30513642Ssam 	register char *s1;
30613642Ssam 
30717834Sralph 	if (!isascii(*in) || !isalpha(*in)) {
30813642Ssam 		strcpy(out, in);
30913642Ssam 		return;
31013642Ssam 	}
31113642Ssam 
31213642Ssam 	s1=pre;
31317834Sralph 	while (isascii(*in) && isalpha(*in))
31413642Ssam 		*s1++ = *in++;
31513642Ssam 	*s1 = '\0';
31613642Ssam 	s1 = npart;
31713642Ssam 	while (*in != '\0')
31813642Ssam 		*s1++ = *in++;
31913642Ssam 	*s1 = '\0';
32013642Ssam 
32113642Ssam 	tpre[0] = '\0';
32213642Ssam 	if ((fn = fopen(DIALFILE, "r")) == NULL)
32313642Ssam 		DEBUG(2, "CAN'T OPEN %s\n", DIALFILE);
32413642Ssam 	else {
32513642Ssam 		while (cfgets(buf, BUFSIZ, fn)) {
32617834Sralph 			if (sscanf(buf, "%s%s", p, tpre) != 2)
32717834Sralph 				continue;
32813642Ssam 			if (strcmp(p, pre) == SAME)
32913642Ssam 				goto found;
33013642Ssam 			tpre[0] = '\0';
33113642Ssam 		}
33213642Ssam 		DEBUG(2, "CAN'T FIND dialcodes prefix '%s'\n", pre);
33313642Ssam 	found:;
33413642Ssam 		fclose(fn);
33513642Ssam 	}
33613642Ssam 
33713642Ssam 	strcpy(out, tpre);
33813642Ssam 	strcat(out, npart);
33913642Ssam }
34013642Ssam 
34118619Sralph /*
34218619Sralph  *	read and decode a line from device file
34313642Ssam  *
34413642Ssam  *	return code - FAIL at end-of file; 0 otherwise
34513642Ssam  */
34613642Ssam 
34713642Ssam rddev(fp, dev)
34813642Ssam register struct Devices *dev;
34913642Ssam FILE *fp;
35013642Ssam {
35117834Sralph 	register int na;
35213642Ssam 
35317834Sralph 	if (!cfgets(dev->D_argbfr, sizeof(dev->D_argbfr), fp))
35417834Sralph 		return FAIL;
35517834Sralph 	na = getargs(dev->D_argbfr, dev->D_arg, 20);
35617834Sralph 	ASSERT(na >= 4, "BAD DEVICE ENTRY", dev->D_argbfr, 0);
35717834Sralph 	if (na == 4) {
35817834Sralph 		dev->D_brand = "";
35917834Sralph 		na++;
36017834Sralph 	}
36113642Ssam 	dev->D_speed = atoi(fdig(dev->D_class));
36217834Sralph 	dev->D_numargs = na;
36317834Sralph 	return 0;
36413642Ssam }
36513642Ssam 
36618619Sralph /*
36718619Sralph  *	set system attribute vector
36813642Ssam  *
36913642Ssam  *	return codes:
37013642Ssam  *		>0  -  number of arguments in vector - succeeded
37113642Ssam  *		CF_SYSTEM  -  system name not found
37213642Ssam  *		CF_TIME  -  wrong time to call
37313642Ssam  */
37413642Ssam 
37513642Ssam finds(fsys, sysnam, info, flds)
37613642Ssam char *sysnam, info[], *flds[];
37713642Ssam FILE *fsys;
37813642Ssam {
37913642Ssam 	int na;
38013642Ssam 	int fcode = 0;
38113642Ssam 
38213642Ssam 	/* format of fields
38313642Ssam 	 *	0 name;
38413642Ssam 	 *	1 time
38513642Ssam 	 *	2 acu/hardwired
38613642Ssam 	 *	3 speed
38713642Ssam 	 *	etc
38813642Ssam 	 */
38913642Ssam 	while (cfgets(info, MAXC, fsys) != NULL) {
39017834Sralph 		na = getargs(info, flds, MAXC/10);
39123596Sbloom 		if (strncmp(sysnam, flds[F_NAME], MAXBASENAME) != SAME)
39213642Ssam 			continue;
39318619Sralph 		if (ifdate(flds[F_TIME]) != FAIL)
39413642Ssam 			/*  found a good entry  */
39517834Sralph 			return na;
39613642Ssam 		DEBUG(2, "Wrong time ('%s') to call\n", flds[F_TIME]);
39713642Ssam 		fcode = CF_TIME;
39813642Ssam 	}
39917834Sralph 	return fcode ? fcode : CF_SYSTEM;
40013642Ssam }
40113642Ssam 
40218619Sralph /*
40318619Sralph  *	do login conversation
40413642Ssam  *
40523596Sbloom  *	return codes:  SUCCESS  |  FAIL
40613642Ssam  */
40713642Ssam 
40813642Ssam login(nf, flds, fn)
40913642Ssam register char *flds[];
41013642Ssam int nf, fn;
41113642Ssam {
41213642Ssam 	register char *want, *altern;
41313642Ssam 	int k, ok;
41413642Ssam 
41517834Sralph 	ASSERT(nf > 4, "TOO FEW LOG FIELDS", CNULL, nf);
41617834Sralph 	if (setjmp(Cjbuf))
41717834Sralph 		return FAIL;
41817834Sralph 	AbortOn = NULL;
41913642Ssam 	for (k = F_LOGIN; k < nf; k += 2) {
42013642Ssam 		want = flds[k];
421*33562Srick 		if (want == NULL)
422*33562Srick 			want = "";
42313642Ssam 		ok = FAIL;
42417834Sralph 		while (ok != SUCCESS) {
42513642Ssam 			altern = index(want, '-');
42613642Ssam 			if (altern != NULL)
42713642Ssam 				*altern++ = '\0';
42817834Sralph 			if (strcmp(want, "ABORT") == 0) {
42917834Sralph 				AbortOn = flds[k+1];
43017834Sralph 				DEBUG(4, "ABORT ON: %s\n", AbortOn);
43117834Sralph 				goto nextfield;
43217834Sralph 			}
43325705Sbloom 			DEBUG(4, "wanted \"%s\"\n", want);
43413642Ssam 			ok = expect(want, fn);
43517834Sralph 			DEBUG(4, "got: %s\n", ok ? "?" : "that");
43617834Sralph 			if (ok == FAIL) {
43717834Sralph 				if (altern == NULL) {
43817834Sralph 					logent("LOGIN", _FAILED);
43917834Sralph 					return FAIL;
44017834Sralph 				}
44117834Sralph 				want = index(altern, '-');
44217834Sralph 				if (want != NULL)
44317834Sralph 					*want++ = '\0';
44417834Sralph 				sendthem(altern, fn);
44517834Sralph 			} else
44617834Sralph 				if (ok == ABORT) {
447*33562Srick 					char sbuf[MAXFULLNAME];
448*33562Srick 					sprintf(sbuf, "LOGIN ABORTED on \"%s\"",						AbortOn);
449*33562Srick 					logent(sbuf, _FAILED);
45023596Sbloom 					return ABORT;
45117834Sralph 				}
45213642Ssam 		}
45317834Sralph 		sleep(1);
45413642Ssam 		if (k+1 < nf)
45513642Ssam 			sendthem(flds[k+1], fn);
45617834Sralph nextfield: ;
45713642Ssam 	}
45817834Sralph 	return SUCCESS;
45913642Ssam }
46013642Ssam 
46113642Ssam 
46217834Sralph /* conditional table generation to support odd speeds */
46313642Ssam struct sg_spds {int sp_val, sp_name;} spds[] = {
46413642Ssam #ifdef B50
46513642Ssam 	{  50,	 B50},
46613642Ssam #endif
46713642Ssam #ifdef B75
46813642Ssam 	{  75,	 B75},
46913642Ssam #endif
47013642Ssam #ifdef B110
47113642Ssam 	{ 110,	B110},
47213642Ssam #endif
47313642Ssam #ifdef B150
47413642Ssam 	{ 150,	B150},
47513642Ssam #endif
47613642Ssam #ifdef B200
47713642Ssam 	{ 200,	B200},
47813642Ssam #endif
47913642Ssam #ifdef B300
48013642Ssam 	{ 300,  B300},
48113642Ssam #endif
48213642Ssam #ifdef B600
48313642Ssam 	{600,	B600},
48413642Ssam #endif
48513642Ssam #ifdef B1200
48613642Ssam 	{1200, B1200},
48713642Ssam #endif
48813642Ssam #ifdef B1800
48913642Ssam 	{1800, B1800},
49013642Ssam #endif
49113642Ssam #ifdef B2000
49213642Ssam 	{2000, B2000},
49313642Ssam #endif
49413642Ssam #ifdef B2400
49513642Ssam 	{2400, B2400},
49613642Ssam #endif
49713642Ssam #ifdef B3600
49813642Ssam 	{3600, B3600},
49913642Ssam #endif
50013642Ssam #ifdef B4800
50113642Ssam 	{4800, B4800},
50213642Ssam #endif
50313642Ssam #ifdef B7200
50413642Ssam 	{7200, B7200},
50513642Ssam #endif
50613642Ssam #ifdef B9600
50713642Ssam 	{9600, B9600},
50813642Ssam #endif
50913642Ssam #ifdef B19200
51017834Sralph 	{19200, B19200},
51113642Ssam #endif
51217834Sralph #ifdef EXTA
51317834Sralph 	{19200, EXTA},
51417834Sralph #endif
51513642Ssam 	{0, 0}
51613642Ssam };
51713642Ssam 
51818619Sralph /*
51918619Sralph  *	set speed/echo/mode...
52013642Ssam  *
52113642Ssam  *	return codes:  none
52213642Ssam  */
52313642Ssam 
52413642Ssam fixline(tty, spwant)
52513642Ssam int tty, spwant;
52613642Ssam {
52717834Sralph #ifdef	USG
52813642Ssam 	struct termio ttbuf;
52917834Sralph #else	!USG
53013642Ssam 	struct sgttyb ttbuf;
53117834Sralph #endif !USG
53213642Ssam 	register struct sg_spds *ps;
53313642Ssam 	int speed = -1;
53413642Ssam 
53513642Ssam 	for (ps = spds; ps->sp_val; ps++)
53613642Ssam 		if (ps->sp_val == spwant)
53713642Ssam 			speed = ps->sp_name;
53817834Sralph 	ASSERT(speed >= 0, "BAD SPEED", CNULL, speed);
53917834Sralph #ifdef	USG
54023596Sbloom 	if (ioctl(tty, TCGETA, &ttbuf) < 0)
54123596Sbloom 		return FAIL;
54213642Ssam 	/* ttbuf.sg_flags = (ANYP|RAW);
54313642Ssam 	ttbuf.sg_ispeed = ttbuf.sg_ospeed = speed; */
54413642Ssam 	ttbuf.c_iflag = (ushort)0;
54513642Ssam 	ttbuf.c_oflag = (ushort)0;
54613642Ssam 	ttbuf.c_cflag = (speed|CS8|HUPCL|CREAD);
54713642Ssam 	ttbuf.c_lflag = (ushort)0;
54813642Ssam 	ttbuf.c_cc[VMIN] = 6;
54913642Ssam 	ttbuf.c_cc[VTIME] = 1;
55023596Sbloom 	if (ioctl(tty, TCSETA, &ttbuf) < 0)
55123596Sbloom 		return FAIL;
55217834Sralph #else	!USG
55323596Sbloom 	if (ioctl(tty, TIOCGETP, &ttbuf) < 0)
55423596Sbloom 		return FAIL;
55513642Ssam 	ttbuf.sg_flags = (ANYP|RAW);
55613642Ssam 	ttbuf.sg_ispeed = ttbuf.sg_ospeed = speed;
55723596Sbloom 	if (ioctl(tty, TIOCSETP, &ttbuf) < 0)
55823596Sbloom 		return FAIL;
55913642Ssam #endif
56017834Sralph #ifndef	USG
56123596Sbloom 	if (ioctl(tty, TIOCHPCL, STBNULL) < 0)
56223596Sbloom 		return FAIL;
56323596Sbloom 	if (ioctl(tty, TIOCEXCL, STBNULL) < 0)
56423596Sbloom 		return FAIL;
56513642Ssam #endif
56617834Sralph 	linebaudrate = spwant;
56723596Sbloom 	return SUCCESS;
56813642Ssam }
56913642Ssam 
57017834Sralph #define MR 100
57113642Ssam 
57218619Sralph /*
57318619Sralph  *	look for expected string
57413642Ssam  *
57513642Ssam  *	return codes:
57613642Ssam  *		0  -  found
57713642Ssam  *		FAIL  -  lost line or too many characters read
57813642Ssam  *		some character  -  timed out
57913642Ssam  */
58013642Ssam 
58113642Ssam expect(str, fn)
58213642Ssam register char *str;
58313642Ssam int fn;
58413642Ssam {
58514592Skarels 	char rdvec[MR];
58617834Sralph 	register char *rp = rdvec, *strptr;
58717834Sralph 	int kr, cnt_char;
58813642Ssam 	char nextch;
58925127Sbloom 	int timo = MAXMSGTIME;
59013642Ssam 
59117834Sralph 	if (*str == '\0' || strcmp(str, "\"\"") == SAME)
59217834Sralph 		return SUCCESS;
59317834Sralph 	/* Cleanup str, convert \0xx strings to one char  */
59417834Sralph 	for (strptr = str; *strptr; strptr++) {
59517834Sralph 		if (*strptr == '\\')
59617834Sralph 			switch(*++strptr) {
59717834Sralph 			case 's':
59817834Sralph 				DEBUG(5, "BLANK\n", CNULL);
59917834Sralph 				*strptr = ' ';
60017834Sralph 				break;
60117834Sralph 			default:
60217834Sralph 				strptr--;  /* back up to backslash */
60317834Sralph 				sscanf(strptr + 1,"%o", &cnt_char);
60417834Sralph 				DEBUG(6, "BACKSLASHED %02xH\n", cnt_char);
60517834Sralph 				*strptr = (char) (cnt_char);
60617834Sralph 				strcpy(&strptr[1], &strptr[4]);
60717834Sralph 			}
60817834Sralph 	}
60917834Sralph 
61025127Sbloom 	strptr = index(str, '~');
61125127Sbloom 	if (strptr != NULL) {
61225127Sbloom 		*strptr++ = '\0';
61325127Sbloom 		timo = atoi(strptr);
61425127Sbloom 		if (timo <= 0)
61525127Sbloom 			timo = MAXMSGTIME;
61625127Sbloom 	}
61725127Sbloom 
61817834Sralph 	if (setjmp(Sjbuf))
61917834Sralph 		return FAIL;
62013642Ssam 	signal(SIGALRM, alarmtr);
62125127Sbloom 	alarm(timo);
62225127Sbloom 	*rp = 0;
62313642Ssam 	while (notin(str, rdvec)) {
62425705Sbloom 		int c;
62517834Sralph 		if(AbortOn != NULL && !notin(AbortOn, rdvec)) {
62617834Sralph 			DEBUG(1, "Call aborted on '%s'\n", AbortOn);
62717834Sralph 			alarm(0);
62817834Sralph 			return ABORT;
62917834Sralph 		}
63013642Ssam 		kr = read(fn, &nextch, 1);
63113642Ssam 		if (kr <= 0) {
63213642Ssam 			alarm(0);
63313642Ssam 			DEBUG(4, "lost line kr - %d\n, ", kr);
63413642Ssam 			logent("LOGIN", "LOST LINE");
63517834Sralph 			return FAIL;
63613642Ssam 		}
63713642Ssam 		c = nextch & 0177;
63825705Sbloom 		if (c == '\0')
63925705Sbloom 			continue;
64025705Sbloom 		DEBUG(4, (isprint(c) || isspace(c)) ? "%c" : "\\%03o", c);
64125705Sbloom 		*rp++ = c;
64213642Ssam 		if (rp >= rdvec + MR) {
64317834Sralph 			register char *p;
64417834Sralph 			for (p = rdvec+MR/2; p < rp; p++)
64517834Sralph 				*(p-MR/2) = *p;
64617834Sralph 			rp -= MR/2;
64713642Ssam 		}
64813642Ssam 		*rp = '\0';
64913642Ssam 	}
65013642Ssam 	alarm(0);
65117834Sralph 	return SUCCESS;
65213642Ssam }
65313642Ssam 
65413642Ssam 
65513642Ssam /*
65613642Ssam  * Determine next file descriptor that would be allocated.
65713642Ssam  * This permits later closing of a file whose open was interrupted.
65813642Ssam  * It is a UNIX kernel problem, but it has to be handled.
65913642Ssam  * unc!smb (Steve Bellovin) probably first discovered it.
66013642Ssam  */
66113642Ssam getnextfd()
66213642Ssam {
66313642Ssam 	close(next_fd = open("/", 0));
66413642Ssam }
66513642Ssam 
66617834Sralph /*
66717834Sralph  *	send line of login sequence
66813642Ssam  *
66913642Ssam  *	return codes:  none
67013642Ssam  */
67113642Ssam sendthem(str, fn)
67213642Ssam register char *str;
67313642Ssam int fn;
67413642Ssam {
67513642Ssam 	register char *strptr;
67613642Ssam 	int i, n, cr = 1;
67717834Sralph 	register char c;
67813642Ssam 	static int p_init = 0;
67913642Ssam 
68025705Sbloom 	DEBUG(5, "send \"%s\"\n", str);
68113642Ssam 
68213642Ssam 	if (!p_init) {
68313642Ssam 		p_init++;
68413642Ssam 		bld_partab(P_EVEN);
68513642Ssam 	}
68613642Ssam 
68713642Ssam 	if (prefix("BREAK", str)) {
68813642Ssam 		sscanf(&str[5], "%1d", &i);
68913642Ssam 		if (i <= 0 || i > 10)
69013642Ssam 			i = 3;
69113642Ssam 		/* send break */
69213642Ssam 		genbrk(fn, i);
69313642Ssam 		return;
69413642Ssam 	}
69513642Ssam 
69613642Ssam 	if (prefix("PAUSE", str)) {
69713642Ssam 		sscanf(&str[5], "%1d", &i);
69813642Ssam 		if (i <= 0 || i > 10)
69913642Ssam 			i = 3;
70013642Ssam 		/* pause for a while */
70113642Ssam 		sleep((unsigned)i);
70213642Ssam 		return;
70313642Ssam 	}
70413642Ssam 
70513642Ssam 	if (strcmp(str, "EOT") == SAME) {
70613642Ssam 		p_chwrite(fn, '\04');
70713642Ssam 		return;
70813642Ssam 	}
70913642Ssam 
71013642Ssam 	/* Send a '\n' */
71125705Sbloom 	if (strcmp(str, "LF") == SAME) {
71225705Sbloom 		p_chwrite(fn, '\n');
71325705Sbloom 		return;
71425705Sbloom 	}
71513642Ssam 
71613642Ssam 	/* Send a '\r' */
71725705Sbloom 	if (strcmp(str, "CR") == SAME) {
71825705Sbloom 		p_chwrite(fn, '\r');
71925705Sbloom 		return;
72025705Sbloom 	}
72113642Ssam 
72213642Ssam 	/* Set parity as needed */
72313642Ssam 	if (strcmp(str, "P_ZERO") == SAME) {
72413642Ssam 		bld_partab(P_ZERO);
72513642Ssam 		return;
72613642Ssam 	}
72713642Ssam 	if (strcmp(str, "P_ONE") == SAME) {
72813642Ssam 		bld_partab(P_ONE);
72913642Ssam 		return;
73013642Ssam 	}
73113642Ssam 	if (strcmp(str, "P_EVEN") == SAME) {
73213642Ssam 		bld_partab(P_EVEN);
73313642Ssam 		return;
73413642Ssam 	}
73513642Ssam 	if (strcmp(str, "P_ODD") == SAME) {
73613642Ssam 		bld_partab(P_ODD);
73713642Ssam 		return;
73813642Ssam 	}
73913642Ssam 
74013642Ssam 	/* If "", just send '\r' */
74117834Sralph 	if (strcmp(str, "\"\"") == SAME) {
74217834Sralph 		p_chwrite(fn, '\r');
74317834Sralph 		return;
74417834Sralph 	}
74517834Sralph 
74625705Sbloom 	strptr = str;
74725705Sbloom 	while ((c = *strptr++) != '\0') {
74817834Sralph 		if (c == '\\') {
74917834Sralph 			switch(*strptr++) {
75025705Sbloom 			case '\0':
75125705Sbloom 				DEBUG(5, "TRAILING BACKSLASH IGNORED\n", CNULL);
75225705Sbloom 				--strptr;
75325705Sbloom 				continue;
75417834Sralph 			case 's':
75517834Sralph 				DEBUG(5, "BLANK\n", CNULL);
75625705Sbloom 				c = ' ';
75717834Sralph 				break;
75817834Sralph 			case 'd':
75917834Sralph 				DEBUG(5, "DELAY\n", CNULL);
76017834Sralph 				sleep(1);
76117834Sralph 				continue;
76225705Sbloom 			case 'n':
76325705Sbloom 				DEBUG(5, "NEW LINE\n", CNULL);
76425705Sbloom 				c = '\n';
76525705Sbloom 				break;
76617834Sralph 			case 'r':
76717834Sralph 				DEBUG(5, "RETURN\n", CNULL);
76825705Sbloom 				c = '\r';
76917834Sralph 				break;
77017834Sralph 			case 'b':
77117834Sralph 				if (isdigit(*strptr)) {
77217834Sralph 					i = (*strptr++ - '0');
77317834Sralph 					if (i <= 0 || i > 10)
77417834Sralph 						i = 3;
77517834Sralph 				} else
77613642Ssam 					i = 3;
77717834Sralph 				/* send break */
77817834Sralph 				genbrk(fn, i);
77917834Sralph 				if (*strptr == '\0')
78017834Sralph 					cr = 0;
78113642Ssam 				continue;
78217834Sralph 			case 'c':
78317834Sralph 				if (*strptr == '\0') {
78417834Sralph 					DEBUG(5, "NO CR\n", CNULL);
78517834Sralph 					cr = 0;
78625705Sbloom 				} else
78725705Sbloom 					DEBUG(5, "NO CR - IGNORED NOT EOL\n", CNULL);
78813642Ssam 				continue;
78925705Sbloom #define isoctal(x)	((x >= '0') && (x <= '7'))
79017834Sralph 			default:
79125705Sbloom 				if (isoctal(strptr[-1])) {
79217834Sralph 					i = 0;
79317834Sralph 					n = 0;
79425705Sbloom 					--strptr;
79525705Sbloom 					while (isoctal(*strptr) && ++n <= 3)
79625705Sbloom 						i = i * 8 + (*strptr++ - '0');
79725705Sbloom 					DEBUG(5, "\\%o\n", i);
79817834Sralph 					p_chwrite(fn, (char)i);
79917834Sralph 					continue;
80017834Sralph 				}
80113642Ssam 			}
80225705Sbloom 		}
80325705Sbloom 		p_chwrite(fn, c);
80413642Ssam 	}
80513642Ssam 
80613642Ssam 	if (cr)
80713642Ssam 		p_chwrite(fn, '\r');
80813642Ssam 	return;
80913642Ssam }
81013642Ssam 
81113642Ssam p_chwrite(fd, c)
81213642Ssam int fd;
81317834Sralph char c;
81413642Ssam {
81517834Sralph 	c = par_tab[c&0177];
81617834Sralph 	if (write(fd, &c, 1) != 1) {
81717834Sralph 		logent(sys_errlist[errno], "BAD WRITE");
81817834Sralph 		longjmp(Cjbuf, 2);
81917834Sralph 	}
82013642Ssam }
82113642Ssam 
82213642Ssam /*
82313642Ssam  * generate parity table for use by p_chwrite.
82413642Ssam  */
82513642Ssam bld_partab(type)
82613642Ssam int type;
82713642Ssam {
82813642Ssam 	register int i, j, n;
82913642Ssam 
83013642Ssam 	for (i = 0; i < sizeof(par_tab); i++) {
83113642Ssam 		n = 0;
83213642Ssam 		for (j = i&(sizeof(par_tab)-1); j; j = (j-1)&j)
83313642Ssam 			n++;
83413642Ssam 		par_tab[i] = i;
83513642Ssam 		if (type == P_ONE
83613642Ssam 		 || (type == P_EVEN && (n&01) != 0)
83713642Ssam 		 || (type == P_ODD && (n&01) == 0))
83813642Ssam 			par_tab[i] |= sizeof(par_tab);
83913642Ssam 	}
84013642Ssam }
84113642Ssam 
84218619Sralph /*
84318619Sralph  *	check for occurrence of substring "sh"
84413642Ssam  *
84513642Ssam  *	return codes:
84613642Ssam  *		0  -  found the string
84713642Ssam  *		1  -  not in the string
84813642Ssam  */
84913642Ssam notin(sh, lg)
85013642Ssam register char *sh, *lg;
85113642Ssam {
85213642Ssam 	while (*lg != '\0') {
85313642Ssam 		if (wprefix(sh, lg))
85418619Sralph 			return 0;
85513642Ssam 		else
85613642Ssam 			lg++;
85713642Ssam 	}
85818619Sralph 	return 1;
85913642Ssam }
86013642Ssam 
86118619Sralph /*
86223596Sbloom  *	Allow multiple date specifications separated by ','.
86313642Ssam  */
86418619Sralph ifdate(p)
86518619Sralph register char *p;
86613642Ssam {
86725705Sbloom 	register char *np;
86818619Sralph 	register int ret, g;
86923596Sbloom 	int rtime, i;
87013642Ssam 
87123596Sbloom 	/*  pick up retry time for failures  */
87223596Sbloom 	/*  global variable Retrytime is set here  */
87323596Sbloom 	if ((np = index(p, ';')) == NULL) {
87423596Sbloom 		Retrytime = RETRYTIME;
87523596Sbloom 	} else {
87623596Sbloom 		i = sscanf(np+1, "%d", &rtime);
87723596Sbloom 		if (i < 1 || rtime < 0)
87823596Sbloom 			rtime = 5;
87923596Sbloom 		Retrytime  = rtime * 60;
88023596Sbloom 	}
88123596Sbloom 
88218619Sralph 	ret = FAIL;
88318619Sralph 	MaxGrade = '\0';
88418619Sralph 	do {
88523596Sbloom 		np = strpbrk(p, ",|");	/* prefer , but allow | for compat */
88623596Sbloom 		if (np)
88723596Sbloom 			*np = '\0';
88818619Sralph 		g = ifadate(p);
88918619Sralph 		DEBUG(11,"ifadate returns %o\n", g);
89018619Sralph 		if (g != FAIL) {
89118619Sralph 			ret = SUCCESS;
89218619Sralph 			if (g > MaxGrade)
89318619Sralph 				MaxGrade = g;
89418619Sralph 		}
89523596Sbloom 		if (np)
89623596Sbloom 			*np = ',';
89723596Sbloom 		p = np + 1;
89823596Sbloom 	} while (np);
89923596Sbloom 	if (MaxGrade == '\0')
90023596Sbloom 		MaxGrade = DefMaxGrade;
90118619Sralph 	return ret;
90213642Ssam }
90313642Ssam 
90418619Sralph /*
90518619Sralph  *	this routine will check a string (string)
90613642Ssam  *	like "MoTu0800-1730" to see if the present
90713642Ssam  *	time is within the given limits.
90813642Ssam  *	SIDE EFFECT - Retrytime is set
90913642Ssam  *
91013642Ssam  *	return codes:
91113642Ssam  *		0  -  not within limits
91213642Ssam  *		1  -  within limits
91313642Ssam  */
91413642Ssam 
91518619Sralph ifadate(string)
91618619Sralph char *string;
91713642Ssam {
91813642Ssam 	static char *days[]={
91913642Ssam 		"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", 0
92013642Ssam 	};
92113642Ssam 	time_t clock;
92218619Sralph 	register char *s = string;
92317834Sralph 	int i, tl, th, tn, dayok=0;
92413642Ssam 	struct tm *localtime();
92513642Ssam 	struct tm *tp;
92618619Sralph 	char *p, MGrade;
92713642Ssam 
92823596Sbloom 	if ((p = index(s, '/')) == NULL)
92918619Sralph 		MGrade = DefMaxGrade;
93018619Sralph 	else
93118619Sralph 		MGrade = p[1];
93218619Sralph 
93313642Ssam 	time(&clock);
93413642Ssam 	tp = localtime(&clock);
93517834Sralph 	while (isascii(*s) && isalpha(*s)) {
93613642Ssam 		for (i = 0; days[i]; i++) {
93713642Ssam 			if (prefix(days[i], s))
93813642Ssam 				if (tp->tm_wday == i)
93913642Ssam 					dayok = 1;
94013642Ssam 		}
94113642Ssam 
94213642Ssam 		if (prefix("Wk", s))
94313642Ssam 			if (tp->tm_wday >= 1 && tp->tm_wday <= 5)
94413642Ssam 				dayok = 1;
94513642Ssam 		if (prefix("Any", s))
94613642Ssam 			dayok = 1;
94717834Sralph 		if (prefix("Evening", s)) {
94817834Sralph 			/* Sat or Sun */
94917834Sralph 			if (tp->tm_wday == 6 || tp->tm_wday == 0
95017834Sralph 				|| tp->tm_hour >= 17 || tp->tm_hour < 8)
95117834Sralph 					dayok = 1;
95217834Sralph 		}
95317834Sralph 		if (prefix("Night", s)) {
95417834Sralph 			if (tp->tm_wday == 6  /* Sat */
95518619Sralph 				|| tp->tm_hour >= 23 || tp->tm_hour < 8
95618619Sralph 					/* Sunday before 5pm */
95718619Sralph 				|| (tp->tm_wday == 0 && tp->tm_hour < 17))
95817834Sralph 					dayok = 1;
95917834Sralph 		}
96025705Sbloom 		if (prefix("NonPeak", s)) { /* For Tymnet and PC Pursuit */
96125705Sbloom 			/* Sat or Sun */
96225705Sbloom 			if (tp->tm_wday == 6 || tp->tm_wday == 0
96325705Sbloom 				|| tp->tm_hour >= 18 || tp->tm_hour < 7)
96425705Sbloom 					dayok = 1;
96525705Sbloom 		}
96613642Ssam 		s++;
96713642Ssam 	}
96813642Ssam 
96918619Sralph 	if (dayok == 0 && s != string)
97018619Sralph 		return FAIL;
97113642Ssam 	i = sscanf(s, "%d-%d", &tl, &th);
97218619Sralph   	if (i < 2)
97318619Sralph   		return MGrade;
97418619Sralph 	tn = tp->tm_hour * 100 + tp->tm_min;
97518619Sralph   	if (th < tl) { 		/* crosses midnight */
97618619Sralph   		if (tl <= tn || tn < th)
97718619Sralph   			return MGrade;
97825966Sbloom   	} else {
97917834Sralph 		if (tl <= tn && tn < th)
98018619Sralph 			return MGrade;
98125966Sbloom 	}
98218619Sralph 	return FAIL;
98313642Ssam }
98413642Ssam 
98518619Sralph /*
98618619Sralph  *	find first digit in string
98713642Ssam  *
98813642Ssam  *	return - pointer to first digit in string or end of string
98913642Ssam  */
99013642Ssam char *
99113642Ssam fdig(cp)
99213642Ssam register char *cp;
99313642Ssam {
99413642Ssam 	register char *c;
99513642Ssam 
99613642Ssam 	for (c = cp; *c; c++)
99713642Ssam 		if (*c >= '0' && *c <= '9')
99813642Ssam 			break;
99917834Sralph 	return c;
100013642Ssam }
100113642Ssam 
100213642Ssam /*
100313642Ssam  * Compare strings:  s1>s2: >0  s1==s2: 0  s1<s2: <0
100413642Ssam  * Strings are compared as if they contain all capital letters.
100513642Ssam  */
100613642Ssam snccmp(s1, s2)
100713642Ssam register char *s1, *s2;
100813642Ssam {
100913642Ssam 	char c1, c2;
101013642Ssam 
101125127Sbloom 	if (islower(*s1))
101225127Sbloom 		c1 = toupper(*s1);
101325127Sbloom 	else
101425127Sbloom 		c1 = *s1;
101525127Sbloom 	if (islower(*s2))
101625127Sbloom 		c2 = toupper(*s2);
101725127Sbloom 	else
101825127Sbloom 		c2 = *s2;
101913642Ssam 
102013642Ssam 	while (c1 == c2) {
102125127Sbloom 		if (*s1++ == '\0')
102217834Sralph 			return 0;
102313642Ssam 		s2++;
102425127Sbloom 		if (islower(*s1))
102525127Sbloom 			c1 = toupper(*s1);
102625127Sbloom 		else
102725127Sbloom 			c1 = *s1;
102825127Sbloom 		if (islower(*s2))
102925127Sbloom 			c2 = toupper(*s2);
103025127Sbloom 		else
103125127Sbloom 			c2 = *s2;
103213642Ssam 	}
103317834Sralph 	return c1 - c2;
103413642Ssam }
103525127Sbloom 
103617834Sralph /*
103725127Sbloom  * Compare strings:  s1>s2: >0  s1==s2: 0  s1<s2: <0
103825127Sbloom  * Strings are compared as if they contain all capital letters.
103925127Sbloom  */
104025127Sbloom sncncmp(s1, s2, n)
104125127Sbloom register char *s1, *s2;
104225127Sbloom register int n;
104325127Sbloom {
104425127Sbloom 	char c1, c2;
104525127Sbloom 
104625127Sbloom 	if (islower(*s1))
104725127Sbloom 		c1 = toupper(*s1);
104825127Sbloom 	else
104925127Sbloom 		c1 = *s1;
105025127Sbloom 	if (islower(*s2))
105125127Sbloom 		c2 = toupper(*s2);
105225127Sbloom 	else
105325127Sbloom 		c2 = *s2;
105425127Sbloom 
105525127Sbloom 	while ( --n >= 0 && c1 == c2) {
105625127Sbloom 		if (*s1++ == '\0')
105725127Sbloom 			return 0;
105825127Sbloom 		s2++;
105925127Sbloom 		if (islower(*s1))
106025127Sbloom 			c1 = toupper(*s1);
106125127Sbloom 		else
106225127Sbloom 			c1 = *s1;
106325127Sbloom 		if (islower(*s2))
106425127Sbloom 			c2 = toupper(*s2);
106525127Sbloom 		else
106625127Sbloom 			c2 = *s2;
106725127Sbloom 	}
106825127Sbloom 	return n<0 ? 0 : (c1 - c2);
106925127Sbloom }
107025127Sbloom /*
107117834Sralph  * do chat script
107217834Sralph  * occurs after local port is opened,
107317834Sralph  * before 'dialing' the other machine.
107417834Sralph  */
107517834Sralph dochat(dev, flds, fd)
107617834Sralph register struct Devices *dev;
107717834Sralph char *flds[];
107817834Sralph int fd;
107917834Sralph {
108017834Sralph 	register int i;
108117834Sralph 	register char *p;
108217834Sralph 	char bfr[sizeof(dev->D_argbfr)];
108317834Sralph 
108417834Sralph 	if (dev->D_numargs <= 5)
108517834Sralph 		return(0);
108617834Sralph 	DEBUG(4, "dochat called %d\n", dev->D_numargs);
108717834Sralph 	for (i = 0; i < dev->D_numargs-5; i++) {
108817834Sralph 		sprintf(bfr, dev->D_arg[D_CHAT+i], flds[F_PHONE]);
108917834Sralph 		if (strcmp(bfr, dev->D_arg[D_CHAT+i])) {
109017834Sralph 			p = malloc((unsigned)strlen(bfr)+1);
109117834Sralph 			if (p != NULL) {
109217834Sralph 				strcpy(p, bfr);
109317834Sralph 				dev->D_arg[D_CHAT+i] = p;
109417834Sralph 			}
109517834Sralph 		}
109617834Sralph 	}
109717834Sralph 	/* following is a kludge because login() arglist is a kludge */
109817834Sralph 	i = login(dev->D_numargs, &dev->D_arg[D_CHAT-5], fd);
109917834Sralph 	/*
110017834Sralph 	 * If login() last did a sendthem(), must pause so things can settle.
110117834Sralph 	 * But don't bother if chat failed.
110217834Sralph 	 */
110317834Sralph 	if (i == 0 && (dev->D_numargs&01))
110417834Sralph 		sleep(2);
110517834Sralph 	return(i);
110617834Sralph }
110725705Sbloom 
110825705Sbloom /*
110925705Sbloom  *	fix kill/echo/raw on line
111025705Sbloom  *
111125705Sbloom  *	return codes:  none
111225705Sbloom  */
111325705Sbloom fixmode(tty)
111425705Sbloom register int tty;
111525705Sbloom {
111625705Sbloom #ifdef	USG
111725705Sbloom 	struct termio ttbuf;
111825705Sbloom #else	!USG
111925705Sbloom 	struct sgttyb ttbuf;
112025705Sbloom #endif	!USG
112125705Sbloom 	register struct sg_spds *ps;
112225705Sbloom 	int speed;
112325705Sbloom 
112425705Sbloom 	if (IsTcpIp)
112525705Sbloom 		return;
112625705Sbloom #ifdef	USG
112725705Sbloom 	ioctl(tty, TCGETA, &ttbuf);
112825705Sbloom 	ttbuf.c_iflag = ttbuf.c_oflag = ttbuf.c_lflag = (ushort)0;
112925705Sbloom 	speed = ttbuf.c_cflag &= (CBAUD);
113025705Sbloom 	ttbuf.c_cflag |= (CS8|CREAD);
113125705Sbloom 	ttbuf.c_cc[VMIN] = 6;
113225705Sbloom 	ttbuf.c_cc[VTIME] = 1;
113325705Sbloom 	ioctl(tty, TCSETA, &ttbuf);
113425705Sbloom #else	!USG
113525705Sbloom 	ioctl(tty, TIOCGETP, &ttbuf);
113625705Sbloom 	ttbuf.sg_flags = (ANYP | RAW);
113725705Sbloom 	ioctl(tty, TIOCSETP, &ttbuf);
113825705Sbloom 	speed = ttbuf.sg_ispeed;
113925705Sbloom 	ioctl(tty, TIOCEXCL, STBNULL);
114025705Sbloom #endif	!USG
114125705Sbloom 
114225705Sbloom 	for (ps = spds; ps->sp_val; ps++)
114325705Sbloom 		if (ps->sp_name == speed) {
114425705Sbloom 			linebaudrate = ps->sp_val;
114525705Sbloom 			DEBUG(9,"Incoming baudrate is %d\n", linebaudrate);
114625705Sbloom 			return;
114725705Sbloom 		}
114825705Sbloom 	ASSERT(linebaudrate >= 0, "BAD SPEED", CNULL, speed);
114925705Sbloom }
115025705Sbloom 
1151