xref: /original-bsd/usr.bin/tip/aculib/ventel.c (revision 57124d5e)
1 /*
2  * Copyright (c) 1983 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #ifndef lint
8 static char sccsid[] = "@(#)ventel.c	5.1 (Berkeley) 04/30/85";
9 #endif not lint
10 
11 /*
12  * Routines for calling up on a Ventel Modem
13  * The Ventel is expected to be strapped for local echo (just like uucp)
14  */
15 #include "tip.h"
16 
17 #define	MAXRETRY	5
18 
19 static	int sigALRM();
20 static	int timeout = 0;
21 static	jmp_buf timeoutbuf;
22 
23 /*
24  * some sleep calls have been replaced by this macro
25  * because some ventel modems require two <cr>s in less than
26  * a second in order to 'wake up'... yes, it is dirty...
27  */
28 #define delay(num,denom) busyloop(CPUSPEED*num/denom)
29 #define CPUSPEED 1000000	/* VAX 780 is 1MIPS */
30 #define	DELAY(n)	{ register long N = (n); while (--N > 0); }
31 busyloop(n) { DELAY(n); }
32 
33 ven_dialer(num, acu)
34 	register char *num;
35 	char *acu;
36 {
37 	register char *cp;
38 	register int connected = 0;
39 	char *msg, *index(), line[80];
40 
41 	/*
42 	 * Get in synch with a couple of carriage returns
43 	 */
44 	if (!vensync(FD)) {
45 		printf("can't synchronize with ventel\n");
46 #ifdef ACULOG
47 		logent(value(HOST), num, "ventel", "can't synch up");
48 #endif
49 		return (0);
50 	}
51 	if (boolean(value(VERBOSE)))
52 		printf("\ndialing...");
53 	fflush(stdout);
54 	ioctl(FD, TIOCHPCL, 0);
55 	echo("#k$\r$\n$D$I$A$L$:$ ");
56 	for (cp = num; *cp; cp++) {
57 		delay(1, 10);
58 		write(FD, cp, 1);
59 	}
60 	delay(1, 10);
61 	write(FD, "\r", 1);
62 	gobble('\n', line);
63 	if (gobble('\n', line))
64 		connected = gobble('!', line);
65 	ioctl(FD, TIOCFLUSH);
66 #ifdef ACULOG
67 	if (timeout) {
68 		sprintf(line, "%d second dial timeout",
69 			number(value(DIALTIMEOUT)));
70 		logent(value(HOST), num, "ventel", line);
71 	}
72 #endif
73 	if (timeout)
74 		ven_disconnect();	/* insurance */
75 	if (connected || timeout || !boolean(value(VERBOSE)))
76 		return (connected);
77 	/* call failed, parse response for user */
78 	cp = index(line, '\r');
79 	if (cp)
80 		*cp = '\0';
81 	for (cp = line; cp = index(cp, ' '); cp++)
82 		if (cp[1] == ' ')
83 			break;
84 	if (cp) {
85 		while (*cp == ' ')
86 			cp++;
87 		msg = cp;
88 		while (*cp) {
89 			if (isupper(*cp))
90 				*cp = tolower(*cp);
91 			cp++;
92 		}
93 		printf("%s...", msg);
94 	}
95 	return (connected);
96 }
97 
98 ven_disconnect()
99 {
100 
101 	close(FD);
102 }
103 
104 ven_abort()
105 {
106 
107 	write(FD, "\03", 1);
108 	close(FD);
109 }
110 
111 static int
112 echo(s)
113 	register char *s;
114 {
115 	char c;
116 
117 	while (c = *s++) switch (c) {
118 
119 	case '$':
120 		read(FD, &c, 1);
121 		s++;
122 		break;
123 
124 	case '#':
125 		c = *s++;
126 		write(FD, &c, 1);
127 		break;
128 
129 	default:
130 		write(FD, &c, 1);
131 		read(FD, &c, 1);
132 	}
133 }
134 
135 static int
136 sigALRM()
137 {
138 
139 	printf("\07timeout waiting for reply\n");
140 	timeout = 1;
141 	longjmp(timeoutbuf, 1);
142 }
143 
144 static int
145 gobble(match, response)
146 	register char match;
147 	char response[];
148 {
149 	register char *cp = response;
150 	char c;
151 	int (*f)();
152 
153 	signal(SIGALRM, sigALRM);
154 	timeout = 0;
155 	do {
156 		if (setjmp(timeoutbuf)) {
157 			signal(SIGALRM, f);
158 			*cp = '\0';
159 			return (0);
160 		}
161 		alarm(number(value(DIALTIMEOUT)));
162 		read(FD, cp, 1);
163 		alarm(0);
164 		c = (*cp++ &= 0177);
165 #ifdef notdef
166 		if (boolean(value(VERBOSE)))
167 			putchar(c);
168 #endif
169 	} while (c != '\n' && c != match);
170 	signal(SIGALRM, SIG_DFL);
171 	*cp = '\0';
172 	return (c == match);
173 }
174 
175 #define min(a,b)	((a)>(b)?(b):(a))
176 /*
177  * This convoluted piece of code attempts to get
178  * the ventel in sync.  If you don't have FIONREAD
179  * there are gory ways to simulate this.
180  */
181 static int
182 vensync(fd)
183 {
184 	int already = 0, nread;
185 	char buf[60];
186 
187 	/*
188 	 * Toggle DTR to force anyone off that might have left
189 	 * the modem connected, and insure a consistent state
190 	 * to start from.
191 	 *
192 	 * If you don't have the ioctl calls to diddle directly
193 	 * with DTR, you can always try setting the baud rate to 0.
194 	 */
195 	ioctl(FD, TIOCCDTR, 0);
196 	sleep(1);
197 	ioctl(FD, TIOCSDTR, 0);
198 	while (already < MAXRETRY) {
199 		/*
200 		 * After reseting the modem, send it two \r's to
201 		 * autobaud on. Make sure to delay between them
202 		 * so the modem can frame the incoming characters.
203 		 */
204 		write(fd, "\r", 1);
205 		delay(1,10);
206 		write(fd, "\r", 1);
207 		sleep(2);
208 		if (ioctl(fd, FIONREAD, (caddr_t)&nread) < 0) {
209 			perror("tip: ioctl");
210 			continue;
211 		}
212 		while (nread > 0) {
213 			read(fd, buf, min(nread, 60));
214 			if ((buf[nread - 1] & 0177) == '$')
215 				return (1);
216 			nread -= min(nread, 60);
217 		}
218 		sleep(1);
219 		already++;
220 	}
221 	return (0);
222 }
223 
224