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