127000Sdonn /* 227000Sdonn * Copyright (c) 1986 Regents of the University of California. 327000Sdonn * All rights reserved. The Berkeley software License Agreement 427000Sdonn * specifies the terms and conditions for redistribution. 527000Sdonn */ 627000Sdonn 727000Sdonn #ifndef lint 8*30517Skarels static char sccsid[] = "@(#)courier.c 5.2 (Berkeley) 02/17/87"; 927000Sdonn #endif 1027000Sdonn 1127000Sdonn #define write cour_write 1227000Sdonn /* 13*30517Skarels * Routines for calling up on a Courier modem. 14*30517Skarels * Derived from Hayes driver. 1527000Sdonn */ 1627000Sdonn #include "tip.h" 1727000Sdonn #include <stdio.h> 1827000Sdonn 1927000Sdonn #define MAXRETRY 5 2027000Sdonn 2127000Sdonn static int sigALRM(); 2227000Sdonn static int timeout = 0; 23*30517Skarels static int connected = 0; 2427000Sdonn static jmp_buf timeoutbuf, intbuf; 2527000Sdonn static int (*osigint)(); 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 3527000Sdonn if (boolean(value(VERBOSE))) 3627000Sdonn printf("Using \"%s\"\n", acu); 3727000Sdonn 3827000Sdonn ioctl(FD, TIOCHPCL, 0); 3927000Sdonn /* 4027000Sdonn * Get in synch. 4127000Sdonn */ 4227000Sdonn if (!coursync()) { 43*30517Skarels badsynch: 4427000Sdonn printf("can't synchronize with courier\n"); 4527000Sdonn #ifdef ACULOG 4627000Sdonn logent(value(HOST), num, "courier", "can't synch up"); 4727000Sdonn #endif 4827000Sdonn return (0); 4927000Sdonn } 50*30517Skarels write(FD, "AT E0\r", 6); /* turn off echoing */ 51*30517Skarels sleep(1); 52*30517Skarels #ifdef DEBUG 53*30517Skarels if (boolean(value(VERBOSE))) 54*30517Skarels verbose_read(); 55*30517Skarels #endif 56*30517Skarels ioctl(FD, TIOCFLUSH, 0); /* flush any clutter */ 57*30517Skarels write(FD, "AT C1 E0 H0 Q0 X6 V1\r", 21); 58*30517Skarels if (!cour_swallow("\r\nOK\r\n")) 59*30517Skarels goto badsynch; 6027000Sdonn fflush(stdout); 6127000Sdonn write(FD, "AT D", 4); 6227000Sdonn for (cp = num; *cp; cp++) 6327000Sdonn if (*cp == '=') 6427000Sdonn *cp = ','; 6527000Sdonn write(FD, num, strlen(num)); 6627000Sdonn write(FD, "\r", 1); 6727000Sdonn connected = cour_connect(); 6827000Sdonn #ifdef ACULOG 6927000Sdonn if (timeout) { 7027000Sdonn sprintf(line, "%d second dial timeout", 7127000Sdonn number(value(DIALTIMEOUT))); 7227000Sdonn logent(value(HOST), num, "cour", line); 7327000Sdonn } 7427000Sdonn #endif 7527000Sdonn if (timeout) 7627000Sdonn cour_disconnect(); 7727000Sdonn return (connected); 7827000Sdonn } 7927000Sdonn 8027000Sdonn cour_disconnect() 81*30517Skarels { 82*30517Skarels /* first hang up the modem*/ 83*30517Skarels ioctl(FD, TIOCCDTR, 0); 84*30517Skarels sleep(1); 85*30517Skarels ioctl(FD, TIOCSDTR, 0); 86*30517Skarels coursync(); /* reset */ 8727000Sdonn close(FD); 8827000Sdonn } 8927000Sdonn 9027000Sdonn cour_abort() 91*30517Skarels { 92*30517Skarels write(FD, "\r", 1); /* send anything to abort the call */ 93*30517Skarels cour_disconnect(); 9427000Sdonn } 9527000Sdonn 9627000Sdonn static int 9727000Sdonn sigALRM() 9827000Sdonn { 9927000Sdonn printf("\07timeout waiting for reply\n"); 10027000Sdonn timeout = 1; 10127000Sdonn longjmp(timeoutbuf, 1); 10227000Sdonn } 10327000Sdonn 10427000Sdonn static int 10527000Sdonn cour_swallow(match) 10627000Sdonn register char *match; 10727000Sdonn { 10827000Sdonn char c; 10927000Sdonn int (*f)(); 11027000Sdonn 11127000Sdonn f = signal(SIGALRM, sigALRM); 11227000Sdonn timeout = 0; 11327000Sdonn do { 11427000Sdonn if (*match =='\0') { 11527000Sdonn signal(SIGALRM, f); 116*30517Skarels return (1); 11727000Sdonn } 11827000Sdonn if (setjmp(timeoutbuf)) { 11927000Sdonn signal(SIGALRM, f); 12027000Sdonn return (0); 12127000Sdonn } 12227000Sdonn alarm(number(value(DIALTIMEOUT))); 12327000Sdonn read(FD, &c, 1); 12427000Sdonn alarm(0); 12527000Sdonn c &= 0177; 126*30517Skarels #ifdef DEBUG 12727000Sdonn if (boolean(value(VERBOSE))) 12827000Sdonn putchar(c); 129*30517Skarels #endif 13027000Sdonn } while (c == *match++); 131*30517Skarels #ifdef DEBUG 13227000Sdonn if (boolean(value(VERBOSE))) 13327000Sdonn fflush(stdout); 134*30517Skarels #endif 13527000Sdonn signal(SIGALRM, SIG_DFL); 13627000Sdonn return (0); 13727000Sdonn } 13827000Sdonn 13927000Sdonn struct baud_msg { 14027000Sdonn char *msg; 14127000Sdonn int baud; 14227000Sdonn } baud_msg[] = { 14327000Sdonn "", B300, 14427000Sdonn " 1200", B1200, 14527000Sdonn " 2400", B2400, 14627000Sdonn 0, 0, 14727000Sdonn }; 14827000Sdonn 14927000Sdonn static int 15027000Sdonn cour_connect() 15127000Sdonn { 15227000Sdonn char c; 15327000Sdonn int nc, nl, n; 15427000Sdonn struct sgttyb sb; 15527000Sdonn char dialer_buf[64]; 15627000Sdonn struct baud_msg *bm; 15727000Sdonn int (*f)(); 15827000Sdonn 15927000Sdonn if (cour_swallow("\r\n") == 0) 16027000Sdonn return (0); 16127000Sdonn f = signal(SIGALRM, sigALRM); 16227000Sdonn again: 16327000Sdonn nc = 0; nl = sizeof(dialer_buf)-1; 16427000Sdonn bzero(dialer_buf, sizeof(dialer_buf)); 16527000Sdonn timeout = 0; 16627000Sdonn for (nc = 0, nl = sizeof(dialer_buf)-1 ; nl > 0 ; nc++, nl--) { 16727000Sdonn if (setjmp(timeoutbuf)) 16827000Sdonn break; 16927000Sdonn alarm(number(value(DIALTIMEOUT))); 17027000Sdonn n = read(FD, &c, 1); 17127000Sdonn alarm(0); 17227000Sdonn if (n <= 0) 17327000Sdonn break; 17427000Sdonn c &= 0x7f; 17527000Sdonn if (c == '\r') { 17627000Sdonn if (cour_swallow("\n") == 0) 17727000Sdonn break; 17827000Sdonn if (!dialer_buf[0]) 17927000Sdonn goto again; 180*30517Skarels if (strcmp(dialer_buf, "RINGING") == 0 && 181*30517Skarels boolean(value(VERBOSE))) { 182*30517Skarels #ifdef DEBUG 18327000Sdonn printf("%s\r\n", dialer_buf); 184*30517Skarels #endif 18527000Sdonn goto again; 18627000Sdonn } 18727000Sdonn if (strncmp(dialer_buf, "CONNECT", 18827000Sdonn sizeof("CONNECT")-1) != 0) 18927000Sdonn break; 19027000Sdonn for (bm = baud_msg ; bm ; bm++) 19127000Sdonn if (strcmp(bm->msg, 19227000Sdonn dialer_buf+sizeof("CONNECT")-1) == 0) { 19327000Sdonn if (ioctl(FD, TIOCGETP, &sb) < 0) { 19427000Sdonn perror("TIOCGETP"); 19527000Sdonn goto error; 19627000Sdonn } 19727000Sdonn sb.sg_ispeed = sb.sg_ospeed = bm->baud; 19827000Sdonn if (ioctl(FD, TIOCSETP, &sb) < 0) { 19927000Sdonn perror("TIOCSETP"); 20027000Sdonn goto error; 20127000Sdonn } 20227000Sdonn signal(SIGALRM, f); 203*30517Skarels #ifdef DEBUG 20427000Sdonn if (boolean(value(VERBOSE))) 20527000Sdonn printf("%s\r\n", dialer_buf); 206*30517Skarels #endif 20727000Sdonn return (1); 20827000Sdonn } 20927000Sdonn break; 21027000Sdonn } 21127000Sdonn dialer_buf[nc] = c; 21227000Sdonn #ifdef notdef 21327000Sdonn if (boolean(value(VERBOSE))) 21427000Sdonn putchar(c); 21527000Sdonn #endif 21627000Sdonn } 21727000Sdonn error1: 21827000Sdonn printf("%s\r\n", dialer_buf); 21927000Sdonn error: 22027000Sdonn signal(SIGALRM, f); 22127000Sdonn return (0); 22227000Sdonn } 22327000Sdonn 22427000Sdonn /* 22527000Sdonn * This convoluted piece of code attempts to get 226*30517Skarels * the courier in sync. 22727000Sdonn */ 22827000Sdonn static int 22927000Sdonn coursync() 23027000Sdonn { 23127000Sdonn int already = 0; 232*30517Skarels int len; 233*30517Skarels char buf[40]; 23427000Sdonn 23527000Sdonn while (already++ < MAXRETRY) { 23627000Sdonn ioctl(FD, TIOCFLUSH, 0); /* flush any clutter */ 23727000Sdonn write(FD, "\rAT Z\r", 6); /* reset modem */ 238*30517Skarels bzero(buf, sizeof(buf)); 23927000Sdonn sleep(1); 240*30517Skarels ioctl(FD, FIONREAD, &len); 241*30517Skarels if (len) { 242*30517Skarels len = read(FD, buf, sizeof(buf)); 243*30517Skarels #ifdef DEBUG 244*30517Skarels buf[len] = '\0'; 245*30517Skarels printf("coursync: (\"%s\")\n\r", buf); 246*30517Skarels #endif 247*30517Skarels if (index(buf, '0') || 248*30517Skarels (index(buf, 'O') && index(buf, 'K'))) 249*30517Skarels return(1); 25027000Sdonn } 251*30517Skarels /* 252*30517Skarels * If not strapped for DTR control, 253*30517Skarels * try to get command mode. 254*30517Skarels */ 255*30517Skarels sleep(1); 25627000Sdonn write(FD, "+++", 3); 257*30517Skarels sleep(1); 258*30517Skarels /* 259*30517Skarels * Toggle DTR to force anyone off that might have left 260*30517Skarels * the modem connected. 261*30517Skarels */ 262*30517Skarels ioctl(FD, TIOCCDTR, 0); 263*30517Skarels sleep(1); 264*30517Skarels ioctl(FD, TIOCSDTR, 0); 26527000Sdonn } 26627000Sdonn write(FD, "\rAT Z\r", 6); 267*30517Skarels return (0); 26827000Sdonn } 26927000Sdonn 27027000Sdonn #undef write 27127000Sdonn 27227000Sdonn cour_write(fd, cp, n) 27327000Sdonn int fd; 27427000Sdonn char *cp; 27527000Sdonn int n; 27627000Sdonn { 27727000Sdonn struct sgttyb sb; 278*30517Skarels #ifdef notdef 27927000Sdonn if (boolean(value(VERBOSE))) 28027000Sdonn write(1, cp, n); 281*30517Skarels #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 293*30517Skarels #ifdef DEBUG 29427000Sdonn verbose_read() 29527000Sdonn { 29627000Sdonn int n = 0; 29727000Sdonn char buf[BUFSIZ]; 298*30517Skarels 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 } 307*30517Skarels #endif 30827000Sdonn 30927000Sdonn /* 31027000Sdonn * Code stolen from /usr/src/lib/libc/gen/sleep.c 31127000Sdonn */ 31227000Sdonn #include <sys/time.h> 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 32527000Sdonn static int 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 35027000Sdonn static 35127000Sdonn cour_napx() 35227000Sdonn { 35327000Sdonn ringring = 1; 35427000Sdonn } 355