Commit | Line | Data |
---|---|---|
15637ed4 RG |
1 | /* |
2 | * Copyright (c) 1983 The Regents of the University of California. | |
3 | * 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[] = "@(#)ventel.c 5.4 (Berkeley) 3/2/91"; | |
36 | #endif /* not lint */ | |
37 | ||
38 | /* | |
39 | * Routines for calling up on a Ventel Modem | |
40 | * The Ventel is expected to be strapped for local echo (just like uucp) | |
41 | */ | |
42 | #include "tip.h" | |
43 | ||
44 | #define MAXRETRY 5 | |
45 | ||
46 | static void sigALRM(); | |
47 | static int timeout = 0; | |
48 | static jmp_buf timeoutbuf; | |
49 | ||
50 | /* | |
51 | * some sleep calls have been replaced by this macro | |
52 | * because some ventel modems require two <cr>s in less than | |
53 | * a second in order to 'wake up'... yes, it is dirty... | |
54 | */ | |
55 | #define delay(num,denom) busyloop(CPUSPEED*num/denom) | |
56 | #define CPUSPEED 1000000 /* VAX 780 is 1MIPS */ | |
57 | #define DELAY(n) { register long N = (n); while (--N > 0); } | |
58 | busyloop(n) { DELAY(n); } | |
59 | ||
60 | ven_dialer(num, acu) | |
61 | register char *num; | |
62 | char *acu; | |
63 | { | |
64 | register char *cp; | |
65 | register int connected = 0; | |
66 | char *msg, *index(), line[80]; | |
67 | static int gobble(), vensync(); | |
68 | static void echo(); | |
69 | ||
70 | /* | |
71 | * Get in synch with a couple of carriage returns | |
72 | */ | |
73 | if (!vensync(FD)) { | |
74 | printf("can't synchronize with ventel\n"); | |
75 | #ifdef ACULOG | |
76 | logent(value(HOST), num, "ventel", "can't synch up"); | |
77 | #endif | |
78 | return (0); | |
79 | } | |
80 | if (boolean(value(VERBOSE))) | |
81 | printf("\ndialing..."); | |
82 | fflush(stdout); | |
83 | ioctl(FD, TIOCHPCL, 0); | |
84 | echo("#k$\r$\n$D$I$A$L$:$ "); | |
85 | for (cp = num; *cp; cp++) { | |
86 | delay(1, 10); | |
87 | write(FD, cp, 1); | |
88 | } | |
89 | delay(1, 10); | |
90 | write(FD, "\r", 1); | |
91 | gobble('\n', line); | |
92 | if (gobble('\n', line)) | |
93 | connected = gobble('!', line); | |
94 | ioctl(FD, TIOCFLUSH); | |
95 | #ifdef ACULOG | |
96 | if (timeout) { | |
97 | sprintf(line, "%d second dial timeout", | |
98 | number(value(DIALTIMEOUT))); | |
99 | logent(value(HOST), num, "ventel", line); | |
100 | } | |
101 | #endif | |
102 | if (timeout) | |
103 | ven_disconnect(); /* insurance */ | |
104 | if (connected || timeout || !boolean(value(VERBOSE))) | |
105 | return (connected); | |
106 | /* call failed, parse response for user */ | |
107 | cp = index(line, '\r'); | |
108 | if (cp) | |
109 | *cp = '\0'; | |
110 | for (cp = line; cp = index(cp, ' '); cp++) | |
111 | if (cp[1] == ' ') | |
112 | break; | |
113 | if (cp) { | |
114 | while (*cp == ' ') | |
115 | cp++; | |
116 | msg = cp; | |
117 | while (*cp) { | |
118 | if (isupper(*cp)) | |
119 | *cp = tolower(*cp); | |
120 | cp++; | |
121 | } | |
122 | printf("%s...", msg); | |
123 | } | |
124 | return (connected); | |
125 | } | |
126 | ||
127 | ven_disconnect() | |
128 | { | |
129 | ||
130 | close(FD); | |
131 | } | |
132 | ||
133 | ven_abort() | |
134 | { | |
135 | ||
136 | write(FD, "\03", 1); | |
137 | close(FD); | |
138 | } | |
139 | ||
140 | static void | |
141 | echo(s) | |
142 | register char *s; | |
143 | { | |
144 | char c; | |
145 | ||
146 | while (c = *s++) switch (c) { | |
147 | ||
148 | case '$': | |
149 | read(FD, &c, 1); | |
150 | s++; | |
151 | break; | |
152 | ||
153 | case '#': | |
154 | c = *s++; | |
155 | write(FD, &c, 1); | |
156 | break; | |
157 | ||
158 | default: | |
159 | write(FD, &c, 1); | |
160 | read(FD, &c, 1); | |
161 | } | |
162 | } | |
163 | ||
164 | static void | |
165 | sigALRM() | |
166 | { | |
167 | printf("\07timeout waiting for reply\n"); | |
168 | timeout = 1; | |
169 | longjmp(timeoutbuf, 1); | |
170 | } | |
171 | ||
172 | static int | |
173 | gobble(match, response) | |
174 | register char match; | |
175 | char response[]; | |
176 | { | |
177 | register char *cp = response; | |
178 | sig_t f; | |
179 | char c; | |
180 | ||
181 | f = signal(SIGALRM, sigALRM); | |
182 | timeout = 0; | |
183 | do { | |
184 | if (setjmp(timeoutbuf)) { | |
185 | signal(SIGALRM, f); | |
186 | *cp = '\0'; | |
187 | return (0); | |
188 | } | |
189 | alarm(number(value(DIALTIMEOUT))); | |
190 | read(FD, cp, 1); | |
191 | alarm(0); | |
192 | c = (*cp++ &= 0177); | |
193 | #ifdef notdef | |
194 | if (boolean(value(VERBOSE))) | |
195 | putchar(c); | |
196 | #endif | |
197 | } while (c != '\n' && c != match); | |
198 | signal(SIGALRM, SIG_DFL); | |
199 | *cp = '\0'; | |
200 | return (c == match); | |
201 | } | |
202 | ||
203 | #define min(a,b) ((a)>(b)?(b):(a)) | |
204 | /* | |
205 | * This convoluted piece of code attempts to get | |
206 | * the ventel in sync. If you don't have FIONREAD | |
207 | * there are gory ways to simulate this. | |
208 | */ | |
209 | static int | |
210 | vensync(fd) | |
211 | { | |
212 | int already = 0, nread; | |
213 | char buf[60]; | |
214 | ||
215 | /* | |
216 | * Toggle DTR to force anyone off that might have left | |
217 | * the modem connected, and insure a consistent state | |
218 | * to start from. | |
219 | * | |
220 | * If you don't have the ioctl calls to diddle directly | |
221 | * with DTR, you can always try setting the baud rate to 0. | |
222 | */ | |
223 | ioctl(FD, TIOCCDTR, 0); | |
224 | sleep(1); | |
225 | ioctl(FD, TIOCSDTR, 0); | |
226 | while (already < MAXRETRY) { | |
227 | /* | |
228 | * After reseting the modem, send it two \r's to | |
229 | * autobaud on. Make sure to delay between them | |
230 | * so the modem can frame the incoming characters. | |
231 | */ | |
232 | write(fd, "\r", 1); | |
233 | delay(1,10); | |
234 | write(fd, "\r", 1); | |
235 | sleep(2); | |
236 | if (ioctl(fd, FIONREAD, (caddr_t)&nread) < 0) { | |
237 | perror("tip: ioctl"); | |
238 | continue; | |
239 | } | |
240 | while (nread > 0) { | |
241 | read(fd, buf, min(nread, 60)); | |
242 | if ((buf[nread - 1] & 0177) == '$') | |
243 | return (1); | |
244 | nread -= min(nread, 60); | |
245 | } | |
246 | sleep(1); | |
247 | already++; | |
248 | } | |
249 | return (0); | |
250 | } | |
251 |