xref: /csrg-svn/usr.bin/tip/aculib/courier.c (revision 27000)
1*27000Sdonn /*
2*27000Sdonn  * Copyright (c) 1986 Regents of the University of California.
3*27000Sdonn  * All rights reserved.  The Berkeley software License Agreement
4*27000Sdonn  * specifies the terms and conditions for redistribution.
5*27000Sdonn  */
6*27000Sdonn 
7*27000Sdonn #ifndef lint
8*27000Sdonn static char sccsid[] = "@(#)courier.c	5.1 (Berkeley) 04/03/86";
9*27000Sdonn #endif
10*27000Sdonn 
11*27000Sdonn #define write cour_write
12*27000Sdonn /*
13*27000Sdonn  * Routines for calling up on a Hayes Smartmodem
14*27000Sdonn  */
15*27000Sdonn #include "tip.h"
16*27000Sdonn #include <stdio.h>
17*27000Sdonn 
18*27000Sdonn #define	MAXRETRY	5
19*27000Sdonn 
20*27000Sdonn static	int sigALRM();
21*27000Sdonn static	int timeout = 0;
22*27000Sdonn static	jmp_buf timeoutbuf, intbuf;
23*27000Sdonn static	int (*osigint)();
24*27000Sdonn 
25*27000Sdonn cour_dialer(num, acu)
26*27000Sdonn 	register char *num;
27*27000Sdonn 	char *acu;
28*27000Sdonn {
29*27000Sdonn 	register char *cp;
30*27000Sdonn 	register int connected = 0;
31*27000Sdonn #ifdef ACULOG
32*27000Sdonn 	char line[80];
33*27000Sdonn #endif
34*27000Sdonn 	if (boolean(value(VERBOSE)))
35*27000Sdonn 		printf("Using \"%s\"\n", acu);
36*27000Sdonn 
37*27000Sdonn 	ioctl(FD, TIOCHPCL, 0);
38*27000Sdonn 	/*
39*27000Sdonn 	 * Get in synch.
40*27000Sdonn 	 */
41*27000Sdonn 	if (!coursync()) {
42*27000Sdonn 		printf("can't synchronize with courier\n");
43*27000Sdonn #ifdef ACULOG
44*27000Sdonn 		logent(value(HOST), num, "courier", "can't synch up");
45*27000Sdonn #endif
46*27000Sdonn 		return (0);
47*27000Sdonn 	}
48*27000Sdonn 	fflush(stdout);
49*27000Sdonn 	write(FD, "AT D", 4);
50*27000Sdonn 	for (cp = num; *cp; cp++)
51*27000Sdonn 		if (*cp == '=')
52*27000Sdonn 			*cp = ',';
53*27000Sdonn 	write(FD, num, strlen(num));
54*27000Sdonn 	write(FD, "\r", 1);
55*27000Sdonn 	connected = cour_connect();
56*27000Sdonn #ifdef ACULOG
57*27000Sdonn 	if (timeout) {
58*27000Sdonn 		sprintf(line, "%d second dial timeout",
59*27000Sdonn 			number(value(DIALTIMEOUT)));
60*27000Sdonn 		logent(value(HOST), num, "cour", line);
61*27000Sdonn 	}
62*27000Sdonn #endif
63*27000Sdonn 	if (timeout)
64*27000Sdonn 		cour_disconnect();
65*27000Sdonn 	return (connected);
66*27000Sdonn }
67*27000Sdonn 
68*27000Sdonn cour_disconnect()
69*27000Sdonn   {
70*27000Sdonn 	close(FD);
71*27000Sdonn }
72*27000Sdonn 
73*27000Sdonn cour_abort()
74*27000Sdonn   {
75*27000Sdonn 	write(FD, "\rAT Z\r", 6);
76*27000Sdonn 	close(FD);
77*27000Sdonn }
78*27000Sdonn 
79*27000Sdonn static int
80*27000Sdonn sigALRM()
81*27000Sdonn {
82*27000Sdonn 	printf("\07timeout waiting for reply\n");
83*27000Sdonn 	timeout = 1;
84*27000Sdonn 	longjmp(timeoutbuf, 1);
85*27000Sdonn }
86*27000Sdonn 
87*27000Sdonn static int
88*27000Sdonn cour_swallow(match)
89*27000Sdonn   register char *match;
90*27000Sdonn   {
91*27000Sdonn 	char c;
92*27000Sdonn 	int (*f)();
93*27000Sdonn 
94*27000Sdonn 	f = signal(SIGALRM, sigALRM);
95*27000Sdonn 	timeout = 0;
96*27000Sdonn 	do {
97*27000Sdonn 		if (*match =='\0') {
98*27000Sdonn 			signal(SIGALRM, f);
99*27000Sdonn 			return 1;
100*27000Sdonn 		}
101*27000Sdonn 		if (setjmp(timeoutbuf)) {
102*27000Sdonn 			signal(SIGALRM, f);
103*27000Sdonn 			return (0);
104*27000Sdonn 		}
105*27000Sdonn 		alarm(number(value(DIALTIMEOUT)));
106*27000Sdonn 		read(FD, &c, 1);
107*27000Sdonn 		alarm(0);
108*27000Sdonn 		c &= 0177;
109*27000Sdonn 		if (boolean(value(VERBOSE)))
110*27000Sdonn 			putchar(c);
111*27000Sdonn 	} while (c == *match++);
112*27000Sdonn 	if (boolean(value(VERBOSE)))
113*27000Sdonn 		fflush(stdout);
114*27000Sdonn 	signal(SIGALRM, SIG_DFL);
115*27000Sdonn 	return (0);
116*27000Sdonn }
117*27000Sdonn 
118*27000Sdonn struct baud_msg {
119*27000Sdonn 	char *msg;
120*27000Sdonn 	int baud;
121*27000Sdonn } baud_msg[] = {
122*27000Sdonn 	"",		B300,
123*27000Sdonn 	" 1200",	B1200,
124*27000Sdonn 	" 2400",	B2400,
125*27000Sdonn 	0,		0,
126*27000Sdonn };
127*27000Sdonn 
128*27000Sdonn static int
129*27000Sdonn cour_connect()
130*27000Sdonn {
131*27000Sdonn 	char c;
132*27000Sdonn 	int nc, nl, n;
133*27000Sdonn 	struct sgttyb sb;
134*27000Sdonn 	char dialer_buf[64];
135*27000Sdonn 	struct baud_msg *bm;
136*27000Sdonn 	int (*f)();
137*27000Sdonn 
138*27000Sdonn 	if (cour_swallow("\r\n") == 0)
139*27000Sdonn 		return (0);
140*27000Sdonn 	f = signal(SIGALRM, sigALRM);
141*27000Sdonn again:
142*27000Sdonn 	nc = 0; nl = sizeof(dialer_buf)-1;
143*27000Sdonn 	bzero(dialer_buf, sizeof(dialer_buf));
144*27000Sdonn 	timeout = 0;
145*27000Sdonn 	for (nc = 0, nl = sizeof(dialer_buf)-1 ; nl > 0 ; nc++, nl--) {
146*27000Sdonn 		if (setjmp(timeoutbuf))
147*27000Sdonn 			break;
148*27000Sdonn 		alarm(number(value(DIALTIMEOUT)));
149*27000Sdonn 		n = read(FD, &c, 1);
150*27000Sdonn 		alarm(0);
151*27000Sdonn 		if (n <= 0)
152*27000Sdonn 			break;
153*27000Sdonn 		c &= 0x7f;
154*27000Sdonn 		if (c == '\r') {
155*27000Sdonn 			if (cour_swallow("\n") == 0)
156*27000Sdonn 				break;
157*27000Sdonn 			if (!dialer_buf[0])
158*27000Sdonn 				goto again;
159*27000Sdonn 			if (strcmp(dialer_buf, "RINGING") == 0) {
160*27000Sdonn 				printf("%s\r\n", dialer_buf);
161*27000Sdonn 				goto again;
162*27000Sdonn 			}
163*27000Sdonn 			if (strncmp(dialer_buf, "CONNECT",
164*27000Sdonn 				    sizeof("CONNECT")-1) != 0)
165*27000Sdonn 				break;
166*27000Sdonn 			for (bm = baud_msg ; bm ; bm++)
167*27000Sdonn 				if (strcmp(bm->msg,
168*27000Sdonn 				    dialer_buf+sizeof("CONNECT")-1) == 0) {
169*27000Sdonn 					if (ioctl(FD, TIOCGETP, &sb) < 0) {
170*27000Sdonn 						perror("TIOCGETP");
171*27000Sdonn 						goto error;
172*27000Sdonn 					}
173*27000Sdonn 					sb.sg_ispeed = sb.sg_ospeed = bm->baud;
174*27000Sdonn 					if (ioctl(FD, TIOCSETP, &sb) < 0) {
175*27000Sdonn 						perror("TIOCSETP");
176*27000Sdonn 						goto error;
177*27000Sdonn 					}
178*27000Sdonn 					signal(SIGALRM, f);
179*27000Sdonn 					if (boolean(value(VERBOSE)))
180*27000Sdonn 						printf("%s\r\n", dialer_buf);
181*27000Sdonn 					return (1);
182*27000Sdonn 				}
183*27000Sdonn 			break;
184*27000Sdonn 		}
185*27000Sdonn 		dialer_buf[nc] = c;
186*27000Sdonn #ifdef notdef
187*27000Sdonn 		if (boolean(value(VERBOSE)))
188*27000Sdonn 			putchar(c);
189*27000Sdonn #endif
190*27000Sdonn 	}
191*27000Sdonn error1:
192*27000Sdonn 	printf("%s\r\n", dialer_buf);
193*27000Sdonn error:
194*27000Sdonn 	signal(SIGALRM, f);
195*27000Sdonn 	return (0);
196*27000Sdonn }
197*27000Sdonn 
198*27000Sdonn /*
199*27000Sdonn  * This convoluted piece of code attempts to get
200*27000Sdonn  * the courier in sync.  If you don't have FIONREAD
201*27000Sdonn  * there are gory ways to simulate this.
202*27000Sdonn  */
203*27000Sdonn static int
204*27000Sdonn coursync()
205*27000Sdonn {
206*27000Sdonn 	int already = 0;
207*27000Sdonn 
208*27000Sdonn 	/*
209*27000Sdonn 	 * Toggle DTR to force anyone off that might have left
210*27000Sdonn 	 * the modem connected, and insure a consistent state
211*27000Sdonn 	 * to start from.
212*27000Sdonn 	 *
213*27000Sdonn 	 * If you don't have the ioctl calls to diddle directly
214*27000Sdonn 	 * with DTR, you can always try setting the baud rate to 0.
215*27000Sdonn 	 */
216*27000Sdonn 	ioctl(FD, TIOCCDTR, 0);
217*27000Sdonn 	sleep(2);
218*27000Sdonn 	ioctl(FD, TIOCSDTR, 0);
219*27000Sdonn 	while (already++ < MAXRETRY) {
220*27000Sdonn 		ioctl(FD, TIOCFLUSH, 0);	/* flush any clutter */
221*27000Sdonn 		write(FD, "\rAT Z\r", 6);	/* reset modem */
222*27000Sdonn 		sleep(2);
223*27000Sdonn 		verbose_read();
224*27000Sdonn 		write(FD, "AT E0\r", 6);	/* turn off echoing */
225*27000Sdonn 		sleep(2);
226*27000Sdonn 		verbose_read();
227*27000Sdonn 		ioctl(FD, TIOCFLUSH, 0);	/* flush any clutter */
228*27000Sdonn 		sleep(1);
229*27000Sdonn 		write(FD, "AT C1 E0 H0 Q0 X6 V1\r", 21);
230*27000Sdonn 		if (cour_swallow("\r\nOK\r\n")) {
231*27000Sdonn 			ioctl(FD, TIOCFLUSH, 0);
232*27000Sdonn 			return 1;
233*27000Sdonn 		}
234*27000Sdonn 		sleep(2);
235*27000Sdonn 		write(FD, "+++", 3);
236*27000Sdonn 		sleep(2);
237*27000Sdonn 	}
238*27000Sdonn 	write(FD, "\rAT Z\r", 6);
239*27000Sdonn 	return 0;
240*27000Sdonn }
241*27000Sdonn 
242*27000Sdonn #undef write
243*27000Sdonn 
244*27000Sdonn cour_write(fd, cp, n)
245*27000Sdonn int fd;
246*27000Sdonn char *cp;
247*27000Sdonn int n;
248*27000Sdonn {
249*27000Sdonn 	struct sgttyb sb;
250*27000Sdonn 	if (boolean(value(VERBOSE)))
251*27000Sdonn 		write(1, cp, n);
252*27000Sdonn 	ioctl(fd, TIOCGETP, &sb);
253*27000Sdonn 	ioctl(fd, TIOCSETP, &sb);
254*27000Sdonn 	cour_nap();
255*27000Sdonn 	for ( ; n-- ; cp++) {
256*27000Sdonn 		write(fd, cp, 1);
257*27000Sdonn 		ioctl(fd, TIOCGETP, &sb);
258*27000Sdonn 		ioctl(fd, TIOCSETP, &sb);
259*27000Sdonn 		cour_nap();
260*27000Sdonn 	}
261*27000Sdonn }
262*27000Sdonn 
263*27000Sdonn verbose_read()
264*27000Sdonn {
265*27000Sdonn 	int n = 0;
266*27000Sdonn 	char buf[BUFSIZ];
267*27000Sdonn 	if (!boolean(value(VERBOSE)))
268*27000Sdonn 		return;
269*27000Sdonn 	if (ioctl(FD, FIONREAD, &n) < 0)
270*27000Sdonn 		return;
271*27000Sdonn 	if (n <= 0)
272*27000Sdonn 		return;
273*27000Sdonn 	if (read(FD, buf, n) != n)
274*27000Sdonn 		return;
275*27000Sdonn 	write(1, buf, n);
276*27000Sdonn }
277*27000Sdonn 
278*27000Sdonn /*
279*27000Sdonn  * Code stolen from /usr/src/lib/libc/gen/sleep.c
280*27000Sdonn  */
281*27000Sdonn #include <sys/time.h>
282*27000Sdonn 
283*27000Sdonn #define mask(s) (1<<((s)-1))
284*27000Sdonn #define setvec(vec, a) \
285*27000Sdonn         vec.sv_handler = a; vec.sv_mask = vec.sv_onstack = 0
286*27000Sdonn 
287*27000Sdonn static napms = 50; /* Give the courier 50 milliseconds between characters */
288*27000Sdonn 
289*27000Sdonn static int ringring;
290*27000Sdonn 
291*27000Sdonn cour_nap()
292*27000Sdonn {
293*27000Sdonn 
294*27000Sdonn         static int cour_napx();
295*27000Sdonn 	int omask;
296*27000Sdonn         struct itimerval itv, oitv;
297*27000Sdonn         register struct itimerval *itp = &itv;
298*27000Sdonn         struct sigvec vec, ovec;
299*27000Sdonn 
300*27000Sdonn         timerclear(&itp->it_interval);
301*27000Sdonn         timerclear(&itp->it_value);
302*27000Sdonn         if (setitimer(ITIMER_REAL, itp, &oitv) < 0)
303*27000Sdonn                 return;
304*27000Sdonn         setvec(ovec, SIG_DFL);
305*27000Sdonn         omask = sigblock(mask(SIGALRM));
306*27000Sdonn         itp->it_value.tv_sec = napms/1000;
307*27000Sdonn 	itp->it_value.tv_usec = ((napms%1000)*1000);
308*27000Sdonn         setvec(vec, cour_napx);
309*27000Sdonn         ringring = 0;
310*27000Sdonn         (void) sigvec(SIGALRM, &vec, &ovec);
311*27000Sdonn         (void) setitimer(ITIMER_REAL, itp, (struct itimerval *)0);
312*27000Sdonn         while (!ringring)
313*27000Sdonn                 sigpause(omask &~ mask(SIGALRM));
314*27000Sdonn         (void) sigvec(SIGALRM, &ovec, (struct sigvec *)0);
315*27000Sdonn         (void) setitimer(ITIMER_REAL, &oitv, (struct itimerval *)0);
316*27000Sdonn 	(void) sigsetmask(omask);
317*27000Sdonn }
318*27000Sdonn 
319*27000Sdonn static
320*27000Sdonn cour_napx()
321*27000Sdonn {
322*27000Sdonn         ringring = 1;
323*27000Sdonn }
324