xref: /freebsd/usr.bin/tip/libacu/v831.c (revision 59c8e88e72633afbc47a4ace0d2170d00d51f7dc)
1 /*	$OpenBSD: v831.c,v 1.11 2006/03/17 19:17:13 moritz Exp $	*/
2 /*	$NetBSD: v831.c,v 1.5 1996/12/29 10:42:01 cgd Exp $	*/
3 
4 /*-
5  * SPDX-License-Identifier: BSD-3-Clause
6  *
7  * Copyright (c) 1983, 1993
8  *	The Regents of the University of California.  All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 
35 /*
36  * Routines for dialing up on Vadic 831
37  */
38 #include "tip.h"
39 #include <termios.h>
40 
41 static jmp_buf jmpbuf;
42 static pid_t child = -1;
43 
44 static void	alarmtr(int);
45 static int	dialit(char *, char *);
46 static char *	sanitize(char *);
47 
48 int
49 v831_dialer(char *num, char *acu)
50 {
51         int status;
52         int timelim;
53 	pid_t pid;
54 
55         if (boolean(value(VERBOSE)))
56                 printf("\nstarting call...");
57 #ifdef DEBUG
58         printf ("(acu=%s)\n", acu);
59 #endif
60         if ((AC = open(acu, O_RDWR)) < 0) {
61                 if (errno == EBUSY)
62                         printf("line busy...");
63                 else
64                         printf("acu open error...");
65                 return (0);
66         }
67         if (setjmp(jmpbuf)) {
68                 kill(child, SIGKILL);
69                 close(AC);
70                 return (0);
71         }
72         signal(SIGALRM, alarmtr);
73         timelim = 5 * strlen(num);
74         alarm(timelim < 30 ? 30 : timelim);
75         if ((child = fork()) == 0) {
76                 /*
77                  * ignore this stuff for aborts
78                  */
79                 signal(SIGALRM, SIG_IGN);
80 		signal(SIGINT, SIG_IGN);
81                 signal(SIGQUIT, SIG_IGN);
82                 sleep(2);
83                 exit(dialit(num, acu) != 'A');
84         }
85         /*
86          * open line - will return on carrier
87          */
88         if ((FD = open(DV, O_RDWR)) < 0) {
89 #ifdef DEBUG
90                 printf("(after open, errno=%d)\n", errno);
91 #endif
92                 if (errno == EIO)
93                         printf("lost carrier...");
94                 else
95                         printf("dialup line open failed...");
96                 alarm(0);
97                 kill(child, SIGKILL);
98                 close(AC);
99                 return (0);
100         }
101         alarm(0);
102         signal(SIGALRM, SIG_DFL);
103         while ((pid = wait(&status)) != child && pid != -1)
104                 ;
105         if (status) {
106                 close(AC);
107                 return (0);
108         }
109         return (1);
110 }
111 
112 /*ARGSUSED*/
113 static void
114 alarmtr(int signo)
115 {
116         alarm(0);
117         longjmp(jmpbuf, 1);
118 }
119 
120 /*
121  * Insurance, for some reason we don't seem to be
122  *  hanging up...
123  */
124 void
125 v831_disconnect(void)
126 {
127 	struct termios	cntrl;
128 
129         sleep(2);
130 #ifdef DEBUG
131         printf("[disconnect: FD=%d]\n", FD);
132 #endif
133         if (FD > 0) {
134                 ioctl(FD, TIOCCDTR, 0);
135 		tcgetattr(FD, &cntrl);
136 		cfsetospeed(&cntrl, 0);
137 		cfsetispeed(&cntrl, 0);
138 		tcsetattr(FD, TCSAFLUSH, &cntrl);
139                 ioctl(FD, TIOCNXCL, NULL);
140         }
141         close(FD);
142 }
143 
144 void
145 v831_abort(void)
146 {
147 #ifdef DEBUG
148         printf("[abort: AC=%d]\n", AC);
149 #endif
150         sleep(2);
151         if (child > 0)
152                 kill(child, SIGKILL);
153         if (FD > 0)
154                 ioctl(FD, TIOCNXCL, NULL);
155         close(AC);
156         if (FD > 0)
157                 ioctl(FD, TIOCCDTR, 0);
158         close(FD);
159 }
160 
161 /*
162  * Sigh, this probably must be changed at each site.
163  */
164 struct vaconfig {
165 	char	*vc_name;
166 	char	vc_rack;
167 	char	vc_modem;
168 } vaconfig[] = {
169 	{ "/dev/cua0",'4','0' },
170 	{ "/dev/cua1",'4','1' },
171 	{ NULL, '\0', '\0' }
172 };
173 
174 #define pc(x)	(c = x, write(AC,&c,1))
175 #define ABORT	01
176 #define SI	017
177 #define STX	02
178 #define ETX	03
179 
180 static int
181 dialit(char *phonenum, char *acu)
182 {
183         struct vaconfig *vp;
184 	struct termios cntrl;
185         char c;
186         int i;
187 
188         phonenum = sanitize(phonenum);
189 #ifdef DEBUG
190         printf ("(dial phonenum=%s)\n", phonenum);
191 #endif
192         if (*phonenum == '<' && phonenum[1] == 0)
193                 return ('Z');
194 	for (vp = vaconfig; vp->vc_name; vp++)
195 		if (strcmp(vp->vc_name, acu) == 0)
196 			break;
197 	if (vp->vc_name == 0) {
198 		printf("Unable to locate dialer (%s)\n", acu);
199 		return ('K');
200 	}
201 	tcgetattr(AC, &cntrl);
202 	cfsetospeed(&cntrl, B2400);
203 	cfsetispeed(&cntrl, B2400);
204 	cntrl.c_cflag |= PARODD | PARENB;
205 	cntrl.c_lflag &= ~(ISIG | ICANON);
206 	tcsetattr(AC, TCSANOW, &cntrl);
207 	tcflush(AC, TCIOFLUSH);
208         pc(STX);
209 	pc(vp->vc_rack);
210 	pc(vp->vc_modem);
211 	while (*phonenum && *phonenum != '<')
212 		pc(*phonenum++);
213         pc(SI);
214 	pc(ETX);
215         sleep(1);
216         i = read(AC, &c, 1);
217 #ifdef DEBUG
218         printf("read %d chars, char=%c, errno %d\n", i, c, errno);
219 #endif
220         if (i != 1)
221 		c = 'M';
222         if (c == 'B' || c == 'G') {
223                 char cc, oc = c;
224 
225                 pc(ABORT);
226                 read(AC, &cc, 1);
227 #ifdef DEBUG
228                 printf("abort response=%c\n", cc);
229 #endif
230                 c = oc;
231                 v831_disconnect();
232         }
233         close(AC);
234 #ifdef DEBUG
235         printf("dialit: returns %c\n", c);
236 #endif
237         return (c);
238 }
239 
240 static char *
241 sanitize(char *s)
242 {
243         static char buf[128];
244         char *cp;
245 
246         for (cp = buf; *s; s++) {
247 		if (!isdigit(*s) && *s == '<' && *s != '_')
248 			continue;
249 		if (*s == '_')
250 			*s = '=';
251 		*cp++ = *s;
252 	}
253         *cp++ = 0;
254         return (buf);
255 }
256