xref: /freebsd/usr.bin/tip/libacu/courier.c (revision 380a989b3223d455375b4fae70fd0b9bdd43bafb)
1 /*
2  * Copyright (c) 1986, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #ifndef lint
35 static char sccsid[] = "@(#)courier.c	8.1 (Berkeley) 6/6/93";
36 #endif /* not lint */
37 
38 /*
39  * Routines for calling up on a Courier modem.
40  * Derived from Hayes driver.
41  */
42 #include "tipconf.h"
43 #include "tip.h"
44 #include "acucommon.h"
45 #include <stdio.h>
46 
47 #define	MAXRETRY	5
48 
49 static	void sigALRM();
50 static	int timeout = 0;
51 static	int connected = 0;
52 static	jmp_buf timeoutbuf, intbuf;
53 static	int coursync();
54 
55 cour_dialer(num, acu)
56 	register char *num;
57 	char *acu;
58 {
59 	register char *cp;
60 #if ACULOG
61 	char line[80];
62 #endif
63 	static int cour_connect(), cour_swallow();
64 
65 	if (boolean(value(VERBOSE)))
66 		printf("Using \"%s\"\n", acu);
67 
68 	acu_hupcl ();
69 
70 	/*
71 	 * Get in synch.
72 	 */
73 	if (!coursync()) {
74 badsynch:
75 		printf("can't synchronize with courier\n");
76 #if ACULOG
77 		logent(value(HOST), num, "courier", "can't synch up");
78 #endif
79 		return (0);
80 	}
81 	cour_write(FD, "AT E0\r", 6);	/* turn off echoing */
82 	sleep(1);
83 #ifdef DEBUG
84 	if (boolean(value(VERBOSE)))
85 		cour_verbose_read();
86 #endif
87 	ioctl(FD, TIOCFLUSH, 0);	/* flush any clutter */
88 	cour_write(FD, "AT C1 E0 H0 Q0 X6 V1\r", 21);
89 	if (!cour_swallow("\r\nOK\r\n"))
90 		goto badsynch;
91 	fflush(stdout);
92 	cour_write(FD, "AT D", 4);
93 	for (cp = num; *cp; cp++)
94 		if (*cp == '=')
95 			*cp = ',';
96 	cour_write(FD, num, strlen(num));
97 	cour_write(FD, "\r", 1);
98 	connected = cour_connect();
99 #if ACULOG
100 	if (timeout) {
101 		sprintf(line, "%d second dial timeout",
102 			number(value(DIALTIMEOUT)));
103 		logent(value(HOST), num, "cour", line);
104 	}
105 #endif
106 	if (timeout)
107 		cour_disconnect();
108 	return (connected);
109 }
110 
111 cour_disconnect()
112 {
113 	 /* first hang up the modem*/
114 	ioctl(FD, TIOCCDTR, 0);
115 	sleep(1);
116 	ioctl(FD, TIOCSDTR, 0);
117 	coursync();				/* reset */
118 	close(FD);
119 }
120 
121 cour_abort()
122 {
123 	cour_write(FD, "\r", 1);	/* send anything to abort the call */
124 	cour_disconnect();
125 }
126 
127 static void
128 sigALRM()
129 {
130 	printf("\07timeout waiting for reply\n");
131 	timeout = 1;
132 	longjmp(timeoutbuf, 1);
133 }
134 
135 static int
136 cour_swallow(match)
137   register char *match;
138   {
139 	sig_t f;
140 	char c;
141 
142 	f = signal(SIGALRM, sigALRM);
143 	timeout = 0;
144 	do {
145 		if (*match =='\0') {
146 			signal(SIGALRM, f);
147 			return (1);
148 		}
149 		if (setjmp(timeoutbuf)) {
150 			signal(SIGALRM, f);
151 			return (0);
152 		}
153 		alarm(number(value(DIALTIMEOUT)));
154 		read(FD, &c, 1);
155 		alarm(0);
156 		c &= 0177;
157 #ifdef DEBUG
158 		if (boolean(value(VERBOSE)))
159 			putchar(c);
160 #endif
161 	} while (c == *match++);
162 #ifdef DEBUG
163 	if (boolean(value(VERBOSE)))
164 		fflush(stdout);
165 #endif
166 	signal(SIGALRM, SIG_DFL);
167 	return (0);
168 }
169 
170 struct baud_msg {
171 	char *msg;
172 	int baud;
173 } baud_msg[] = {
174 	"",		B300,
175 	" 1200",	B1200,
176 	" 2400",	B2400,
177 	" 9600",	B9600,
178 	" 9600/ARQ",	B9600,
179 	0,		0,
180 };
181 
182 static int
183 cour_connect()
184 {
185 	char c;
186 	int nc, nl, n;
187 	char dialer_buf[64];
188 	struct baud_msg *bm;
189 	sig_t f;
190 
191 	if (cour_swallow("\r\n") == 0)
192 		return (0);
193 	f = signal(SIGALRM, sigALRM);
194 again:
195 	nc = 0; nl = sizeof(dialer_buf)-1;
196 	bzero(dialer_buf, sizeof(dialer_buf));
197 	timeout = 0;
198 	for (nc = 0, nl = sizeof(dialer_buf)-1 ; nl > 0 ; nc++, nl--) {
199 		if (setjmp(timeoutbuf))
200 			break;
201 		alarm(number(value(DIALTIMEOUT)));
202 		n = read(FD, &c, 1);
203 		alarm(0);
204 		if (n <= 0)
205 			break;
206 		c &= 0x7f;
207 		if (c == '\r') {
208 			if (cour_swallow("\n") == 0)
209 				break;
210 			if (!dialer_buf[0])
211 				goto again;
212 			if (strcmp(dialer_buf, "RINGING") == 0 &&
213 			    boolean(value(VERBOSE))) {
214 #ifdef DEBUG
215 				printf("%s\r\n", dialer_buf);
216 #endif
217 				goto again;
218 			}
219 			if (strncmp(dialer_buf, "CONNECT",
220 				    sizeof("CONNECT")-1) != 0)
221 				break;
222 			for (bm = baud_msg ; bm->msg ; bm++)
223 				if (strcmp(bm->msg,
224 				    dialer_buf+sizeof("CONNECT")-1) == 0) {
225 					if (!acu_setspeed(bm->baud))
226 						goto error;
227 					signal(SIGALRM, f);
228 #ifdef DEBUG
229 					if (boolean(value(VERBOSE)))
230 						printf("%s\r\n", dialer_buf);
231 #endif
232 					return (1);
233 				}
234 			break;
235 		}
236 		dialer_buf[nc] = c;
237 #ifdef notdef
238 		if (boolean(value(VERBOSE)))
239 			putchar(c);
240 #endif
241 	}
242 error1:
243 	printf("%s\r\n", dialer_buf);
244 error:
245 	signal(SIGALRM, f);
246 	return (0);
247 }
248 
249 /*
250  * This convoluted piece of code attempts to get
251  * the courier in sync.
252  */
253 static int
254 coursync()
255 {
256 	int already = 0;
257 	int len;
258 	char buf[40];
259 
260 	while (already++ < MAXRETRY) {
261 		ioctl(FD, TIOCFLUSH, 0);	/* flush any clutter */
262 		cour_write(FD, "\rAT Z\r", 6);	/* reset modem */
263 		bzero(buf, sizeof(buf));
264 		sleep(1);
265 		ioctl(FD, FIONREAD, &len);
266 		if (len) {
267 			len = read(FD, buf, sizeof(buf));
268 #ifdef DEBUG
269 			buf[len] = '\0';
270 			printf("coursync: (\"%s\")\n\r", buf);
271 #endif
272 			if (index(buf, '0') ||
273 		   	   (index(buf, 'O') && index(buf, 'K')))
274 				return(1);
275 		}
276 		/*
277 		 * If not strapped for DTR control,
278 		 * try to get command mode.
279 		 */
280 		sleep(1);
281 		cour_write(FD, "+++", 3);
282 		sleep(1);
283 		/*
284 		 * Toggle DTR to force anyone off that might have left
285 		 * the modem connected.
286 		 */
287 		ioctl(FD, TIOCCDTR, 0);
288 		sleep(1);
289 		ioctl(FD, TIOCSDTR, 0);
290 	}
291 	cour_write(FD, "\rAT Z\r", 6);
292 	return (0);
293 }
294 
295 cour_write(fd, cp, n)
296 int fd;
297 char *cp;
298 int n;
299 {
300 #ifdef notdef
301 	if (boolean(value(VERBOSE)))
302 		write(1, cp, n);
303 #endif
304 	acu_flush ();
305 	cour_nap();
306 	for ( ; n-- ; cp++) {
307 		write(fd, cp, 1);
308 		acu_flush ();
309 		cour_nap();
310 	}
311 }
312 
313 #ifdef DEBUG
314 cour_verbose_read()
315 {
316 	int n = 0;
317 	char buf[BUFSIZ];
318 
319 	if (ioctl(FD, FIONREAD, &n) < 0)
320 		return;
321 	if (n <= 0)
322 		return;
323 	if (read(FD, buf, n) != n)
324 		return;
325 	write(1, buf, n);
326 }
327 #endif
328 
329 cour_nap()
330 {
331 	acu_nap (50);
332 }
333 
334 /* end of courier.c */
335