xref: /csrg-svn/usr.bin/tip/aculib/courier.c (revision 39253)
127000Sdonn /*
235492Sbostic  * Copyright (c) 1986 The Regents of the University of California.
335492Sbostic  * All rights reserved.
435492Sbostic  *
535492Sbostic  * Redistribution and use in source and binary forms are permitted
635492Sbostic  * provided that the above copyright notice and this paragraph are
735492Sbostic  * duplicated in all such forms and that any documentation,
835492Sbostic  * advertising materials, and other materials related to such
935492Sbostic  * distribution and use acknowledge that the software was developed
1035492Sbostic  * by the University of California, Berkeley.  The name of the
1135492Sbostic  * University may not be used to endorse or promote products derived
1235492Sbostic  * from this software without specific prior written permission.
1335492Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1435492Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1535492Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1627000Sdonn  */
1727000Sdonn 
1827000Sdonn #ifndef lint
19*39253Sbostic static char sccsid[] = "@(#)courier.c	5.4 (Berkeley) 10/03/89";
2035492Sbostic #endif /* not lint */
2127000Sdonn 
2227000Sdonn #define write cour_write
2327000Sdonn /*
2430517Skarels  * Routines for calling up on a Courier modem.
2530517Skarels  * Derived from Hayes driver.
2627000Sdonn  */
2727000Sdonn #include "tip.h"
2827000Sdonn #include <stdio.h>
2927000Sdonn 
3027000Sdonn #define	MAXRETRY	5
3127000Sdonn 
32*39253Sbostic static	void sigALRM();
3327000Sdonn static	int timeout = 0;
3430517Skarels static	int connected = 0;
3527000Sdonn static	jmp_buf timeoutbuf, intbuf;
3627000Sdonn static	int (*osigint)();
3727000Sdonn 
3827000Sdonn cour_dialer(num, acu)
3927000Sdonn 	register char *num;
4027000Sdonn 	char *acu;
4127000Sdonn {
4227000Sdonn 	register char *cp;
4327000Sdonn #ifdef ACULOG
4427000Sdonn 	char line[80];
4527000Sdonn #endif
4627000Sdonn 	if (boolean(value(VERBOSE)))
4727000Sdonn 		printf("Using \"%s\"\n", acu);
4827000Sdonn 
4927000Sdonn 	ioctl(FD, TIOCHPCL, 0);
5027000Sdonn 	/*
5127000Sdonn 	 * Get in synch.
5227000Sdonn 	 */
5327000Sdonn 	if (!coursync()) {
5430517Skarels badsynch:
5527000Sdonn 		printf("can't synchronize with courier\n");
5627000Sdonn #ifdef ACULOG
5727000Sdonn 		logent(value(HOST), num, "courier", "can't synch up");
5827000Sdonn #endif
5927000Sdonn 		return (0);
6027000Sdonn 	}
6130517Skarels 	write(FD, "AT E0\r", 6);	/* turn off echoing */
6230517Skarels 	sleep(1);
6330517Skarels #ifdef DEBUG
6430517Skarels 	if (boolean(value(VERBOSE)))
6530517Skarels 		verbose_read();
6630517Skarels #endif
6730517Skarels 	ioctl(FD, TIOCFLUSH, 0);	/* flush any clutter */
6830517Skarels 	write(FD, "AT C1 E0 H0 Q0 X6 V1\r", 21);
6930517Skarels 	if (!cour_swallow("\r\nOK\r\n"))
7030517Skarels 		goto badsynch;
7127000Sdonn 	fflush(stdout);
7227000Sdonn 	write(FD, "AT D", 4);
7327000Sdonn 	for (cp = num; *cp; cp++)
7427000Sdonn 		if (*cp == '=')
7527000Sdonn 			*cp = ',';
7627000Sdonn 	write(FD, num, strlen(num));
7727000Sdonn 	write(FD, "\r", 1);
7827000Sdonn 	connected = cour_connect();
7927000Sdonn #ifdef ACULOG
8027000Sdonn 	if (timeout) {
8127000Sdonn 		sprintf(line, "%d second dial timeout",
8227000Sdonn 			number(value(DIALTIMEOUT)));
8327000Sdonn 		logent(value(HOST), num, "cour", line);
8427000Sdonn 	}
8527000Sdonn #endif
8627000Sdonn 	if (timeout)
8727000Sdonn 		cour_disconnect();
8827000Sdonn 	return (connected);
8927000Sdonn }
9027000Sdonn 
9127000Sdonn cour_disconnect()
9230517Skarels {
9330517Skarels 	 /* first hang up the modem*/
9430517Skarels 	ioctl(FD, TIOCCDTR, 0);
9530517Skarels 	sleep(1);
9630517Skarels 	ioctl(FD, TIOCSDTR, 0);
9730517Skarels 	coursync();				/* reset */
9827000Sdonn 	close(FD);
9927000Sdonn }
10027000Sdonn 
10127000Sdonn cour_abort()
10230517Skarels {
10330517Skarels 	write(FD, "\r", 1);	/* send anything to abort the call */
10430517Skarels 	cour_disconnect();
10527000Sdonn }
10627000Sdonn 
107*39253Sbostic static void
10827000Sdonn sigALRM()
10927000Sdonn {
11027000Sdonn 	printf("\07timeout waiting for reply\n");
11127000Sdonn 	timeout = 1;
11227000Sdonn 	longjmp(timeoutbuf, 1);
11327000Sdonn }
11427000Sdonn 
11527000Sdonn static int
11627000Sdonn cour_swallow(match)
11727000Sdonn   register char *match;
11827000Sdonn   {
119*39253Sbostic 	sig_t f;
12027000Sdonn 	char c;
12127000Sdonn 
12227000Sdonn 	f = signal(SIGALRM, sigALRM);
12327000Sdonn 	timeout = 0;
12427000Sdonn 	do {
12527000Sdonn 		if (*match =='\0') {
12627000Sdonn 			signal(SIGALRM, f);
12730517Skarels 			return (1);
12827000Sdonn 		}
12927000Sdonn 		if (setjmp(timeoutbuf)) {
13027000Sdonn 			signal(SIGALRM, f);
13127000Sdonn 			return (0);
13227000Sdonn 		}
13327000Sdonn 		alarm(number(value(DIALTIMEOUT)));
13427000Sdonn 		read(FD, &c, 1);
13527000Sdonn 		alarm(0);
13627000Sdonn 		c &= 0177;
13730517Skarels #ifdef DEBUG
13827000Sdonn 		if (boolean(value(VERBOSE)))
13927000Sdonn 			putchar(c);
14030517Skarels #endif
14127000Sdonn 	} while (c == *match++);
14230517Skarels #ifdef DEBUG
14327000Sdonn 	if (boolean(value(VERBOSE)))
14427000Sdonn 		fflush(stdout);
14530517Skarels #endif
14627000Sdonn 	signal(SIGALRM, SIG_DFL);
14727000Sdonn 	return (0);
14827000Sdonn }
14927000Sdonn 
15027000Sdonn struct baud_msg {
15127000Sdonn 	char *msg;
15227000Sdonn 	int baud;
15327000Sdonn } baud_msg[] = {
15427000Sdonn 	"",		B300,
15527000Sdonn 	" 1200",	B1200,
15627000Sdonn 	" 2400",	B2400,
15727000Sdonn 	0,		0,
15827000Sdonn };
15927000Sdonn 
16027000Sdonn static int
16127000Sdonn cour_connect()
16227000Sdonn {
16327000Sdonn 	char c;
16427000Sdonn 	int nc, nl, n;
16527000Sdonn 	struct sgttyb sb;
16627000Sdonn 	char dialer_buf[64];
16727000Sdonn 	struct baud_msg *bm;
168*39253Sbostic 	sig_t f;
16927000Sdonn 
17027000Sdonn 	if (cour_swallow("\r\n") == 0)
17127000Sdonn 		return (0);
17227000Sdonn 	f = signal(SIGALRM, sigALRM);
17327000Sdonn again:
17427000Sdonn 	nc = 0; nl = sizeof(dialer_buf)-1;
17527000Sdonn 	bzero(dialer_buf, sizeof(dialer_buf));
17627000Sdonn 	timeout = 0;
17727000Sdonn 	for (nc = 0, nl = sizeof(dialer_buf)-1 ; nl > 0 ; nc++, nl--) {
17827000Sdonn 		if (setjmp(timeoutbuf))
17927000Sdonn 			break;
18027000Sdonn 		alarm(number(value(DIALTIMEOUT)));
18127000Sdonn 		n = read(FD, &c, 1);
18227000Sdonn 		alarm(0);
18327000Sdonn 		if (n <= 0)
18427000Sdonn 			break;
18527000Sdonn 		c &= 0x7f;
18627000Sdonn 		if (c == '\r') {
18727000Sdonn 			if (cour_swallow("\n") == 0)
18827000Sdonn 				break;
18927000Sdonn 			if (!dialer_buf[0])
19027000Sdonn 				goto again;
19130517Skarels 			if (strcmp(dialer_buf, "RINGING") == 0 &&
19230517Skarels 			    boolean(value(VERBOSE))) {
19330517Skarels #ifdef DEBUG
19427000Sdonn 				printf("%s\r\n", dialer_buf);
19530517Skarels #endif
19627000Sdonn 				goto again;
19727000Sdonn 			}
19827000Sdonn 			if (strncmp(dialer_buf, "CONNECT",
19927000Sdonn 				    sizeof("CONNECT")-1) != 0)
20027000Sdonn 				break;
20127000Sdonn 			for (bm = baud_msg ; bm ; bm++)
20227000Sdonn 				if (strcmp(bm->msg,
20327000Sdonn 				    dialer_buf+sizeof("CONNECT")-1) == 0) {
20427000Sdonn 					if (ioctl(FD, TIOCGETP, &sb) < 0) {
20527000Sdonn 						perror("TIOCGETP");
20627000Sdonn 						goto error;
20727000Sdonn 					}
20827000Sdonn 					sb.sg_ispeed = sb.sg_ospeed = bm->baud;
20927000Sdonn 					if (ioctl(FD, TIOCSETP, &sb) < 0) {
21027000Sdonn 						perror("TIOCSETP");
21127000Sdonn 						goto error;
21227000Sdonn 					}
21327000Sdonn 					signal(SIGALRM, f);
21430517Skarels #ifdef DEBUG
21527000Sdonn 					if (boolean(value(VERBOSE)))
21627000Sdonn 						printf("%s\r\n", dialer_buf);
21730517Skarels #endif
21827000Sdonn 					return (1);
21927000Sdonn 				}
22027000Sdonn 			break;
22127000Sdonn 		}
22227000Sdonn 		dialer_buf[nc] = c;
22327000Sdonn #ifdef notdef
22427000Sdonn 		if (boolean(value(VERBOSE)))
22527000Sdonn 			putchar(c);
22627000Sdonn #endif
22727000Sdonn 	}
22827000Sdonn error1:
22927000Sdonn 	printf("%s\r\n", dialer_buf);
23027000Sdonn error:
23127000Sdonn 	signal(SIGALRM, f);
23227000Sdonn 	return (0);
23327000Sdonn }
23427000Sdonn 
23527000Sdonn /*
23627000Sdonn  * This convoluted piece of code attempts to get
23730517Skarels  * the courier in sync.
23827000Sdonn  */
23927000Sdonn static int
24027000Sdonn coursync()
24127000Sdonn {
24227000Sdonn 	int already = 0;
24330517Skarels 	int len;
24430517Skarels 	char buf[40];
24527000Sdonn 
24627000Sdonn 	while (already++ < MAXRETRY) {
24727000Sdonn 		ioctl(FD, TIOCFLUSH, 0);	/* flush any clutter */
24827000Sdonn 		write(FD, "\rAT Z\r", 6);	/* reset modem */
24930517Skarels 		bzero(buf, sizeof(buf));
25027000Sdonn 		sleep(1);
25130517Skarels 		ioctl(FD, FIONREAD, &len);
25230517Skarels 		if (len) {
25330517Skarels 			len = read(FD, buf, sizeof(buf));
25430517Skarels #ifdef DEBUG
25530517Skarels 			buf[len] = '\0';
25630517Skarels 			printf("coursync: (\"%s\")\n\r", buf);
25730517Skarels #endif
25830517Skarels 			if (index(buf, '0') ||
25930517Skarels 		   	   (index(buf, 'O') && index(buf, 'K')))
26030517Skarels 				return(1);
26127000Sdonn 		}
26230517Skarels 		/*
26330517Skarels 		 * If not strapped for DTR control,
26430517Skarels 		 * try to get command mode.
26530517Skarels 		 */
26630517Skarels 		sleep(1);
26727000Sdonn 		write(FD, "+++", 3);
26830517Skarels 		sleep(1);
26930517Skarels 		/*
27030517Skarels 		 * Toggle DTR to force anyone off that might have left
27130517Skarels 		 * the modem connected.
27230517Skarels 		 */
27330517Skarels 		ioctl(FD, TIOCCDTR, 0);
27430517Skarels 		sleep(1);
27530517Skarels 		ioctl(FD, TIOCSDTR, 0);
27627000Sdonn 	}
27727000Sdonn 	write(FD, "\rAT Z\r", 6);
27830517Skarels 	return (0);
27927000Sdonn }
28027000Sdonn 
28127000Sdonn #undef write
28227000Sdonn 
28327000Sdonn cour_write(fd, cp, n)
28427000Sdonn int fd;
28527000Sdonn char *cp;
28627000Sdonn int n;
28727000Sdonn {
28827000Sdonn 	struct sgttyb sb;
28930517Skarels #ifdef notdef
29027000Sdonn 	if (boolean(value(VERBOSE)))
29127000Sdonn 		write(1, cp, n);
29230517Skarels #endif
29327000Sdonn 	ioctl(fd, TIOCGETP, &sb);
29427000Sdonn 	ioctl(fd, TIOCSETP, &sb);
29527000Sdonn 	cour_nap();
29627000Sdonn 	for ( ; n-- ; cp++) {
29727000Sdonn 		write(fd, cp, 1);
29827000Sdonn 		ioctl(fd, TIOCGETP, &sb);
29927000Sdonn 		ioctl(fd, TIOCSETP, &sb);
30027000Sdonn 		cour_nap();
30127000Sdonn 	}
30227000Sdonn }
30327000Sdonn 
30430517Skarels #ifdef DEBUG
30527000Sdonn verbose_read()
30627000Sdonn {
30727000Sdonn 	int n = 0;
30827000Sdonn 	char buf[BUFSIZ];
30930517Skarels 
31027000Sdonn 	if (ioctl(FD, FIONREAD, &n) < 0)
31127000Sdonn 		return;
31227000Sdonn 	if (n <= 0)
31327000Sdonn 		return;
31427000Sdonn 	if (read(FD, buf, n) != n)
31527000Sdonn 		return;
31627000Sdonn 	write(1, buf, n);
31727000Sdonn }
31830517Skarels #endif
31927000Sdonn 
32027000Sdonn /*
32127000Sdonn  * Code stolen from /usr/src/lib/libc/gen/sleep.c
32227000Sdonn  */
32327000Sdonn #include <sys/time.h>
32427000Sdonn 
32527000Sdonn #define mask(s) (1<<((s)-1))
32627000Sdonn #define setvec(vec, a) \
32727000Sdonn         vec.sv_handler = a; vec.sv_mask = vec.sv_onstack = 0
32827000Sdonn 
32927000Sdonn static napms = 50; /* Give the courier 50 milliseconds between characters */
33027000Sdonn 
33127000Sdonn static int ringring;
33227000Sdonn 
33327000Sdonn cour_nap()
33427000Sdonn {
33527000Sdonn 
336*39253Sbostic         static void cour_napx();
33727000Sdonn 	int omask;
33827000Sdonn         struct itimerval itv, oitv;
33927000Sdonn         register struct itimerval *itp = &itv;
34027000Sdonn         struct sigvec vec, ovec;
34127000Sdonn 
34227000Sdonn         timerclear(&itp->it_interval);
34327000Sdonn         timerclear(&itp->it_value);
34427000Sdonn         if (setitimer(ITIMER_REAL, itp, &oitv) < 0)
34527000Sdonn                 return;
34627000Sdonn         setvec(ovec, SIG_DFL);
34727000Sdonn         omask = sigblock(mask(SIGALRM));
34827000Sdonn         itp->it_value.tv_sec = napms/1000;
34927000Sdonn 	itp->it_value.tv_usec = ((napms%1000)*1000);
35027000Sdonn         setvec(vec, cour_napx);
35127000Sdonn         ringring = 0;
35227000Sdonn         (void) sigvec(SIGALRM, &vec, &ovec);
35327000Sdonn         (void) setitimer(ITIMER_REAL, itp, (struct itimerval *)0);
35427000Sdonn         while (!ringring)
35527000Sdonn                 sigpause(omask &~ mask(SIGALRM));
35627000Sdonn         (void) sigvec(SIGALRM, &ovec, (struct sigvec *)0);
35727000Sdonn         (void) setitimer(ITIMER_REAL, &oitv, (struct itimerval *)0);
35827000Sdonn 	(void) sigsetmask(omask);
35927000Sdonn }
36027000Sdonn 
361*39253Sbostic static void
36227000Sdonn cour_napx()
36327000Sdonn {
36427000Sdonn         ringring = 1;
36527000Sdonn }
366