BSD 4_3_Reno release
[unix-history] / usr / src / usr.bin / tip / aculib / hayes.c
CommitLineData
051b1e55 1/*
be11e13c
KB
2 * Copyright (c) 1983 The Regents of the University of California.
3 * All rights reserved.
4 *
1c15e888
C
5 * Redistribution and use in source and binary forms are permitted
6 * provided that: (1) source distributions retain this entire copyright
7 * notice and comment, and (2) distributions including binaries display
8 * the following acknowledgement: ``This product includes software
9 * developed by the University of California, Berkeley and its contributors''
10 * in the documentation or other materials provided with the distribution
11 * and in all advertising materials mentioning features or use of this
12 * software. Neither the name of the University nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
051b1e55
DF
18 */
19
e316be98 20#ifndef lint
1c15e888 21static char sccsid[] = "@(#)hayes.c 5.3 (Berkeley) 6/1/90";
be11e13c 22#endif /* not lint */
e316be98
MAN
23
24/*
25 * Routines for calling up on a Hayes Modem
26 * (based on the old VenTel driver).
27 * The modem is expected to be strapped for "echo".
28 * Also, the switches enabling the DTR and CD lines
29 * must be set correctly.
30 * NOTICE:
31 * The easy way to hang up a modem is always simply to
32 * clear the DTR signal. However, if the +++ sequence
33 * (which switches the modem back to local mode) is sent
34 * before modem is hung up, removal of the DTR signal
35 * has no effect (except that it prevents the modem from
36 * recognizing commands).
37 * (by Helge Skrivervik, Calma Company, Sunnyvale, CA. 1984)
38 */
39/*
40 * TODO:
41 * It is probably not a good idea to switch the modem
42 * state between 'verbose' and terse (status messages).
43 * This should be kicked out and we should use verbose
44 * mode only. This would make it consistent with normal
45 * interactive use thru the command 'tip dialer'.
46 */
47#include "tip.h"
48
49#define min(a,b) ((a < b) ? a : b)
50
51static int sigALRM();
52static int timeout = 0;
53static jmp_buf timeoutbuf;
54static char gobble();
55#define DUMBUFLEN 40
56static char dumbuf[DUMBUFLEN];
57
58#define DIALING 1
59#define IDLE 2
60#define CONNECTED 3
61#define FAILED 4
62static int state = IDLE;
63
64hay_dialer(num, acu)
65 register char *num;
66 char *acu;
67{
68 register char *cp;
69 register int connected = 0;
70 char dummy;
71#ifdef ACULOG
72 char line[80];
73#endif
74 if (hay_sync() == 0) /* make sure we can talk to the modem */
75 return(0);
76 if (boolean(value(VERBOSE)))
77 printf("\ndialing...");
78 fflush(stdout);
79 ioctl(FD, TIOCHPCL, 0);
80 ioctl(FD, TIOCFLUSH, 0); /* get rid of garbage */
81 write(FD, "ATv0\r", 5); /* tell modem to use short status codes */
82 gobble("\r");
83 gobble("\r");
84 write(FD, "ATTD", 4); /* send dial command */
85 write(FD, num, strlen(num));
86 state = DIALING;
87 write(FD, "\r", 1);
88 connected = 0;
89 if (gobble("\r")) {
90 if ((dummy = gobble("01234")) != '1')
91 error_rep(dummy);
92 else
93 connected = 1;
94 }
95 if (connected)
96 state = CONNECTED;
97 else {
98 state = FAILED;
99 return (connected); /* lets get out of here.. */
100 }
101 ioctl(FD, TIOCFLUSH, 0);
102#ifdef ACULOG
103 if (timeout) {
104 sprintf(line, "%d second dial timeout",
105 number(value(DIALTIMEOUT)));
106 logent(value(HOST), num, "hayes", line);
107 }
108#endif
109 if (timeout)
110 hay_disconnect(); /* insurance */
111 return (connected);
112}
113
114
115hay_disconnect()
116{
117 char c;
118 int len, rlen;
119
120 /* first hang up the modem*/
121#ifdef DEBUG
122 printf("\rdisconnecting modem....\n\r");
123#endif
124 ioctl(FD, TIOCCDTR, 0);
125 sleep(1);
126 ioctl(FD, TIOCSDTR, 0);
127 goodbye();
128}
129
130hay_abort()
131{
132
133 char c;
134
135 write(FD, "\r", 1); /* send anything to abort the call */
136 hay_disconnect();
137}
138
139static int
140sigALRM()
141{
142
143 printf("\07timeout waiting for reply\n\r");
144 timeout = 1;
145 longjmp(timeoutbuf, 1);
146}
147
148static char
149gobble(match)
150 register char *match;
151{
152 char c;
153 int (*f)();
154 int i, status = 0;
155
156 signal(SIGALRM, sigALRM);
157 timeout = 0;
158#ifdef DEBUG
159 printf("\ngobble: waiting for %s\n", match);
160#endif
161 do {
162 if (setjmp(timeoutbuf)) {
163 signal(SIGALRM, f);
164 return (0);
165 }
166 alarm(number(value(DIALTIMEOUT)));
167 read(FD, &c, 1);
168 alarm(0);
169 c &= 0177;
170#ifdef DEBUG
171 printf("%c 0x%x ", c, c);
172#endif
173 for (i = 0; i < strlen(match); i++)
174 if (c == match[i])
175 status = c;
176 } while (status == 0);
177 signal(SIGALRM, SIG_DFL);
178#ifdef DEBUG
179 printf("\n");
180#endif
181 return (status);
182}
183
184error_rep(c)
185 register char c;
186{
187 printf("\n\r");
188 switch (c) {
189
190 case '0':
191 printf("OK");
192 break;
193
194 case '1':
195 printf("CONNECT");
196 break;
197
198 case '2':
199 printf("RING");
200 break;
201
202 case '3':
203 printf("NO CARRIER");
204 break;
205
206 case '4':
207 printf("ERROR in input");
208 break;
209
210 case '5':
211 printf("CONNECT 1200");
212 break;
213
214 default:
215 printf("Unknown Modem error: %c (0x%x)", c, c);
216 }
217 printf("\n\r");
218 return;
219}
220
221/*
222 * set modem back to normal verbose status codes.
223 */
224goodbye()
225{
226 int len, rlen;
227 char c;
228
229 ioctl(FD, TIOCFLUSH, &len); /* get rid of trash */
230 if (hay_sync()) {
231 sleep(1);
232#ifndef DEBUG
233 ioctl(FD, TIOCFLUSH, 0);
234#endif
235 write(FD, "ATH0\r", 5); /* insurance */
236#ifndef DEBUG
237 c = gobble("03");
238 if (c != '0' && c != '3') {
239 printf("cannot hang up modem\n\r");
240 printf("please use 'tip dialer' to make sure the line is hung up\n\r");
241 }
242#endif
243 sleep(1);
244 ioctl(FD, FIONREAD, &len);
245#ifdef DEBUG
246 printf("goodbye1: len=%d -- ", len);
247 rlen = read(FD, dumbuf, min(len, DUMBUFLEN));
248 dumbuf[rlen] = '\0';
249 printf("read (%d): %s\r\n", rlen, dumbuf);
250#endif
251 write(FD, "ATv1\r", 5);
252 sleep(1);
253#ifdef DEBUG
254 ioctl(FD, FIONREAD, &len);
255 printf("goodbye2: len=%d -- ", len);
256 rlen = read(FD, dumbuf, min(len, DUMBUFLEN));
257 dumbuf[rlen] = '\0';
258 printf("read (%d): %s\r\n", rlen, dumbuf);
259#endif
260 }
261 ioctl(FD, TIOCFLUSH, 0); /* clear the input buffer */
262 ioctl(FD, TIOCCDTR, 0); /* clear DTR (insurance) */
263 close(FD);
264}
265
266#define MAXRETRY 5
267
268hay_sync()
269{
270 int len, retry = 0;
271
272 while (retry++ <= MAXRETRY) {
273 write(FD, "AT\r", 3);
274 sleep(1);
275 ioctl(FD, FIONREAD, &len);
276 if (len) {
277 len = read(FD, dumbuf, min(len, DUMBUFLEN));
278 if (index(dumbuf, '0') ||
279 (index(dumbuf, 'O') && index(dumbuf, 'K')))
280 return(1);
281#ifdef DEBUG
282 dumbuf[len] = '\0';
283 printf("hay_sync: (\"%s\") %d\n\r", dumbuf, retry);
284#endif
285 }
286 ioctl(FD, TIOCCDTR, 0);
287 ioctl(FD, TIOCSDTR, 0);
288 }
289 printf("Cannot synchronize with hayes...\n\r");
290 return(0);
291}