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