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