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*59675Shibler static char sccsid[] = "@(#)courier.c 5.8 (Berkeley) 05/03/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 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))) 56*59675Shibler 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 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 { 9446867Sbostic 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, 148*59675Shibler " 9600", B9600, 149*59675Shibler " 9600/ARQ", B9600, 15027000Sdonn 0, 0, 15127000Sdonn }; 15227000Sdonn 15327000Sdonn static int 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; 194*59675Shibler 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 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 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 296*59675Shibler 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 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 35127000Sdonn cour_napx() 35227000Sdonn { 35327000Sdonn ringring = 1; 35427000Sdonn } 355