xref: /csrg-svn/usr.bin/uucp/uucico/conn.c (revision 33948)
133581Srick #ifndef lint
2*33948Srick static char sccsid[] = "@(#)conn.c	5.13	(Berkeley) 04/05/88";
333581Srick #endif
413642Ssam 
523596Sbloom #include <signal.h>
613642Ssam #include "uucp.h"
713642Ssam #include <setjmp.h>
813642Ssam #include <ctype.h>
913642Ssam #include <errno.h>
1017834Sralph #ifdef	USG
1113642Ssam #include <termio.h>
1213642Ssam #include <fcntl.h>
1313642Ssam #endif
1417834Sralph #ifndef	USG
1513642Ssam #include <sgtty.h>
1613642Ssam #endif
1717834Sralph #ifdef BSD4_2
1817834Sralph #include <sys/time.h>
1917834Sralph #else
2017834Sralph #include <time.h>
2117834Sralph #endif
2213642Ssam 
2313642Ssam #define MAXC 1000
2413642Ssam 
2513642Ssam extern jmp_buf Sjbuf;
2617834Sralph jmp_buf Cjbuf;
2718619Sralph extern int errno, onesys;
2817834Sralph extern char *sys_errlist[];
2918619Sralph extern char MaxGrade, DefMaxGrade;
3013642Ssam 
3113642Ssam /* Parity control during login procedure */
3213642Ssam #define	P_ZERO	0
3313642Ssam #define	P_ONE	1
3413642Ssam #define	P_EVEN	2
3513642Ssam #define	P_ODD	3
3617834Sralph 
3717834Sralph #define ABORT -2
3817834Sralph 
3917834Sralph char 	*AbortOn = NULL;
4013642Ssam char	par_tab[128];	/* must be power of two */
4117834Sralph int	linebaudrate;	/* used for the sleep test in pk1.c */
4213642Ssam int next_fd = -1;	/* predicted fd to close interrupted opens */
4325705Sbloom 
4425705Sbloom char *PCP = "PCP";	/* PC Pursuit device type */
4525127Sbloom /*
4625127Sbloom  *	catch alarm routine for "expect".
4713642Ssam  */
4813642Ssam alarmtr()
4913642Ssam {
5013642Ssam 	signal(SIGALRM, alarmtr);
5113642Ssam 	if (next_fd >= 0) {
5213642Ssam 		if (close(next_fd))
5313642Ssam 			logent("FAIL", "ACU LINE CLOSE");
5413642Ssam 		next_fd = -1;
5513642Ssam 	}
5613642Ssam 	longjmp(Sjbuf, 1);
5713642Ssam }
5813642Ssam 
5925705Sbloom /* This template is for seismo to call ihnp4
6025705Sbloom  * the 3 lines marked ---> will be overwritten for the appropriate city
6125705Sbloom  */
6225705Sbloom #define PCP_BAUD	3
6325705Sbloom #define PCP_PHONE	4
6433562Srick #define PCP_CITY	14
6533562Srick #define PCP_PASSWORD	16
6633562Srick #define PCP_RPHONE	20
6733562Srick #define NPCFIELDS	23
6825705Sbloom 
6925705Sbloom static char *PCFlds[] = {
7025705Sbloom 	"PC-PURSUIT",
7125705Sbloom 	"Any",
7225705Sbloom 	"ACU",
7325705Sbloom 	"1200",
7433562Srick 	CNULL,
7533562Srick 	CNULL,
7633562Srick 	"P_ZERO",	/* Telenet insists on zero parity */
7725705Sbloom 	"ABORT",
7833562Srick 	"BUSY",		/* Abort on Busy Signal */
7933562Srick 	CNULL,
8033562Srick 	"\\d\\d\\r\\d\\r",	/* Get telenet's attention */
8133562Srick 	"TERMINAL=~3-\r-TERM~3-\r-TERM~5", 	/* Terminal type ? */
8233562Srick 	"\\r",
8333562Srick 	"@",		/* telenet's prompt */
8433562Srick 	"D/DCWAS/21,telenetloginstring", /* overwritten later */
8533562Srick 	"PASSWORD",
8633562Srick 	CNULL,		/* telenet password */
8733562Srick 	"CONNECTED",	/* We're now talking to a Hayes in the remote city */
8833562Srick 	"ATZ",		/* Reset it */
8933562Srick 	"OK",
9033562Srick 	"ATDT6907171", /* overwritten */
9133562Srick 	"CONNECT",
9233562Srick 	"\\d\\r",		/* We're in !*/
9333562Srick 	CNULL,
9425705Sbloom };
9525705Sbloom 
9633562Srick static char PCP_brand[25];
9725705Sbloom 
9818619Sralph /*
9918619Sralph  *	place a telephone call to system and login, etc.
10013642Ssam  *
10113642Ssam  *	return codes:
10213642Ssam  *		CF_SYSTEM: don't know system
10313642Ssam  *		CF_TIME: wrong time to call
10413642Ssam  *		CF_DIAL: call failed
10513642Ssam  *		CF_NODEV: no devices available to place call
10613642Ssam  *		CF_LOGIN: login/password dialog failed
10713642Ssam  *
10813642Ssam  *		>0  - file no.  -  connect ok
10913642Ssam  */
11013642Ssam 
11113642Ssam int Dcf = -1;
11217834Sralph char *Flds[MAXC/10];
11325966Sbloom char LineType[10];
11417834Sralph extern int LocalOnly;
11513642Ssam 
11613642Ssam conn(system)
11713642Ssam char *system;
11813642Ssam {
11925705Sbloom 	int nf;
12018619Sralph 	char info[MAXC], wkpre[NAMESIZE], file[NAMESIZE];
12113642Ssam 	register FILE *fsys;
12213642Ssam 	int fcode = 0;
12313642Ssam 
12413642Ssam 	nf = 0;
12513642Ssam 
12613642Ssam 	fsys = fopen(SYSFILE, "r");
127*33948Srick 	if (fsys == NULL) {
128*33948Srick 		syslog(LOG_ERR, "fopen(%s) failed: %m", SYSFILE);
129*33948Srick 		cleanup(FAIL);
130*33948Srick 	}
13113642Ssam 
13217834Sralph 	DEBUG(4, "finds (%s) called\n", system);
13325127Sbloom keeplooking:
13417834Sralph 	while((nf = finds(fsys, system, info, Flds)) > 0) {
13525966Sbloom 		strncpy(LineType, Flds[F_LINE], 10);
13617834Sralph 		if (LocalOnly) {
13725966Sbloom 			if (strcmp("TCP", LineType)
13825966Sbloom 				&& strcmp("DIR", LineType)
13925966Sbloom 				&& strcmp("LOCAL", LineType) ) {
14025705Sbloom 					fcode = CF_TIME;
14125705Sbloom 					continue;
14225705Sbloom 			}
14317834Sralph 		}
14423596Sbloom 		sprintf(wkpre, "%c.%.*s", CMDPRE, SYSNSIZE, Rmtname);
14518619Sralph 		if (!onesys && MaxGrade != DefMaxGrade &&
14625705Sbloom 			!iswrk(file, "chk", Spool, wkpre))  {
14725705Sbloom 				fcode = CF_TIME;
14825705Sbloom 				continue;
14925705Sbloom 		}
15025705Sbloom 		/* For GTE's PC Pursuit */
15125966Sbloom 		if (snccmp(LineType, PCP) == SAME) {
15225705Sbloom 			FILE *dfp;
15325705Sbloom 			int status;
15425705Sbloom 			static struct Devices dev;
15533562Srick 
15625705Sbloom 			dfp = fopen(DEVFILE, "r");
157*33948Srick 			if (dfp == NULL) {
158*33948Srick 				syslog(LOG_ERR, "fopen(%s) failed: %m",
159*33948Srick 					DEVFILE);
160*33948Srick 				cleanup(FAIL);
161*33948Srick 			}
16225705Sbloom 			while ((status=rddev(dfp, &dev)) != FAIL
16325705Sbloom 				&& strcmp(PCP, dev.D_type) != SAME)
16425705Sbloom 					;
16525705Sbloom 			fclose(dfp);
16625705Sbloom 			if (status == FAIL)
16725705Sbloom 				continue;
16825705Sbloom 			if (mlock(PCP) == FAIL) {
16925705Sbloom 				fcode = CF_NODEV;
17025705Sbloom 				logent("DEVICE", "NO");
17125705Sbloom 				continue;
17225705Sbloom 			}
17325705Sbloom 			PCFlds[PCP_BAUD] = dev.D_class;
17425705Sbloom 			PCFlds[PCP_PHONE] = dev.D_calldev;
17533562Srick 			sprintf(PCFlds[PCP_CITY], "c d/%s%s,%s",
17633562Srick 				Flds[F_CLASS],
17733562Srick 				index(Flds[F_CLASS], '/') == NULL ? "/12" : "",
17833562Srick 				dev.D_arg[D_CHAT]);
17933562Srick 			PCFlds[PCP_PASSWORD] = dev.D_line;
18033562Srick 			strncpy(&PCFlds[PCP_RPHONE][4], Flds[F_PHONE], 7);
18125705Sbloom 			strncpy(PCP_brand, dev.D_brand, sizeof(PCP_brand));
18233562Srick 			if ((fcode = getto(PCFlds)) < 0) {
18333562Srick 				rmlock(PCP);
18425705Sbloom 				continue;
18533562Srick 			}
18625705Sbloom 			Dcf = fcode;
18725705Sbloom 			fcode = login(NPCFIELDS, PCFlds, Dcf);
18833562Srick 			if (fcode == SUCCESS)
18933562Srick 				break;
19033562Srick 			fcode = CF_DIAL;
19133562Srick 			rmlock(PCP);
19233562Srick 			/* end PC Pursuit */
19333562Srick 		} else if ((fcode = getto(Flds)) > 0)  {
19433562Srick 			Dcf = fcode;
19513642Ssam 			break;
19633562Srick 		}
19713642Ssam 	}
19813642Ssam 
19925127Sbloom 	if (nf <= 0) {
20025127Sbloom 		fclose(fsys);
20117834Sralph 		return fcode ? fcode : nf;
20225127Sbloom 	}
20313642Ssam 
20425705Sbloom 
20525705Sbloom 	if (fcode >= 0) {
20625705Sbloom 		DEBUG(4, "login %s\n", "called");
20733562Srick 		fcode = login(nf, Flds, Dcf); }
20825705Sbloom 	if (fcode < 0) {
20913642Ssam 		clsacu();
21025705Sbloom 		if (fcode == ABORT) {
21125127Sbloom 			fcode = CF_DIAL;
21225127Sbloom 			goto  keeplooking;
21325127Sbloom 		} else {
21425127Sbloom 			fclose(fsys);
21523596Sbloom 			return CF_LOGIN;
21625127Sbloom 		}
21713642Ssam 	}
21825127Sbloom 	fclose(fsys);
21925705Sbloom 	fioclex(Dcf);
22025705Sbloom 	return Dcf;
22113642Ssam }
22213642Ssam 
22325127Sbloom /*
22425127Sbloom  *	connect to remote machine
22513642Ssam  *
22613642Ssam  *	return codes:
22713642Ssam  *		>0  -  file number - ok
22813642Ssam  *		FAIL  -  failed
22913642Ssam  */
23013642Ssam 
23113642Ssam getto(flds)
23213642Ssam register char *flds[];
23313642Ssam {
23413642Ssam 	register struct condev *cd;
23513642Ssam 	int nulldev(), diropn();
23625127Sbloom 	char *line;
23713642Ssam 
23817834Sralph 	DEBUG(4, "getto: call no. %s ", flds[F_PHONE]);
23913642Ssam 	DEBUG(4, "for sys %s\n", flds[F_NAME]);
24013642Ssam 
24125127Sbloom 	if (snccmp(flds[F_LINE], "LOCAL") == SAME)
24225127Sbloom 		line = "ACU";
24325127Sbloom 	else
24425127Sbloom 		line = flds[F_LINE];
24525127Sbloom #ifdef DIALINOUT
24625127Sbloom 	if (snccmp(line, "ACU") != SAME)
24725127Sbloom 		reenable();
24825127Sbloom #endif DIALINOUT
24913642Ssam 	CU_end = nulldev;
25025705Sbloom 	if (snccmp(line, PCP) == SAME) {
25125705Sbloom 		for(cd = condevs; cd->CU_meth != NULL; cd++) {
25225705Sbloom 			if (snccmp(PCP_brand, cd->CU_brand) == SAME) {
25325705Sbloom 				CU_end = cd->CU_clos;
25425705Sbloom 				return diropn(flds);
25525705Sbloom 			}
25613642Ssam 		}
25725705Sbloom 		logent(PCP_brand, "UNSUPPORTED ACU TYPE");
25825705Sbloom 	} else {
25925705Sbloom 		for (cd = condevs; cd->CU_meth != NULL; cd++) {
26025705Sbloom 			if (snccmp(cd->CU_meth, line) == SAME) {
26125705Sbloom 				DEBUG(4, "Using %s to call\n", cd->CU_meth);
26225705Sbloom 				return (*(cd->CU_gen))(flds);
26325705Sbloom 			}
26425705Sbloom 		}
26525705Sbloom 		DEBUG(1, "Can't find %s, assuming DIR\n", flds[F_LINE]);
26613642Ssam 	}
26717834Sralph 	return diropn(flds);	/* search failed, so use direct */
26817834Sralph }
26913642Ssam 
27025127Sbloom /*
27125127Sbloom  *	close call unit
27213642Ssam  *
27313642Ssam  *	return codes:  none
27413642Ssam  */
27513642Ssam 
27613642Ssam int (*CU_end)() = nulldev;
27713642Ssam clsacu()
27813642Ssam {
27917834Sralph 	/* make *sure* Dcf is no longer exclusive.
28017834Sralph 	 * Otherwise dual call-in/call-out modems could get stuck.
28117834Sralph 	 * Unfortunately, doing this here is not ideal, but it is the
28217834Sralph 	 * easiest place to put the call.
28317834Sralph 	 * Hopefully everyone honors the LCK protocol, of course
28417834Sralph 	 */
28525705Sbloom #ifdef	TIOCNXCL
28623596Sbloom 	if (!IsTcpIp && Dcf >= 0 && ioctl(Dcf, TIOCNXCL, STBNULL) < 0)
28723596Sbloom 		DEBUG(5, "clsacu ioctl %s\n", sys_errlist[errno]);
28817834Sralph #endif
28917834Sralph 	if  (setjmp(Sjbuf))
29017834Sralph 		logent(Rmtname, "CLOSE TIMEOUT");
29117834Sralph 	else {
29217834Sralph 		signal(SIGALRM, alarmtr);
29317834Sralph 		alarm(20);
29417834Sralph 		(*(CU_end))(Dcf);
29517834Sralph 		alarm(0);
29617834Sralph 	}
29713642Ssam 	if (close(Dcf) == 0) {
29813642Ssam 		DEBUG(4, "fd %d NOT CLOSED by CU_clos\n", Dcf);
29913642Ssam 		logent("clsacu", "NOT CLOSED by CU_clos");
30013642Ssam 	}
30113642Ssam 	Dcf = -1;
30213642Ssam 	CU_end = nulldev;
30313642Ssam }
30413642Ssam 
30525127Sbloom /*
30625127Sbloom  *	expand phone number for given prefix and number
30713642Ssam  */
30813642Ssam 
30913642Ssam exphone(in, out)
31013642Ssam register char *in, *out;
31113642Ssam {
31213642Ssam 	FILE *fn;
31313642Ssam 	char pre[MAXPH], npart[MAXPH], tpre[MAXPH], p[MAXPH];
31413642Ssam 	char buf[BUFSIZ];
31513642Ssam 	register char *s1;
31613642Ssam 
31717834Sralph 	if (!isascii(*in) || !isalpha(*in)) {
31813642Ssam 		strcpy(out, in);
31913642Ssam 		return;
32013642Ssam 	}
32113642Ssam 
32213642Ssam 	s1=pre;
32317834Sralph 	while (isascii(*in) && isalpha(*in))
32413642Ssam 		*s1++ = *in++;
32513642Ssam 	*s1 = '\0';
32613642Ssam 	s1 = npart;
32713642Ssam 	while (*in != '\0')
32813642Ssam 		*s1++ = *in++;
32913642Ssam 	*s1 = '\0';
33013642Ssam 
33113642Ssam 	tpre[0] = '\0';
33213642Ssam 	if ((fn = fopen(DIALFILE, "r")) == NULL)
33313642Ssam 		DEBUG(2, "CAN'T OPEN %s\n", DIALFILE);
33413642Ssam 	else {
33513642Ssam 		while (cfgets(buf, BUFSIZ, fn)) {
33617834Sralph 			if (sscanf(buf, "%s%s", p, tpre) != 2)
33717834Sralph 				continue;
33813642Ssam 			if (strcmp(p, pre) == SAME)
33913642Ssam 				goto found;
34013642Ssam 			tpre[0] = '\0';
34113642Ssam 		}
34213642Ssam 		DEBUG(2, "CAN'T FIND dialcodes prefix '%s'\n", pre);
34313642Ssam 	found:;
34413642Ssam 		fclose(fn);
34513642Ssam 	}
34613642Ssam 
34713642Ssam 	strcpy(out, tpre);
34813642Ssam 	strcat(out, npart);
34913642Ssam }
35013642Ssam 
35118619Sralph /*
35218619Sralph  *	read and decode a line from device file
35313642Ssam  *
35413642Ssam  *	return code - FAIL at end-of file; 0 otherwise
35513642Ssam  */
35613642Ssam 
35713642Ssam rddev(fp, dev)
35813642Ssam register struct Devices *dev;
35913642Ssam FILE *fp;
36013642Ssam {
36117834Sralph 	register int na;
36213642Ssam 
36317834Sralph 	if (!cfgets(dev->D_argbfr, sizeof(dev->D_argbfr), fp))
36417834Sralph 		return FAIL;
36517834Sralph 	na = getargs(dev->D_argbfr, dev->D_arg, 20);
366*33948Srick 	if (na < 4) {
367*33948Srick 		syslog(LOG_ERR, "%s: invalid device entry", dev->D_argbfr);
368*33948Srick 		cleanup(FAIL);
369*33948Srick 	}
37017834Sralph 	if (na == 4) {
37117834Sralph 		dev->D_brand = "";
37217834Sralph 		na++;
37317834Sralph 	}
37413642Ssam 	dev->D_speed = atoi(fdig(dev->D_class));
37517834Sralph 	dev->D_numargs = na;
37617834Sralph 	return 0;
37713642Ssam }
37813642Ssam 
37918619Sralph /*
38018619Sralph  *	set system attribute vector
38113642Ssam  *
38213642Ssam  *	return codes:
38313642Ssam  *		>0  -  number of arguments in vector - succeeded
38413642Ssam  *		CF_SYSTEM  -  system name not found
38513642Ssam  *		CF_TIME  -  wrong time to call
38613642Ssam  */
38713642Ssam 
38813642Ssam finds(fsys, sysnam, info, flds)
38913642Ssam char *sysnam, info[], *flds[];
39013642Ssam FILE *fsys;
39113642Ssam {
39213642Ssam 	int na;
39313642Ssam 	int fcode = 0;
39413642Ssam 
39513642Ssam 	/* format of fields
39613642Ssam 	 *	0 name;
39713642Ssam 	 *	1 time
39813642Ssam 	 *	2 acu/hardwired
39913642Ssam 	 *	3 speed
40013642Ssam 	 *	etc
40113642Ssam 	 */
40213642Ssam 	while (cfgets(info, MAXC, fsys) != NULL) {
40317834Sralph 		na = getargs(info, flds, MAXC/10);
40423596Sbloom 		if (strncmp(sysnam, flds[F_NAME], MAXBASENAME) != SAME)
40513642Ssam 			continue;
40618619Sralph 		if (ifdate(flds[F_TIME]) != FAIL)
40713642Ssam 			/*  found a good entry  */
40817834Sralph 			return na;
40913642Ssam 		DEBUG(2, "Wrong time ('%s') to call\n", flds[F_TIME]);
41013642Ssam 		fcode = CF_TIME;
41113642Ssam 	}
41217834Sralph 	return fcode ? fcode : CF_SYSTEM;
41313642Ssam }
41413642Ssam 
41518619Sralph /*
41618619Sralph  *	do login conversation
41713642Ssam  *
41823596Sbloom  *	return codes:  SUCCESS  |  FAIL
41913642Ssam  */
42013642Ssam 
42113642Ssam login(nf, flds, fn)
42213642Ssam register char *flds[];
42313642Ssam int nf, fn;
42413642Ssam {
42513642Ssam 	register char *want, *altern;
42613642Ssam 	int k, ok;
42713642Ssam 
428*33948Srick 	if (nf < 4) {
429*33948Srick 		syslog(LOG_ERR, "Too few log fields: %d", nf);
430*33948Srick 		cleanup(FAIL);
431*33948Srick 	}
43217834Sralph 	if (setjmp(Cjbuf))
43317834Sralph 		return FAIL;
43417834Sralph 	AbortOn = NULL;
43513642Ssam 	for (k = F_LOGIN; k < nf; k += 2) {
43613642Ssam 		want = flds[k];
43733562Srick 		if (want == NULL)
43833562Srick 			want = "";
43913642Ssam 		ok = FAIL;
44017834Sralph 		while (ok != SUCCESS) {
44113642Ssam 			altern = index(want, '-');
44213642Ssam 			if (altern != NULL)
44313642Ssam 				*altern++ = '\0';
44417834Sralph 			if (strcmp(want, "ABORT") == 0) {
44517834Sralph 				AbortOn = flds[k+1];
44617834Sralph 				DEBUG(4, "ABORT ON: %s\n", AbortOn);
44717834Sralph 				goto nextfield;
44817834Sralph 			}
44925705Sbloom 			DEBUG(4, "wanted \"%s\"\n", want);
45013642Ssam 			ok = expect(want, fn);
45117834Sralph 			DEBUG(4, "got: %s\n", ok ? "?" : "that");
45217834Sralph 			if (ok == FAIL) {
45317834Sralph 				if (altern == NULL) {
45417834Sralph 					logent("LOGIN", _FAILED);
45517834Sralph 					return FAIL;
45617834Sralph 				}
45717834Sralph 				want = index(altern, '-');
45817834Sralph 				if (want != NULL)
45917834Sralph 					*want++ = '\0';
46017834Sralph 				sendthem(altern, fn);
46117834Sralph 			} else
46217834Sralph 				if (ok == ABORT) {
46333562Srick 					char sbuf[MAXFULLNAME];
46433562Srick 					sprintf(sbuf, "LOGIN ABORTED on \"%s\"",						AbortOn);
46533562Srick 					logent(sbuf, _FAILED);
46623596Sbloom 					return ABORT;
46717834Sralph 				}
46813642Ssam 		}
46917834Sralph 		sleep(1);
47013642Ssam 		if (k+1 < nf)
47113642Ssam 			sendthem(flds[k+1], fn);
47217834Sralph nextfield: ;
47313642Ssam 	}
47417834Sralph 	return SUCCESS;
47513642Ssam }
47613642Ssam 
47713642Ssam 
47817834Sralph /* conditional table generation to support odd speeds */
47913642Ssam struct sg_spds {int sp_val, sp_name;} spds[] = {
48013642Ssam #ifdef B50
48113642Ssam 	{  50,	 B50},
48213642Ssam #endif
48313642Ssam #ifdef B75
48413642Ssam 	{  75,	 B75},
48513642Ssam #endif
48613642Ssam #ifdef B110
48713642Ssam 	{ 110,	B110},
48813642Ssam #endif
48913642Ssam #ifdef B150
49013642Ssam 	{ 150,	B150},
49113642Ssam #endif
49213642Ssam #ifdef B200
49313642Ssam 	{ 200,	B200},
49413642Ssam #endif
49513642Ssam #ifdef B300
49613642Ssam 	{ 300,  B300},
49713642Ssam #endif
49813642Ssam #ifdef B600
49913642Ssam 	{600,	B600},
50013642Ssam #endif
50113642Ssam #ifdef B1200
50213642Ssam 	{1200, B1200},
50313642Ssam #endif
50413642Ssam #ifdef B1800
50513642Ssam 	{1800, B1800},
50613642Ssam #endif
50713642Ssam #ifdef B2000
50813642Ssam 	{2000, B2000},
50913642Ssam #endif
51013642Ssam #ifdef B2400
51113642Ssam 	{2400, B2400},
51213642Ssam #endif
51313642Ssam #ifdef B3600
51413642Ssam 	{3600, B3600},
51513642Ssam #endif
51613642Ssam #ifdef B4800
51713642Ssam 	{4800, B4800},
51813642Ssam #endif
51913642Ssam #ifdef B7200
52013642Ssam 	{7200, B7200},
52113642Ssam #endif
52213642Ssam #ifdef B9600
52313642Ssam 	{9600, B9600},
52413642Ssam #endif
52513642Ssam #ifdef B19200
52617834Sralph 	{19200, B19200},
52713642Ssam #endif
52817834Sralph #ifdef EXTA
52917834Sralph 	{19200, EXTA},
53017834Sralph #endif
53113642Ssam 	{0, 0}
53213642Ssam };
53313642Ssam 
53418619Sralph /*
53518619Sralph  *	set speed/echo/mode...
53613642Ssam  *
53713642Ssam  *	return codes:  none
53813642Ssam  */
53913642Ssam 
54013642Ssam fixline(tty, spwant)
54113642Ssam int tty, spwant;
54213642Ssam {
54317834Sralph #ifdef	USG
54413642Ssam 	struct termio ttbuf;
54517834Sralph #else	!USG
54613642Ssam 	struct sgttyb ttbuf;
54717834Sralph #endif !USG
54813642Ssam 	register struct sg_spds *ps;
54913642Ssam 	int speed = -1;
55013642Ssam 
55113642Ssam 	for (ps = spds; ps->sp_val; ps++)
55213642Ssam 		if (ps->sp_val == spwant)
55313642Ssam 			speed = ps->sp_name;
554*33948Srick 	if (speed < 0) {
555*33948Srick 		syslog(LOG_ERR, "unrecognized speed: %d", speed);
556*33948Srick 		cleanup(FAIL);
557*33948Srick 	}
55817834Sralph #ifdef	USG
55923596Sbloom 	if (ioctl(tty, TCGETA, &ttbuf) < 0)
56023596Sbloom 		return FAIL;
56113642Ssam 	/* ttbuf.sg_flags = (ANYP|RAW);
56213642Ssam 	ttbuf.sg_ispeed = ttbuf.sg_ospeed = speed; */
56313642Ssam 	ttbuf.c_iflag = (ushort)0;
56413642Ssam 	ttbuf.c_oflag = (ushort)0;
56513642Ssam 	ttbuf.c_cflag = (speed|CS8|HUPCL|CREAD);
56613642Ssam 	ttbuf.c_lflag = (ushort)0;
56713642Ssam 	ttbuf.c_cc[VMIN] = 6;
56813642Ssam 	ttbuf.c_cc[VTIME] = 1;
56923596Sbloom 	if (ioctl(tty, TCSETA, &ttbuf) < 0)
57023596Sbloom 		return FAIL;
57117834Sralph #else	!USG
57223596Sbloom 	if (ioctl(tty, TIOCGETP, &ttbuf) < 0)
57323596Sbloom 		return FAIL;
57413642Ssam 	ttbuf.sg_flags = (ANYP|RAW);
57513642Ssam 	ttbuf.sg_ispeed = ttbuf.sg_ospeed = speed;
57623596Sbloom 	if (ioctl(tty, TIOCSETP, &ttbuf) < 0)
57723596Sbloom 		return FAIL;
57813642Ssam #endif
57917834Sralph #ifndef	USG
58023596Sbloom 	if (ioctl(tty, TIOCHPCL, STBNULL) < 0)
58123596Sbloom 		return FAIL;
58223596Sbloom 	if (ioctl(tty, TIOCEXCL, STBNULL) < 0)
58323596Sbloom 		return FAIL;
58413642Ssam #endif
58517834Sralph 	linebaudrate = spwant;
58623596Sbloom 	return SUCCESS;
58713642Ssam }
58813642Ssam 
58917834Sralph #define MR 100
59013642Ssam 
59118619Sralph /*
59218619Sralph  *	look for expected string
59313642Ssam  *
59413642Ssam  *	return codes:
59513642Ssam  *		0  -  found
59613642Ssam  *		FAIL  -  lost line or too many characters read
59713642Ssam  *		some character  -  timed out
59813642Ssam  */
59913642Ssam 
60013642Ssam expect(str, fn)
60113642Ssam register char *str;
60213642Ssam int fn;
60313642Ssam {
60414592Skarels 	char rdvec[MR];
60517834Sralph 	register char *rp = rdvec, *strptr;
60617834Sralph 	int kr, cnt_char;
60713642Ssam 	char nextch;
60825127Sbloom 	int timo = MAXMSGTIME;
60913642Ssam 
61017834Sralph 	if (*str == '\0' || strcmp(str, "\"\"") == SAME)
61117834Sralph 		return SUCCESS;
61217834Sralph 	/* Cleanup str, convert \0xx strings to one char  */
61317834Sralph 	for (strptr = str; *strptr; strptr++) {
61417834Sralph 		if (*strptr == '\\')
61517834Sralph 			switch(*++strptr) {
61617834Sralph 			case 's':
61717834Sralph 				DEBUG(5, "BLANK\n", CNULL);
61817834Sralph 				*strptr = ' ';
61917834Sralph 				break;
62017834Sralph 			default:
62117834Sralph 				strptr--;  /* back up to backslash */
62217834Sralph 				sscanf(strptr + 1,"%o", &cnt_char);
62317834Sralph 				DEBUG(6, "BACKSLASHED %02xH\n", cnt_char);
62417834Sralph 				*strptr = (char) (cnt_char);
62517834Sralph 				strcpy(&strptr[1], &strptr[4]);
62617834Sralph 			}
62717834Sralph 	}
62817834Sralph 
62925127Sbloom 	strptr = index(str, '~');
63025127Sbloom 	if (strptr != NULL) {
63125127Sbloom 		*strptr++ = '\0';
63225127Sbloom 		timo = atoi(strptr);
63325127Sbloom 		if (timo <= 0)
63425127Sbloom 			timo = MAXMSGTIME;
63525127Sbloom 	}
63625127Sbloom 
63717834Sralph 	if (setjmp(Sjbuf))
63817834Sralph 		return FAIL;
63913642Ssam 	signal(SIGALRM, alarmtr);
64025127Sbloom 	alarm(timo);
64125127Sbloom 	*rp = 0;
64213642Ssam 	while (notin(str, rdvec)) {
64325705Sbloom 		int c;
64417834Sralph 		if(AbortOn != NULL && !notin(AbortOn, rdvec)) {
64517834Sralph 			DEBUG(1, "Call aborted on '%s'\n", AbortOn);
64617834Sralph 			alarm(0);
64717834Sralph 			return ABORT;
64817834Sralph 		}
64913642Ssam 		kr = read(fn, &nextch, 1);
65013642Ssam 		if (kr <= 0) {
65113642Ssam 			alarm(0);
65213642Ssam 			DEBUG(4, "lost line kr - %d\n, ", kr);
65313642Ssam 			logent("LOGIN", "LOST LINE");
65417834Sralph 			return FAIL;
65513642Ssam 		}
65613642Ssam 		c = nextch & 0177;
65725705Sbloom 		if (c == '\0')
65825705Sbloom 			continue;
65925705Sbloom 		DEBUG(4, (isprint(c) || isspace(c)) ? "%c" : "\\%03o", c);
66025705Sbloom 		*rp++ = c;
66113642Ssam 		if (rp >= rdvec + MR) {
66217834Sralph 			register char *p;
66317834Sralph 			for (p = rdvec+MR/2; p < rp; p++)
66417834Sralph 				*(p-MR/2) = *p;
66517834Sralph 			rp -= MR/2;
66613642Ssam 		}
66713642Ssam 		*rp = '\0';
66813642Ssam 	}
66913642Ssam 	alarm(0);
67017834Sralph 	return SUCCESS;
67113642Ssam }
67213642Ssam 
67313642Ssam 
67413642Ssam /*
67513642Ssam  * Determine next file descriptor that would be allocated.
67613642Ssam  * This permits later closing of a file whose open was interrupted.
67713642Ssam  * It is a UNIX kernel problem, but it has to be handled.
67813642Ssam  * unc!smb (Steve Bellovin) probably first discovered it.
67913642Ssam  */
68013642Ssam getnextfd()
68113642Ssam {
68213642Ssam 	close(next_fd = open("/", 0));
68313642Ssam }
68413642Ssam 
68517834Sralph /*
68617834Sralph  *	send line of login sequence
68713642Ssam  *
68813642Ssam  *	return codes:  none
68913642Ssam  */
69013642Ssam sendthem(str, fn)
69113642Ssam register char *str;
69213642Ssam int fn;
69313642Ssam {
69413642Ssam 	register char *strptr;
69513642Ssam 	int i, n, cr = 1;
69617834Sralph 	register char c;
69713642Ssam 	static int p_init = 0;
69813642Ssam 
69925705Sbloom 	DEBUG(5, "send \"%s\"\n", str);
70013642Ssam 
70113642Ssam 	if (!p_init) {
70213642Ssam 		p_init++;
703*33948Srick 		bld_partab(P_ZERO);
70413642Ssam 	}
70513642Ssam 
70613642Ssam 	if (prefix("BREAK", str)) {
70713642Ssam 		sscanf(&str[5], "%1d", &i);
70813642Ssam 		if (i <= 0 || i > 10)
70913642Ssam 			i = 3;
71013642Ssam 		/* send break */
71113642Ssam 		genbrk(fn, i);
71213642Ssam 		return;
71313642Ssam 	}
71413642Ssam 
71513642Ssam 	if (prefix("PAUSE", str)) {
71613642Ssam 		sscanf(&str[5], "%1d", &i);
71713642Ssam 		if (i <= 0 || i > 10)
71813642Ssam 			i = 3;
71913642Ssam 		/* pause for a while */
72013642Ssam 		sleep((unsigned)i);
72113642Ssam 		return;
72213642Ssam 	}
72313642Ssam 
72413642Ssam 	if (strcmp(str, "EOT") == SAME) {
72513642Ssam 		p_chwrite(fn, '\04');
72613642Ssam 		return;
72713642Ssam 	}
72813642Ssam 
72913642Ssam 	/* Send a '\n' */
73025705Sbloom 	if (strcmp(str, "LF") == SAME) {
73125705Sbloom 		p_chwrite(fn, '\n');
73225705Sbloom 		return;
73325705Sbloom 	}
73413642Ssam 
73513642Ssam 	/* Send a '\r' */
73625705Sbloom 	if (strcmp(str, "CR") == SAME) {
73725705Sbloom 		p_chwrite(fn, '\r');
73825705Sbloom 		return;
73925705Sbloom 	}
74013642Ssam 
74113642Ssam 	/* Set parity as needed */
74213642Ssam 	if (strcmp(str, "P_ZERO") == SAME) {
74313642Ssam 		bld_partab(P_ZERO);
74413642Ssam 		return;
74513642Ssam 	}
74613642Ssam 	if (strcmp(str, "P_ONE") == SAME) {
74713642Ssam 		bld_partab(P_ONE);
74813642Ssam 		return;
74913642Ssam 	}
75013642Ssam 	if (strcmp(str, "P_EVEN") == SAME) {
75113642Ssam 		bld_partab(P_EVEN);
75213642Ssam 		return;
75313642Ssam 	}
75413642Ssam 	if (strcmp(str, "P_ODD") == SAME) {
75513642Ssam 		bld_partab(P_ODD);
75613642Ssam 		return;
75713642Ssam 	}
75813642Ssam 
75913642Ssam 	/* If "", just send '\r' */
76017834Sralph 	if (strcmp(str, "\"\"") == SAME) {
76117834Sralph 		p_chwrite(fn, '\r');
76217834Sralph 		return;
76317834Sralph 	}
76417834Sralph 
76525705Sbloom 	strptr = str;
76625705Sbloom 	while ((c = *strptr++) != '\0') {
76717834Sralph 		if (c == '\\') {
76817834Sralph 			switch(*strptr++) {
76925705Sbloom 			case '\0':
77025705Sbloom 				DEBUG(5, "TRAILING BACKSLASH IGNORED\n", CNULL);
77125705Sbloom 				--strptr;
77225705Sbloom 				continue;
77317834Sralph 			case 's':
77417834Sralph 				DEBUG(5, "BLANK\n", CNULL);
77525705Sbloom 				c = ' ';
77617834Sralph 				break;
77717834Sralph 			case 'd':
77817834Sralph 				DEBUG(5, "DELAY\n", CNULL);
77917834Sralph 				sleep(1);
78017834Sralph 				continue;
78125705Sbloom 			case 'n':
78225705Sbloom 				DEBUG(5, "NEW LINE\n", CNULL);
78325705Sbloom 				c = '\n';
78425705Sbloom 				break;
78517834Sralph 			case 'r':
78617834Sralph 				DEBUG(5, "RETURN\n", CNULL);
78725705Sbloom 				c = '\r';
78817834Sralph 				break;
78917834Sralph 			case 'b':
79017834Sralph 				if (isdigit(*strptr)) {
79117834Sralph 					i = (*strptr++ - '0');
79217834Sralph 					if (i <= 0 || i > 10)
79317834Sralph 						i = 3;
79417834Sralph 				} else
79513642Ssam 					i = 3;
79617834Sralph 				/* send break */
79717834Sralph 				genbrk(fn, i);
79817834Sralph 				if (*strptr == '\0')
79917834Sralph 					cr = 0;
80013642Ssam 				continue;
80117834Sralph 			case 'c':
80217834Sralph 				if (*strptr == '\0') {
80317834Sralph 					DEBUG(5, "NO CR\n", CNULL);
80417834Sralph 					cr = 0;
80525705Sbloom 				} else
80625705Sbloom 					DEBUG(5, "NO CR - IGNORED NOT EOL\n", CNULL);
80713642Ssam 				continue;
80825705Sbloom #define isoctal(x)	((x >= '0') && (x <= '7'))
80917834Sralph 			default:
81025705Sbloom 				if (isoctal(strptr[-1])) {
81117834Sralph 					i = 0;
81217834Sralph 					n = 0;
81325705Sbloom 					--strptr;
81425705Sbloom 					while (isoctal(*strptr) && ++n <= 3)
81525705Sbloom 						i = i * 8 + (*strptr++ - '0');
81625705Sbloom 					DEBUG(5, "\\%o\n", i);
81717834Sralph 					p_chwrite(fn, (char)i);
81817834Sralph 					continue;
81917834Sralph 				}
82013642Ssam 			}
82125705Sbloom 		}
82225705Sbloom 		p_chwrite(fn, c);
82313642Ssam 	}
82413642Ssam 
82513642Ssam 	if (cr)
82613642Ssam 		p_chwrite(fn, '\r');
82713642Ssam 	return;
82813642Ssam }
82913642Ssam 
83013642Ssam p_chwrite(fd, c)
83113642Ssam int fd;
83217834Sralph char c;
83313642Ssam {
83417834Sralph 	c = par_tab[c&0177];
83517834Sralph 	if (write(fd, &c, 1) != 1) {
83617834Sralph 		logent(sys_errlist[errno], "BAD WRITE");
83717834Sralph 		longjmp(Cjbuf, 2);
83817834Sralph 	}
83913642Ssam }
84013642Ssam 
84113642Ssam /*
84213642Ssam  * generate parity table for use by p_chwrite.
84313642Ssam  */
84413642Ssam bld_partab(type)
84513642Ssam int type;
84613642Ssam {
84713642Ssam 	register int i, j, n;
84813642Ssam 
84913642Ssam 	for (i = 0; i < sizeof(par_tab); i++) {
85013642Ssam 		n = 0;
85113642Ssam 		for (j = i&(sizeof(par_tab)-1); j; j = (j-1)&j)
85213642Ssam 			n++;
85313642Ssam 		par_tab[i] = i;
85413642Ssam 		if (type == P_ONE
85513642Ssam 		 || (type == P_EVEN && (n&01) != 0)
85613642Ssam 		 || (type == P_ODD && (n&01) == 0))
85713642Ssam 			par_tab[i] |= sizeof(par_tab);
85813642Ssam 	}
85913642Ssam }
86013642Ssam 
86118619Sralph /*
86218619Sralph  *	check for occurrence of substring "sh"
86313642Ssam  *
86413642Ssam  *	return codes:
86513642Ssam  *		0  -  found the string
86613642Ssam  *		1  -  not in the string
86713642Ssam  */
86813642Ssam notin(sh, lg)
86913642Ssam register char *sh, *lg;
87013642Ssam {
87113642Ssam 	while (*lg != '\0') {
87213642Ssam 		if (wprefix(sh, lg))
87318619Sralph 			return 0;
87413642Ssam 		else
87513642Ssam 			lg++;
87613642Ssam 	}
87718619Sralph 	return 1;
87813642Ssam }
87913642Ssam 
88018619Sralph /*
88123596Sbloom  *	Allow multiple date specifications separated by ','.
88213642Ssam  */
88318619Sralph ifdate(p)
88418619Sralph register char *p;
88513642Ssam {
88625705Sbloom 	register char *np;
88718619Sralph 	register int ret, g;
88823596Sbloom 	int rtime, i;
88913642Ssam 
89023596Sbloom 	/*  pick up retry time for failures  */
89123596Sbloom 	/*  global variable Retrytime is set here  */
89223596Sbloom 	if ((np = index(p, ';')) == NULL) {
89323596Sbloom 		Retrytime = RETRYTIME;
89423596Sbloom 	} else {
89523596Sbloom 		i = sscanf(np+1, "%d", &rtime);
89623596Sbloom 		if (i < 1 || rtime < 0)
89723596Sbloom 			rtime = 5;
89823596Sbloom 		Retrytime  = rtime * 60;
89923596Sbloom 	}
90023596Sbloom 
90118619Sralph 	ret = FAIL;
90218619Sralph 	MaxGrade = '\0';
90318619Sralph 	do {
90423596Sbloom 		np = strpbrk(p, ",|");	/* prefer , but allow | for compat */
90523596Sbloom 		if (np)
90623596Sbloom 			*np = '\0';
90718619Sralph 		g = ifadate(p);
90818619Sralph 		DEBUG(11,"ifadate returns %o\n", g);
90918619Sralph 		if (g != FAIL) {
91018619Sralph 			ret = SUCCESS;
91118619Sralph 			if (g > MaxGrade)
91218619Sralph 				MaxGrade = g;
91318619Sralph 		}
91423596Sbloom 		if (np)
91523596Sbloom 			*np = ',';
91623596Sbloom 		p = np + 1;
91723596Sbloom 	} while (np);
91823596Sbloom 	if (MaxGrade == '\0')
91923596Sbloom 		MaxGrade = DefMaxGrade;
92018619Sralph 	return ret;
92113642Ssam }
92213642Ssam 
92318619Sralph /*
92418619Sralph  *	this routine will check a string (string)
92513642Ssam  *	like "MoTu0800-1730" to see if the present
92613642Ssam  *	time is within the given limits.
92713642Ssam  *	SIDE EFFECT - Retrytime is set
92813642Ssam  *
92913642Ssam  *	return codes:
93013642Ssam  *		0  -  not within limits
93113642Ssam  *		1  -  within limits
93213642Ssam  */
93313642Ssam 
93418619Sralph ifadate(string)
93518619Sralph char *string;
93613642Ssam {
93713642Ssam 	static char *days[]={
93813642Ssam 		"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", 0
93913642Ssam 	};
94013642Ssam 	time_t clock;
94118619Sralph 	register char *s = string;
94217834Sralph 	int i, tl, th, tn, dayok=0;
94313642Ssam 	struct tm *localtime();
94413642Ssam 	struct tm *tp;
94518619Sralph 	char *p, MGrade;
94613642Ssam 
94723596Sbloom 	if ((p = index(s, '/')) == NULL)
94818619Sralph 		MGrade = DefMaxGrade;
94918619Sralph 	else
95018619Sralph 		MGrade = p[1];
95118619Sralph 
95213642Ssam 	time(&clock);
95313642Ssam 	tp = localtime(&clock);
95417834Sralph 	while (isascii(*s) && isalpha(*s)) {
95513642Ssam 		for (i = 0; days[i]; i++) {
95613642Ssam 			if (prefix(days[i], s))
95713642Ssam 				if (tp->tm_wday == i)
95813642Ssam 					dayok = 1;
95913642Ssam 		}
96013642Ssam 
96113642Ssam 		if (prefix("Wk", s))
96213642Ssam 			if (tp->tm_wday >= 1 && tp->tm_wday <= 5)
96313642Ssam 				dayok = 1;
96413642Ssam 		if (prefix("Any", s))
96513642Ssam 			dayok = 1;
96617834Sralph 		if (prefix("Evening", s)) {
96717834Sralph 			/* Sat or Sun */
96817834Sralph 			if (tp->tm_wday == 6 || tp->tm_wday == 0
96917834Sralph 				|| tp->tm_hour >= 17 || tp->tm_hour < 8)
97017834Sralph 					dayok = 1;
97117834Sralph 		}
97217834Sralph 		if (prefix("Night", s)) {
97317834Sralph 			if (tp->tm_wday == 6  /* Sat */
97418619Sralph 				|| tp->tm_hour >= 23 || tp->tm_hour < 8
97518619Sralph 					/* Sunday before 5pm */
97618619Sralph 				|| (tp->tm_wday == 0 && tp->tm_hour < 17))
97717834Sralph 					dayok = 1;
97817834Sralph 		}
97925705Sbloom 		if (prefix("NonPeak", s)) { /* For Tymnet and PC Pursuit */
98025705Sbloom 			/* Sat or Sun */
98125705Sbloom 			if (tp->tm_wday == 6 || tp->tm_wday == 0
98225705Sbloom 				|| tp->tm_hour >= 18 || tp->tm_hour < 7)
98325705Sbloom 					dayok = 1;
98425705Sbloom 		}
98513642Ssam 		s++;
98613642Ssam 	}
98713642Ssam 
98818619Sralph 	if (dayok == 0 && s != string)
98918619Sralph 		return FAIL;
99013642Ssam 	i = sscanf(s, "%d-%d", &tl, &th);
99118619Sralph   	if (i < 2)
99218619Sralph   		return MGrade;
99318619Sralph 	tn = tp->tm_hour * 100 + tp->tm_min;
99418619Sralph   	if (th < tl) { 		/* crosses midnight */
99518619Sralph   		if (tl <= tn || tn < th)
99618619Sralph   			return MGrade;
99725966Sbloom   	} else {
99817834Sralph 		if (tl <= tn && tn < th)
99918619Sralph 			return MGrade;
100025966Sbloom 	}
100118619Sralph 	return FAIL;
100213642Ssam }
100313642Ssam 
100418619Sralph /*
100518619Sralph  *	find first digit in string
100613642Ssam  *
100713642Ssam  *	return - pointer to first digit in string or end of string
100813642Ssam  */
100913642Ssam char *
101013642Ssam fdig(cp)
101113642Ssam register char *cp;
101213642Ssam {
101313642Ssam 	register char *c;
101413642Ssam 
101513642Ssam 	for (c = cp; *c; c++)
101613642Ssam 		if (*c >= '0' && *c <= '9')
101713642Ssam 			break;
101817834Sralph 	return c;
101913642Ssam }
102013642Ssam 
102113642Ssam /*
102213642Ssam  * Compare strings:  s1>s2: >0  s1==s2: 0  s1<s2: <0
102313642Ssam  * Strings are compared as if they contain all capital letters.
102413642Ssam  */
102513642Ssam snccmp(s1, s2)
102613642Ssam register char *s1, *s2;
102713642Ssam {
102813642Ssam 	char c1, c2;
102913642Ssam 
103025127Sbloom 	if (islower(*s1))
103125127Sbloom 		c1 = toupper(*s1);
103225127Sbloom 	else
103325127Sbloom 		c1 = *s1;
103425127Sbloom 	if (islower(*s2))
103525127Sbloom 		c2 = toupper(*s2);
103625127Sbloom 	else
103725127Sbloom 		c2 = *s2;
103813642Ssam 
103913642Ssam 	while (c1 == c2) {
104025127Sbloom 		if (*s1++ == '\0')
104117834Sralph 			return 0;
104213642Ssam 		s2++;
104325127Sbloom 		if (islower(*s1))
104425127Sbloom 			c1 = toupper(*s1);
104525127Sbloom 		else
104625127Sbloom 			c1 = *s1;
104725127Sbloom 		if (islower(*s2))
104825127Sbloom 			c2 = toupper(*s2);
104925127Sbloom 		else
105025127Sbloom 			c2 = *s2;
105113642Ssam 	}
105217834Sralph 	return c1 - c2;
105313642Ssam }
105425127Sbloom 
105517834Sralph /*
105625127Sbloom  * Compare strings:  s1>s2: >0  s1==s2: 0  s1<s2: <0
105725127Sbloom  * Strings are compared as if they contain all capital letters.
105825127Sbloom  */
105925127Sbloom sncncmp(s1, s2, n)
106025127Sbloom register char *s1, *s2;
106125127Sbloom register int n;
106225127Sbloom {
106325127Sbloom 	char c1, c2;
106425127Sbloom 
106525127Sbloom 	if (islower(*s1))
106625127Sbloom 		c1 = toupper(*s1);
106725127Sbloom 	else
106825127Sbloom 		c1 = *s1;
106925127Sbloom 	if (islower(*s2))
107025127Sbloom 		c2 = toupper(*s2);
107125127Sbloom 	else
107225127Sbloom 		c2 = *s2;
107325127Sbloom 
107425127Sbloom 	while ( --n >= 0 && c1 == c2) {
107525127Sbloom 		if (*s1++ == '\0')
107625127Sbloom 			return 0;
107725127Sbloom 		s2++;
107825127Sbloom 		if (islower(*s1))
107925127Sbloom 			c1 = toupper(*s1);
108025127Sbloom 		else
108125127Sbloom 			c1 = *s1;
108225127Sbloom 		if (islower(*s2))
108325127Sbloom 			c2 = toupper(*s2);
108425127Sbloom 		else
108525127Sbloom 			c2 = *s2;
108625127Sbloom 	}
108725127Sbloom 	return n<0 ? 0 : (c1 - c2);
108825127Sbloom }
108925127Sbloom /*
109017834Sralph  * do chat script
109117834Sralph  * occurs after local port is opened,
109217834Sralph  * before 'dialing' the other machine.
109317834Sralph  */
109417834Sralph dochat(dev, flds, fd)
109517834Sralph register struct Devices *dev;
109617834Sralph char *flds[];
109717834Sralph int fd;
109817834Sralph {
109917834Sralph 	register int i;
110017834Sralph 	register char *p;
110117834Sralph 	char bfr[sizeof(dev->D_argbfr)];
110217834Sralph 
110317834Sralph 	if (dev->D_numargs <= 5)
110417834Sralph 		return(0);
110517834Sralph 	DEBUG(4, "dochat called %d\n", dev->D_numargs);
110617834Sralph 	for (i = 0; i < dev->D_numargs-5; i++) {
110717834Sralph 		sprintf(bfr, dev->D_arg[D_CHAT+i], flds[F_PHONE]);
110817834Sralph 		if (strcmp(bfr, dev->D_arg[D_CHAT+i])) {
110917834Sralph 			p = malloc((unsigned)strlen(bfr)+1);
111017834Sralph 			if (p != NULL) {
111117834Sralph 				strcpy(p, bfr);
111217834Sralph 				dev->D_arg[D_CHAT+i] = p;
111317834Sralph 			}
111417834Sralph 		}
111517834Sralph 	}
111617834Sralph 	/* following is a kludge because login() arglist is a kludge */
111717834Sralph 	i = login(dev->D_numargs, &dev->D_arg[D_CHAT-5], fd);
111817834Sralph 	/*
111917834Sralph 	 * If login() last did a sendthem(), must pause so things can settle.
112017834Sralph 	 * But don't bother if chat failed.
112117834Sralph 	 */
112217834Sralph 	if (i == 0 && (dev->D_numargs&01))
112317834Sralph 		sleep(2);
112417834Sralph 	return(i);
112517834Sralph }
112625705Sbloom 
112725705Sbloom /*
112825705Sbloom  *	fix kill/echo/raw on line
112925705Sbloom  *
113025705Sbloom  *	return codes:  none
113125705Sbloom  */
113225705Sbloom fixmode(tty)
113325705Sbloom register int tty;
113425705Sbloom {
113525705Sbloom #ifdef	USG
113625705Sbloom 	struct termio ttbuf;
113725705Sbloom #else	!USG
113825705Sbloom 	struct sgttyb ttbuf;
113925705Sbloom #endif	!USG
114025705Sbloom 	register struct sg_spds *ps;
114125705Sbloom 	int speed;
114225705Sbloom 
114325705Sbloom 	if (IsTcpIp)
114425705Sbloom 		return;
114525705Sbloom #ifdef	USG
114625705Sbloom 	ioctl(tty, TCGETA, &ttbuf);
114725705Sbloom 	ttbuf.c_iflag = ttbuf.c_oflag = ttbuf.c_lflag = (ushort)0;
114825705Sbloom 	speed = ttbuf.c_cflag &= (CBAUD);
114925705Sbloom 	ttbuf.c_cflag |= (CS8|CREAD);
115025705Sbloom 	ttbuf.c_cc[VMIN] = 6;
115125705Sbloom 	ttbuf.c_cc[VTIME] = 1;
115225705Sbloom 	ioctl(tty, TCSETA, &ttbuf);
115325705Sbloom #else	!USG
115425705Sbloom 	ioctl(tty, TIOCGETP, &ttbuf);
115525705Sbloom 	ttbuf.sg_flags = (ANYP | RAW);
115625705Sbloom 	ioctl(tty, TIOCSETP, &ttbuf);
115725705Sbloom 	speed = ttbuf.sg_ispeed;
115825705Sbloom 	ioctl(tty, TIOCEXCL, STBNULL);
115925705Sbloom #endif	!USG
116025705Sbloom 
116125705Sbloom 	for (ps = spds; ps->sp_val; ps++)
116225705Sbloom 		if (ps->sp_name == speed) {
116325705Sbloom 			linebaudrate = ps->sp_val;
116425705Sbloom 			DEBUG(9,"Incoming baudrate is %d\n", linebaudrate);
116525705Sbloom 			return;
116625705Sbloom 		}
1167*33948Srick 	if (linebaudrate < 0) {
1168*33948Srick 		syslog(LOG_ERR, "unrecognized speed: %d", linebaudrate);
1169*33948Srick 		cleanup(FAIL);
1170*33948Srick 	}
117125705Sbloom }
1172