Commit | Line | Data |
---|---|---|
1485b502 DS |
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 | |
fb6da896 | 8 | static char sccsid[] = "@(#)courier.c 5.2 (Berkeley) %G%"; |
1485b502 DS |
9 | #endif |
10 | ||
11 | #define write cour_write | |
12 | /* | |
fb6da896 MK |
13 | * Routines for calling up on a Courier modem. |
14 | * Derived from Hayes driver. | |
1485b502 DS |
15 | */ |
16 | #include "tip.h" | |
17 | #include <stdio.h> | |
18 | ||
19 | #define MAXRETRY 5 | |
20 | ||
21 | static int sigALRM(); | |
22 | static int timeout = 0; | |
fb6da896 | 23 | static int connected = 0; |
1485b502 DS |
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; | |
1485b502 DS |
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()) { | |
fb6da896 | 43 | badsynch: |
1485b502 DS |
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 | } | |
fb6da896 MK |
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; | |
1485b502 DS |
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() | |
fb6da896 MK |
81 | { |
82 | /* first hang up the modem*/ | |
83 | ioctl(FD, TIOCCDTR, 0); | |
84 | sleep(1); | |
85 | ioctl(FD, TIOCSDTR, 0); | |
86 | coursync(); /* reset */ | |
1485b502 DS |
87 | close(FD); |
88 | } | |
89 | ||
90 | cour_abort() | |
fb6da896 MK |
91 | { |
92 | write(FD, "\r", 1); /* send anything to abort the call */ | |
93 | cour_disconnect(); | |
1485b502 DS |
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); | |
fb6da896 | 116 | return (1); |
1485b502 DS |
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; | |
fb6da896 | 126 | #ifdef DEBUG |
1485b502 DS |
127 | if (boolean(value(VERBOSE))) |
128 | putchar(c); | |
fb6da896 | 129 | #endif |
1485b502 | 130 | } while (c == *match++); |
fb6da896 | 131 | #ifdef DEBUG |
1485b502 DS |
132 | if (boolean(value(VERBOSE))) |
133 | fflush(stdout); | |
fb6da896 | 134 | #endif |
1485b502 DS |
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; | |
fb6da896 MK |
180 | if (strcmp(dialer_buf, "RINGING") == 0 && |
181 | boolean(value(VERBOSE))) { | |
182 | #ifdef DEBUG | |
1485b502 | 183 | printf("%s\r\n", dialer_buf); |
fb6da896 | 184 | #endif |
1485b502 DS |
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); | |
fb6da896 | 203 | #ifdef DEBUG |
1485b502 DS |
204 | if (boolean(value(VERBOSE))) |
205 | printf("%s\r\n", dialer_buf); | |
fb6da896 | 206 | #endif |
1485b502 DS |
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 | |
fb6da896 | 226 | * the courier in sync. |
1485b502 DS |
227 | */ |
228 | static int | |
229 | coursync() | |
230 | { | |
231 | int already = 0; | |
fb6da896 MK |
232 | int len; |
233 | char buf[40]; | |
1485b502 | 234 | |
1485b502 DS |
235 | while (already++ < MAXRETRY) { |
236 | ioctl(FD, TIOCFLUSH, 0); /* flush any clutter */ | |
237 | write(FD, "\rAT Z\r", 6); /* reset modem */ | |
fb6da896 | 238 | bzero(buf, sizeof(buf)); |
1485b502 | 239 | sleep(1); |
fb6da896 MK |
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); | |
1485b502 | 250 | } |
fb6da896 MK |
251 | /* |
252 | * If not strapped for DTR control, | |
253 | * try to get command mode. | |
254 | */ | |
255 | sleep(1); | |
1485b502 | 256 | write(FD, "+++", 3); |
fb6da896 MK |
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); | |
1485b502 DS |
265 | } |
266 | write(FD, "\rAT Z\r", 6); | |
fb6da896 | 267 | return (0); |
1485b502 DS |
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; | |
fb6da896 | 278 | #ifdef notdef |
1485b502 DS |
279 | if (boolean(value(VERBOSE))) |
280 | write(1, cp, n); | |
fb6da896 | 281 | #endif |
1485b502 DS |
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 | ||
fb6da896 | 293 | #ifdef DEBUG |
1485b502 DS |
294 | verbose_read() |
295 | { | |
296 | int n = 0; | |
297 | char buf[BUFSIZ]; | |
fb6da896 | 298 | |
1485b502 DS |
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 | } | |
fb6da896 | 307 | #endif |
1485b502 DS |
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 | } |