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