Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[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  * @(#)courier.c        8.1 (Berkeley) 6/6/93
34  */
35
36 /*
37  * Routines for calling up on a Courier modem.
38  * Derived from Hayes driver.
39  */
40 #include "tipconf.h"
41 #include "tip.h"
42 #include "acucommon.h"
43 #include <stdio.h>
44
45 #define MAXRETRY        5
46
47 static  void sigALRM();
48 static  int timeout = 0;
49 static  int connected = 0;
50 static  jmp_buf timeoutbuf, intbuf;
51 static  int coursync();
52
53 cour_dialer(num, acu)
54         register char *num;
55         char *acu;
56 {
57         register char *cp;
58 #if ACULOG
59         char line[80];
60 #endif
61         static int cour_connect(), cour_swallow();
62
63         if (boolean(value(VERBOSE)))
64                 printf("Using \"%s\"\n", acu);
65
66         acu_hupcl ();
67
68         /*
69          * Get in synch.
70          */
71         if (!coursync()) {
72 badsynch:
73                 printf("can't synchronize with courier\n");
74 #if ACULOG
75                 logent(value(HOST), num, "courier", "can't synch up");
76 #endif
77                 return (0);
78         }
79         cour_write(FD, "AT E0\r", 6);   /* turn off echoing */
80         sleep(1);
81 #ifdef DEBUG
82         if (boolean(value(VERBOSE)))
83                 cour_verbose_read();
84 #endif
85         ioctl(FD, TIOCFLUSH, 0);        /* flush any clutter */
86         cour_write(FD, "AT C1 E0 H0 Q0 X6 V1\r", 21);
87         if (!cour_swallow("\r\nOK\r\n"))
88                 goto badsynch;
89         fflush(stdout);
90         cour_write(FD, "AT D", 4);
91         for (cp = num; *cp; cp++)
92                 if (*cp == '=')
93                         *cp = ',';
94         cour_write(FD, num, strlen(num));
95         cour_write(FD, "\r", 1);
96         connected = cour_connect();
97 #if ACULOG
98         if (timeout) {
99                 sprintf(line, "%d second dial timeout",
100                         number(value(DIALTIMEOUT)));
101                 logent(value(HOST), num, "cour", line);
102         }
103 #endif
104         if (timeout)
105                 cour_disconnect();
106         return (connected);
107 }
108
109 cour_disconnect()
110 {
111          /* first hang up the modem*/
112         ioctl(FD, TIOCCDTR, 0);
113         sleep(1);
114         ioctl(FD, TIOCSDTR, 0);
115         coursync();                             /* reset */
116         close(FD);
117 }
118
119 cour_abort()
120 {
121         cour_write(FD, "\r", 1);        /* send anything to abort the call */
122         cour_disconnect();
123 }
124
125 static void
126 sigALRM()
127 {
128         printf("\07timeout waiting for reply\n");
129         timeout = 1;
130         longjmp(timeoutbuf, 1);
131 }
132
133 static int
134 cour_swallow(match)
135   register char *match;
136   {
137         sig_t f;
138         char c;
139
140         f = signal(SIGALRM, sigALRM);
141         timeout = 0;
142         do {
143                 if (*match =='\0') {
144                         signal(SIGALRM, f);
145                         return (1);
146                 }
147                 if (setjmp(timeoutbuf)) {
148                         signal(SIGALRM, f);
149                         return (0);
150                 }
151                 alarm(number(value(DIALTIMEOUT)));
152                 read(FD, &c, 1);
153                 alarm(0);
154                 c &= 0177;
155 #ifdef DEBUG
156                 if (boolean(value(VERBOSE)))
157                         putchar(c);
158 #endif
159         } while (c == *match++);
160 #ifdef DEBUG
161         if (boolean(value(VERBOSE)))
162                 fflush(stdout);
163 #endif
164         signal(SIGALRM, SIG_DFL);
165         return (0);
166 }
167
168 struct baud_msg {
169         char *msg;
170         int baud;
171 } baud_msg[] = {
172         "",             B300,
173         " 1200",        B1200,
174         " 2400",        B2400,
175         " 9600",        B9600,
176         " 9600/ARQ",    B9600,
177         0,              0,
178 };
179
180 static int
181 cour_connect()
182 {
183         char c;
184         int nc, nl, n;
185         char dialer_buf[64];
186         struct baud_msg *bm;
187         sig_t f;
188
189         if (cour_swallow("\r\n") == 0)
190                 return (0);
191         f = signal(SIGALRM, sigALRM);
192 again:
193         nc = 0; nl = sizeof(dialer_buf)-1;
194         bzero(dialer_buf, sizeof(dialer_buf));
195         timeout = 0;
196         for (nc = 0, nl = sizeof(dialer_buf)-1 ; nl > 0 ; nc++, nl--) {
197                 if (setjmp(timeoutbuf))
198                         break;
199                 alarm(number(value(DIALTIMEOUT)));
200                 n = read(FD, &c, 1);
201                 alarm(0);
202                 if (n <= 0)
203                         break;
204                 c &= 0x7f;
205                 if (c == '\r') {
206                         if (cour_swallow("\n") == 0)
207                                 break;
208                         if (!dialer_buf[0])
209                                 goto again;
210                         if (strcmp(dialer_buf, "RINGING") == 0 &&
211                             boolean(value(VERBOSE))) {
212 #ifdef DEBUG
213                                 printf("%s\r\n", dialer_buf);
214 #endif
215                                 goto again;
216                         }
217                         if (strncmp(dialer_buf, "CONNECT",
218                                     sizeof("CONNECT")-1) != 0)
219                                 break;
220                         for (bm = baud_msg ; bm->msg ; bm++)
221                                 if (strcmp(bm->msg,
222                                     dialer_buf+sizeof("CONNECT")-1) == 0) {
223                                         if (!acu_setspeed(bm->baud))
224                                                 goto error;
225                                         signal(SIGALRM, f);
226 #ifdef DEBUG
227                                         if (boolean(value(VERBOSE)))
228                                                 printf("%s\r\n", dialer_buf);
229 #endif
230                                         return (1);
231                                 }
232                         break;
233                 }
234                 dialer_buf[nc] = c;
235 #ifdef notdef
236                 if (boolean(value(VERBOSE)))
237                         putchar(c);
238 #endif
239         }
240 error1:
241         printf("%s\r\n", dialer_buf);
242 error:
243         signal(SIGALRM, f);
244         return (0);
245 }
246
247 /*
248  * This convoluted piece of code attempts to get
249  * the courier in sync.
250  */
251 static int
252 coursync()
253 {
254         int already = 0;
255         int len;
256         char buf[40];
257
258         while (already++ < MAXRETRY) {
259                 ioctl(FD, TIOCFLUSH, 0);        /* flush any clutter */
260                 cour_write(FD, "\rAT Z\r", 6);  /* reset modem */
261                 bzero(buf, sizeof(buf));
262                 sleep(1);
263                 ioctl(FD, FIONREAD, &len);
264                 if (len) {
265                         len = read(FD, buf, sizeof(buf));
266 #ifdef DEBUG
267                         buf[len] = '\0';
268                         printf("coursync: (\"%s\")\n\r", buf);
269 #endif
270                         if (index(buf, '0') ||
271                            (index(buf, 'O') && index(buf, 'K')))
272                                 return(1);
273                 }
274                 /*
275                  * If not strapped for DTR control,
276                  * try to get command mode.
277                  */
278                 sleep(1);
279                 cour_write(FD, "+++", 3);
280                 sleep(1);
281                 /*
282                  * Toggle DTR to force anyone off that might have left
283                  * the modem connected.
284                  */
285                 ioctl(FD, TIOCCDTR, 0);
286                 sleep(1);
287                 ioctl(FD, TIOCSDTR, 0);
288         }
289         cour_write(FD, "\rAT Z\r", 6);
290         return (0);
291 }
292
293 cour_write(fd, cp, n)
294 int fd;
295 char *cp;
296 int n;
297 {
298 #ifdef notdef
299         if (boolean(value(VERBOSE)))
300                 write(1, cp, n);
301 #endif
302         acu_flush ();
303         cour_nap();
304         for ( ; n-- ; cp++) {
305                 write(fd, cp, 1);
306                 acu_flush ();
307                 cour_nap();
308         }
309 }
310
311 #ifdef DEBUG
312 cour_verbose_read()
313 {
314         int n = 0;
315         char buf[BUFSIZ];
316
317         if (ioctl(FD, FIONREAD, &n) < 0)
318                 return;
319         if (n <= 0)
320                 return;
321         if (read(FD, buf, n) != n)
322                 return;
323         write(1, buf, n);
324 }
325 #endif
326
327 cour_nap()
328 {
329         acu_nap (50);
330 }
331
332 /* end of courier.c */