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#include <sys/cdefs.h>
36__FBSDID("$FreeBSD$");
37
38#ifndef lint
39#if 0
40static char sccsid[] = "@(#)v831.c	8.1 (Berkeley) 6/6/93";
41static const char rcsid[] = "$OpenBSD: v831.c,v 1.11 2006/03/17 19:17:13 moritz Exp $";
42#endif
43#endif /* not lint */
44
45/*
46 * Routines for dialing up on Vadic 831
47 */
48#include "tip.h"
49#include <termios.h>
50
51static jmp_buf jmpbuf;
52static pid_t child = -1;
53
54static void	alarmtr(int);
55static int	dialit(char *, char *);
56static char *	sanitize(char *);
57
58int
59v831_dialer(char *num, char *acu)
60{
61        int status;
62        int timelim;
63	pid_t pid;
64
65        if (boolean(value(VERBOSE)))
66                printf("\nstarting call...");
67#ifdef DEBUG
68        printf ("(acu=%s)\n", acu);
69#endif
70        if ((AC = open(acu, O_RDWR)) < 0) {
71                if (errno == EBUSY)
72                        printf("line busy...");
73                else
74                        printf("acu open error...");
75                return (0);
76        }
77        if (setjmp(jmpbuf)) {
78                kill(child, SIGKILL);
79                close(AC);
80                return (0);
81        }
82        signal(SIGALRM, alarmtr);
83        timelim = 5 * strlen(num);
84        alarm(timelim < 30 ? 30 : timelim);
85        if ((child = fork()) == 0) {
86                /*
87                 * ignore this stuff for aborts
88                 */
89                signal(SIGALRM, SIG_IGN);
90		signal(SIGINT, SIG_IGN);
91                signal(SIGQUIT, SIG_IGN);
92                sleep(2);
93                exit(dialit(num, acu) != 'A');
94        }
95        /*
96         * open line - will return on carrier
97         */
98        if ((FD = open(DV, O_RDWR)) < 0) {
99#ifdef DEBUG
100                printf("(after open, errno=%d)\n", errno);
101#endif
102                if (errno == EIO)
103                        printf("lost carrier...");
104                else
105                        printf("dialup line open failed...");
106                alarm(0);
107                kill(child, SIGKILL);
108                close(AC);
109                return (0);
110        }
111        alarm(0);
112        signal(SIGALRM, SIG_DFL);
113        while ((pid = wait(&status)) != child && pid != -1)
114                ;
115        if (status) {
116                close(AC);
117                return (0);
118        }
119        return (1);
120}
121
122/*ARGSUSED*/
123static void
124alarmtr(int signo)
125{
126        alarm(0);
127        longjmp(jmpbuf, 1);
128}
129
130/*
131 * Insurance, for some reason we don't seem to be
132 *  hanging up...
133 */
134void
135v831_disconnect(void)
136{
137	struct termios	cntrl;
138
139        sleep(2);
140#ifdef DEBUG
141        printf("[disconnect: FD=%d]\n", FD);
142#endif
143        if (FD > 0) {
144                ioctl(FD, TIOCCDTR, 0);
145		tcgetattr(FD, &cntrl);
146		cfsetospeed(&cntrl, 0);
147		cfsetispeed(&cntrl, 0);
148		tcsetattr(FD, TCSAFLUSH, &cntrl);
149                ioctl(FD, TIOCNXCL, NULL);
150        }
151        close(FD);
152}
153
154void
155v831_abort(void)
156{
157#ifdef DEBUG
158        printf("[abort: AC=%d]\n", AC);
159#endif
160        sleep(2);
161        if (child > 0)
162                kill(child, SIGKILL);
163        if (FD > 0)
164                ioctl(FD, TIOCNXCL, NULL);
165        close(AC);
166        if (FD > 0)
167                ioctl(FD, TIOCCDTR, 0);
168        close(FD);
169}
170
171/*
172 * Sigh, this probably must be changed at each site.
173 */
174struct vaconfig {
175	char	*vc_name;
176	char	vc_rack;
177	char	vc_modem;
178} vaconfig[] = {
179	{ "/dev/cua0",'4','0' },
180	{ "/dev/cua1",'4','1' },
181	{ NULL, '\0', '\0' }
182};
183
184#define pc(x)	(c = x, write(AC,&c,1))
185#define ABORT	01
186#define SI	017
187#define STX	02
188#define ETX	03
189
190static int
191dialit(char *phonenum, char *acu)
192{
193        struct vaconfig *vp;
194	struct termios cntrl;
195        char c;
196        int i;
197
198        phonenum = sanitize(phonenum);
199#ifdef DEBUG
200        printf ("(dial phonenum=%s)\n", phonenum);
201#endif
202        if (*phonenum == '<' && phonenum[1] == 0)
203                return ('Z');
204	for (vp = vaconfig; vp->vc_name; vp++)
205		if (strcmp(vp->vc_name, acu) == 0)
206			break;
207	if (vp->vc_name == 0) {
208		printf("Unable to locate dialer (%s)\n", acu);
209		return ('K');
210	}
211	tcgetattr(AC, &cntrl);
212	cfsetospeed(&cntrl, B2400);
213	cfsetispeed(&cntrl, B2400);
214	cntrl.c_cflag |= PARODD | PARENB;
215	cntrl.c_lflag &= ~(ISIG | ICANON);
216	tcsetattr(AC, TCSANOW, &cntrl);
217	tcflush(AC, TCIOFLUSH);
218        pc(STX);
219	pc(vp->vc_rack);
220	pc(vp->vc_modem);
221	while (*phonenum && *phonenum != '<')
222		pc(*phonenum++);
223        pc(SI);
224	pc(ETX);
225        sleep(1);
226        i = read(AC, &c, 1);
227#ifdef DEBUG
228        printf("read %d chars, char=%c, errno %d\n", i, c, errno);
229#endif
230        if (i != 1)
231		c = 'M';
232        if (c == 'B' || c == 'G') {
233                char cc, oc = c;
234
235                pc(ABORT);
236                read(AC, &cc, 1);
237#ifdef DEBUG
238                printf("abort response=%c\n", cc);
239#endif
240                c = oc;
241                v831_disconnect();
242        }
243        close(AC);
244#ifdef DEBUG
245        printf("dialit: returns %c\n", c);
246#endif
247        return (c);
248}
249
250static char *
251sanitize(char *s)
252{
253        static char buf[128];
254        char *cp;
255
256        for (cp = buf; *s; s++) {
257		if (!isdigit(*s) && *s == '<' && *s != '_')
258			continue;
259		if (*s == '_')
260			*s = '=';
261		*cp++ = *s;
262	}
263        *cp++ = 0;
264        return (buf);
265}
266