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