xref: /original-bsd/usr.bin/tip/aculib/courier.c (revision 57124d5e)
1 /*
2  * Copyright (c) 1986 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[] = "@(#)courier.c	5.2 (Berkeley) 02/17/87";
9 #endif
10 
11 #define write cour_write
12 /*
13  * Routines for calling up on a Courier modem.
14  * Derived from Hayes driver.
15  */
16 #include "tip.h"
17 #include <stdio.h>
18 
19 #define	MAXRETRY	5
20 
21 static	int sigALRM();
22 static	int timeout = 0;
23 static	int connected = 0;
24 static	jmp_buf timeoutbuf, intbuf;
25 static	int (*osigint)();
26 
27 cour_dialer(num, acu)
28 	register char *num;
29 	char *acu;
30 {
31 	register char *cp;
32 #ifdef ACULOG
33 	char line[80];
34 #endif
35 	if (boolean(value(VERBOSE)))
36 		printf("Using \"%s\"\n", acu);
37 
38 	ioctl(FD, TIOCHPCL, 0);
39 	/*
40 	 * Get in synch.
41 	 */
42 	if (!coursync()) {
43 badsynch:
44 		printf("can't synchronize with courier\n");
45 #ifdef ACULOG
46 		logent(value(HOST), num, "courier", "can't synch up");
47 #endif
48 		return (0);
49 	}
50 	write(FD, "AT E0\r", 6);	/* turn off echoing */
51 	sleep(1);
52 #ifdef DEBUG
53 	if (boolean(value(VERBOSE)))
54 		verbose_read();
55 #endif
56 	ioctl(FD, TIOCFLUSH, 0);	/* flush any clutter */
57 	write(FD, "AT C1 E0 H0 Q0 X6 V1\r", 21);
58 	if (!cour_swallow("\r\nOK\r\n"))
59 		goto badsynch;
60 	fflush(stdout);
61 	write(FD, "AT D", 4);
62 	for (cp = num; *cp; cp++)
63 		if (*cp == '=')
64 			*cp = ',';
65 	write(FD, num, strlen(num));
66 	write(FD, "\r", 1);
67 	connected = cour_connect();
68 #ifdef ACULOG
69 	if (timeout) {
70 		sprintf(line, "%d second dial timeout",
71 			number(value(DIALTIMEOUT)));
72 		logent(value(HOST), num, "cour", line);
73 	}
74 #endif
75 	if (timeout)
76 		cour_disconnect();
77 	return (connected);
78 }
79 
80 cour_disconnect()
81 {
82 	 /* first hang up the modem*/
83 	ioctl(FD, TIOCCDTR, 0);
84 	sleep(1);
85 	ioctl(FD, TIOCSDTR, 0);
86 	coursync();				/* reset */
87 	close(FD);
88 }
89 
90 cour_abort()
91 {
92 	write(FD, "\r", 1);	/* send anything to abort the call */
93 	cour_disconnect();
94 }
95 
96 static int
97 sigALRM()
98 {
99 	printf("\07timeout waiting for reply\n");
100 	timeout = 1;
101 	longjmp(timeoutbuf, 1);
102 }
103 
104 static int
105 cour_swallow(match)
106   register char *match;
107   {
108 	char c;
109 	int (*f)();
110 
111 	f = signal(SIGALRM, sigALRM);
112 	timeout = 0;
113 	do {
114 		if (*match =='\0') {
115 			signal(SIGALRM, f);
116 			return (1);
117 		}
118 		if (setjmp(timeoutbuf)) {
119 			signal(SIGALRM, f);
120 			return (0);
121 		}
122 		alarm(number(value(DIALTIMEOUT)));
123 		read(FD, &c, 1);
124 		alarm(0);
125 		c &= 0177;
126 #ifdef DEBUG
127 		if (boolean(value(VERBOSE)))
128 			putchar(c);
129 #endif
130 	} while (c == *match++);
131 #ifdef DEBUG
132 	if (boolean(value(VERBOSE)))
133 		fflush(stdout);
134 #endif
135 	signal(SIGALRM, SIG_DFL);
136 	return (0);
137 }
138 
139 struct baud_msg {
140 	char *msg;
141 	int baud;
142 } baud_msg[] = {
143 	"",		B300,
144 	" 1200",	B1200,
145 	" 2400",	B2400,
146 	0,		0,
147 };
148 
149 static int
150 cour_connect()
151 {
152 	char c;
153 	int nc, nl, n;
154 	struct sgttyb sb;
155 	char dialer_buf[64];
156 	struct baud_msg *bm;
157 	int (*f)();
158 
159 	if (cour_swallow("\r\n") == 0)
160 		return (0);
161 	f = signal(SIGALRM, sigALRM);
162 again:
163 	nc = 0; nl = sizeof(dialer_buf)-1;
164 	bzero(dialer_buf, sizeof(dialer_buf));
165 	timeout = 0;
166 	for (nc = 0, nl = sizeof(dialer_buf)-1 ; nl > 0 ; nc++, nl--) {
167 		if (setjmp(timeoutbuf))
168 			break;
169 		alarm(number(value(DIALTIMEOUT)));
170 		n = read(FD, &c, 1);
171 		alarm(0);
172 		if (n <= 0)
173 			break;
174 		c &= 0x7f;
175 		if (c == '\r') {
176 			if (cour_swallow("\n") == 0)
177 				break;
178 			if (!dialer_buf[0])
179 				goto again;
180 			if (strcmp(dialer_buf, "RINGING") == 0 &&
181 			    boolean(value(VERBOSE))) {
182 #ifdef DEBUG
183 				printf("%s\r\n", dialer_buf);
184 #endif
185 				goto again;
186 			}
187 			if (strncmp(dialer_buf, "CONNECT",
188 				    sizeof("CONNECT")-1) != 0)
189 				break;
190 			for (bm = baud_msg ; bm ; bm++)
191 				if (strcmp(bm->msg,
192 				    dialer_buf+sizeof("CONNECT")-1) == 0) {
193 					if (ioctl(FD, TIOCGETP, &sb) < 0) {
194 						perror("TIOCGETP");
195 						goto error;
196 					}
197 					sb.sg_ispeed = sb.sg_ospeed = bm->baud;
198 					if (ioctl(FD, TIOCSETP, &sb) < 0) {
199 						perror("TIOCSETP");
200 						goto error;
201 					}
202 					signal(SIGALRM, f);
203 #ifdef DEBUG
204 					if (boolean(value(VERBOSE)))
205 						printf("%s\r\n", dialer_buf);
206 #endif
207 					return (1);
208 				}
209 			break;
210 		}
211 		dialer_buf[nc] = c;
212 #ifdef notdef
213 		if (boolean(value(VERBOSE)))
214 			putchar(c);
215 #endif
216 	}
217 error1:
218 	printf("%s\r\n", dialer_buf);
219 error:
220 	signal(SIGALRM, f);
221 	return (0);
222 }
223 
224 /*
225  * This convoluted piece of code attempts to get
226  * the courier in sync.
227  */
228 static int
229 coursync()
230 {
231 	int already = 0;
232 	int len;
233 	char buf[40];
234 
235 	while (already++ < MAXRETRY) {
236 		ioctl(FD, TIOCFLUSH, 0);	/* flush any clutter */
237 		write(FD, "\rAT Z\r", 6);	/* reset modem */
238 		bzero(buf, sizeof(buf));
239 		sleep(1);
240 		ioctl(FD, FIONREAD, &len);
241 		if (len) {
242 			len = read(FD, buf, sizeof(buf));
243 #ifdef DEBUG
244 			buf[len] = '\0';
245 			printf("coursync: (\"%s\")\n\r", buf);
246 #endif
247 			if (index(buf, '0') ||
248 		   	   (index(buf, 'O') && index(buf, 'K')))
249 				return(1);
250 		}
251 		/*
252 		 * If not strapped for DTR control,
253 		 * try to get command mode.
254 		 */
255 		sleep(1);
256 		write(FD, "+++", 3);
257 		sleep(1);
258 		/*
259 		 * Toggle DTR to force anyone off that might have left
260 		 * the modem connected.
261 		 */
262 		ioctl(FD, TIOCCDTR, 0);
263 		sleep(1);
264 		ioctl(FD, TIOCSDTR, 0);
265 	}
266 	write(FD, "\rAT Z\r", 6);
267 	return (0);
268 }
269 
270 #undef write
271 
272 cour_write(fd, cp, n)
273 int fd;
274 char *cp;
275 int n;
276 {
277 	struct sgttyb sb;
278 #ifdef notdef
279 	if (boolean(value(VERBOSE)))
280 		write(1, cp, n);
281 #endif
282 	ioctl(fd, TIOCGETP, &sb);
283 	ioctl(fd, TIOCSETP, &sb);
284 	cour_nap();
285 	for ( ; n-- ; cp++) {
286 		write(fd, cp, 1);
287 		ioctl(fd, TIOCGETP, &sb);
288 		ioctl(fd, TIOCSETP, &sb);
289 		cour_nap();
290 	}
291 }
292 
293 #ifdef DEBUG
294 verbose_read()
295 {
296 	int n = 0;
297 	char buf[BUFSIZ];
298 
299 	if (ioctl(FD, FIONREAD, &n) < 0)
300 		return;
301 	if (n <= 0)
302 		return;
303 	if (read(FD, buf, n) != n)
304 		return;
305 	write(1, buf, n);
306 }
307 #endif
308 
309 /*
310  * Code stolen from /usr/src/lib/libc/gen/sleep.c
311  */
312 #include <sys/time.h>
313 
314 #define mask(s) (1<<((s)-1))
315 #define setvec(vec, a) \
316         vec.sv_handler = a; vec.sv_mask = vec.sv_onstack = 0
317 
318 static napms = 50; /* Give the courier 50 milliseconds between characters */
319 
320 static int ringring;
321 
322 cour_nap()
323 {
324 
325         static int cour_napx();
326 	int omask;
327         struct itimerval itv, oitv;
328         register struct itimerval *itp = &itv;
329         struct sigvec vec, ovec;
330 
331         timerclear(&itp->it_interval);
332         timerclear(&itp->it_value);
333         if (setitimer(ITIMER_REAL, itp, &oitv) < 0)
334                 return;
335         setvec(ovec, SIG_DFL);
336         omask = sigblock(mask(SIGALRM));
337         itp->it_value.tv_sec = napms/1000;
338 	itp->it_value.tv_usec = ((napms%1000)*1000);
339         setvec(vec, cour_napx);
340         ringring = 0;
341         (void) sigvec(SIGALRM, &vec, &ovec);
342         (void) setitimer(ITIMER_REAL, itp, (struct itimerval *)0);
343         while (!ringring)
344                 sigpause(omask &~ mask(SIGALRM));
345         (void) sigvec(SIGALRM, &ovec, (struct sigvec *)0);
346         (void) setitimer(ITIMER_REAL, &oitv, (struct itimerval *)0);
347 	(void) sigsetmask(omask);
348 }
349 
350 static
351 cour_napx()
352 {
353         ringring = 1;
354 }
355