xref: /original-bsd/usr.bin/tip/aculib/ventel.c (revision 048a349a)
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 are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #ifndef lint
19 static char sccsid[] = "@(#)ventel.c	5.2 (Berkeley) 09/13/88";
20 #endif /* not lint */
21 
22 /*
23  * Routines for calling up on a Ventel Modem
24  * The Ventel is expected to be strapped for local echo (just like uucp)
25  */
26 #include "tip.h"
27 
28 #define	MAXRETRY	5
29 
30 static	int sigALRM();
31 static	int timeout = 0;
32 static	jmp_buf timeoutbuf;
33 
34 /*
35  * some sleep calls have been replaced by this macro
36  * because some ventel modems require two <cr>s in less than
37  * a second in order to 'wake up'... yes, it is dirty...
38  */
39 #define delay(num,denom) busyloop(CPUSPEED*num/denom)
40 #define CPUSPEED 1000000	/* VAX 780 is 1MIPS */
41 #define	DELAY(n)	{ register long N = (n); while (--N > 0); }
42 busyloop(n) { DELAY(n); }
43 
44 ven_dialer(num, acu)
45 	register char *num;
46 	char *acu;
47 {
48 	register char *cp;
49 	register int connected = 0;
50 	char *msg, *index(), line[80];
51 
52 	/*
53 	 * Get in synch with a couple of carriage returns
54 	 */
55 	if (!vensync(FD)) {
56 		printf("can't synchronize with ventel\n");
57 #ifdef ACULOG
58 		logent(value(HOST), num, "ventel", "can't synch up");
59 #endif
60 		return (0);
61 	}
62 	if (boolean(value(VERBOSE)))
63 		printf("\ndialing...");
64 	fflush(stdout);
65 	ioctl(FD, TIOCHPCL, 0);
66 	echo("#k$\r$\n$D$I$A$L$:$ ");
67 	for (cp = num; *cp; cp++) {
68 		delay(1, 10);
69 		write(FD, cp, 1);
70 	}
71 	delay(1, 10);
72 	write(FD, "\r", 1);
73 	gobble('\n', line);
74 	if (gobble('\n', line))
75 		connected = gobble('!', line);
76 	ioctl(FD, TIOCFLUSH);
77 #ifdef ACULOG
78 	if (timeout) {
79 		sprintf(line, "%d second dial timeout",
80 			number(value(DIALTIMEOUT)));
81 		logent(value(HOST), num, "ventel", line);
82 	}
83 #endif
84 	if (timeout)
85 		ven_disconnect();	/* insurance */
86 	if (connected || timeout || !boolean(value(VERBOSE)))
87 		return (connected);
88 	/* call failed, parse response for user */
89 	cp = index(line, '\r');
90 	if (cp)
91 		*cp = '\0';
92 	for (cp = line; cp = index(cp, ' '); cp++)
93 		if (cp[1] == ' ')
94 			break;
95 	if (cp) {
96 		while (*cp == ' ')
97 			cp++;
98 		msg = cp;
99 		while (*cp) {
100 			if (isupper(*cp))
101 				*cp = tolower(*cp);
102 			cp++;
103 		}
104 		printf("%s...", msg);
105 	}
106 	return (connected);
107 }
108 
109 ven_disconnect()
110 {
111 
112 	close(FD);
113 }
114 
115 ven_abort()
116 {
117 
118 	write(FD, "\03", 1);
119 	close(FD);
120 }
121 
122 static int
123 echo(s)
124 	register char *s;
125 {
126 	char c;
127 
128 	while (c = *s++) switch (c) {
129 
130 	case '$':
131 		read(FD, &c, 1);
132 		s++;
133 		break;
134 
135 	case '#':
136 		c = *s++;
137 		write(FD, &c, 1);
138 		break;
139 
140 	default:
141 		write(FD, &c, 1);
142 		read(FD, &c, 1);
143 	}
144 }
145 
146 static int
147 sigALRM()
148 {
149 
150 	printf("\07timeout waiting for reply\n");
151 	timeout = 1;
152 	longjmp(timeoutbuf, 1);
153 }
154 
155 static int
156 gobble(match, response)
157 	register char match;
158 	char response[];
159 {
160 	register char *cp = response;
161 	char c;
162 	int (*f)();
163 
164 	signal(SIGALRM, sigALRM);
165 	timeout = 0;
166 	do {
167 		if (setjmp(timeoutbuf)) {
168 			signal(SIGALRM, f);
169 			*cp = '\0';
170 			return (0);
171 		}
172 		alarm(number(value(DIALTIMEOUT)));
173 		read(FD, cp, 1);
174 		alarm(0);
175 		c = (*cp++ &= 0177);
176 #ifdef notdef
177 		if (boolean(value(VERBOSE)))
178 			putchar(c);
179 #endif
180 	} while (c != '\n' && c != match);
181 	signal(SIGALRM, SIG_DFL);
182 	*cp = '\0';
183 	return (c == match);
184 }
185 
186 #define min(a,b)	((a)>(b)?(b):(a))
187 /*
188  * This convoluted piece of code attempts to get
189  * the ventel in sync.  If you don't have FIONREAD
190  * there are gory ways to simulate this.
191  */
192 static int
193 vensync(fd)
194 {
195 	int already = 0, nread;
196 	char buf[60];
197 
198 	/*
199 	 * Toggle DTR to force anyone off that might have left
200 	 * the modem connected, and insure a consistent state
201 	 * to start from.
202 	 *
203 	 * If you don't have the ioctl calls to diddle directly
204 	 * with DTR, you can always try setting the baud rate to 0.
205 	 */
206 	ioctl(FD, TIOCCDTR, 0);
207 	sleep(1);
208 	ioctl(FD, TIOCSDTR, 0);
209 	while (already < MAXRETRY) {
210 		/*
211 		 * After reseting the modem, send it two \r's to
212 		 * autobaud on. Make sure to delay between them
213 		 * so the modem can frame the incoming characters.
214 		 */
215 		write(fd, "\r", 1);
216 		delay(1,10);
217 		write(fd, "\r", 1);
218 		sleep(2);
219 		if (ioctl(fd, FIONREAD, (caddr_t)&nread) < 0) {
220 			perror("tip: ioctl");
221 			continue;
222 		}
223 		while (nread > 0) {
224 			read(fd, buf, min(nread, 60));
225 			if ((buf[nread - 1] & 0177) == '$')
226 				return (1);
227 			nread -= min(nread, 60);
228 		}
229 		sleep(1);
230 		already++;
231 	}
232 	return (0);
233 }
234 
235