xref: /illumos-gate/usr/src/cmd/tip/aculib/biz31.c (revision 7a6d80f1660abd4755c68cbd094d4a914681d26e)
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 #include "tip.h"
13 
14 #define	MAXRETRY	3		/* sync up retry count */
15 #define	DISCONNECT_CMD	"\21\25\11\24"	/* disconnection string */
16 
17 static int	detect(char *);
18 static int	bizsync(int);
19 static void	echo(char *);
20 static void	flush(char *);
21 static void	sigALRM(void);
22 static int	timeout = 0;
23 static sigjmp_buf	timeoutbuf;
24 
25 void	biz31_disconnect(void);
26 
27 /*
28  * Dial up on a BIZCOMP Model 1031 with either
29  * 	tone dialing (mod = "f")
30  *	pulse dialing (mod = "w")
31  */
32 static int
33 biz_dialer(char *num, char *mod)
34 {
35 	int connected = 0;
36 
37 	if (!bizsync(FD)) {
38 		logent(value(HOST), "", "biz", "out of sync");
39 		(void) printf("bizcomp out of sync\n");
40 		delock(uucplock);
41 		exit(0);
42 	}
43 	if (boolean(value(VERBOSE)))
44 		(void) printf("\nstarting call...");
45 	echo("#\rk$\r$\n");			/* disable auto-answer */
46 	echo("$>$.$ #\r");			/* tone/pulse dialing */
47 	echo(mod);
48 	echo("$\r$\n");
49 	echo("$>$.$ #\re$ ");			/* disconnection sequence */
50 	echo(DISCONNECT_CMD);
51 	echo("\r$\n$\r$\n");
52 	echo("$>$.$ #\rr$ ");			/* repeat dial */
53 	echo(num);
54 	echo("\r$\n");
55 	if (boolean(value(VERBOSE)))
56 		(void) printf("ringing...");
57 	/*
58 	 * The reply from the BIZCOMP should be:
59 	 *	`^G NO CONNECTION\r\n^G\r\n'	failure
60 	 *	` CONNECTION\r\n^G'		success
61 	 */
62 	connected = detect(" ");
63 #ifdef ACULOG
64 	if (timeout) {
65 		char line[80];
66 
67 		(void) sprintf(line, "%d second dial timeout",
68 		    number(value(DIALTIMEOUT)));
69 		logent(value(HOST), num, "biz", line);
70 	}
71 #endif
72 	if (!connected)
73 		flush(" NO CONNECTION\r\n\07\r\n");
74 	else
75 		flush("CONNECTION\r\n\07");
76 	if (timeout)
77 		biz31_disconnect();	/* insurance */
78 	return (connected);
79 }
80 
81 /* ARGSUSED */
82 int
83 biz31w_dialer(char *num, char *acu)
84 {
85 
86 	return (biz_dialer(num, "w"));
87 }
88 
89 /* ARGSUSED */
90 int
91 biz31f_dialer(char *num, char *acu)
92 {
93 
94 	return (biz_dialer(num, "f"));
95 }
96 
97 void
98 biz31_disconnect(void)
99 {
100 
101 	(void) write(FD, DISCONNECT_CMD, 4);
102 	(void) sleep(2);
103 	(void) ioctl(FD, TCFLSH, TCOFLUSH);
104 }
105 
106 void
107 biz31_abort(void)
108 {
109 
110 	(void) write(FD, "\33", 1);
111 }
112 
113 static void
114 echo(char *s)
115 {
116 	char c;
117 
118 	while (c = *s++) {
119 		switch (c) {
120 		case '$':
121 			(void) read(FD, &c, 1);
122 			s++;
123 			break;
124 
125 		case '#':
126 			c = *s++;
127 			(void) write(FD, &c, 1);
128 			break;
129 
130 		default:
131 			(void) write(FD, &c, 1);
132 			(void) read(FD, &c, 1);
133 		}
134 	}
135 }
136 
137 static void
138 sigALRM(void)
139 {
140 
141 	timeout = 1;
142 	siglongjmp(timeoutbuf, 1);
143 }
144 
145 static int
146 detect(char *s)
147 {
148 	char c;
149 	sig_handler_t f;
150 
151 	f = signal(SIGALRM, (sig_handler_t)sigALRM);
152 	timeout = 0;
153 	while (*s) {
154 		if (sigsetjmp(timeoutbuf, 1)) {
155 			(void) printf("\07timeout waiting for reply\n");
156 			biz31_abort();
157 			break;
158 		}
159 		(void) alarm(number(value(DIALTIMEOUT)));
160 		(void) read(FD, &c, 1);
161 		(void) alarm(0);
162 		if (c != *s++)
163 			break;
164 	}
165 	(void) signal(SIGALRM, f);
166 	return (timeout == 0);
167 }
168 
169 static void
170 flush(char *s)
171 {
172 	char c;
173 	sig_handler_t f;
174 
175 	f = signal(SIGALRM, (sig_handler_t)sigALRM);
176 	while (*s++) {
177 		if (sigsetjmp(timeoutbuf, 1))
178 			break;
179 		(void) alarm(10);
180 		(void) read(FD, &c, 1);
181 		(void) alarm(0);
182 	}
183 	(void) signal(SIGALRM, f);
184 	timeout = 0;			/* guard against disconnection */
185 }
186 
187 /*
188  * This convoluted piece of code attempts to get
189  *  the bizcomp in sync.  If you don't have the capacity or nread
190  *  call there are gory ways to simulate this.
191  */
192 static int
193 bizsync(int fd)
194 {
195 #ifdef FIOCAPACITY
196 	struct capacity b;
197 #define	chars(b)	((b).cp_nbytes)
198 #define	IOCTL	FIOCAPACITY
199 #endif
200 #ifdef FIONREAD
201 	long b;
202 #define	chars(b)	(b)
203 #define	IOCTL	FIONREAD
204 #endif
205 	int already = 0;
206 	char buf[10];
207 
208 retry:
209 	if (ioctl(fd, IOCTL, (caddr_t)&b) >= 0 && chars(b) > 0)
210 		(void) ioctl(fd, TCFLSH, TCIOFLUSH);
211 	(void) write(fd, "\rp>\r", 4);
212 	(void) sleep(1);
213 	if (ioctl(fd, IOCTL, (caddr_t)&b) >= 0) {
214 		if (chars(b) != 10) {
215 	nono:
216 			if (already > MAXRETRY)
217 				return (0);
218 			(void) write(fd, DISCONNECT_CMD, 4);
219 			(void) sleep(2);
220 			already++;
221 			goto retry;
222 		} else {
223 			(void) read(fd, buf, 10);
224 			if (strncmp(buf, "p >\r\n\r\n>", 8))
225 				goto nono;
226 		}
227 	}
228 	return (1);
229 }
230