]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/tip/libacu/ventel.c
zfs: merge openzfs/zfs@7d9f3ef0e (zfs-2.1-release) into stable/13
[FreeBSD/FreeBSD.git] / usr.bin / tip / libacu / ventel.c
1 /*      $OpenBSD: ventel.c,v 1.12 2006/03/17 19:17:13 moritz Exp $      */
2 /*      $NetBSD: ventel.c,v 1.6 1997/02/11 09:24:21 mrg Exp $   */
3
4 /*-
5  * SPDX-License-Identifier: BSD-3-Clause
6  *
7  * Copyright (c) 1983, 1993
8  *      The Regents of the University of California.  All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
37
38 #ifndef lint
39 #if 0
40 static char sccsid[] = "@(#)ventel.c    8.1 (Berkeley) 6/6/93";
41 static const char rcsid[] = "$OpenBSD: ventel.c,v 1.12 2006/03/17 19:17:13 moritz Exp $";
42 #endif
43 #endif /* not lint */
44
45 /*
46  * Routines for calling up on a Ventel Modem
47  * The Ventel is expected to be strapped for local echo (just like uucp)
48  */
49 #include "tip.h"
50 #include <termios.h>
51 #include <sys/ioctl.h>
52
53 #define MAXRETRY        5
54
55 static  int dialtimeout = 0;
56 static  jmp_buf timeoutbuf;
57
58 static void     echo(char *);
59 static void     sigALRM(int);
60 static int      gobble(char, char *);
61 static int      vensync(int);
62
63 /*
64  * some sleep calls have been replaced by this macro
65  * because some ventel modems require two <cr>s in less than
66  * a second in order to 'wake up'... yes, it is dirty...
67  */
68 #define delay(num,denom) busyloop(CPUSPEED*num/denom)
69 #define CPUSPEED 1000000        /* VAX 780 is 1MIPS */
70 #define DELAY(n) do { long N = (n); while (--N > 0); } while (0)
71 #define busyloop(n) do { DELAY(n); } while (0)
72
73 int
74 ven_dialer(char *num, char *acu)
75 {
76         char *cp;
77         int connected = 0;
78         char *msg, line[80];
79         struct termios  cntrl;
80
81         /*
82          * Get in synch with a couple of carriage returns
83          */
84         if (!vensync(FD)) {
85                 printf("can't synchronize with ventel\n");
86 #ifdef ACULOG
87                 logent(value(HOST), num, "ventel", "can't synch up");
88 #endif
89                 return (0);
90         }
91         if (boolean(value(VERBOSE)))
92                 printf("\ndialing...");
93         fflush(stdout);
94         tcgetattr(FD, &cntrl);
95         cntrl.c_cflag |= HUPCL;
96         tcsetattr(FD, TCSANOW, &cntrl);
97         echo("#k$\r$\n$D$I$A$L$:$ ");
98         for (cp = num; *cp; cp++) {
99                 delay(1, 10);
100                 write(FD, cp, 1);
101         }
102         delay(1, 10);
103         write(FD, "\r", 1);
104         gobble('\n', line);
105         if (gobble('\n', line))
106                 connected = gobble('!', line);
107         tcflush(FD, TCIOFLUSH);
108 #ifdef ACULOG
109         if (dialtimeout) {
110                 (void)snprintf(line, sizeof line, "%ld second dial timeout",
111                         number(value(DIALTIMEOUT)));
112                 logent(value(HOST), num, "ventel", line);
113         }
114 #endif
115         if (dialtimeout)
116                 ven_disconnect();       /* insurance */
117         if (connected || dialtimeout || !boolean(value(VERBOSE)))
118                 return (connected);
119         /* call failed, parse response for user */
120         cp = strchr(line, '\r');
121         if (cp)
122                 *cp = '\0';
123         for (cp = line; (cp = strchr(cp, ' ')) != NULL; cp++)
124                 if (cp[1] == ' ')
125                         break;
126         if (cp) {
127                 while (*cp == ' ')
128                         cp++;
129                 msg = cp;
130                 while (*cp) {
131                         if (isupper(*cp))
132                                 *cp = tolower(*cp);
133                         cp++;
134                 }
135                 printf("%s...", msg);
136         }
137         return (connected);
138 }
139
140 void
141 ven_disconnect(void)
142 {
143         close(FD);
144 }
145
146 void
147 ven_abort(void)
148 {
149         write(FD, "\03", 1);
150         close(FD);
151 }
152
153 static void
154 echo(char *s)
155 {
156         char c;
157
158         while ((c = *s++) != '\0')
159                 switch (c) {
160                 case '$':
161                         read(FD, &c, 1);
162                         s++;
163                         break;
164
165                 case '#':
166                         c = *s++;
167                         write(FD, &c, 1);
168                         break;
169
170                 default:
171                         write(FD, &c, 1);
172                         read(FD, &c, 1);
173                 }
174 }
175
176 /*ARGSUSED*/
177 static void
178 sigALRM(int signo)
179 {
180         printf("\07timeout waiting for reply\n");
181         dialtimeout = 1;
182         longjmp(timeoutbuf, 1);
183 }
184
185 static int
186 gobble(char match, char response[])
187 {
188         char *cp = response;
189         sig_t f;
190         char c;
191
192         f = signal(SIGALRM, sigALRM);
193         dialtimeout = 0;
194         do {
195                 if (setjmp(timeoutbuf)) {
196                         signal(SIGALRM, f);
197                         *cp = '\0';
198                         return (0);
199                 }
200                 alarm(number(value(DIALTIMEOUT)));
201                 read(FD, cp, 1);
202                 alarm(0);
203                 c = (*cp++ &= 0177);
204 #ifdef notdef
205                 if (boolean(value(VERBOSE)))
206                         putchar(c);
207 #endif
208         } while (c != '\n' && c != match);
209         signal(SIGALRM, SIG_DFL);
210         *cp = '\0';
211         return (c == match);
212 }
213
214 #define min(a,b)        ((a)>(b)?(b):(a))
215 /*
216  * This convoluted piece of code attempts to get
217  * the ventel in sync.  If you don't have FIONREAD
218  * there are gory ways to simulate this.
219  */
220 static int
221 vensync(int fd)
222 {
223         int already = 0, nread;
224         char buf[60];
225
226         /*
227          * Toggle DTR to force anyone off that might have left
228          * the modem connected, and insure a consistent state
229          * to start from.
230          *
231          * If you don't have the ioctl calls to diddle directly
232          * with DTR, you can always try setting the baud rate to 0.
233          */
234         ioctl(FD, TIOCCDTR, 0);
235         sleep(1);
236         ioctl(FD, TIOCSDTR, 0);
237         while (already < MAXRETRY) {
238                 /*
239                  * After reseting the modem, send it two \r's to
240                  * autobaud on. Make sure to delay between them
241                  * so the modem can frame the incoming characters.
242                  */
243                 write(fd, "\r", 1);
244                 delay(1,10);
245                 write(fd, "\r", 1);
246                 sleep(2);
247                 if (ioctl(fd, FIONREAD, (caddr_t)&nread) < 0) {
248                         perror("tip: ioctl");
249                         continue;
250                 }
251                 while (nread > 0) {
252                         read(fd, buf, min(nread, 60));
253                         if ((buf[nread - 1] & 0177) == '$')
254                                 return (1);
255                         nread -= min(nread, 60);
256                 }
257                 sleep(1);
258                 already++;
259         }
260         return (0);
261 }