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