]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - usr.bin/tip/libacu/hayes.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / usr.bin / tip / libacu / hayes.c
1 /*      $OpenBSD: hayes.c,v 1.13 2006/03/17 19:17:13 moritz Exp $       */
2 /*      $NetBSD: hayes.c,v 1.6 1997/02/11 09:24:17 mrg Exp $    */
3
4 /*
5  * Copyright (c) 1983, 1993
6  *      The Regents of the University of California.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35
36 #ifndef lint
37 #if 0
38 static char sccsid[] = "@(#)hayes.c     8.1 (Berkeley) 6/6/93";
39 static const char rcsid[] = "$OpenBSD: hayes.c,v 1.13 2006/03/17 19:17:13 moritz Exp $";
40 #endif
41 #endif /* not lint */
42
43 /*
44  * Routines for calling up on a Hayes Modem
45  * (based on the old VenTel driver).
46  * The modem is expected to be strapped for "echo".
47  * Also, the switches enabling the DTR and CD lines
48  * must be set correctly.
49  * NOTICE:
50  * The easy way to hang up a modem is always simply to
51  * clear the DTR signal. However, if the +++ sequence
52  * (which switches the modem back to local mode) is sent
53  * before modem is hung up, removal of the DTR signal
54  * has no effect (except that it prevents the modem from
55  * recognizing commands).
56  * (by Helge Skrivervik, Calma Company, Sunnyvale, CA. 1984) 
57  */
58 /*
59  * TODO:
60  * It is probably not a good idea to switch the modem
61  * state between 'verbose' and terse (status messages).
62  * This should be kicked out and we should use verbose 
63  * mode only. This would make it consistent with normal
64  * interactive use thru the command 'tip dialer'.
65  */
66 #include "tip.h"
67
68 #include <termios.h>
69 #include <sys/ioctl.h>
70
71 #define min(a,b)        ((a < b) ? a : b)
72
73 static  int dialtimeout = 0;
74 static  jmp_buf timeoutbuf;
75
76 #define DUMBUFLEN       40
77 static char dumbuf[DUMBUFLEN];
78
79 #define DIALING         1
80 #define IDLE            2
81 #define CONNECTED       3
82 #define FAILED          4
83 static  int state = IDLE;
84
85 static void     sigALRM(int);
86 static char     gobble(char *);
87 static void     error_rep(char);
88 static void     goodbye(void);
89 static int      hay_sync(void);
90
91 int
92 hay_dialer(char *num, char *acu)
93 {
94         char *cp;
95         int connected = 0;
96         char dummy;
97         struct termios cntrl;
98 #ifdef ACULOG
99         char line[80];
100 #endif
101         if (hay_sync() == 0)            /* make sure we can talk to the modem */
102                 return(0);
103         if (boolean(value(VERBOSE)))
104                 printf("\ndialing...");
105         fflush(stdout);
106         tcgetattr(FD, &cntrl);
107         cntrl.c_cflag |= HUPCL;
108         tcsetattr(FD, TCSANOW, &cntrl);
109         tcflush(FD, TCIOFLUSH);
110         write(FD, "ATv0\r", 5); /* tell modem to use short status codes */
111         gobble("\r");
112         gobble("\r");
113         write(FD, "ATTD", 4);   /* send dial command */
114         for (cp = num; *cp; cp++)
115                 if (*cp == '=')
116                         *cp = ',';
117         write(FD, num, strlen(num));
118         state = DIALING;
119         write(FD, "\r", 1);
120         connected = 0;
121         if (gobble("\r")) {
122                 if ((dummy = gobble("01234")) != '1')
123                         error_rep(dummy);
124                 else
125                         connected = 1;
126         }
127         if (connected)
128                 state = CONNECTED;
129         else {
130                 state = FAILED;
131                 return (connected);     /* lets get out of here.. */
132         }
133         tcflush(FD, TCIOFLUSH);
134 #ifdef ACULOG
135         if (dialtimeout) {
136                 (void)snprintf(line, sizeof line, "%ld second dial timeout",
137                         number(value(DIALTIMEOUT)));
138                 logent(value(HOST), num, "hayes", line);
139         }
140 #endif
141         if (dialtimeout)
142                 hay_disconnect();       /* insurance */
143         return (connected);
144 }
145
146 void
147 hay_disconnect(void)
148 {
149         /* first hang up the modem*/
150 #ifdef DEBUG
151         printf("\rdisconnecting modem....\n\r");
152 #endif
153         ioctl(FD, TIOCCDTR, 0);
154         sleep(1);
155         ioctl(FD, TIOCSDTR, 0);
156         goodbye();
157 }
158
159 void
160 hay_abort(void)
161 {
162         write(FD, "\r", 1);     /* send anything to abort the call */
163         hay_disconnect();
164 }
165
166 /*ARGSUSED*/
167 static void
168 sigALRM(int signo)
169 {
170         printf("\07timeout waiting for reply\n\r");
171         dialtimeout = 1;
172         longjmp(timeoutbuf, 1);
173 }
174
175 static char
176 gobble(char *match)
177 {
178         char c;
179         sig_t f;
180         size_t i;
181         int status = 0;
182
183         f = signal(SIGALRM, sigALRM);
184         dialtimeout = 0;
185 #ifdef DEBUG
186         printf("\ngobble: waiting for %s\n", match);
187 #endif
188         do {
189                 if (setjmp(timeoutbuf)) {
190                         signal(SIGALRM, f);
191                         return (0);
192                 }
193                 alarm(number(value(DIALTIMEOUT)));
194                 read(FD, &c, 1);
195                 alarm(0);
196                 c &= 0177;
197 #ifdef DEBUG
198                 printf("%c 0x%x ", c, c);
199 #endif
200                 for (i = 0; i < strlen(match); i++)
201                         if (c == match[i])
202                                 status = c;
203         } while (status == 0);
204         signal(SIGALRM, SIG_DFL);
205 #ifdef DEBUG
206         printf("\n");
207 #endif
208         return (status);
209 }
210
211 static void
212 error_rep(char c)
213 {
214         printf("\n\r");
215         switch (c) {
216
217         case '0':
218                 printf("OK");
219                 break;
220
221         case '1':
222                 printf("CONNECT");
223                 break;
224
225         case '2':
226                 printf("RING");
227                 break;
228
229         case '3':
230                 printf("NO CARRIER");
231                 break;
232
233         case '4':
234                 printf("ERROR in input");
235                 break;
236
237         case '5':
238                 printf("CONNECT 1200");
239                 break;
240
241         default:
242                 printf("Unknown Modem error: %c (0x%x)", c, c);
243         }
244         printf("\n\r");
245         return;
246 }
247
248 /*
249  * set modem back to normal verbose status codes.
250  */
251 static void
252 goodbye(void)
253 {
254         int len;
255         char c;
256
257         tcflush(FD, TCIOFLUSH);
258         if (hay_sync()) {
259                 sleep(1);
260 #ifndef DEBUG
261                 tcflush(FD, TCIOFLUSH);
262 #endif
263                 write(FD, "ATH0\r", 5);         /* insurance */
264 #ifndef DEBUG
265                 c = gobble("03");
266                 if (c != '0' && c != '3') {
267                         printf("cannot hang up modem\n\r");
268                         printf("please use 'tip dialer' to make sure the line is hung up\n\r");
269                 }
270 #endif
271                 sleep(1);
272                 ioctl(FD, FIONREAD, &len);
273 #ifdef DEBUG
274                 printf("goodbye1: len=%d -- ", len);
275                 rlen = read(FD, dumbuf, min(len, DUMBUFLEN));
276                 dumbuf[rlen] = '\0';
277                 printf("read (%d): %s\r\n", rlen, dumbuf);
278 #endif
279                 write(FD, "ATv1\r", 5);
280                 sleep(1);
281 #ifdef DEBUG
282                 ioctl(FD, FIONREAD, &len);
283                 printf("goodbye2: len=%d -- ", len);
284                 rlen = read(FD, dumbuf, min(len, DUMBUFLEN));
285                 dumbuf[rlen] = '\0';
286                 printf("read (%d): %s\r\n", rlen, dumbuf);
287 #endif
288         }
289         tcflush(FD, TCIOFLUSH);
290         ioctl(FD, TIOCCDTR, 0);         /* clear DTR (insurance) */
291         close(FD);
292 }
293
294 #define MAXRETRY        5
295
296 static int
297 hay_sync(void)
298 {
299         int len, retry = 0;
300
301         while (retry++ <= MAXRETRY) {
302                 write(FD, "AT\r", 3);
303                 sleep(1);
304                 ioctl(FD, FIONREAD, &len);
305                 if (len) {
306                         len = read(FD, dumbuf, min(len, DUMBUFLEN));
307                         if (strchr(dumbuf, '0') || 
308                         (strchr(dumbuf, 'O') && strchr(dumbuf, 'K')))
309                                 return(1);
310 #ifdef DEBUG
311                         dumbuf[len] = '\0';
312                         printf("hay_sync: (\"%s\") %d\n\r", dumbuf, retry);
313 #endif
314                 }
315                 ioctl(FD, TIOCCDTR, 0);
316                 ioctl(FD, TIOCSDTR, 0);
317         }
318         printf("Cannot synchronize with hayes...\n\r");
319         return(0);
320 }