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