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