127000Sdonn /* 235492Sbostic * Copyright (c) 1986 The Regents of the University of California. 335492Sbostic * All rights reserved. 435492Sbostic * 542770Sbostic * %sccs.include.redist.c% 627000Sdonn */ 727000Sdonn 827000Sdonn #ifndef lint 9*46867Sbostic static char sccsid[] = "@(#)courier.c 5.7 (Berkeley) 03/02/91"; 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; 25*46867Sbostic static int coursync(); 2627000Sdonn 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 35*46867Sbostic static int cour_connect(), cour_swallow(); 36*46867Sbostic 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 } 52*46867Sbostic cour_write(FD, "AT E0\r", 6); /* turn off echoing */ 5330517Skarels sleep(1); 5430517Skarels #ifdef DEBUG 5530517Skarels if (boolean(value(VERBOSE))) 5630517Skarels verbose_read(); 5730517Skarels #endif 5830517Skarels ioctl(FD, TIOCFLUSH, 0); /* flush any clutter */ 59*46867Sbostic 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); 63*46867Sbostic cour_write(FD, "AT D", 4); 6427000Sdonn for (cp = num; *cp; cp++) 6527000Sdonn if (*cp == '=') 6627000Sdonn *cp = ','; 67*46867Sbostic cour_write(FD, num, strlen(num)); 68*46867Sbostic 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 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 9227000Sdonn cour_abort() 9330517Skarels { 94*46867Sbostic cour_write(FD, "\r", 1); /* send anything to abort the call */ 9530517Skarels cour_disconnect(); 9627000Sdonn } 9727000Sdonn 9839253Sbostic static void 9927000Sdonn sigALRM() 10027000Sdonn { 10127000Sdonn printf("\07timeout waiting for reply\n"); 10227000Sdonn timeout = 1; 10327000Sdonn longjmp(timeoutbuf, 1); 10427000Sdonn } 10527000Sdonn 10627000Sdonn static int 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, 14827000Sdonn 0, 0, 14927000Sdonn }; 15027000Sdonn 15127000Sdonn static int 15227000Sdonn cour_connect() 15327000Sdonn { 15427000Sdonn char c; 15527000Sdonn int nc, nl, n; 15627000Sdonn struct sgttyb sb; 15727000Sdonn char dialer_buf[64]; 15827000Sdonn struct baud_msg *bm; 15939253Sbostic sig_t f; 16027000Sdonn 16127000Sdonn if (cour_swallow("\r\n") == 0) 16227000Sdonn return (0); 16327000Sdonn f = signal(SIGALRM, sigALRM); 16427000Sdonn again: 16527000Sdonn nc = 0; nl = sizeof(dialer_buf)-1; 16627000Sdonn bzero(dialer_buf, sizeof(dialer_buf)); 16727000Sdonn timeout = 0; 16827000Sdonn for (nc = 0, nl = sizeof(dialer_buf)-1 ; nl > 0 ; nc++, nl--) { 16927000Sdonn if (setjmp(timeoutbuf)) 17027000Sdonn break; 17127000Sdonn alarm(number(value(DIALTIMEOUT))); 17227000Sdonn n = read(FD, &c, 1); 17327000Sdonn alarm(0); 17427000Sdonn if (n <= 0) 17527000Sdonn break; 17627000Sdonn c &= 0x7f; 17727000Sdonn if (c == '\r') { 17827000Sdonn if (cour_swallow("\n") == 0) 17927000Sdonn break; 18027000Sdonn if (!dialer_buf[0]) 18127000Sdonn goto again; 18230517Skarels if (strcmp(dialer_buf, "RINGING") == 0 && 18330517Skarels boolean(value(VERBOSE))) { 18430517Skarels #ifdef DEBUG 18527000Sdonn printf("%s\r\n", dialer_buf); 18630517Skarels #endif 18727000Sdonn goto again; 18827000Sdonn } 18927000Sdonn if (strncmp(dialer_buf, "CONNECT", 19027000Sdonn sizeof("CONNECT")-1) != 0) 19127000Sdonn break; 19227000Sdonn for (bm = baud_msg ; bm ; bm++) 19327000Sdonn if (strcmp(bm->msg, 19427000Sdonn dialer_buf+sizeof("CONNECT")-1) == 0) { 19527000Sdonn if (ioctl(FD, TIOCGETP, &sb) < 0) { 19627000Sdonn perror("TIOCGETP"); 19727000Sdonn goto error; 19827000Sdonn } 19927000Sdonn sb.sg_ispeed = sb.sg_ospeed = bm->baud; 20027000Sdonn if (ioctl(FD, TIOCSETP, &sb) < 0) { 20127000Sdonn perror("TIOCSETP"); 20227000Sdonn goto error; 20327000Sdonn } 20427000Sdonn signal(SIGALRM, f); 20530517Skarels #ifdef DEBUG 20627000Sdonn if (boolean(value(VERBOSE))) 20727000Sdonn printf("%s\r\n", dialer_buf); 20830517Skarels #endif 20927000Sdonn return (1); 21027000Sdonn } 21127000Sdonn break; 21227000Sdonn } 21327000Sdonn dialer_buf[nc] = c; 21427000Sdonn #ifdef notdef 21527000Sdonn if (boolean(value(VERBOSE))) 21627000Sdonn putchar(c); 21727000Sdonn #endif 21827000Sdonn } 21927000Sdonn error1: 22027000Sdonn printf("%s\r\n", dialer_buf); 22127000Sdonn error: 22227000Sdonn signal(SIGALRM, f); 22327000Sdonn return (0); 22427000Sdonn } 22527000Sdonn 22627000Sdonn /* 22727000Sdonn * This convoluted piece of code attempts to get 22830517Skarels * the courier in sync. 22927000Sdonn */ 23027000Sdonn static int 23127000Sdonn coursync() 23227000Sdonn { 23327000Sdonn int already = 0; 23430517Skarels int len; 23530517Skarels char buf[40]; 23627000Sdonn 23727000Sdonn while (already++ < MAXRETRY) { 23827000Sdonn ioctl(FD, TIOCFLUSH, 0); /* flush any clutter */ 239*46867Sbostic cour_write(FD, "\rAT Z\r", 6); /* reset modem */ 24030517Skarels bzero(buf, sizeof(buf)); 24127000Sdonn sleep(1); 24230517Skarels ioctl(FD, FIONREAD, &len); 24330517Skarels if (len) { 24430517Skarels len = read(FD, buf, sizeof(buf)); 24530517Skarels #ifdef DEBUG 24630517Skarels buf[len] = '\0'; 24730517Skarels printf("coursync: (\"%s\")\n\r", buf); 24830517Skarels #endif 24930517Skarels if (index(buf, '0') || 25030517Skarels (index(buf, 'O') && index(buf, 'K'))) 25130517Skarels return(1); 25227000Sdonn } 25330517Skarels /* 25430517Skarels * If not strapped for DTR control, 25530517Skarels * try to get command mode. 25630517Skarels */ 25730517Skarels sleep(1); 258*46867Sbostic cour_write(FD, "+++", 3); 25930517Skarels sleep(1); 26030517Skarels /* 26130517Skarels * Toggle DTR to force anyone off that might have left 26230517Skarels * the modem connected. 26330517Skarels */ 26430517Skarels ioctl(FD, TIOCCDTR, 0); 26530517Skarels sleep(1); 26630517Skarels ioctl(FD, TIOCSDTR, 0); 26727000Sdonn } 268*46867Sbostic cour_write(FD, "\rAT Z\r", 6); 26930517Skarels return (0); 27027000Sdonn } 27127000Sdonn 27227000Sdonn cour_write(fd, cp, n) 27327000Sdonn int fd; 27427000Sdonn char *cp; 27527000Sdonn int n; 27627000Sdonn { 27727000Sdonn struct sgttyb sb; 27830517Skarels #ifdef notdef 27927000Sdonn if (boolean(value(VERBOSE))) 28027000Sdonn write(1, cp, n); 28130517Skarels #endif 28227000Sdonn ioctl(fd, TIOCGETP, &sb); 28327000Sdonn ioctl(fd, TIOCSETP, &sb); 28427000Sdonn cour_nap(); 28527000Sdonn for ( ; n-- ; cp++) { 28627000Sdonn write(fd, cp, 1); 28727000Sdonn ioctl(fd, TIOCGETP, &sb); 28827000Sdonn ioctl(fd, TIOCSETP, &sb); 28927000Sdonn cour_nap(); 29027000Sdonn } 29127000Sdonn } 29227000Sdonn 29330517Skarels #ifdef DEBUG 29427000Sdonn verbose_read() 29527000Sdonn { 29627000Sdonn int n = 0; 29727000Sdonn char buf[BUFSIZ]; 29830517Skarels 29927000Sdonn if (ioctl(FD, FIONREAD, &n) < 0) 30027000Sdonn return; 30127000Sdonn if (n <= 0) 30227000Sdonn return; 30327000Sdonn if (read(FD, buf, n) != n) 30427000Sdonn return; 30527000Sdonn write(1, buf, n); 30627000Sdonn } 30730517Skarels #endif 30827000Sdonn 30927000Sdonn /* 31027000Sdonn * Code stolen from /usr/src/lib/libc/gen/sleep.c 31127000Sdonn */ 31227000Sdonn #define mask(s) (1<<((s)-1)) 31327000Sdonn #define setvec(vec, a) \ 31427000Sdonn vec.sv_handler = a; vec.sv_mask = vec.sv_onstack = 0 31527000Sdonn 31627000Sdonn static napms = 50; /* Give the courier 50 milliseconds between characters */ 31727000Sdonn 31827000Sdonn static int ringring; 31927000Sdonn 32027000Sdonn cour_nap() 32127000Sdonn { 32227000Sdonn 32339253Sbostic static void cour_napx(); 32427000Sdonn int omask; 32527000Sdonn struct itimerval itv, oitv; 32627000Sdonn register struct itimerval *itp = &itv; 32727000Sdonn struct sigvec vec, ovec; 32827000Sdonn 32927000Sdonn timerclear(&itp->it_interval); 33027000Sdonn timerclear(&itp->it_value); 33127000Sdonn if (setitimer(ITIMER_REAL, itp, &oitv) < 0) 33227000Sdonn return; 33327000Sdonn setvec(ovec, SIG_DFL); 33427000Sdonn omask = sigblock(mask(SIGALRM)); 33527000Sdonn itp->it_value.tv_sec = napms/1000; 33627000Sdonn itp->it_value.tv_usec = ((napms%1000)*1000); 33727000Sdonn setvec(vec, cour_napx); 33827000Sdonn ringring = 0; 33927000Sdonn (void) sigvec(SIGALRM, &vec, &ovec); 34027000Sdonn (void) setitimer(ITIMER_REAL, itp, (struct itimerval *)0); 34127000Sdonn while (!ringring) 34227000Sdonn sigpause(omask &~ mask(SIGALRM)); 34327000Sdonn (void) sigvec(SIGALRM, &ovec, (struct sigvec *)0); 34427000Sdonn (void) setitimer(ITIMER_REAL, &oitv, (struct itimerval *)0); 34527000Sdonn (void) sigsetmask(omask); 34627000Sdonn } 34727000Sdonn 34839253Sbostic static void 34927000Sdonn cour_napx() 35027000Sdonn { 35127000Sdonn ringring = 1; 35227000Sdonn } 353