xref: /original-bsd/usr.bin/uucp/uucico/conn.c (revision 22631af3)
105c9bca4Sbostic /*-
2*22631af3Sbostic  * Copyright (c) 1985, 1993
3*22631af3Sbostic  *	The Regents of the University of California.  All rights reserved.
405c9bca4Sbostic  *
505c9bca4Sbostic  * %sccs.include.proprietary.c%
605c9bca4Sbostic  */
705c9bca4Sbostic 
8ce9e9b91Srick #ifndef lint
9*22631af3Sbostic static char sccsid[] = "@(#)conn.c	8.1 (Berkeley) 06/06/93";
1005c9bca4Sbostic #endif /* not lint */
118757e372Ssam 
128757e372Ssam #include <signal.h>
13e05f97bfSbloom #include "uucp.h"
148757e372Ssam #include <setjmp.h>
158757e372Ssam #include <ctype.h>
168757e372Ssam #include <errno.h>
17ef0102e5Sralph #ifdef	USG
188757e372Ssam #include <termio.h>
198757e372Ssam #include <fcntl.h>
208757e372Ssam #endif
21ef0102e5Sralph #ifndef	USG
228757e372Ssam #include <sgtty.h>
238757e372Ssam #endif
24ef0102e5Sralph #ifdef BSD4_2
25ef0102e5Sralph #include <sys/time.h>
26ef0102e5Sralph #else
27ef0102e5Sralph #include <time.h>
28ef0102e5Sralph #endif
298757e372Ssam 
308757e372Ssam #define MAXC 1000
318757e372Ssam 
328757e372Ssam extern jmp_buf Sjbuf;
33ef0102e5Sralph jmp_buf Cjbuf;
34991054b8Sralph extern int errno, onesys;
35e40fdfd4Storek extern const char *const sys_errlist[];
36991054b8Sralph extern char MaxGrade, DefMaxGrade;
378757e372Ssam 
388757e372Ssam /* Parity control during login procedure */
398757e372Ssam #define	P_ZERO	0
408757e372Ssam #define	P_ONE	1
418757e372Ssam #define	P_EVEN	2
428757e372Ssam #define	P_ODD	3
438757e372Ssam 
44ef0102e5Sralph #define ABORT -2
45ef0102e5Sralph 
46ef0102e5Sralph char 	*AbortOn = NULL;
47ef0102e5Sralph char	par_tab[128];	/* must be power of two */
48ef0102e5Sralph int	linebaudrate;	/* used for the sleep test in pk1.c */
498757e372Ssam int next_fd = -1;	/* predicted fd to close interrupted opens */
50c0845685Sbloom 
51c0845685Sbloom char *PCP = "PCP";	/* PC Pursuit device type */
52af5ea5faSbloom /*
53af5ea5faSbloom  *	catch alarm routine for "expect".
548757e372Ssam  */
5572626698Sbostic void
alarmtr()568757e372Ssam alarmtr()
578757e372Ssam {
588757e372Ssam 	signal(SIGALRM, alarmtr);
598757e372Ssam 	if (next_fd >= 0) {
608757e372Ssam 		if (close(next_fd))
618757e372Ssam 			logent("FAIL", "ACU LINE CLOSE");
628757e372Ssam 		next_fd = -1;
638757e372Ssam 	}
648757e372Ssam 	longjmp(Sjbuf, 1);
658757e372Ssam }
668757e372Ssam 
67c0845685Sbloom /* This template is for seismo to call ihnp4
68c0845685Sbloom  * the 3 lines marked ---> will be overwritten for the appropriate city
69c0845685Sbloom  */
70c0845685Sbloom #define PCP_BAUD	3
71c0845685Sbloom #define PCP_PHONE	4
72c5c1a0c2Srick #define PCP_CITY	14
73c5c1a0c2Srick #define PCP_PASSWORD	16
74c5c1a0c2Srick #define PCP_RPHONE	20
75c5c1a0c2Srick #define NPCFIELDS	23
76c0845685Sbloom 
77c0845685Sbloom static char *PCFlds[] = {
78c0845685Sbloom 	"PC-PURSUIT",
79c0845685Sbloom 	"Any",
80c0845685Sbloom 	"ACU",
81c0845685Sbloom 	"1200",
82c5c1a0c2Srick 	CNULL,
83c5c1a0c2Srick 	CNULL,
84c5c1a0c2Srick 	"P_ZERO",	/* Telenet insists on zero parity */
85c0845685Sbloom 	"ABORT",
86c5c1a0c2Srick 	"BUSY",		/* Abort on Busy Signal */
87c5c1a0c2Srick 	CNULL,
88c5c1a0c2Srick 	"\\d\\d\\r\\d\\r",	/* Get telenet's attention */
89c5c1a0c2Srick 	"TERMINAL=~3-\r-TERM~3-\r-TERM~5", 	/* Terminal type ? */
90c5c1a0c2Srick 	"\\r",
91c5c1a0c2Srick 	"@",		/* telenet's prompt */
92c5c1a0c2Srick 	"D/DCWAS/21,telenetloginstring", /* overwritten later */
93c5c1a0c2Srick 	"PASSWORD",
94c5c1a0c2Srick 	CNULL,		/* telenet password */
95c5c1a0c2Srick 	"CONNECTED",	/* We're now talking to a Hayes in the remote city */
96c5c1a0c2Srick 	"ATZ",		/* Reset it */
97c5c1a0c2Srick 	"OK",
98c5c1a0c2Srick 	"ATDT6907171", /* overwritten */
99c5c1a0c2Srick 	"CONNECT",
100c5c1a0c2Srick 	"\\d\\r",		/* We're in !*/
101c5c1a0c2Srick 	CNULL,
102c0845685Sbloom };
103c0845685Sbloom 
104c5c1a0c2Srick static char PCP_brand[25];
1058ab21806Srick int Dcf = -1;
1068ab21806Srick char *Flds[MAXC/10];
1078ab21806Srick char LineType[10];
1088ab21806Srick extern int LocalOnly;
109c0845685Sbloom 
110991054b8Sralph /*
111991054b8Sralph  *	place a telephone call to system and login, etc.
1128757e372Ssam  *
1138757e372Ssam  *	return codes:
1148757e372Ssam  *		CF_SYSTEM: don't know system
1158757e372Ssam  *		CF_TIME: wrong time to call
1168757e372Ssam  *		CF_DIAL: call failed
1178757e372Ssam  *		CF_NODEV: no devices available to place call
1188757e372Ssam  *		CF_LOGIN: login/password dialog failed
1198757e372Ssam  *
1208757e372Ssam  *		>0  - file no.  -  connect ok
1218757e372Ssam  */
conn(system)1228757e372Ssam conn(system)
1238757e372Ssam char *system;
1248757e372Ssam {
125c0845685Sbloom 	int nf;
126991054b8Sralph 	char info[MAXC], wkpre[NAMESIZE], file[NAMESIZE];
1278757e372Ssam 	register FILE *fsys;
1288757e372Ssam 	int fcode = 0;
1298757e372Ssam 
1308757e372Ssam 	nf = 0;
1318757e372Ssam 
1328757e372Ssam 	fsys = fopen(SYSFILE, "r");
1337e40e16eSrick 	if (fsys == NULL) {
1347e40e16eSrick 		syslog(LOG_ERR, "fopen(%s) failed: %m", SYSFILE);
1357e40e16eSrick 		cleanup(FAIL);
1367e40e16eSrick 	}
1378757e372Ssam 
138ef0102e5Sralph 	DEBUG(4, "finds (%s) called\n", system);
139af5ea5faSbloom keeplooking:
140ef0102e5Sralph 	while((nf = finds(fsys, system, info, Flds)) > 0) {
141877cef39Sbloom 		strncpy(LineType, Flds[F_LINE], 10);
142ef0102e5Sralph 		if (LocalOnly) {
143877cef39Sbloom 			if (strcmp("TCP", LineType)
144877cef39Sbloom 				&& strcmp("DIR", LineType)
145877cef39Sbloom 				&& strcmp("LOCAL", LineType) ) {
146c0845685Sbloom 					fcode = CF_TIME;
147c0845685Sbloom 					continue;
148c0845685Sbloom 			}
149ef0102e5Sralph 		}
150e05f97bfSbloom 		sprintf(wkpre, "%c.%.*s", CMDPRE, SYSNSIZE, Rmtname);
151991054b8Sralph 		if (!onesys && MaxGrade != DefMaxGrade &&
152c0845685Sbloom 			!iswrk(file, "chk", Spool, wkpre))  {
153c0845685Sbloom 				fcode = CF_TIME;
154c0845685Sbloom 				continue;
1558757e372Ssam 		}
156c0845685Sbloom 		/* For GTE's PC Pursuit */
157877cef39Sbloom 		if (snccmp(LineType, PCP) == SAME) {
158c0845685Sbloom 			FILE *dfp;
159c0845685Sbloom 			int status;
160c0845685Sbloom 			static struct Devices dev;
161c5c1a0c2Srick 
162c0845685Sbloom 			dfp = fopen(DEVFILE, "r");
1637e40e16eSrick 			if (dfp == NULL) {
1647e40e16eSrick 				syslog(LOG_ERR, "fopen(%s) failed: %m",
1657e40e16eSrick 					DEVFILE);
1667e40e16eSrick 				cleanup(FAIL);
1677e40e16eSrick 			}
168c0845685Sbloom 			while ((status=rddev(dfp, &dev)) != FAIL
169c0845685Sbloom 				&& strcmp(PCP, dev.D_type) != SAME)
170c0845685Sbloom 					;
171c0845685Sbloom 			fclose(dfp);
172c0845685Sbloom 			if (status == FAIL)
173c0845685Sbloom 				continue;
174c0845685Sbloom 			if (mlock(PCP) == FAIL) {
175c0845685Sbloom 				fcode = CF_NODEV;
176c0845685Sbloom 				logent("DEVICE", "NO");
177c0845685Sbloom 				continue;
178c0845685Sbloom 			}
179c0845685Sbloom 			PCFlds[PCP_BAUD] = dev.D_class;
180c0845685Sbloom 			PCFlds[PCP_PHONE] = dev.D_calldev;
181c5c1a0c2Srick 			sprintf(PCFlds[PCP_CITY], "c d/%s%s,%s",
182c5c1a0c2Srick 				Flds[F_CLASS],
183c5c1a0c2Srick 				index(Flds[F_CLASS], '/') == NULL ? "/12" : "",
184c5c1a0c2Srick 				dev.D_arg[D_CHAT]);
185c5c1a0c2Srick 			PCFlds[PCP_PASSWORD] = dev.D_line;
186c5c1a0c2Srick 			strncpy(&PCFlds[PCP_RPHONE][4], Flds[F_PHONE], 7);
187c0845685Sbloom 			strncpy(PCP_brand, dev.D_brand, sizeof(PCP_brand));
188c5c1a0c2Srick 			if ((fcode = getto(PCFlds)) < 0) {
189c5c1a0c2Srick 				rmlock(PCP);
190c0845685Sbloom 				continue;
191c0845685Sbloom 			}
192c5c1a0c2Srick 			Dcf = fcode;
193c5c1a0c2Srick 			fcode = login(NPCFIELDS, PCFlds, Dcf);
194c5c1a0c2Srick 			if (fcode == SUCCESS)
195c0845685Sbloom 				break;
196c5c1a0c2Srick 			fcode = CF_DIAL;
197c5c1a0c2Srick 			rmlock(PCP);
198c5c1a0c2Srick 			/* end PC Pursuit */
199c5c1a0c2Srick 		} else if ((fcode = getto(Flds)) > 0)  {
200c5c1a0c2Srick 			Dcf = fcode;
201c5c1a0c2Srick 			break;
202c5c1a0c2Srick 		}
2038757e372Ssam 	}
2048757e372Ssam 
205af5ea5faSbloom 	if (nf <= 0) {
206af5ea5faSbloom 		fclose(fsys);
207ef0102e5Sralph 		return fcode ? fcode : nf;
208af5ea5faSbloom 	}
2098757e372Ssam 
210c0845685Sbloom 
211c0845685Sbloom 	if (fcode >= 0) {
2128757e372Ssam 		DEBUG(4, "login %s\n", "called");
2138ab21806Srick 		setproctitle("login");
214c5c1a0c2Srick 		fcode = login(nf, Flds, Dcf); }
215c0845685Sbloom 	if (fcode < 0) {
2168757e372Ssam 		clsacu();
217c0845685Sbloom 		if (fcode == ABORT) {
218af5ea5faSbloom 			fcode = CF_DIAL;
219af5ea5faSbloom 			goto  keeplooking;
220af5ea5faSbloom 		} else {
221af5ea5faSbloom 			fclose(fsys);
222ef0102e5Sralph 			return CF_LOGIN;
2238757e372Ssam 		}
224af5ea5faSbloom 	}
225af5ea5faSbloom 	fclose(fsys);
226c0845685Sbloom 	fioclex(Dcf);
227c0845685Sbloom 	return Dcf;
2288757e372Ssam }
2298757e372Ssam 
2308ab21806Srick int nulldev();
2318ab21806Srick int (*CU_end)() = nulldev;
2328ab21806Srick 
233af5ea5faSbloom /*
234af5ea5faSbloom  *	connect to remote machine
2358757e372Ssam  *
2368757e372Ssam  *	return codes:
2378757e372Ssam  *		>0  -  file number - ok
2388757e372Ssam  *		FAIL  -  failed
2398757e372Ssam  */
getto(flds)2408757e372Ssam getto(flds)
2418757e372Ssam register char *flds[];
2428757e372Ssam {
2438757e372Ssam 	register struct condev *cd;
2441dd63ca2Sbostic 	int diropn();
245af5ea5faSbloom 	char *line;
2468757e372Ssam 
247ef0102e5Sralph 	DEBUG(4, "getto: call no. %s ", flds[F_PHONE]);
2488757e372Ssam 	DEBUG(4, "for sys %s\n", flds[F_NAME]);
2498757e372Ssam 
250af5ea5faSbloom 	if (snccmp(flds[F_LINE], "LOCAL") == SAME)
251af5ea5faSbloom 		line = "ACU";
252af5ea5faSbloom 	else
253af5ea5faSbloom 		line = flds[F_LINE];
254af5ea5faSbloom #ifdef DIALINOUT
255af5ea5faSbloom 	if (snccmp(line, "ACU") != SAME)
256af5ea5faSbloom 		reenable();
257af5ea5faSbloom #endif DIALINOUT
2588757e372Ssam 	CU_end = nulldev;
259c0845685Sbloom 	if (snccmp(line, PCP) == SAME) {
260c0845685Sbloom 		for(cd = condevs; cd->CU_meth != NULL; cd++) {
261c0845685Sbloom 			if (snccmp(PCP_brand, cd->CU_brand) == SAME) {
262c0845685Sbloom 				CU_end = cd->CU_clos;
263c0845685Sbloom 				return diropn(flds);
264c0845685Sbloom 			}
265c0845685Sbloom 		}
266c0845685Sbloom 		logent(PCP_brand, "UNSUPPORTED ACU TYPE");
267c0845685Sbloom 	} else {
2688757e372Ssam 		for (cd = condevs; cd->CU_meth != NULL; cd++) {
269af5ea5faSbloom 			if (snccmp(cd->CU_meth, line) == SAME) {
2708757e372Ssam 				DEBUG(4, "Using %s to call\n", cd->CU_meth);
271ef0102e5Sralph 				return (*(cd->CU_gen))(flds);
2728757e372Ssam 			}
2738757e372Ssam 		}
274af5ea5faSbloom 		DEBUG(1, "Can't find %s, assuming DIR\n", flds[F_LINE]);
275c0845685Sbloom 	}
276ef0102e5Sralph 	return diropn(flds);	/* search failed, so use direct */
2778757e372Ssam }
2788757e372Ssam 
279af5ea5faSbloom /*
280af5ea5faSbloom  *	close call unit
2818757e372Ssam  *
2828757e372Ssam  *	return codes:  none
2838757e372Ssam  */
clsacu()2848757e372Ssam clsacu()
2858757e372Ssam {
286ef0102e5Sralph 	/* make *sure* Dcf is no longer exclusive.
287ef0102e5Sralph 	 * Otherwise dual call-in/call-out modems could get stuck.
288ef0102e5Sralph 	 * Unfortunately, doing this here is not ideal, but it is the
289ef0102e5Sralph 	 * easiest place to put the call.
290ef0102e5Sralph 	 * Hopefully everyone honors the LCK protocol, of course
291ef0102e5Sralph 	 */
292c0845685Sbloom #ifdef	TIOCNXCL
293e05f97bfSbloom 	if (!IsTcpIp && Dcf >= 0 && ioctl(Dcf, TIOCNXCL, STBNULL) < 0)
294e05f97bfSbloom 		DEBUG(5, "clsacu ioctl %s\n", sys_errlist[errno]);
295ef0102e5Sralph #endif
296ef0102e5Sralph 	if  (setjmp(Sjbuf))
297ef0102e5Sralph 		logent(Rmtname, "CLOSE TIMEOUT");
298ef0102e5Sralph 	else {
299ef0102e5Sralph 		signal(SIGALRM, alarmtr);
300ef0102e5Sralph 		alarm(20);
3018757e372Ssam 		(*(CU_end))(Dcf);
302ef0102e5Sralph 		alarm(0);
303ef0102e5Sralph 	}
3048757e372Ssam 	if (close(Dcf) == 0) {
3058757e372Ssam 		DEBUG(4, "fd %d NOT CLOSED by CU_clos\n", Dcf);
3068757e372Ssam 		logent("clsacu", "NOT CLOSED by CU_clos");
3078757e372Ssam 	}
3088757e372Ssam 	Dcf = -1;
3098757e372Ssam 	CU_end = nulldev;
3108757e372Ssam }
3118757e372Ssam 
312af5ea5faSbloom /*
313af5ea5faSbloom  *	expand phone number for given prefix and number
3148757e372Ssam  */
exphone(in,out)3158757e372Ssam exphone(in, out)
3168757e372Ssam register char *in, *out;
3178757e372Ssam {
3188757e372Ssam 	FILE *fn;
3198757e372Ssam 	char pre[MAXPH], npart[MAXPH], tpre[MAXPH], p[MAXPH];
3208757e372Ssam 	char buf[BUFSIZ];
3218757e372Ssam 	register char *s1;
3228757e372Ssam 
323ef0102e5Sralph 	if (!isascii(*in) || !isalpha(*in)) {
3248757e372Ssam 		strcpy(out, in);
3258757e372Ssam 		return;
3268757e372Ssam 	}
3278757e372Ssam 
3288757e372Ssam 	s1=pre;
329ef0102e5Sralph 	while (isascii(*in) && isalpha(*in))
3308757e372Ssam 		*s1++ = *in++;
3318757e372Ssam 	*s1 = '\0';
3328757e372Ssam 	s1 = npart;
3338757e372Ssam 	while (*in != '\0')
3348757e372Ssam 		*s1++ = *in++;
3358757e372Ssam 	*s1 = '\0';
3368757e372Ssam 
3378757e372Ssam 	tpre[0] = '\0';
3388757e372Ssam 	if ((fn = fopen(DIALFILE, "r")) == NULL)
3398757e372Ssam 		DEBUG(2, "CAN'T OPEN %s\n", DIALFILE);
3408757e372Ssam 	else {
3418757e372Ssam 		while (cfgets(buf, BUFSIZ, fn)) {
342ef0102e5Sralph 			if (sscanf(buf, "%s%s", p, tpre) != 2)
343ef0102e5Sralph 				continue;
3448757e372Ssam 			if (strcmp(p, pre) == SAME)
3458757e372Ssam 				goto found;
3468757e372Ssam 			tpre[0] = '\0';
3478757e372Ssam 		}
3488757e372Ssam 		DEBUG(2, "CAN'T FIND dialcodes prefix '%s'\n", pre);
3498757e372Ssam 	found:;
3508757e372Ssam 		fclose(fn);
3518757e372Ssam 	}
3528757e372Ssam 
3538757e372Ssam 	strcpy(out, tpre);
3548757e372Ssam 	strcat(out, npart);
3558757e372Ssam }
3568757e372Ssam 
357991054b8Sralph /*
358991054b8Sralph  *	read and decode a line from device file
3598757e372Ssam  *
3608757e372Ssam  *	return code - FAIL at end-of file; 0 otherwise
3618757e372Ssam  */
rddev(fp,dev)3628757e372Ssam rddev(fp, dev)
3638757e372Ssam register struct Devices *dev;
3648757e372Ssam FILE *fp;
3658757e372Ssam {
366ef0102e5Sralph 	register int na;
3678757e372Ssam 
368ef0102e5Sralph 	if (!cfgets(dev->D_argbfr, sizeof(dev->D_argbfr), fp))
369ef0102e5Sralph 		return FAIL;
370ef0102e5Sralph 	na = getargs(dev->D_argbfr, dev->D_arg, 20);
3717e40e16eSrick 	if (na < 4) {
3727e40e16eSrick 		syslog(LOG_ERR, "%s: invalid device entry", dev->D_argbfr);
3737e40e16eSrick 		cleanup(FAIL);
3747e40e16eSrick 	}
375ef0102e5Sralph 	if (na == 4) {
376ef0102e5Sralph 		dev->D_brand = "";
377ef0102e5Sralph 		na++;
378ef0102e5Sralph 	}
3798757e372Ssam 	dev->D_speed = atoi(fdig(dev->D_class));
380ef0102e5Sralph 	dev->D_numargs = na;
381ef0102e5Sralph 	return 0;
3828757e372Ssam }
3838757e372Ssam 
384991054b8Sralph /*
385991054b8Sralph  *	set system attribute vector
3868757e372Ssam  *
3878757e372Ssam  *	return codes:
3888757e372Ssam  *		>0  -  number of arguments in vector - succeeded
3898757e372Ssam  *		CF_SYSTEM  -  system name not found
3908757e372Ssam  *		CF_TIME  -  wrong time to call
3918757e372Ssam  */
finds(fsys,sysnam,info,flds)3928757e372Ssam finds(fsys, sysnam, info, flds)
3938757e372Ssam char *sysnam, info[], *flds[];
3948757e372Ssam FILE *fsys;
3958757e372Ssam {
3968757e372Ssam 	int na;
3978757e372Ssam 	int fcode = 0;
3988757e372Ssam 
3998757e372Ssam 	/* format of fields
4008757e372Ssam 	 *	0 name;
4018757e372Ssam 	 *	1 time
4028757e372Ssam 	 *	2 acu/hardwired
4038757e372Ssam 	 *	3 speed
4048757e372Ssam 	 *	etc
4058757e372Ssam 	 */
4068757e372Ssam 	while (cfgets(info, MAXC, fsys) != NULL) {
407ef0102e5Sralph 		na = getargs(info, flds, MAXC/10);
408e05f97bfSbloom 		if (strncmp(sysnam, flds[F_NAME], MAXBASENAME) != SAME)
4098757e372Ssam 			continue;
410991054b8Sralph 		if (ifdate(flds[F_TIME]) != FAIL)
4118757e372Ssam 			/*  found a good entry  */
412ef0102e5Sralph 			return na;
4138757e372Ssam 		DEBUG(2, "Wrong time ('%s') to call\n", flds[F_TIME]);
4148757e372Ssam 		fcode = CF_TIME;
4158757e372Ssam 	}
416ef0102e5Sralph 	return fcode ? fcode : CF_SYSTEM;
4178757e372Ssam }
4188757e372Ssam 
419991054b8Sralph /*
420991054b8Sralph  *	do login conversation
4218757e372Ssam  *
422e05f97bfSbloom  *	return codes:  SUCCESS  |  FAIL
4238757e372Ssam  */
login(nf,flds,fn)4248757e372Ssam login(nf, flds, fn)
4258757e372Ssam register char *flds[];
4268757e372Ssam int nf, fn;
4278757e372Ssam {
4288757e372Ssam 	register char *want, *altern;
4298757e372Ssam 	int k, ok;
4308757e372Ssam 
4317e40e16eSrick 	if (nf < 4) {
4327e40e16eSrick 		syslog(LOG_ERR, "Too few log fields: %d", nf);
4337e40e16eSrick 		cleanup(FAIL);
4347e40e16eSrick 	}
435ef0102e5Sralph 	if (setjmp(Cjbuf))
436ef0102e5Sralph 		return FAIL;
437ef0102e5Sralph 	AbortOn = NULL;
4388757e372Ssam 	for (k = F_LOGIN; k < nf; k += 2) {
4398757e372Ssam 		want = flds[k];
440c5c1a0c2Srick 		if (want == NULL)
441c5c1a0c2Srick 			want = "";
4428757e372Ssam 		ok = FAIL;
443ef0102e5Sralph 		while (ok != SUCCESS) {
4448757e372Ssam 			altern = index(want, '-');
4458757e372Ssam 			if (altern != NULL)
4468757e372Ssam 				*altern++ = '\0';
447ef0102e5Sralph 			if (strcmp(want, "ABORT") == 0) {
448ef0102e5Sralph 				AbortOn = flds[k+1];
449ef0102e5Sralph 				DEBUG(4, "ABORT ON: %s\n", AbortOn);
450ef0102e5Sralph 				goto nextfield;
451ef0102e5Sralph 			}
452c0845685Sbloom 			DEBUG(4, "wanted \"%s\"\n", want);
4538757e372Ssam 			ok = expect(want, fn);
454ef0102e5Sralph 			DEBUG(4, "got: %s\n", ok ? "?" : "that");
455ef0102e5Sralph 			if (ok == FAIL) {
4568757e372Ssam 				if (altern == NULL) {
457ef0102e5Sralph 					logent("LOGIN", _FAILED);
458ef0102e5Sralph 					return FAIL;
4598757e372Ssam 				}
4608757e372Ssam 				want = index(altern, '-');
4618757e372Ssam 				if (want != NULL)
4628757e372Ssam 					*want++ = '\0';
4638757e372Ssam 				sendthem(altern, fn);
464ef0102e5Sralph 			} else
465ef0102e5Sralph 				if (ok == ABORT) {
466c5c1a0c2Srick 					char sbuf[MAXFULLNAME];
467c5c1a0c2Srick 					sprintf(sbuf, "LOGIN ABORTED on \"%s\"",						AbortOn);
468c5c1a0c2Srick 					logent(sbuf, _FAILED);
469e05f97bfSbloom 					return ABORT;
4708757e372Ssam 				}
471ef0102e5Sralph 		}
472ef0102e5Sralph 		sleep(1);
4738757e372Ssam 		if (k+1 < nf)
4748757e372Ssam 			sendthem(flds[k+1], fn);
475ef0102e5Sralph nextfield: ;
4768757e372Ssam 	}
477ef0102e5Sralph 	return SUCCESS;
4788757e372Ssam }
4798757e372Ssam 
4808757e372Ssam 
481ef0102e5Sralph /* conditional table generation to support odd speeds */
4828757e372Ssam struct sg_spds {int sp_val, sp_name;} spds[] = {
4838757e372Ssam #ifdef B50
4848757e372Ssam 	{  50,	 B50},
4858757e372Ssam #endif
4868757e372Ssam #ifdef B75
4878757e372Ssam 	{  75,	 B75},
4888757e372Ssam #endif
4898757e372Ssam #ifdef B110
4908757e372Ssam 	{ 110,	B110},
4918757e372Ssam #endif
4928757e372Ssam #ifdef B150
4938757e372Ssam 	{ 150,	B150},
4948757e372Ssam #endif
4958757e372Ssam #ifdef B200
4968757e372Ssam 	{ 200,	B200},
4978757e372Ssam #endif
4988757e372Ssam #ifdef B300
4998757e372Ssam 	{ 300,  B300},
5008757e372Ssam #endif
5018757e372Ssam #ifdef B600
5028757e372Ssam 	{600,	B600},
5038757e372Ssam #endif
5048757e372Ssam #ifdef B1200
5058757e372Ssam 	{1200, B1200},
5068757e372Ssam #endif
5078757e372Ssam #ifdef B1800
5088757e372Ssam 	{1800, B1800},
5098757e372Ssam #endif
5108757e372Ssam #ifdef B2000
5118757e372Ssam 	{2000, B2000},
5128757e372Ssam #endif
5138757e372Ssam #ifdef B2400
5148757e372Ssam 	{2400, B2400},
5158757e372Ssam #endif
5168757e372Ssam #ifdef B3600
5178757e372Ssam 	{3600, B3600},
5188757e372Ssam #endif
5198757e372Ssam #ifdef B4800
5208757e372Ssam 	{4800, B4800},
5218757e372Ssam #endif
5228757e372Ssam #ifdef B7200
5238757e372Ssam 	{7200, B7200},
5248757e372Ssam #endif
5258757e372Ssam #ifdef B9600
5268757e372Ssam 	{9600, B9600},
5278757e372Ssam #endif
5288757e372Ssam #ifdef B19200
5298757e372Ssam 	{19200, B19200},
5308757e372Ssam #endif
531ef0102e5Sralph #ifdef EXTA
532ef0102e5Sralph 	{19200, EXTA},
533ef0102e5Sralph #endif
5348757e372Ssam 	{0, 0}
5358757e372Ssam };
5368757e372Ssam 
537991054b8Sralph /*
538991054b8Sralph  *	set speed/echo/mode...
5398757e372Ssam  *
5408757e372Ssam  *	return codes:  none
5418757e372Ssam  */
fixline(tty,spwant)5428757e372Ssam fixline(tty, spwant)
5438757e372Ssam int tty, spwant;
5448757e372Ssam {
545ef0102e5Sralph #ifdef	USG
5468757e372Ssam 	struct termio ttbuf;
547ef0102e5Sralph #else	!USG
5488757e372Ssam 	struct sgttyb ttbuf;
549ef0102e5Sralph #endif !USG
5508757e372Ssam 	register struct sg_spds *ps;
5518757e372Ssam 	int speed = -1;
5528757e372Ssam 
5538757e372Ssam 	for (ps = spds; ps->sp_val; ps++)
5548757e372Ssam 		if (ps->sp_val == spwant)
5558757e372Ssam 			speed = ps->sp_name;
5567e40e16eSrick 	if (speed < 0) {
5577e40e16eSrick 		syslog(LOG_ERR, "unrecognized speed: %d", speed);
5587e40e16eSrick 		cleanup(FAIL);
5597e40e16eSrick 	}
560ef0102e5Sralph #ifdef	USG
561e05f97bfSbloom 	if (ioctl(tty, TCGETA, &ttbuf) < 0)
562e05f97bfSbloom 		return FAIL;
5638757e372Ssam 	/* ttbuf.sg_flags = (ANYP|RAW);
5648757e372Ssam 	ttbuf.sg_ispeed = ttbuf.sg_ospeed = speed; */
5658757e372Ssam 	ttbuf.c_iflag = (ushort)0;
5668757e372Ssam 	ttbuf.c_oflag = (ushort)0;
5678757e372Ssam 	ttbuf.c_cflag = (speed|CS8|HUPCL|CREAD);
5688757e372Ssam 	ttbuf.c_lflag = (ushort)0;
5698757e372Ssam 	ttbuf.c_cc[VMIN] = 6;
5708757e372Ssam 	ttbuf.c_cc[VTIME] = 1;
571e05f97bfSbloom 	if (ioctl(tty, TCSETA, &ttbuf) < 0)
572e05f97bfSbloom 		return FAIL;
573ef0102e5Sralph #else	!USG
574e05f97bfSbloom 	if (ioctl(tty, TIOCGETP, &ttbuf) < 0)
575e05f97bfSbloom 		return FAIL;
5768757e372Ssam 	ttbuf.sg_flags = (ANYP|RAW);
5778757e372Ssam 	ttbuf.sg_ispeed = ttbuf.sg_ospeed = speed;
578e05f97bfSbloom 	if (ioctl(tty, TIOCSETP, &ttbuf) < 0)
579e05f97bfSbloom 		return FAIL;
5808757e372Ssam #endif
581ef0102e5Sralph #ifndef	USG
582e05f97bfSbloom 	if (ioctl(tty, TIOCHPCL, STBNULL) < 0)
583e05f97bfSbloom 		return FAIL;
584e05f97bfSbloom 	if (ioctl(tty, TIOCEXCL, STBNULL) < 0)
585e05f97bfSbloom 		return FAIL;
5868757e372Ssam #endif
587ef0102e5Sralph 	linebaudrate = spwant;
588e05f97bfSbloom 	return SUCCESS;
5898757e372Ssam }
5908757e372Ssam 
591ef0102e5Sralph #define MR 100
5928757e372Ssam 
593991054b8Sralph /*
594991054b8Sralph  *	look for expected string
5958757e372Ssam  *
5968757e372Ssam  *	return codes:
5978757e372Ssam  *		0  -  found
5988757e372Ssam  *		FAIL  -  lost line or too many characters read
5998757e372Ssam  *		some character  -  timed out
6008757e372Ssam  */
expect(str,fn)6018757e372Ssam expect(str, fn)
6028757e372Ssam register char *str;
6038757e372Ssam int fn;
6048757e372Ssam {
60516364d9cSkarels 	char rdvec[MR];
606ef0102e5Sralph 	register char *rp = rdvec, *strptr;
607ef0102e5Sralph 	int kr, cnt_char;
6088757e372Ssam 	char nextch;
609af5ea5faSbloom 	int timo = MAXMSGTIME;
6108757e372Ssam 
611ef0102e5Sralph 	if (*str == '\0' || strcmp(str, "\"\"") == SAME)
612ef0102e5Sralph 		return SUCCESS;
613ef0102e5Sralph 	/* Cleanup str, convert \0xx strings to one char  */
614ef0102e5Sralph 	for (strptr = str; *strptr; strptr++) {
615ef0102e5Sralph 		if (*strptr == '\\')
616ef0102e5Sralph 			switch(*++strptr) {
617ef0102e5Sralph 			case 's':
618ef0102e5Sralph 				DEBUG(5, "BLANK\n", CNULL);
6198ab21806Srick 				strptr--;
620ef0102e5Sralph 				*strptr = ' ';
6218ab21806Srick 				strcpy(&strptr[1], &strptr[4]);
622ef0102e5Sralph 				break;
623ef0102e5Sralph 			default:
624ef0102e5Sralph 				strptr--;  /* back up to backslash */
625ef0102e5Sralph 				sscanf(strptr + 1,"%o", &cnt_char);
626ef0102e5Sralph 				DEBUG(6, "BACKSLASHED %02xH\n", cnt_char);
627ef0102e5Sralph 				*strptr = (char) (cnt_char);
628ef0102e5Sralph 				strcpy(&strptr[1], &strptr[4]);
6298757e372Ssam 			}
630ef0102e5Sralph 	}
631ef0102e5Sralph 
632af5ea5faSbloom 	strptr = index(str, '~');
633af5ea5faSbloom 	if (strptr != NULL) {
634af5ea5faSbloom 		*strptr++ = '\0';
635af5ea5faSbloom 		timo = atoi(strptr);
636af5ea5faSbloom 		if (timo <= 0)
637af5ea5faSbloom 			timo = MAXMSGTIME;
638af5ea5faSbloom 	}
639af5ea5faSbloom 
640ef0102e5Sralph 	if (setjmp(Sjbuf))
641ef0102e5Sralph 		return FAIL;
6428757e372Ssam 	signal(SIGALRM, alarmtr);
643af5ea5faSbloom 	alarm(timo);
644af5ea5faSbloom 	*rp = 0;
6458757e372Ssam 	while (notin(str, rdvec)) {
646c0845685Sbloom 		int c;
647ef0102e5Sralph 		if(AbortOn != NULL && !notin(AbortOn, rdvec)) {
648ef0102e5Sralph 			DEBUG(1, "Call aborted on '%s'\n", AbortOn);
649ef0102e5Sralph 			alarm(0);
650ef0102e5Sralph 			return ABORT;
651ef0102e5Sralph 		}
6528757e372Ssam 		kr = read(fn, &nextch, 1);
6538757e372Ssam 		if (kr <= 0) {
6548757e372Ssam 			alarm(0);
6558757e372Ssam 			DEBUG(4, "lost line kr - %d\n, ", kr);
6568757e372Ssam 			logent("LOGIN", "LOST LINE");
657ef0102e5Sralph 			return FAIL;
6588757e372Ssam 		}
6598757e372Ssam 		c = nextch & 0177;
660c0845685Sbloom 		if (c == '\0')
661c0845685Sbloom 			continue;
662c0845685Sbloom 		DEBUG(4, (isprint(c) || isspace(c)) ? "%c" : "\\%03o", c);
663c0845685Sbloom 		*rp++ = c;
6648757e372Ssam 		if (rp >= rdvec + MR) {
665ef0102e5Sralph 			register char *p;
666ef0102e5Sralph 			for (p = rdvec+MR/2; p < rp; p++)
667ef0102e5Sralph 				*(p-MR/2) = *p;
668ef0102e5Sralph 			rp -= MR/2;
6698757e372Ssam 		}
6708757e372Ssam 		*rp = '\0';
6718757e372Ssam 	}
6728757e372Ssam 	alarm(0);
673ef0102e5Sralph 	return SUCCESS;
6748757e372Ssam }
6758757e372Ssam 
6768757e372Ssam 
6778757e372Ssam /*
6788757e372Ssam  * Determine next file descriptor that would be allocated.
6798757e372Ssam  * This permits later closing of a file whose open was interrupted.
6808757e372Ssam  * It is a UNIX kernel problem, but it has to be handled.
6818757e372Ssam  * unc!smb (Steve Bellovin) probably first discovered it.
6828757e372Ssam  */
getnextfd()6838757e372Ssam getnextfd()
6848757e372Ssam {
6858757e372Ssam 	close(next_fd = open("/", 0));
6868757e372Ssam }
6878757e372Ssam 
688ef0102e5Sralph /*
689ef0102e5Sralph  *	send line of login sequence
6908757e372Ssam  *
6918757e372Ssam  *	return codes:  none
6928757e372Ssam  */
sendthem(str,fn)6938757e372Ssam sendthem(str, fn)
6948757e372Ssam register char *str;
6958757e372Ssam int fn;
6968757e372Ssam {
6978757e372Ssam 	register char *strptr;
6988757e372Ssam 	int i, n, cr = 1;
699ef0102e5Sralph 	register char c;
7008757e372Ssam 	static int p_init = 0;
7018757e372Ssam 
702c0845685Sbloom 	DEBUG(5, "send \"%s\"\n", str);
7038757e372Ssam 
7048757e372Ssam 	if (!p_init) {
7058757e372Ssam 		p_init++;
7067e40e16eSrick 		bld_partab(P_ZERO);
7078757e372Ssam 	}
7088757e372Ssam 
7098757e372Ssam 	if (prefix("BREAK", str)) {
7108757e372Ssam 		sscanf(&str[5], "%1d", &i);
7118757e372Ssam 		if (i <= 0 || i > 10)
7128757e372Ssam 			i = 3;
7138757e372Ssam 		/* send break */
7148757e372Ssam 		genbrk(fn, i);
7158757e372Ssam 		return;
7168757e372Ssam 	}
7178757e372Ssam 
7188757e372Ssam 	if (prefix("PAUSE", str)) {
7198757e372Ssam 		sscanf(&str[5], "%1d", &i);
7208757e372Ssam 		if (i <= 0 || i > 10)
7218757e372Ssam 			i = 3;
7228757e372Ssam 		/* pause for a while */
7238757e372Ssam 		sleep((unsigned)i);
7248757e372Ssam 		return;
7258757e372Ssam 	}
7268757e372Ssam 
7278757e372Ssam 	if (strcmp(str, "EOT") == SAME) {
7288757e372Ssam 		p_chwrite(fn, '\04');
7298757e372Ssam 		return;
7308757e372Ssam 	}
7318757e372Ssam 
7328757e372Ssam 	/* Send a '\n' */
733c0845685Sbloom 	if (strcmp(str, "LF") == SAME) {
734c0845685Sbloom 		p_chwrite(fn, '\n');
735c0845685Sbloom 		return;
736c0845685Sbloom 	}
7378757e372Ssam 
7388757e372Ssam 	/* Send a '\r' */
739c0845685Sbloom 	if (strcmp(str, "CR") == SAME) {
740c0845685Sbloom 		p_chwrite(fn, '\r');
741c0845685Sbloom 		return;
742c0845685Sbloom 	}
7438757e372Ssam 
7448757e372Ssam 	/* Set parity as needed */
7458757e372Ssam 	if (strcmp(str, "P_ZERO") == SAME) {
7468757e372Ssam 		bld_partab(P_ZERO);
7478757e372Ssam 		return;
7488757e372Ssam 	}
7498757e372Ssam 	if (strcmp(str, "P_ONE") == SAME) {
7508757e372Ssam 		bld_partab(P_ONE);
7518757e372Ssam 		return;
7528757e372Ssam 	}
7538757e372Ssam 	if (strcmp(str, "P_EVEN") == SAME) {
7548757e372Ssam 		bld_partab(P_EVEN);
7558757e372Ssam 		return;
7568757e372Ssam 	}
7578757e372Ssam 	if (strcmp(str, "P_ODD") == SAME) {
7588757e372Ssam 		bld_partab(P_ODD);
7598757e372Ssam 		return;
7608757e372Ssam 	}
7618757e372Ssam 
7628757e372Ssam 	/* If "", just send '\r' */
763ef0102e5Sralph 	if (strcmp(str, "\"\"") == SAME) {
764ef0102e5Sralph 		p_chwrite(fn, '\r');
765ef0102e5Sralph 		return;
766ef0102e5Sralph 	}
767ef0102e5Sralph 
768c0845685Sbloom 	strptr = str;
769c0845685Sbloom 	while ((c = *strptr++) != '\0') {
770ef0102e5Sralph 		if (c == '\\') {
771ef0102e5Sralph 			switch(*strptr++) {
772c0845685Sbloom 			case '\0':
773c0845685Sbloom 				DEBUG(5, "TRAILING BACKSLASH IGNORED\n", CNULL);
774c0845685Sbloom 				--strptr;
775c0845685Sbloom 				continue;
7768757e372Ssam 			case 's':
777ef0102e5Sralph 				DEBUG(5, "BLANK\n", CNULL);
778c0845685Sbloom 				c = ' ';
7798757e372Ssam 				break;
7808757e372Ssam 			case 'd':
781ef0102e5Sralph 				DEBUG(5, "DELAY\n", CNULL);
7828757e372Ssam 				sleep(1);
7838757e372Ssam 				continue;
784c0845685Sbloom 			case 'n':
785c0845685Sbloom 				DEBUG(5, "NEW LINE\n", CNULL);
786c0845685Sbloom 				c = '\n';
787c0845685Sbloom 				break;
7888757e372Ssam 			case 'r':
789ef0102e5Sralph 				DEBUG(5, "RETURN\n", CNULL);
790c0845685Sbloom 				c = '\r';
7918757e372Ssam 				break;
7928757e372Ssam 			case 'b':
793ef0102e5Sralph 				if (isdigit(*strptr)) {
794ef0102e5Sralph 					i = (*strptr++ - '0');
7958757e372Ssam 					if (i <= 0 || i > 10)
7968757e372Ssam 						i = 3;
7978757e372Ssam 				} else
7988757e372Ssam 					i = 3;
7998757e372Ssam 				/* send break */
8008757e372Ssam 				genbrk(fn, i);
801ef0102e5Sralph 				if (*strptr == '\0')
802ef0102e5Sralph 					cr = 0;
8038757e372Ssam 				continue;
8048757e372Ssam 			case 'c':
805ef0102e5Sralph 				if (*strptr == '\0') {
806ef0102e5Sralph 					DEBUG(5, "NO CR\n", CNULL);
8078757e372Ssam 					cr = 0;
808c0845685Sbloom 				} else
809c0845685Sbloom 					DEBUG(5, "NO CR - IGNORED NOT EOL\n", CNULL);
8108757e372Ssam 				continue;
811c0845685Sbloom #define isoctal(x)	((x >= '0') && (x <= '7'))
8128757e372Ssam 			default:
813c0845685Sbloom 				if (isoctal(strptr[-1])) {
8148757e372Ssam 					i = 0;
8158757e372Ssam 					n = 0;
816c0845685Sbloom 					--strptr;
817c0845685Sbloom 					while (isoctal(*strptr) && ++n <= 3)
818ef0102e5Sralph 						i = i * 8 + (*strptr++ - '0');
819c0845685Sbloom 					DEBUG(5, "\\%o\n", i);
820ef0102e5Sralph 					p_chwrite(fn, (char)i);
8218757e372Ssam 					continue;
8228757e372Ssam 				}
8238757e372Ssam 			}
824c0845685Sbloom 		}
825ef0102e5Sralph 		p_chwrite(fn, c);
8268757e372Ssam 	}
8278757e372Ssam 
8288757e372Ssam 	if (cr)
8298757e372Ssam 		p_chwrite(fn, '\r');
8308757e372Ssam 	return;
8318757e372Ssam }
8328757e372Ssam 
p_chwrite(fd,c)8338757e372Ssam p_chwrite(fd, c)
8348757e372Ssam int fd;
835ef0102e5Sralph char c;
8368757e372Ssam {
837ef0102e5Sralph 	c = par_tab[c&0177];
838ef0102e5Sralph 	if (write(fd, &c, 1) != 1) {
839ef0102e5Sralph 		logent(sys_errlist[errno], "BAD WRITE");
840ef0102e5Sralph 		longjmp(Cjbuf, 2);
841ef0102e5Sralph 	}
8428757e372Ssam }
8438757e372Ssam 
8448757e372Ssam /*
8458757e372Ssam  * generate parity table for use by p_chwrite.
8468757e372Ssam  */
bld_partab(type)8478757e372Ssam bld_partab(type)
8488757e372Ssam int type;
8498757e372Ssam {
8508757e372Ssam 	register int i, j, n;
8518757e372Ssam 
8528757e372Ssam 	for (i = 0; i < sizeof(par_tab); i++) {
8538757e372Ssam 		n = 0;
8548757e372Ssam 		for (j = i&(sizeof(par_tab)-1); j; j = (j-1)&j)
8558757e372Ssam 			n++;
8568757e372Ssam 		par_tab[i] = i;
8578757e372Ssam 		if (type == P_ONE
8588757e372Ssam 		 || (type == P_EVEN && (n&01) != 0)
8598757e372Ssam 		 || (type == P_ODD && (n&01) == 0))
8608757e372Ssam 			par_tab[i] |= sizeof(par_tab);
8618757e372Ssam 	}
8628757e372Ssam }
8638757e372Ssam 
864991054b8Sralph /*
865991054b8Sralph  *	check for occurrence of substring "sh"
8668757e372Ssam  *
8678757e372Ssam  *	return codes:
8688757e372Ssam  *		0  -  found the string
8698757e372Ssam  *		1  -  not in the string
8708757e372Ssam  */
notin(sh,lg)8718757e372Ssam notin(sh, lg)
8728757e372Ssam register char *sh, *lg;
8738757e372Ssam {
8748757e372Ssam 	while (*lg != '\0') {
8758757e372Ssam 		if (wprefix(sh, lg))
876991054b8Sralph 			return 0;
8778757e372Ssam 		else
8788757e372Ssam 			lg++;
8798757e372Ssam 	}
880991054b8Sralph 	return 1;
8818757e372Ssam }
8828757e372Ssam 
883991054b8Sralph /*
884e05f97bfSbloom  *	Allow multiple date specifications separated by ','.
8858757e372Ssam  */
ifdate(p)886991054b8Sralph ifdate(p)
8878757e372Ssam register char *p;
888991054b8Sralph {
889c0845685Sbloom 	register char *np;
890991054b8Sralph 	register int ret, g;
891e05f97bfSbloom 	int rtime, i;
892e05f97bfSbloom 
893e05f97bfSbloom 	/*  pick up retry time for failures  */
894e05f97bfSbloom 	/*  global variable Retrytime is set here  */
895e05f97bfSbloom 	if ((np = index(p, ';')) == NULL) {
896e05f97bfSbloom 		Retrytime = RETRYTIME;
897e05f97bfSbloom 	} else {
898e05f97bfSbloom 		i = sscanf(np+1, "%d", &rtime);
899e05f97bfSbloom 		if (i < 1 || rtime < 0)
900e05f97bfSbloom 			rtime = 5;
901e05f97bfSbloom 		Retrytime  = rtime * 60;
902e05f97bfSbloom 	}
9038757e372Ssam 
904991054b8Sralph 	ret = FAIL;
905991054b8Sralph 	MaxGrade = '\0';
906991054b8Sralph 	do {
907e05f97bfSbloom 		np = strpbrk(p, ",|");	/* prefer , but allow | for compat */
908e05f97bfSbloom 		if (np)
909e05f97bfSbloom 			*np = '\0';
910991054b8Sralph 		g = ifadate(p);
911991054b8Sralph 		DEBUG(11,"ifadate returns %o\n", g);
912991054b8Sralph 		if (g != FAIL) {
913991054b8Sralph 			ret = SUCCESS;
914991054b8Sralph 			if (g > MaxGrade)
915991054b8Sralph 				MaxGrade = g;
916991054b8Sralph 		}
917e05f97bfSbloom 		if (np)
918e05f97bfSbloom 			*np = ',';
919e05f97bfSbloom 		p = np + 1;
920e05f97bfSbloom 	} while (np);
921e05f97bfSbloom 	if (MaxGrade == '\0')
922e05f97bfSbloom 		MaxGrade = DefMaxGrade;
923ef0102e5Sralph 	return ret;
9248757e372Ssam }
9258757e372Ssam 
926991054b8Sralph /*
927991054b8Sralph  *	this routine will check a string (string)
9288757e372Ssam  *	like "MoTu0800-1730" to see if the present
9298757e372Ssam  *	time is within the given limits.
9308757e372Ssam  *	SIDE EFFECT - Retrytime is set
9318757e372Ssam  *
9328757e372Ssam  *	return codes:
9338757e372Ssam  *		0  -  not within limits
9348757e372Ssam  *		1  -  within limits
9358757e372Ssam  */
9368757e372Ssam 
ifadate(string)937991054b8Sralph ifadate(string)
938991054b8Sralph char *string;
9398757e372Ssam {
9408757e372Ssam 	static char *days[]={
9418757e372Ssam 		"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", 0
9428757e372Ssam 	};
9438757e372Ssam 	time_t clock;
944991054b8Sralph 	register char *s = string;
945ef0102e5Sralph 	int i, tl, th, tn, dayok=0;
9468757e372Ssam 	struct tm *localtime();
9478757e372Ssam 	struct tm *tp;
948991054b8Sralph 	char *p, MGrade;
9498757e372Ssam 
950e05f97bfSbloom 	if ((p = index(s, '/')) == NULL)
951991054b8Sralph 		MGrade = DefMaxGrade;
952991054b8Sralph 	else
953991054b8Sralph 		MGrade = p[1];
954991054b8Sralph 
9558757e372Ssam 	time(&clock);
9568757e372Ssam 	tp = localtime(&clock);
957ef0102e5Sralph 	while (isascii(*s) && isalpha(*s)) {
9588757e372Ssam 		for (i = 0; days[i]; i++) {
9598757e372Ssam 			if (prefix(days[i], s))
9608757e372Ssam 				if (tp->tm_wday == i)
9618757e372Ssam 					dayok = 1;
9628757e372Ssam 		}
9638757e372Ssam 
9648757e372Ssam 		if (prefix("Wk", s))
9658757e372Ssam 			if (tp->tm_wday >= 1 && tp->tm_wday <= 5)
9668757e372Ssam 				dayok = 1;
9678757e372Ssam 		if (prefix("Any", s))
9688757e372Ssam 			dayok = 1;
969ef0102e5Sralph 		if (prefix("Evening", s)) {
970ef0102e5Sralph 			/* Sat or Sun */
971ef0102e5Sralph 			if (tp->tm_wday == 6 || tp->tm_wday == 0
972ef0102e5Sralph 				|| tp->tm_hour >= 17 || tp->tm_hour < 8)
973ef0102e5Sralph 					dayok = 1;
974ef0102e5Sralph 		}
975ef0102e5Sralph 		if (prefix("Night", s)) {
976ef0102e5Sralph 			if (tp->tm_wday == 6  /* Sat */
977991054b8Sralph 				|| tp->tm_hour >= 23 || tp->tm_hour < 8
978991054b8Sralph 					/* Sunday before 5pm */
979991054b8Sralph 				|| (tp->tm_wday == 0 && tp->tm_hour < 17))
980ef0102e5Sralph 					dayok = 1;
981ef0102e5Sralph 		}
982c0845685Sbloom 		if (prefix("NonPeak", s)) { /* For Tymnet and PC Pursuit */
983c0845685Sbloom 			/* Sat or Sun */
984c0845685Sbloom 			if (tp->tm_wday == 6 || tp->tm_wday == 0
985c0845685Sbloom 				|| tp->tm_hour >= 18 || tp->tm_hour < 7)
986c0845685Sbloom 					dayok = 1;
987c0845685Sbloom 		}
9888757e372Ssam 		s++;
9898757e372Ssam 	}
9908757e372Ssam 
991991054b8Sralph 	if (dayok == 0 && s != string)
992991054b8Sralph 		return FAIL;
9938757e372Ssam 	i = sscanf(s, "%d-%d", &tl, &th);
9948757e372Ssam   	if (i < 2)
995991054b8Sralph   		return MGrade;
996ef0102e5Sralph 	tn = tp->tm_hour * 100 + tp->tm_min;
997ef0102e5Sralph   	if (th < tl) { 		/* crosses midnight */
998ef0102e5Sralph   		if (tl <= tn || tn < th)
999991054b8Sralph   			return MGrade;
1000877cef39Sbloom   	} else {
1001ef0102e5Sralph 		if (tl <= tn && tn < th)
1002991054b8Sralph 			return MGrade;
1003877cef39Sbloom 	}
1004991054b8Sralph 	return FAIL;
10058757e372Ssam }
10068757e372Ssam 
1007991054b8Sralph /*
1008991054b8Sralph  *	find first digit in string
10098757e372Ssam  *
10108757e372Ssam  *	return - pointer to first digit in string or end of string
10118757e372Ssam  */
10128757e372Ssam char *
fdig(cp)10138757e372Ssam fdig(cp)
10148757e372Ssam register char *cp;
10158757e372Ssam {
10168757e372Ssam 	register char *c;
10178757e372Ssam 
10188757e372Ssam 	for (c = cp; *c; c++)
10198757e372Ssam 		if (*c >= '0' && *c <= '9')
10208757e372Ssam 			break;
1021ef0102e5Sralph 	return c;
10228757e372Ssam }
10238757e372Ssam 
10248757e372Ssam /*
10258757e372Ssam  * Compare strings:  s1>s2: >0  s1==s2: 0  s1<s2: <0
10268757e372Ssam  * Strings are compared as if they contain all capital letters.
10278757e372Ssam  */
snccmp(s1,s2)10288757e372Ssam snccmp(s1, s2)
10298757e372Ssam register char *s1, *s2;
10308757e372Ssam {
10318757e372Ssam 	char c1, c2;
10328757e372Ssam 
1033af5ea5faSbloom 	if (islower(*s1))
1034af5ea5faSbloom 		c1 = toupper(*s1);
1035af5ea5faSbloom 	else
1036af5ea5faSbloom 		c1 = *s1;
1037af5ea5faSbloom 	if (islower(*s2))
1038af5ea5faSbloom 		c2 = toupper(*s2);
1039af5ea5faSbloom 	else
1040af5ea5faSbloom 		c2 = *s2;
10418757e372Ssam 
10428757e372Ssam 	while (c1 == c2) {
10438757e372Ssam 		if (*s1++ == '\0')
1044ef0102e5Sralph 			return 0;
10458757e372Ssam 		s2++;
1046af5ea5faSbloom 		if (islower(*s1))
1047af5ea5faSbloom 			c1 = toupper(*s1);
1048af5ea5faSbloom 		else
1049af5ea5faSbloom 			c1 = *s1;
1050af5ea5faSbloom 		if (islower(*s2))
1051af5ea5faSbloom 			c2 = toupper(*s2);
1052af5ea5faSbloom 		else
1053af5ea5faSbloom 			c2 = *s2;
10548757e372Ssam 	}
1055ef0102e5Sralph 	return c1 - c2;
1056ef0102e5Sralph }
1057af5ea5faSbloom 
1058af5ea5faSbloom /*
1059af5ea5faSbloom  * Compare strings:  s1>s2: >0  s1==s2: 0  s1<s2: <0
1060af5ea5faSbloom  * Strings are compared as if they contain all capital letters.
1061af5ea5faSbloom  */
sncncmp(s1,s2,n)1062af5ea5faSbloom sncncmp(s1, s2, n)
1063af5ea5faSbloom register char *s1, *s2;
1064af5ea5faSbloom register int n;
1065af5ea5faSbloom {
1066af5ea5faSbloom 	char c1, c2;
1067af5ea5faSbloom 
1068af5ea5faSbloom 	if (islower(*s1))
1069af5ea5faSbloom 		c1 = toupper(*s1);
1070af5ea5faSbloom 	else
1071af5ea5faSbloom 		c1 = *s1;
1072af5ea5faSbloom 	if (islower(*s2))
1073af5ea5faSbloom 		c2 = toupper(*s2);
1074af5ea5faSbloom 	else
1075af5ea5faSbloom 		c2 = *s2;
1076af5ea5faSbloom 
1077af5ea5faSbloom 	while ( --n >= 0 && c1 == c2) {
1078af5ea5faSbloom 		if (*s1++ == '\0')
1079af5ea5faSbloom 			return 0;
1080af5ea5faSbloom 		s2++;
1081af5ea5faSbloom 		if (islower(*s1))
1082af5ea5faSbloom 			c1 = toupper(*s1);
1083af5ea5faSbloom 		else
1084af5ea5faSbloom 			c1 = *s1;
1085af5ea5faSbloom 		if (islower(*s2))
1086af5ea5faSbloom 			c2 = toupper(*s2);
1087af5ea5faSbloom 		else
1088af5ea5faSbloom 			c2 = *s2;
1089af5ea5faSbloom 	}
1090af5ea5faSbloom 	return n<0 ? 0 : (c1 - c2);
1091af5ea5faSbloom }
1092ef0102e5Sralph /*
1093ef0102e5Sralph  * do chat script
1094ef0102e5Sralph  * occurs after local port is opened,
1095ef0102e5Sralph  * before 'dialing' the other machine.
1096ef0102e5Sralph  */
dochat(dev,flds,fd)1097ef0102e5Sralph dochat(dev, flds, fd)
1098ef0102e5Sralph register struct Devices *dev;
1099ef0102e5Sralph char *flds[];
1100ef0102e5Sralph int fd;
1101ef0102e5Sralph {
1102ef0102e5Sralph 	register int i;
1103ef0102e5Sralph 	register char *p;
1104ef0102e5Sralph 	char bfr[sizeof(dev->D_argbfr)];
1105ef0102e5Sralph 
1106ef0102e5Sralph 	if (dev->D_numargs <= 5)
1107ef0102e5Sralph 		return(0);
1108ef0102e5Sralph 	DEBUG(4, "dochat called %d\n", dev->D_numargs);
1109ef0102e5Sralph 	for (i = 0; i < dev->D_numargs-5; i++) {
1110ef0102e5Sralph 		sprintf(bfr, dev->D_arg[D_CHAT+i], flds[F_PHONE]);
1111ef0102e5Sralph 		if (strcmp(bfr, dev->D_arg[D_CHAT+i])) {
1112ef0102e5Sralph 			p = malloc((unsigned)strlen(bfr)+1);
1113ef0102e5Sralph 			if (p != NULL) {
1114ef0102e5Sralph 				strcpy(p, bfr);
1115ef0102e5Sralph 				dev->D_arg[D_CHAT+i] = p;
1116ef0102e5Sralph 			}
1117ef0102e5Sralph 		}
1118ef0102e5Sralph 	}
1119ef0102e5Sralph 	/* following is a kludge because login() arglist is a kludge */
1120ef0102e5Sralph 	i = login(dev->D_numargs, &dev->D_arg[D_CHAT-5], fd);
1121ef0102e5Sralph 	/*
1122ef0102e5Sralph 	 * If login() last did a sendthem(), must pause so things can settle.
1123ef0102e5Sralph 	 * But don't bother if chat failed.
1124ef0102e5Sralph 	 */
1125ef0102e5Sralph 	if (i == 0 && (dev->D_numargs&01))
1126ef0102e5Sralph 		sleep(2);
1127ef0102e5Sralph 	return(i);
11288757e372Ssam }
1129c0845685Sbloom 
1130c0845685Sbloom /*
1131c0845685Sbloom  *	fix kill/echo/raw on line
1132c0845685Sbloom  *
1133c0845685Sbloom  *	return codes:  none
1134c0845685Sbloom  */
fixmode(tty)1135c0845685Sbloom fixmode(tty)
1136c0845685Sbloom register int tty;
1137c0845685Sbloom {
1138c0845685Sbloom #ifdef	USG
1139c0845685Sbloom 	struct termio ttbuf;
1140c0845685Sbloom #else	!USG
1141c0845685Sbloom 	struct sgttyb ttbuf;
1142c0845685Sbloom #endif	!USG
1143c0845685Sbloom 	register struct sg_spds *ps;
1144c0845685Sbloom 	int speed;
1145c0845685Sbloom 
1146c0845685Sbloom 	if (IsTcpIp)
1147c0845685Sbloom 		return;
1148c0845685Sbloom #ifdef	USG
1149c0845685Sbloom 	ioctl(tty, TCGETA, &ttbuf);
1150c0845685Sbloom 	ttbuf.c_iflag = ttbuf.c_oflag = ttbuf.c_lflag = (ushort)0;
1151c0845685Sbloom 	speed = ttbuf.c_cflag &= (CBAUD);
1152c0845685Sbloom 	ttbuf.c_cflag |= (CS8|CREAD);
1153c0845685Sbloom 	ttbuf.c_cc[VMIN] = 6;
1154c0845685Sbloom 	ttbuf.c_cc[VTIME] = 1;
1155c0845685Sbloom 	ioctl(tty, TCSETA, &ttbuf);
1156c0845685Sbloom #else	!USG
1157c0845685Sbloom 	ioctl(tty, TIOCGETP, &ttbuf);
1158c0845685Sbloom 	ttbuf.sg_flags = (ANYP | RAW);
1159c0845685Sbloom 	ioctl(tty, TIOCSETP, &ttbuf);
1160c0845685Sbloom 	speed = ttbuf.sg_ispeed;
1161c0845685Sbloom 	ioctl(tty, TIOCEXCL, STBNULL);
1162c0845685Sbloom #endif	!USG
1163c0845685Sbloom 
1164c0845685Sbloom 	for (ps = spds; ps->sp_val; ps++)
1165c0845685Sbloom 		if (ps->sp_name == speed) {
1166c0845685Sbloom 			linebaudrate = ps->sp_val;
1167c0845685Sbloom 			DEBUG(9,"Incoming baudrate is %d\n", linebaudrate);
1168c0845685Sbloom 			return;
1169c0845685Sbloom 		}
11707e40e16eSrick 	if (linebaudrate < 0) {
11717e40e16eSrick 		syslog(LOG_ERR, "unrecognized speed: %d", linebaudrate);
11727e40e16eSrick 		cleanup(FAIL);
1173c0845685Sbloom 	}
11747e40e16eSrick }
1175