127000Sdonn /*
2*62317Sbostic * Copyright (c) 1986, 1993
3*62317Sbostic * The Regents of the University of California. All rights reserved.
435492Sbostic *
542770Sbostic * %sccs.include.redist.c%
627000Sdonn */
727000Sdonn
827000Sdonn #ifndef lint
9*62317Sbostic static char sccsid[] = "@(#)courier.c 8.1 (Berkeley) 06/06/93";
1035492Sbostic #endif /* not lint */
1127000Sdonn
1227000Sdonn /*
1330517Skarels * Routines for calling up on a Courier modem.
1430517Skarels * Derived from Hayes driver.
1527000Sdonn */
1627000Sdonn #include "tip.h"
1727000Sdonn #include <stdio.h>
1827000Sdonn
1927000Sdonn #define MAXRETRY 5
2027000Sdonn
2139253Sbostic static void sigALRM();
2227000Sdonn static int timeout = 0;
2330517Skarels static int connected = 0;
2427000Sdonn static jmp_buf timeoutbuf, intbuf;
2546867Sbostic static int coursync();
2627000Sdonn
cour_dialer(num,acu)2727000Sdonn cour_dialer(num, acu)
2827000Sdonn register char *num;
2927000Sdonn char *acu;
3027000Sdonn {
3127000Sdonn register char *cp;
3227000Sdonn #ifdef ACULOG
3327000Sdonn char line[80];
3427000Sdonn #endif
3546867Sbostic static int cour_connect(), cour_swallow();
3646867Sbostic
3727000Sdonn if (boolean(value(VERBOSE)))
3827000Sdonn printf("Using \"%s\"\n", acu);
3927000Sdonn
4027000Sdonn ioctl(FD, TIOCHPCL, 0);
4127000Sdonn /*
4227000Sdonn * Get in synch.
4327000Sdonn */
4427000Sdonn if (!coursync()) {
4530517Skarels badsynch:
4627000Sdonn printf("can't synchronize with courier\n");
4727000Sdonn #ifdef ACULOG
4827000Sdonn logent(value(HOST), num, "courier", "can't synch up");
4927000Sdonn #endif
5027000Sdonn return (0);
5127000Sdonn }
5246867Sbostic cour_write(FD, "AT E0\r", 6); /* turn off echoing */
5330517Skarels sleep(1);
5430517Skarels #ifdef DEBUG
5530517Skarels if (boolean(value(VERBOSE)))
5659675Shibler cour_verbose_read();
5730517Skarels #endif
5830517Skarels ioctl(FD, TIOCFLUSH, 0); /* flush any clutter */
5946867Sbostic cour_write(FD, "AT C1 E0 H0 Q0 X6 V1\r", 21);
6030517Skarels if (!cour_swallow("\r\nOK\r\n"))
6130517Skarels goto badsynch;
6227000Sdonn fflush(stdout);
6346867Sbostic cour_write(FD, "AT D", 4);
6427000Sdonn for (cp = num; *cp; cp++)
6527000Sdonn if (*cp == '=')
6627000Sdonn *cp = ',';
6746867Sbostic cour_write(FD, num, strlen(num));
6846867Sbostic cour_write(FD, "\r", 1);
6927000Sdonn connected = cour_connect();
7027000Sdonn #ifdef ACULOG
7127000Sdonn if (timeout) {
7227000Sdonn sprintf(line, "%d second dial timeout",
7327000Sdonn number(value(DIALTIMEOUT)));
7427000Sdonn logent(value(HOST), num, "cour", line);
7527000Sdonn }
7627000Sdonn #endif
7727000Sdonn if (timeout)
7827000Sdonn cour_disconnect();
7927000Sdonn return (connected);
8027000Sdonn }
8127000Sdonn
cour_disconnect()8227000Sdonn cour_disconnect()
8330517Skarels {
8430517Skarels /* first hang up the modem*/
8530517Skarels ioctl(FD, TIOCCDTR, 0);
8630517Skarels sleep(1);
8730517Skarels ioctl(FD, TIOCSDTR, 0);
8830517Skarels coursync(); /* reset */
8927000Sdonn close(FD);
9027000Sdonn }
9127000Sdonn
cour_abort()9227000Sdonn cour_abort()
9330517Skarels {
9446867Sbostic cour_write(FD, "\r", 1); /* send anything to abort the call */
9530517Skarels cour_disconnect();
9627000Sdonn }
9727000Sdonn
9839253Sbostic static void
sigALRM()9927000Sdonn sigALRM()
10027000Sdonn {
10127000Sdonn printf("\07timeout waiting for reply\n");
10227000Sdonn timeout = 1;
10327000Sdonn longjmp(timeoutbuf, 1);
10427000Sdonn }
10527000Sdonn
10627000Sdonn static int
cour_swallow(match)10727000Sdonn cour_swallow(match)
10827000Sdonn register char *match;
10927000Sdonn {
11039253Sbostic sig_t f;
11127000Sdonn char c;
11227000Sdonn
11327000Sdonn f = signal(SIGALRM, sigALRM);
11427000Sdonn timeout = 0;
11527000Sdonn do {
11627000Sdonn if (*match =='\0') {
11727000Sdonn signal(SIGALRM, f);
11830517Skarels return (1);
11927000Sdonn }
12027000Sdonn if (setjmp(timeoutbuf)) {
12127000Sdonn signal(SIGALRM, f);
12227000Sdonn return (0);
12327000Sdonn }
12427000Sdonn alarm(number(value(DIALTIMEOUT)));
12527000Sdonn read(FD, &c, 1);
12627000Sdonn alarm(0);
12727000Sdonn c &= 0177;
12830517Skarels #ifdef DEBUG
12927000Sdonn if (boolean(value(VERBOSE)))
13027000Sdonn putchar(c);
13130517Skarels #endif
13227000Sdonn } while (c == *match++);
13330517Skarels #ifdef DEBUG
13427000Sdonn if (boolean(value(VERBOSE)))
13527000Sdonn fflush(stdout);
13630517Skarels #endif
13727000Sdonn signal(SIGALRM, SIG_DFL);
13827000Sdonn return (0);
13927000Sdonn }
14027000Sdonn
14127000Sdonn struct baud_msg {
14227000Sdonn char *msg;
14327000Sdonn int baud;
14427000Sdonn } baud_msg[] = {
14527000Sdonn "", B300,
14627000Sdonn " 1200", B1200,
14727000Sdonn " 2400", B2400,
14859675Shibler " 9600", B9600,
14959675Shibler " 9600/ARQ", B9600,
15027000Sdonn 0, 0,
15127000Sdonn };
15227000Sdonn
15327000Sdonn static int
cour_connect()15427000Sdonn cour_connect()
15527000Sdonn {
15627000Sdonn char c;
15727000Sdonn int nc, nl, n;
15827000Sdonn struct sgttyb sb;
15927000Sdonn char dialer_buf[64];
16027000Sdonn struct baud_msg *bm;
16139253Sbostic sig_t f;
16227000Sdonn
16327000Sdonn if (cour_swallow("\r\n") == 0)
16427000Sdonn return (0);
16527000Sdonn f = signal(SIGALRM, sigALRM);
16627000Sdonn again:
16727000Sdonn nc = 0; nl = sizeof(dialer_buf)-1;
16827000Sdonn bzero(dialer_buf, sizeof(dialer_buf));
16927000Sdonn timeout = 0;
17027000Sdonn for (nc = 0, nl = sizeof(dialer_buf)-1 ; nl > 0 ; nc++, nl--) {
17127000Sdonn if (setjmp(timeoutbuf))
17227000Sdonn break;
17327000Sdonn alarm(number(value(DIALTIMEOUT)));
17427000Sdonn n = read(FD, &c, 1);
17527000Sdonn alarm(0);
17627000Sdonn if (n <= 0)
17727000Sdonn break;
17827000Sdonn c &= 0x7f;
17927000Sdonn if (c == '\r') {
18027000Sdonn if (cour_swallow("\n") == 0)
18127000Sdonn break;
18227000Sdonn if (!dialer_buf[0])
18327000Sdonn goto again;
18430517Skarels if (strcmp(dialer_buf, "RINGING") == 0 &&
18530517Skarels boolean(value(VERBOSE))) {
18630517Skarels #ifdef DEBUG
18727000Sdonn printf("%s\r\n", dialer_buf);
18830517Skarels #endif
18927000Sdonn goto again;
19027000Sdonn }
19127000Sdonn if (strncmp(dialer_buf, "CONNECT",
19227000Sdonn sizeof("CONNECT")-1) != 0)
19327000Sdonn break;
19459675Shibler for (bm = baud_msg ; bm->msg ; bm++)
19527000Sdonn if (strcmp(bm->msg,
19627000Sdonn dialer_buf+sizeof("CONNECT")-1) == 0) {
19727000Sdonn if (ioctl(FD, TIOCGETP, &sb) < 0) {
19827000Sdonn perror("TIOCGETP");
19927000Sdonn goto error;
20027000Sdonn }
20127000Sdonn sb.sg_ispeed = sb.sg_ospeed = bm->baud;
20227000Sdonn if (ioctl(FD, TIOCSETP, &sb) < 0) {
20327000Sdonn perror("TIOCSETP");
20427000Sdonn goto error;
20527000Sdonn }
20627000Sdonn signal(SIGALRM, f);
20730517Skarels #ifdef DEBUG
20827000Sdonn if (boolean(value(VERBOSE)))
20927000Sdonn printf("%s\r\n", dialer_buf);
21030517Skarels #endif
21127000Sdonn return (1);
21227000Sdonn }
21327000Sdonn break;
21427000Sdonn }
21527000Sdonn dialer_buf[nc] = c;
21627000Sdonn #ifdef notdef
21727000Sdonn if (boolean(value(VERBOSE)))
21827000Sdonn putchar(c);
21927000Sdonn #endif
22027000Sdonn }
22127000Sdonn error1:
22227000Sdonn printf("%s\r\n", dialer_buf);
22327000Sdonn error:
22427000Sdonn signal(SIGALRM, f);
22527000Sdonn return (0);
22627000Sdonn }
22727000Sdonn
22827000Sdonn /*
22927000Sdonn * This convoluted piece of code attempts to get
23030517Skarels * the courier in sync.
23127000Sdonn */
23227000Sdonn static int
coursync()23327000Sdonn coursync()
23427000Sdonn {
23527000Sdonn int already = 0;
23630517Skarels int len;
23730517Skarels char buf[40];
23827000Sdonn
23927000Sdonn while (already++ < MAXRETRY) {
24027000Sdonn ioctl(FD, TIOCFLUSH, 0); /* flush any clutter */
24146867Sbostic cour_write(FD, "\rAT Z\r", 6); /* reset modem */
24230517Skarels bzero(buf, sizeof(buf));
24327000Sdonn sleep(1);
24430517Skarels ioctl(FD, FIONREAD, &len);
24530517Skarels if (len) {
24630517Skarels len = read(FD, buf, sizeof(buf));
24730517Skarels #ifdef DEBUG
24830517Skarels buf[len] = '\0';
24930517Skarels printf("coursync: (\"%s\")\n\r", buf);
25030517Skarels #endif
25130517Skarels if (index(buf, '0') ||
25230517Skarels (index(buf, 'O') && index(buf, 'K')))
25330517Skarels return(1);
25427000Sdonn }
25530517Skarels /*
25630517Skarels * If not strapped for DTR control,
25730517Skarels * try to get command mode.
25830517Skarels */
25930517Skarels sleep(1);
26046867Sbostic cour_write(FD, "+++", 3);
26130517Skarels sleep(1);
26230517Skarels /*
26330517Skarels * Toggle DTR to force anyone off that might have left
26430517Skarels * the modem connected.
26530517Skarels */
26630517Skarels ioctl(FD, TIOCCDTR, 0);
26730517Skarels sleep(1);
26830517Skarels ioctl(FD, TIOCSDTR, 0);
26927000Sdonn }
27046867Sbostic cour_write(FD, "\rAT Z\r", 6);
27130517Skarels return (0);
27227000Sdonn }
27327000Sdonn
cour_write(fd,cp,n)27427000Sdonn cour_write(fd, cp, n)
27527000Sdonn int fd;
27627000Sdonn char *cp;
27727000Sdonn int n;
27827000Sdonn {
27927000Sdonn struct sgttyb sb;
28030517Skarels #ifdef notdef
28127000Sdonn if (boolean(value(VERBOSE)))
28227000Sdonn write(1, cp, n);
28330517Skarels #endif
28427000Sdonn ioctl(fd, TIOCGETP, &sb);
28527000Sdonn ioctl(fd, TIOCSETP, &sb);
28627000Sdonn cour_nap();
28727000Sdonn for ( ; n-- ; cp++) {
28827000Sdonn write(fd, cp, 1);
28927000Sdonn ioctl(fd, TIOCGETP, &sb);
29027000Sdonn ioctl(fd, TIOCSETP, &sb);
29127000Sdonn cour_nap();
29227000Sdonn }
29327000Sdonn }
29427000Sdonn
29530517Skarels #ifdef DEBUG
cour_verbose_read()29659675Shibler cour_verbose_read()
29727000Sdonn {
29827000Sdonn int n = 0;
29927000Sdonn char buf[BUFSIZ];
30030517Skarels
30127000Sdonn if (ioctl(FD, FIONREAD, &n) < 0)
30227000Sdonn return;
30327000Sdonn if (n <= 0)
30427000Sdonn return;
30527000Sdonn if (read(FD, buf, n) != n)
30627000Sdonn return;
30727000Sdonn write(1, buf, n);
30827000Sdonn }
30930517Skarels #endif
31027000Sdonn
31127000Sdonn /*
31227000Sdonn * Code stolen from /usr/src/lib/libc/gen/sleep.c
31327000Sdonn */
31427000Sdonn #define mask(s) (1<<((s)-1))
31527000Sdonn #define setvec(vec, a) \
31627000Sdonn vec.sv_handler = a; vec.sv_mask = vec.sv_onstack = 0
31727000Sdonn
31827000Sdonn static napms = 50; /* Give the courier 50 milliseconds between characters */
31927000Sdonn
32027000Sdonn static int ringring;
32127000Sdonn
cour_nap()32227000Sdonn cour_nap()
32327000Sdonn {
32427000Sdonn
32539253Sbostic static void cour_napx();
32627000Sdonn int omask;
32727000Sdonn struct itimerval itv, oitv;
32827000Sdonn register struct itimerval *itp = &itv;
32927000Sdonn struct sigvec vec, ovec;
33027000Sdonn
33127000Sdonn timerclear(&itp->it_interval);
33227000Sdonn timerclear(&itp->it_value);
33327000Sdonn if (setitimer(ITIMER_REAL, itp, &oitv) < 0)
33427000Sdonn return;
33527000Sdonn setvec(ovec, SIG_DFL);
33627000Sdonn omask = sigblock(mask(SIGALRM));
33727000Sdonn itp->it_value.tv_sec = napms/1000;
33827000Sdonn itp->it_value.tv_usec = ((napms%1000)*1000);
33927000Sdonn setvec(vec, cour_napx);
34027000Sdonn ringring = 0;
34127000Sdonn (void) sigvec(SIGALRM, &vec, &ovec);
34227000Sdonn (void) setitimer(ITIMER_REAL, itp, (struct itimerval *)0);
34327000Sdonn while (!ringring)
34427000Sdonn sigpause(omask &~ mask(SIGALRM));
34527000Sdonn (void) sigvec(SIGALRM, &ovec, (struct sigvec *)0);
34627000Sdonn (void) setitimer(ITIMER_REAL, &oitv, (struct itimerval *)0);
34727000Sdonn (void) sigsetmask(omask);
34827000Sdonn }
34927000Sdonn
35039253Sbostic static void
cour_napx()35127000Sdonn cour_napx()
35227000Sdonn {
35327000Sdonn ringring = 1;
35427000Sdonn }
355