Initial import from FreeBSD RELENG_4:
[dragonfly.git] / usr.bin / tip / libacu / courier.c
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 */