xref: /illumos-gate/usr/src/cmd/tip/aculib/ventel.c (revision 95efa359b507db290a2484b8f615822b1e06096f)
1 /*
2  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 /*
7  * Copyright (c) 1983 Regents of the University of California.
8  * All rights reserved. The Berkeley software License Agreement
9  * specifies the terms and conditions for redistribution.
10  */
11 
12 #pragma ident	"%Z%%M%	%I%	%E% SMI"
13 
14 /*
15  * Routines for calling up on a Ventel Modem
16  * Define VENNOECHO if the Ventel is strapped for "no echo".
17  */
18 #include "tip.h"
19 
20 #define	MAXRETRY	5
21 
22 static int	vensync(int);
23 static int	gobble(char);
24 static void	echo(char *);
25 static void	sigALRM(void);
26 static int	timeout = 0;
27 static sigjmp_buf	timeoutbuf;
28 
29 void	ven_disconnect(void);
30 
31 /* ARGSUSED */
32 int
33 ven_dialer(char *num, char *acu)
34 {
35 	char *cp;
36 	int connected = 0;
37 	struct termios buf;
38 #ifdef ACULOG
39 	char line[80];
40 #endif
41 	/*
42 	 * Get in synch with a couple of carriage returns
43 	 */
44 	if (!vensync(FD)) {
45 		(void) printf("can't synchronize with ventel\n");
46 #ifdef ACULOG
47 		logent(value(HOST), num, "ventel", "can't synch up");
48 #endif
49 		return (0);
50 	}
51 	if (boolean(value(VERBOSE)))
52 		(void) printf("\ndialing...");
53 	(void) fflush(stdout);
54 	(void) ioctl(FD, TCGETS, &buf);
55 	buf.c_cflag |= HUPCL;
56 	(void) ioctl(FD, TCSETSF, &buf);
57 #ifdef VENNOECHO
58 	echo("#k$\r$\n$D$I$A$L$:$ ");
59 	for (cp = num; *cp; cp++) {
60 		(void) sleep(1);
61 		(void) write(FD, cp, 1);
62 	}
63 	echo("\r$\n");
64 #else
65 	echo("k$\r$\n$D$I$A$L$:$ <");
66 	for (cp = num; *cp; cp++) {
67 		char c;
68 
69 		(void) sleep(1);
70 		(void) write(FD, cp, 1);
71 		(void) read(FD, &c, 1);
72 	}
73 	echo(">\r$\n");
74 #endif
75 	if (gobble('\n'))
76 		connected = gobble('!');
77 	(void) ioctl(FD, TCFLSH, TCIOFLUSH);
78 #ifdef ACULOG
79 	if (timeout) {
80 		(void) sprintf(line, "%d second dial timeout",
81 		    number(value(DIALTIMEOUT)));
82 		logent(value(HOST), num, "ventel", line);
83 	}
84 #endif
85 	if (timeout)
86 		ven_disconnect();	/* insurance */
87 	return (connected);
88 }
89 
90 void
91 ven_disconnect(void)
92 {
93 
94 	(void) close(FD);
95 }
96 
97 void
98 ven_abort(void)
99 {
100 
101 	(void) write(FD, "\03", 1);
102 	(void) close(FD);
103 }
104 
105 static void
106 echo(char *s)
107 {
108 	char c;
109 
110 	while (c = *s++) {
111 		switch (c) {
112 		case '$':
113 			(void) read(FD, &c, 1);
114 			s++;
115 			break;
116 
117 		case '#':
118 			c = *s++;
119 			(void) write(FD, &c, 1);
120 			break;
121 
122 		default:
123 			(void) write(FD, &c, 1);
124 			(void) read(FD, &c, 1);
125 		}
126 	}
127 }
128 
129 static void
130 sigALRM(void)
131 {
132 
133 	(void) printf("\07timeout waiting for reply\n");
134 	timeout = 1;
135 	siglongjmp(timeoutbuf, 1);
136 }
137 
138 static int
139 gobble(char match)
140 {
141 	char c;
142 	sig_handler_t f;
143 
144 	f = signal(SIGALRM, (sig_handler_t)sigALRM);
145 	timeout = 0;
146 	do {
147 		if (sigsetjmp(timeoutbuf, 1)) {
148 			(void) signal(SIGALRM, f);
149 			return (0);
150 		}
151 		(void) alarm(number(value(DIALTIMEOUT)));
152 		(void) read(FD, &c, 1);
153 		(void) alarm(0);
154 		c &= 0177;
155 #ifdef notdef
156 		if (boolean(value(VERBOSE)))
157 			(void) putchar(c);
158 #endif
159 	} while (c != '\n' && c != match);
160 	(void) signal(SIGALRM, SIG_DFL);
161 	return (c == match);
162 }
163 
164 #define	min(a, b)	(((a) > (b)) ? (b) : (a))
165 /*
166  * This convoluted piece of code attempts to get
167  * the ventel in sync.  If you don't have FIONREAD
168  * there are gory ways to simulate this.
169  */
170 static int
171 vensync(int fd)
172 {
173 	int already = 0, nread;
174 	char buf[60];
175 	int dtr = TIOCM_DTR;
176 
177 	/*
178 	 * Toggle DTR to force anyone off that might have left
179 	 * the modem connected, and insure a consistent state
180 	 * to start from.
181 	 *
182 	 * If you don't have the ioctl calls to diddle directly
183 	 * with DTR, you can always try setting the baud rate to 0.
184 	 */
185 	(void) ioctl(FD, TIOCMBIC, &dtr);
186 	(void) sleep(2);
187 	(void) ioctl(FD, TIOCMBIS, &dtr);
188 	while (already < MAXRETRY) {
189 		/*
190 		 * After reseting the modem, send it two \r's to
191 		 * autobaud on. Make sure to delay between them
192 		 * so the modem can frame the incoming characters.
193 		 */
194 		(void) write(fd, "\r", 1);
195 #ifdef VMUNIX
196 		{
197 #include <sys/time.h>
198 		struct timeval tv = {0, 500000};
199 
200 		(void) select(0, 0, 0, 0, &tv);
201 		}
202 #else
203 		(void) sleep(1);
204 #endif
205 		(void) write(fd, "\r", 1);
206 		(void) sleep(3);
207 		if (ioctl(fd, FIONREAD, (caddr_t)&nread) < 0) {
208 			perror("tip: ioctl");
209 			continue;
210 		}
211 		while (nread > 0) {
212 			(void) read(fd, buf, min(nread, 60));
213 			if ((buf[nread - 1] & 0177) == '$')
214 				return (1);
215 			nread -= min(nread, 60);
216 		}
217 		(void) sleep(1);
218 		already++;
219 	}
220 	return (0);
221 }
222