127000Sdonn /* 235492Sbostic * Copyright (c) 1986 The Regents of the University of California. 335492Sbostic * All rights reserved. 435492Sbostic * 5*42770Sbostic * %sccs.include.redist.c% 627000Sdonn */ 727000Sdonn 827000Sdonn #ifndef lint 9*42770Sbostic static char sccsid[] = "@(#)courier.c 5.5 (Berkeley) 06/01/90"; 1035492Sbostic #endif /* not lint */ 1127000Sdonn 1227000Sdonn #define write cour_write 1327000Sdonn /* 1430517Skarels * Routines for calling up on a Courier modem. 1530517Skarels * Derived from Hayes driver. 1627000Sdonn */ 1727000Sdonn #include "tip.h" 1827000Sdonn #include <stdio.h> 1927000Sdonn 2027000Sdonn #define MAXRETRY 5 2127000Sdonn 2239253Sbostic static void sigALRM(); 2327000Sdonn static int timeout = 0; 2430517Skarels static int connected = 0; 2527000Sdonn static jmp_buf timeoutbuf, intbuf; 2627000Sdonn static int (*osigint)(); 2727000Sdonn 2827000Sdonn cour_dialer(num, acu) 2927000Sdonn register char *num; 3027000Sdonn char *acu; 3127000Sdonn { 3227000Sdonn register char *cp; 3327000Sdonn #ifdef ACULOG 3427000Sdonn char line[80]; 3527000Sdonn #endif 3627000Sdonn if (boolean(value(VERBOSE))) 3727000Sdonn printf("Using \"%s\"\n", acu); 3827000Sdonn 3927000Sdonn ioctl(FD, TIOCHPCL, 0); 4027000Sdonn /* 4127000Sdonn * Get in synch. 4227000Sdonn */ 4327000Sdonn if (!coursync()) { 4430517Skarels badsynch: 4527000Sdonn printf("can't synchronize with courier\n"); 4627000Sdonn #ifdef ACULOG 4727000Sdonn logent(value(HOST), num, "courier", "can't synch up"); 4827000Sdonn #endif 4927000Sdonn return (0); 5027000Sdonn } 5130517Skarels write(FD, "AT E0\r", 6); /* turn off echoing */ 5230517Skarels sleep(1); 5330517Skarels #ifdef DEBUG 5430517Skarels if (boolean(value(VERBOSE))) 5530517Skarels verbose_read(); 5630517Skarels #endif 5730517Skarels ioctl(FD, TIOCFLUSH, 0); /* flush any clutter */ 5830517Skarels write(FD, "AT C1 E0 H0 Q0 X6 V1\r", 21); 5930517Skarels if (!cour_swallow("\r\nOK\r\n")) 6030517Skarels goto badsynch; 6127000Sdonn fflush(stdout); 6227000Sdonn write(FD, "AT D", 4); 6327000Sdonn for (cp = num; *cp; cp++) 6427000Sdonn if (*cp == '=') 6527000Sdonn *cp = ','; 6627000Sdonn write(FD, num, strlen(num)); 6727000Sdonn write(FD, "\r", 1); 6827000Sdonn connected = cour_connect(); 6927000Sdonn #ifdef ACULOG 7027000Sdonn if (timeout) { 7127000Sdonn sprintf(line, "%d second dial timeout", 7227000Sdonn number(value(DIALTIMEOUT))); 7327000Sdonn logent(value(HOST), num, "cour", line); 7427000Sdonn } 7527000Sdonn #endif 7627000Sdonn if (timeout) 7727000Sdonn cour_disconnect(); 7827000Sdonn return (connected); 7927000Sdonn } 8027000Sdonn 8127000Sdonn cour_disconnect() 8230517Skarels { 8330517Skarels /* first hang up the modem*/ 8430517Skarels ioctl(FD, TIOCCDTR, 0); 8530517Skarels sleep(1); 8630517Skarels ioctl(FD, TIOCSDTR, 0); 8730517Skarels coursync(); /* reset */ 8827000Sdonn close(FD); 8927000Sdonn } 9027000Sdonn 9127000Sdonn cour_abort() 9230517Skarels { 9330517Skarels write(FD, "\r", 1); /* send anything to abort the call */ 9430517Skarels cour_disconnect(); 9527000Sdonn } 9627000Sdonn 9739253Sbostic static void 9827000Sdonn sigALRM() 9927000Sdonn { 10027000Sdonn printf("\07timeout waiting for reply\n"); 10127000Sdonn timeout = 1; 10227000Sdonn longjmp(timeoutbuf, 1); 10327000Sdonn } 10427000Sdonn 10527000Sdonn static int 10627000Sdonn cour_swallow(match) 10727000Sdonn register char *match; 10827000Sdonn { 10939253Sbostic sig_t f; 11027000Sdonn char c; 11127000Sdonn 11227000Sdonn f = signal(SIGALRM, sigALRM); 11327000Sdonn timeout = 0; 11427000Sdonn do { 11527000Sdonn if (*match =='\0') { 11627000Sdonn signal(SIGALRM, f); 11730517Skarels return (1); 11827000Sdonn } 11927000Sdonn if (setjmp(timeoutbuf)) { 12027000Sdonn signal(SIGALRM, f); 12127000Sdonn return (0); 12227000Sdonn } 12327000Sdonn alarm(number(value(DIALTIMEOUT))); 12427000Sdonn read(FD, &c, 1); 12527000Sdonn alarm(0); 12627000Sdonn c &= 0177; 12730517Skarels #ifdef DEBUG 12827000Sdonn if (boolean(value(VERBOSE))) 12927000Sdonn putchar(c); 13030517Skarels #endif 13127000Sdonn } while (c == *match++); 13230517Skarels #ifdef DEBUG 13327000Sdonn if (boolean(value(VERBOSE))) 13427000Sdonn fflush(stdout); 13530517Skarels #endif 13627000Sdonn signal(SIGALRM, SIG_DFL); 13727000Sdonn return (0); 13827000Sdonn } 13927000Sdonn 14027000Sdonn struct baud_msg { 14127000Sdonn char *msg; 14227000Sdonn int baud; 14327000Sdonn } baud_msg[] = { 14427000Sdonn "", B300, 14527000Sdonn " 1200", B1200, 14627000Sdonn " 2400", B2400, 14727000Sdonn 0, 0, 14827000Sdonn }; 14927000Sdonn 15027000Sdonn static int 15127000Sdonn cour_connect() 15227000Sdonn { 15327000Sdonn char c; 15427000Sdonn int nc, nl, n; 15527000Sdonn struct sgttyb sb; 15627000Sdonn char dialer_buf[64]; 15727000Sdonn struct baud_msg *bm; 15839253Sbostic sig_t f; 15927000Sdonn 16027000Sdonn if (cour_swallow("\r\n") == 0) 16127000Sdonn return (0); 16227000Sdonn f = signal(SIGALRM, sigALRM); 16327000Sdonn again: 16427000Sdonn nc = 0; nl = sizeof(dialer_buf)-1; 16527000Sdonn bzero(dialer_buf, sizeof(dialer_buf)); 16627000Sdonn timeout = 0; 16727000Sdonn for (nc = 0, nl = sizeof(dialer_buf)-1 ; nl > 0 ; nc++, nl--) { 16827000Sdonn if (setjmp(timeoutbuf)) 16927000Sdonn break; 17027000Sdonn alarm(number(value(DIALTIMEOUT))); 17127000Sdonn n = read(FD, &c, 1); 17227000Sdonn alarm(0); 17327000Sdonn if (n <= 0) 17427000Sdonn break; 17527000Sdonn c &= 0x7f; 17627000Sdonn if (c == '\r') { 17727000Sdonn if (cour_swallow("\n") == 0) 17827000Sdonn break; 17927000Sdonn if (!dialer_buf[0]) 18027000Sdonn goto again; 18130517Skarels if (strcmp(dialer_buf, "RINGING") == 0 && 18230517Skarels boolean(value(VERBOSE))) { 18330517Skarels #ifdef DEBUG 18427000Sdonn printf("%s\r\n", dialer_buf); 18530517Skarels #endif 18627000Sdonn goto again; 18727000Sdonn } 18827000Sdonn if (strncmp(dialer_buf, "CONNECT", 18927000Sdonn sizeof("CONNECT")-1) != 0) 19027000Sdonn break; 19127000Sdonn for (bm = baud_msg ; bm ; bm++) 19227000Sdonn if (strcmp(bm->msg, 19327000Sdonn dialer_buf+sizeof("CONNECT")-1) == 0) { 19427000Sdonn if (ioctl(FD, TIOCGETP, &sb) < 0) { 19527000Sdonn perror("TIOCGETP"); 19627000Sdonn goto error; 19727000Sdonn } 19827000Sdonn sb.sg_ispeed = sb.sg_ospeed = bm->baud; 19927000Sdonn if (ioctl(FD, TIOCSETP, &sb) < 0) { 20027000Sdonn perror("TIOCSETP"); 20127000Sdonn goto error; 20227000Sdonn } 20327000Sdonn signal(SIGALRM, f); 20430517Skarels #ifdef DEBUG 20527000Sdonn if (boolean(value(VERBOSE))) 20627000Sdonn printf("%s\r\n", dialer_buf); 20730517Skarels #endif 20827000Sdonn return (1); 20927000Sdonn } 21027000Sdonn break; 21127000Sdonn } 21227000Sdonn dialer_buf[nc] = c; 21327000Sdonn #ifdef notdef 21427000Sdonn if (boolean(value(VERBOSE))) 21527000Sdonn putchar(c); 21627000Sdonn #endif 21727000Sdonn } 21827000Sdonn error1: 21927000Sdonn printf("%s\r\n", dialer_buf); 22027000Sdonn error: 22127000Sdonn signal(SIGALRM, f); 22227000Sdonn return (0); 22327000Sdonn } 22427000Sdonn 22527000Sdonn /* 22627000Sdonn * This convoluted piece of code attempts to get 22730517Skarels * the courier in sync. 22827000Sdonn */ 22927000Sdonn static int 23027000Sdonn coursync() 23127000Sdonn { 23227000Sdonn int already = 0; 23330517Skarels int len; 23430517Skarels char buf[40]; 23527000Sdonn 23627000Sdonn while (already++ < MAXRETRY) { 23727000Sdonn ioctl(FD, TIOCFLUSH, 0); /* flush any clutter */ 23827000Sdonn write(FD, "\rAT Z\r", 6); /* reset modem */ 23930517Skarels bzero(buf, sizeof(buf)); 24027000Sdonn sleep(1); 24130517Skarels ioctl(FD, FIONREAD, &len); 24230517Skarels if (len) { 24330517Skarels len = read(FD, buf, sizeof(buf)); 24430517Skarels #ifdef DEBUG 24530517Skarels buf[len] = '\0'; 24630517Skarels printf("coursync: (\"%s\")\n\r", buf); 24730517Skarels #endif 24830517Skarels if (index(buf, '0') || 24930517Skarels (index(buf, 'O') && index(buf, 'K'))) 25030517Skarels return(1); 25127000Sdonn } 25230517Skarels /* 25330517Skarels * If not strapped for DTR control, 25430517Skarels * try to get command mode. 25530517Skarels */ 25630517Skarels sleep(1); 25727000Sdonn write(FD, "+++", 3); 25830517Skarels sleep(1); 25930517Skarels /* 26030517Skarels * Toggle DTR to force anyone off that might have left 26130517Skarels * the modem connected. 26230517Skarels */ 26330517Skarels ioctl(FD, TIOCCDTR, 0); 26430517Skarels sleep(1); 26530517Skarels ioctl(FD, TIOCSDTR, 0); 26627000Sdonn } 26727000Sdonn write(FD, "\rAT Z\r", 6); 26830517Skarels return (0); 26927000Sdonn } 27027000Sdonn 27127000Sdonn #undef write 27227000Sdonn 27327000Sdonn cour_write(fd, cp, n) 27427000Sdonn int fd; 27527000Sdonn char *cp; 27627000Sdonn int n; 27727000Sdonn { 27827000Sdonn struct sgttyb sb; 27930517Skarels #ifdef notdef 28027000Sdonn if (boolean(value(VERBOSE))) 28127000Sdonn write(1, cp, n); 28230517Skarels #endif 28327000Sdonn ioctl(fd, TIOCGETP, &sb); 28427000Sdonn ioctl(fd, TIOCSETP, &sb); 28527000Sdonn cour_nap(); 28627000Sdonn for ( ; n-- ; cp++) { 28727000Sdonn write(fd, cp, 1); 28827000Sdonn ioctl(fd, TIOCGETP, &sb); 28927000Sdonn ioctl(fd, TIOCSETP, &sb); 29027000Sdonn cour_nap(); 29127000Sdonn } 29227000Sdonn } 29327000Sdonn 29430517Skarels #ifdef DEBUG 29527000Sdonn verbose_read() 29627000Sdonn { 29727000Sdonn int n = 0; 29827000Sdonn char buf[BUFSIZ]; 29930517Skarels 30027000Sdonn if (ioctl(FD, FIONREAD, &n) < 0) 30127000Sdonn return; 30227000Sdonn if (n <= 0) 30327000Sdonn return; 30427000Sdonn if (read(FD, buf, n) != n) 30527000Sdonn return; 30627000Sdonn write(1, buf, n); 30727000Sdonn } 30830517Skarels #endif 30927000Sdonn 31027000Sdonn /* 31127000Sdonn * Code stolen from /usr/src/lib/libc/gen/sleep.c 31227000Sdonn */ 31327000Sdonn #include <sys/time.h> 31427000Sdonn 31527000Sdonn #define mask(s) (1<<((s)-1)) 31627000Sdonn #define setvec(vec, a) \ 31727000Sdonn vec.sv_handler = a; vec.sv_mask = vec.sv_onstack = 0 31827000Sdonn 31927000Sdonn static napms = 50; /* Give the courier 50 milliseconds between characters */ 32027000Sdonn 32127000Sdonn static int ringring; 32227000Sdonn 32327000Sdonn cour_nap() 32427000Sdonn { 32527000Sdonn 32639253Sbostic static void cour_napx(); 32727000Sdonn int omask; 32827000Sdonn struct itimerval itv, oitv; 32927000Sdonn register struct itimerval *itp = &itv; 33027000Sdonn struct sigvec vec, ovec; 33127000Sdonn 33227000Sdonn timerclear(&itp->it_interval); 33327000Sdonn timerclear(&itp->it_value); 33427000Sdonn if (setitimer(ITIMER_REAL, itp, &oitv) < 0) 33527000Sdonn return; 33627000Sdonn setvec(ovec, SIG_DFL); 33727000Sdonn omask = sigblock(mask(SIGALRM)); 33827000Sdonn itp->it_value.tv_sec = napms/1000; 33927000Sdonn itp->it_value.tv_usec = ((napms%1000)*1000); 34027000Sdonn setvec(vec, cour_napx); 34127000Sdonn ringring = 0; 34227000Sdonn (void) sigvec(SIGALRM, &vec, &ovec); 34327000Sdonn (void) setitimer(ITIMER_REAL, itp, (struct itimerval *)0); 34427000Sdonn while (!ringring) 34527000Sdonn sigpause(omask &~ mask(SIGALRM)); 34627000Sdonn (void) sigvec(SIGALRM, &ovec, (struct sigvec *)0); 34727000Sdonn (void) setitimer(ITIMER_REAL, &oitv, (struct itimerval *)0); 34827000Sdonn (void) sigsetmask(omask); 34927000Sdonn } 35027000Sdonn 35139253Sbostic static void 35227000Sdonn cour_napx() 35327000Sdonn { 35427000Sdonn ringring = 1; 35527000Sdonn } 356