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
41static jmp_buf jmpbuf;
42static pid_t child = -1;
43
44static void	alarmtr(int);
45static int	dialit(char *, char *);
46static char *	sanitize(char *);
47
48int
49v831_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*/
113static void
114alarmtr(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 */
124void
125v831_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
144void
145v831_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 */
164struct 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
180static int
181dialit(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
240static char *
241sanitize(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