127000Sdonn /* 235492Sbostic * Copyright (c) 1986 The Regents of the University of California. 335492Sbostic * All rights reserved. 435492Sbostic * 535492Sbostic * Redistribution and use in source and binary forms are permitted 635492Sbostic * provided that the above copyright notice and this paragraph are 735492Sbostic * duplicated in all such forms and that any documentation, 835492Sbostic * advertising materials, and other materials related to such 935492Sbostic * distribution and use acknowledge that the software was developed 1035492Sbostic * by the University of California, Berkeley. The name of the 1135492Sbostic * University may not be used to endorse or promote products derived 1235492Sbostic * from this software without specific prior written permission. 1335492Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1435492Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1535492Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1627000Sdonn */ 1727000Sdonn 1827000Sdonn #ifndef lint 19*39253Sbostic static char sccsid[] = "@(#)courier.c 5.4 (Berkeley) 10/03/89"; 2035492Sbostic #endif /* not lint */ 2127000Sdonn 2227000Sdonn #define write cour_write 2327000Sdonn /* 2430517Skarels * Routines for calling up on a Courier modem. 2530517Skarels * Derived from Hayes driver. 2627000Sdonn */ 2727000Sdonn #include "tip.h" 2827000Sdonn #include <stdio.h> 2927000Sdonn 3027000Sdonn #define MAXRETRY 5 3127000Sdonn 32*39253Sbostic static void sigALRM(); 3327000Sdonn static int timeout = 0; 3430517Skarels static int connected = 0; 3527000Sdonn static jmp_buf timeoutbuf, intbuf; 3627000Sdonn static int (*osigint)(); 3727000Sdonn 3827000Sdonn cour_dialer(num, acu) 3927000Sdonn register char *num; 4027000Sdonn char *acu; 4127000Sdonn { 4227000Sdonn register char *cp; 4327000Sdonn #ifdef ACULOG 4427000Sdonn char line[80]; 4527000Sdonn #endif 4627000Sdonn if (boolean(value(VERBOSE))) 4727000Sdonn printf("Using \"%s\"\n", acu); 4827000Sdonn 4927000Sdonn ioctl(FD, TIOCHPCL, 0); 5027000Sdonn /* 5127000Sdonn * Get in synch. 5227000Sdonn */ 5327000Sdonn if (!coursync()) { 5430517Skarels badsynch: 5527000Sdonn printf("can't synchronize with courier\n"); 5627000Sdonn #ifdef ACULOG 5727000Sdonn logent(value(HOST), num, "courier", "can't synch up"); 5827000Sdonn #endif 5927000Sdonn return (0); 6027000Sdonn } 6130517Skarels write(FD, "AT E0\r", 6); /* turn off echoing */ 6230517Skarels sleep(1); 6330517Skarels #ifdef DEBUG 6430517Skarels if (boolean(value(VERBOSE))) 6530517Skarels verbose_read(); 6630517Skarels #endif 6730517Skarels ioctl(FD, TIOCFLUSH, 0); /* flush any clutter */ 6830517Skarels write(FD, "AT C1 E0 H0 Q0 X6 V1\r", 21); 6930517Skarels if (!cour_swallow("\r\nOK\r\n")) 7030517Skarels goto badsynch; 7127000Sdonn fflush(stdout); 7227000Sdonn write(FD, "AT D", 4); 7327000Sdonn for (cp = num; *cp; cp++) 7427000Sdonn if (*cp == '=') 7527000Sdonn *cp = ','; 7627000Sdonn write(FD, num, strlen(num)); 7727000Sdonn write(FD, "\r", 1); 7827000Sdonn connected = cour_connect(); 7927000Sdonn #ifdef ACULOG 8027000Sdonn if (timeout) { 8127000Sdonn sprintf(line, "%d second dial timeout", 8227000Sdonn number(value(DIALTIMEOUT))); 8327000Sdonn logent(value(HOST), num, "cour", line); 8427000Sdonn } 8527000Sdonn #endif 8627000Sdonn if (timeout) 8727000Sdonn cour_disconnect(); 8827000Sdonn return (connected); 8927000Sdonn } 9027000Sdonn 9127000Sdonn cour_disconnect() 9230517Skarels { 9330517Skarels /* first hang up the modem*/ 9430517Skarels ioctl(FD, TIOCCDTR, 0); 9530517Skarels sleep(1); 9630517Skarels ioctl(FD, TIOCSDTR, 0); 9730517Skarels coursync(); /* reset */ 9827000Sdonn close(FD); 9927000Sdonn } 10027000Sdonn 10127000Sdonn cour_abort() 10230517Skarels { 10330517Skarels write(FD, "\r", 1); /* send anything to abort the call */ 10430517Skarels cour_disconnect(); 10527000Sdonn } 10627000Sdonn 107*39253Sbostic static void 10827000Sdonn sigALRM() 10927000Sdonn { 11027000Sdonn printf("\07timeout waiting for reply\n"); 11127000Sdonn timeout = 1; 11227000Sdonn longjmp(timeoutbuf, 1); 11327000Sdonn } 11427000Sdonn 11527000Sdonn static int 11627000Sdonn cour_swallow(match) 11727000Sdonn register char *match; 11827000Sdonn { 119*39253Sbostic sig_t f; 12027000Sdonn char c; 12127000Sdonn 12227000Sdonn f = signal(SIGALRM, sigALRM); 12327000Sdonn timeout = 0; 12427000Sdonn do { 12527000Sdonn if (*match =='\0') { 12627000Sdonn signal(SIGALRM, f); 12730517Skarels return (1); 12827000Sdonn } 12927000Sdonn if (setjmp(timeoutbuf)) { 13027000Sdonn signal(SIGALRM, f); 13127000Sdonn return (0); 13227000Sdonn } 13327000Sdonn alarm(number(value(DIALTIMEOUT))); 13427000Sdonn read(FD, &c, 1); 13527000Sdonn alarm(0); 13627000Sdonn c &= 0177; 13730517Skarels #ifdef DEBUG 13827000Sdonn if (boolean(value(VERBOSE))) 13927000Sdonn putchar(c); 14030517Skarels #endif 14127000Sdonn } while (c == *match++); 14230517Skarels #ifdef DEBUG 14327000Sdonn if (boolean(value(VERBOSE))) 14427000Sdonn fflush(stdout); 14530517Skarels #endif 14627000Sdonn signal(SIGALRM, SIG_DFL); 14727000Sdonn return (0); 14827000Sdonn } 14927000Sdonn 15027000Sdonn struct baud_msg { 15127000Sdonn char *msg; 15227000Sdonn int baud; 15327000Sdonn } baud_msg[] = { 15427000Sdonn "", B300, 15527000Sdonn " 1200", B1200, 15627000Sdonn " 2400", B2400, 15727000Sdonn 0, 0, 15827000Sdonn }; 15927000Sdonn 16027000Sdonn static int 16127000Sdonn cour_connect() 16227000Sdonn { 16327000Sdonn char c; 16427000Sdonn int nc, nl, n; 16527000Sdonn struct sgttyb sb; 16627000Sdonn char dialer_buf[64]; 16727000Sdonn struct baud_msg *bm; 168*39253Sbostic sig_t f; 16927000Sdonn 17027000Sdonn if (cour_swallow("\r\n") == 0) 17127000Sdonn return (0); 17227000Sdonn f = signal(SIGALRM, sigALRM); 17327000Sdonn again: 17427000Sdonn nc = 0; nl = sizeof(dialer_buf)-1; 17527000Sdonn bzero(dialer_buf, sizeof(dialer_buf)); 17627000Sdonn timeout = 0; 17727000Sdonn for (nc = 0, nl = sizeof(dialer_buf)-1 ; nl > 0 ; nc++, nl--) { 17827000Sdonn if (setjmp(timeoutbuf)) 17927000Sdonn break; 18027000Sdonn alarm(number(value(DIALTIMEOUT))); 18127000Sdonn n = read(FD, &c, 1); 18227000Sdonn alarm(0); 18327000Sdonn if (n <= 0) 18427000Sdonn break; 18527000Sdonn c &= 0x7f; 18627000Sdonn if (c == '\r') { 18727000Sdonn if (cour_swallow("\n") == 0) 18827000Sdonn break; 18927000Sdonn if (!dialer_buf[0]) 19027000Sdonn goto again; 19130517Skarels if (strcmp(dialer_buf, "RINGING") == 0 && 19230517Skarels boolean(value(VERBOSE))) { 19330517Skarels #ifdef DEBUG 19427000Sdonn printf("%s\r\n", dialer_buf); 19530517Skarels #endif 19627000Sdonn goto again; 19727000Sdonn } 19827000Sdonn if (strncmp(dialer_buf, "CONNECT", 19927000Sdonn sizeof("CONNECT")-1) != 0) 20027000Sdonn break; 20127000Sdonn for (bm = baud_msg ; bm ; bm++) 20227000Sdonn if (strcmp(bm->msg, 20327000Sdonn dialer_buf+sizeof("CONNECT")-1) == 0) { 20427000Sdonn if (ioctl(FD, TIOCGETP, &sb) < 0) { 20527000Sdonn perror("TIOCGETP"); 20627000Sdonn goto error; 20727000Sdonn } 20827000Sdonn sb.sg_ispeed = sb.sg_ospeed = bm->baud; 20927000Sdonn if (ioctl(FD, TIOCSETP, &sb) < 0) { 21027000Sdonn perror("TIOCSETP"); 21127000Sdonn goto error; 21227000Sdonn } 21327000Sdonn signal(SIGALRM, f); 21430517Skarels #ifdef DEBUG 21527000Sdonn if (boolean(value(VERBOSE))) 21627000Sdonn printf("%s\r\n", dialer_buf); 21730517Skarels #endif 21827000Sdonn return (1); 21927000Sdonn } 22027000Sdonn break; 22127000Sdonn } 22227000Sdonn dialer_buf[nc] = c; 22327000Sdonn #ifdef notdef 22427000Sdonn if (boolean(value(VERBOSE))) 22527000Sdonn putchar(c); 22627000Sdonn #endif 22727000Sdonn } 22827000Sdonn error1: 22927000Sdonn printf("%s\r\n", dialer_buf); 23027000Sdonn error: 23127000Sdonn signal(SIGALRM, f); 23227000Sdonn return (0); 23327000Sdonn } 23427000Sdonn 23527000Sdonn /* 23627000Sdonn * This convoluted piece of code attempts to get 23730517Skarels * the courier in sync. 23827000Sdonn */ 23927000Sdonn static int 24027000Sdonn coursync() 24127000Sdonn { 24227000Sdonn int already = 0; 24330517Skarels int len; 24430517Skarels char buf[40]; 24527000Sdonn 24627000Sdonn while (already++ < MAXRETRY) { 24727000Sdonn ioctl(FD, TIOCFLUSH, 0); /* flush any clutter */ 24827000Sdonn write(FD, "\rAT Z\r", 6); /* reset modem */ 24930517Skarels bzero(buf, sizeof(buf)); 25027000Sdonn sleep(1); 25130517Skarels ioctl(FD, FIONREAD, &len); 25230517Skarels if (len) { 25330517Skarels len = read(FD, buf, sizeof(buf)); 25430517Skarels #ifdef DEBUG 25530517Skarels buf[len] = '\0'; 25630517Skarels printf("coursync: (\"%s\")\n\r", buf); 25730517Skarels #endif 25830517Skarels if (index(buf, '0') || 25930517Skarels (index(buf, 'O') && index(buf, 'K'))) 26030517Skarels return(1); 26127000Sdonn } 26230517Skarels /* 26330517Skarels * If not strapped for DTR control, 26430517Skarels * try to get command mode. 26530517Skarels */ 26630517Skarels sleep(1); 26727000Sdonn write(FD, "+++", 3); 26830517Skarels sleep(1); 26930517Skarels /* 27030517Skarels * Toggle DTR to force anyone off that might have left 27130517Skarels * the modem connected. 27230517Skarels */ 27330517Skarels ioctl(FD, TIOCCDTR, 0); 27430517Skarels sleep(1); 27530517Skarels ioctl(FD, TIOCSDTR, 0); 27627000Sdonn } 27727000Sdonn write(FD, "\rAT Z\r", 6); 27830517Skarels return (0); 27927000Sdonn } 28027000Sdonn 28127000Sdonn #undef write 28227000Sdonn 28327000Sdonn cour_write(fd, cp, n) 28427000Sdonn int fd; 28527000Sdonn char *cp; 28627000Sdonn int n; 28727000Sdonn { 28827000Sdonn struct sgttyb sb; 28930517Skarels #ifdef notdef 29027000Sdonn if (boolean(value(VERBOSE))) 29127000Sdonn write(1, cp, n); 29230517Skarels #endif 29327000Sdonn ioctl(fd, TIOCGETP, &sb); 29427000Sdonn ioctl(fd, TIOCSETP, &sb); 29527000Sdonn cour_nap(); 29627000Sdonn for ( ; n-- ; cp++) { 29727000Sdonn write(fd, cp, 1); 29827000Sdonn ioctl(fd, TIOCGETP, &sb); 29927000Sdonn ioctl(fd, TIOCSETP, &sb); 30027000Sdonn cour_nap(); 30127000Sdonn } 30227000Sdonn } 30327000Sdonn 30430517Skarels #ifdef DEBUG 30527000Sdonn verbose_read() 30627000Sdonn { 30727000Sdonn int n = 0; 30827000Sdonn char buf[BUFSIZ]; 30930517Skarels 31027000Sdonn if (ioctl(FD, FIONREAD, &n) < 0) 31127000Sdonn return; 31227000Sdonn if (n <= 0) 31327000Sdonn return; 31427000Sdonn if (read(FD, buf, n) != n) 31527000Sdonn return; 31627000Sdonn write(1, buf, n); 31727000Sdonn } 31830517Skarels #endif 31927000Sdonn 32027000Sdonn /* 32127000Sdonn * Code stolen from /usr/src/lib/libc/gen/sleep.c 32227000Sdonn */ 32327000Sdonn #include <sys/time.h> 32427000Sdonn 32527000Sdonn #define mask(s) (1<<((s)-1)) 32627000Sdonn #define setvec(vec, a) \ 32727000Sdonn vec.sv_handler = a; vec.sv_mask = vec.sv_onstack = 0 32827000Sdonn 32927000Sdonn static napms = 50; /* Give the courier 50 milliseconds between characters */ 33027000Sdonn 33127000Sdonn static int ringring; 33227000Sdonn 33327000Sdonn cour_nap() 33427000Sdonn { 33527000Sdonn 336*39253Sbostic static void cour_napx(); 33727000Sdonn int omask; 33827000Sdonn struct itimerval itv, oitv; 33927000Sdonn register struct itimerval *itp = &itv; 34027000Sdonn struct sigvec vec, ovec; 34127000Sdonn 34227000Sdonn timerclear(&itp->it_interval); 34327000Sdonn timerclear(&itp->it_value); 34427000Sdonn if (setitimer(ITIMER_REAL, itp, &oitv) < 0) 34527000Sdonn return; 34627000Sdonn setvec(ovec, SIG_DFL); 34727000Sdonn omask = sigblock(mask(SIGALRM)); 34827000Sdonn itp->it_value.tv_sec = napms/1000; 34927000Sdonn itp->it_value.tv_usec = ((napms%1000)*1000); 35027000Sdonn setvec(vec, cour_napx); 35127000Sdonn ringring = 0; 35227000Sdonn (void) sigvec(SIGALRM, &vec, &ovec); 35327000Sdonn (void) setitimer(ITIMER_REAL, itp, (struct itimerval *)0); 35427000Sdonn while (!ringring) 35527000Sdonn sigpause(omask &~ mask(SIGALRM)); 35627000Sdonn (void) sigvec(SIGALRM, &ovec, (struct sigvec *)0); 35727000Sdonn (void) setitimer(ITIMER_REAL, &oitv, (struct itimerval *)0); 35827000Sdonn (void) sigsetmask(omask); 35927000Sdonn } 36027000Sdonn 361*39253Sbostic static void 36227000Sdonn cour_napx() 36327000Sdonn { 36427000Sdonn ringring = 1; 36527000Sdonn } 366