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