1/*
2 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
3 * Use is subject to license terms.
4 */
5
6/*
7 * Copyright (c) 1983 Regents of the University of California.
8 * All rights reserved. The Berkeley software License Agreement
9 * specifies the terms and conditions for redistribution.
10 */
11
12#pragma ident	"%Z%%M%	%I%	%E% SMI"
13
14/*
15 * Routines for dialing up on Vadic 831
16 */
17#include <sys/time.h>
18
19#include "tip.h"
20
21static char	dialit(char *, char *);
22static char	*sanitize(char *);
23static void	alarmtr(void);
24
25static sigjmp_buf	jmpbuf;
26static int	child = -1;
27
28int
29v831_dialer(char *num, char *acu)
30{
31	int status, pid;
32	int timelim;
33
34	if (boolean(value(VERBOSE)))
35		(void) printf("\nstarting call...");
36#ifdef DEBUG
37	(void) printf("(acu=%s)\n", acu);
38#endif
39	if ((AC = open(acu, O_RDWR)) < 0) {
40		if (errno == EBUSY)
41			(void) printf("line busy...");
42		else
43			(void) printf("acu open error...");
44		return (0);
45	}
46	if (sigsetjmp(jmpbuf, 1)) {
47		(void) kill(child, SIGKILL);
48		(void) close(AC);
49		return (0);
50	}
51	(void) signal(SIGALRM, (sig_handler_t)alarmtr);
52	timelim = 5 * strlen(num);
53	(void) alarm(timelim < 30 ? 30 : timelim);
54	if ((child = fork()) == 0) {
55		/*
56		 * ignore this stuff for aborts
57		 */
58		(void) signal(SIGALRM, SIG_IGN);
59		(void) signal(SIGINT, SIG_IGN);
60		(void) signal(SIGQUIT, SIG_IGN);
61		(void) sleep(2);
62		exit(dialit(num, acu) != 'A');
63	}
64	/*
65	 * open line - will return on carrier
66	 */
67	if ((FD = open(DV, O_RDWR)) < 0) {
68#ifdef DEBUG
69		(void) printf("(after open, errno=%d)\n", errno);
70#endif
71		if (errno == EIO)
72			(void) printf("lost carrier...");
73		else
74			(void) printf("dialup line open failed...");
75		(void) alarm(0);
76		(void) kill(child, SIGKILL);
77		(void) close(AC);
78		return (0);
79	}
80	(void) alarm(0);
81	(void) signal(SIGALRM, SIG_DFL);
82	while ((pid = wait(&status)) != child && pid != -1)
83		;
84	if (status) {
85		(void) close(AC);
86		return (0);
87	}
88	return (1);
89}
90
91static void
92alarmtr(void)
93{
94
95	(void) alarm(0);
96	siglongjmp(jmpbuf, 1);
97}
98
99/*
100 * Insurance, for some reason we don't seem to be
101 *  hanging up...
102 */
103void
104v831_disconnect(void)
105{
106	struct termios cntrl;
107	int dtr = TIOCM_DTR;
108
109	(void) sleep(2);
110#ifdef DEBUG
111	printf("[disconnect: FD=%d]\n", FD);
112#endif
113	if (FD > 0) {
114		(void) ioctl(FD, TIOCMBIC, &dtr);
115		(void) ioctl(FD, TCGETS, &cntrl);
116		(void) cfsetospeed(&cntrl, B0);
117		cntrl.c_cflag &= ~XCLUDE;
118		(void) ioctl(FD, TCSETSF, &cntrl);
119	}
120	(void) close(FD);
121}
122
123void
124v831_abort(void)
125{
126	int dtr = TIOCM_DTR;
127	struct termios buf;
128
129#ifdef DEBUG
130	(void) printf("[abort: AC=%d]\n", AC);
131#endif
132	(void) sleep(2);
133	if (child > 0)
134		(void) kill(child, SIGKILL);
135	if (AC > 0) {
136		(void) ioctl(FD, TCGETS, &buf);
137		buf.c_cflag &= ~XCLUDE;
138		(void) ioctl(FD, TCSETSF, &buf);
139		(void) close(AC);
140	}
141	if (FD > 0)
142		(void) ioctl(FD, TIOCMBIC, &dtr);
143	(void) close(FD);
144}
145
146/*
147 * Sigh, this probably must be changed at each site.
148 */
149struct vaconfig {
150	char	*vc_name;
151	char	vc_rack;
152	char	vc_modem;
153} vaconfig[] = {
154	{ "/dev/cua0", '4', '0' },
155	{ "/dev/cua1", '4', '1' },
156	{ 0 }
157};
158
159#define	pc(x)	(c = x, (void) write(AC, &c, 1))
160#define	ABORT	01
161#define	SI	017
162#define	STX	02
163#define	ETX	03
164
165static char
166dialit(char *phonenum, char *acu)
167{
168	struct vaconfig *vp;
169	struct termios cntrl;
170	char c;
171	int i;
172
173	phonenum = sanitize(phonenum);
174#ifdef DEBUG
175	(void) printf("(dial phonenum=%s)\n", phonenum);
176#endif
177	if (*phonenum == '<' && phonenum[1] == 0)
178		return ('Z');
179	for (vp = vaconfig; vp->vc_name; vp++)
180		if (strcmp(vp->vc_name, acu) == 0)
181			break;
182	if (vp->vc_name == 0) {
183		(void) printf("Unable to locate dialer (%s)\n", acu);
184		return ('K');
185	}
186	(void) ioctl(AC, TCGETS, &cntrl);
187	(void) cfsetospeed(&cntrl, B0);
188	(void) cfsetispeed(&cntrl, B0);
189	cntrl.c_cflag &= ~(CSIZE|PARENB|PARODD);
190	(void) cfsetospeed(&cntrl, B2400);
191	cntrl.c_cflag |= CS8;
192	cntrl.c_iflag &= IXOFF|IXANY;
193	cntrl.c_lflag &= ~(ICANON|ISIG);
194	cntrl.c_oflag = 0;
195	cntrl.c_cc[VMIN] = cntrl.c_cc[VTIME] = 0;
196	(void) ioctl(AC, TCSETSF, &cntrl);
197	(void) ioctl(AC, TCFLSH, TCOFLUSH);
198	pc(STX);
199	pc(vp->vc_rack);
200	pc(vp->vc_modem);
201	while (*phonenum && *phonenum != '<')
202		pc(*phonenum++);
203	pc(SI);
204	pc(ETX);
205	(void) sleep(1);
206	i = read(AC, &c, 1);
207#ifdef DEBUG
208	printf("read %d chars, char=%c, errno %d\n", i, c, errno);
209#endif
210	if (i != 1)
211		c = 'M';
212	if (c == 'B' || c == 'G') {
213		char cc, oc = c;
214
215		pc(ABORT);
216		(void) read(AC, &cc, 1);
217#ifdef DEBUG
218		(void) printf("abort response=%c\n", cc);
219#endif
220		c = oc;
221		v831_disconnect();
222	}
223	(void) close(AC);
224#ifdef DEBUG
225	(void) printf("dialit: returns %c\n", c);
226#endif
227	return (c);
228}
229
230static char *
231sanitize(char *s)
232{
233	static char buf[128];
234	char *cp;
235
236	for (cp = buf; *s; s++) {
237		if (!isdigit(*s) && *s == '<' && *s != '_')
238			continue;
239		if (*s == '_')
240			*s = '=';
241		*cp++ = *s;
242	}
243	*cp++ = 0;
244	return (buf);
245}
246