1*27000Sdonn /* 2*27000Sdonn * Copyright (c) 1986 Regents of the University of California. 3*27000Sdonn * All rights reserved. The Berkeley software License Agreement 4*27000Sdonn * specifies the terms and conditions for redistribution. 5*27000Sdonn */ 6*27000Sdonn 7*27000Sdonn #ifndef lint 8*27000Sdonn static char sccsid[] = "@(#)courier.c 5.1 (Berkeley) 04/03/86"; 9*27000Sdonn #endif 10*27000Sdonn 11*27000Sdonn #define write cour_write 12*27000Sdonn /* 13*27000Sdonn * Routines for calling up on a Hayes Smartmodem 14*27000Sdonn */ 15*27000Sdonn #include "tip.h" 16*27000Sdonn #include <stdio.h> 17*27000Sdonn 18*27000Sdonn #define MAXRETRY 5 19*27000Sdonn 20*27000Sdonn static int sigALRM(); 21*27000Sdonn static int timeout = 0; 22*27000Sdonn static jmp_buf timeoutbuf, intbuf; 23*27000Sdonn static int (*osigint)(); 24*27000Sdonn 25*27000Sdonn cour_dialer(num, acu) 26*27000Sdonn register char *num; 27*27000Sdonn char *acu; 28*27000Sdonn { 29*27000Sdonn register char *cp; 30*27000Sdonn register int connected = 0; 31*27000Sdonn #ifdef ACULOG 32*27000Sdonn char line[80]; 33*27000Sdonn #endif 34*27000Sdonn if (boolean(value(VERBOSE))) 35*27000Sdonn printf("Using \"%s\"\n", acu); 36*27000Sdonn 37*27000Sdonn ioctl(FD, TIOCHPCL, 0); 38*27000Sdonn /* 39*27000Sdonn * Get in synch. 40*27000Sdonn */ 41*27000Sdonn if (!coursync()) { 42*27000Sdonn printf("can't synchronize with courier\n"); 43*27000Sdonn #ifdef ACULOG 44*27000Sdonn logent(value(HOST), num, "courier", "can't synch up"); 45*27000Sdonn #endif 46*27000Sdonn return (0); 47*27000Sdonn } 48*27000Sdonn fflush(stdout); 49*27000Sdonn write(FD, "AT D", 4); 50*27000Sdonn for (cp = num; *cp; cp++) 51*27000Sdonn if (*cp == '=') 52*27000Sdonn *cp = ','; 53*27000Sdonn write(FD, num, strlen(num)); 54*27000Sdonn write(FD, "\r", 1); 55*27000Sdonn connected = cour_connect(); 56*27000Sdonn #ifdef ACULOG 57*27000Sdonn if (timeout) { 58*27000Sdonn sprintf(line, "%d second dial timeout", 59*27000Sdonn number(value(DIALTIMEOUT))); 60*27000Sdonn logent(value(HOST), num, "cour", line); 61*27000Sdonn } 62*27000Sdonn #endif 63*27000Sdonn if (timeout) 64*27000Sdonn cour_disconnect(); 65*27000Sdonn return (connected); 66*27000Sdonn } 67*27000Sdonn 68*27000Sdonn cour_disconnect() 69*27000Sdonn { 70*27000Sdonn close(FD); 71*27000Sdonn } 72*27000Sdonn 73*27000Sdonn cour_abort() 74*27000Sdonn { 75*27000Sdonn write(FD, "\rAT Z\r", 6); 76*27000Sdonn close(FD); 77*27000Sdonn } 78*27000Sdonn 79*27000Sdonn static int 80*27000Sdonn sigALRM() 81*27000Sdonn { 82*27000Sdonn printf("\07timeout waiting for reply\n"); 83*27000Sdonn timeout = 1; 84*27000Sdonn longjmp(timeoutbuf, 1); 85*27000Sdonn } 86*27000Sdonn 87*27000Sdonn static int 88*27000Sdonn cour_swallow(match) 89*27000Sdonn register char *match; 90*27000Sdonn { 91*27000Sdonn char c; 92*27000Sdonn int (*f)(); 93*27000Sdonn 94*27000Sdonn f = signal(SIGALRM, sigALRM); 95*27000Sdonn timeout = 0; 96*27000Sdonn do { 97*27000Sdonn if (*match =='\0') { 98*27000Sdonn signal(SIGALRM, f); 99*27000Sdonn return 1; 100*27000Sdonn } 101*27000Sdonn if (setjmp(timeoutbuf)) { 102*27000Sdonn signal(SIGALRM, f); 103*27000Sdonn return (0); 104*27000Sdonn } 105*27000Sdonn alarm(number(value(DIALTIMEOUT))); 106*27000Sdonn read(FD, &c, 1); 107*27000Sdonn alarm(0); 108*27000Sdonn c &= 0177; 109*27000Sdonn if (boolean(value(VERBOSE))) 110*27000Sdonn putchar(c); 111*27000Sdonn } while (c == *match++); 112*27000Sdonn if (boolean(value(VERBOSE))) 113*27000Sdonn fflush(stdout); 114*27000Sdonn signal(SIGALRM, SIG_DFL); 115*27000Sdonn return (0); 116*27000Sdonn } 117*27000Sdonn 118*27000Sdonn struct baud_msg { 119*27000Sdonn char *msg; 120*27000Sdonn int baud; 121*27000Sdonn } baud_msg[] = { 122*27000Sdonn "", B300, 123*27000Sdonn " 1200", B1200, 124*27000Sdonn " 2400", B2400, 125*27000Sdonn 0, 0, 126*27000Sdonn }; 127*27000Sdonn 128*27000Sdonn static int 129*27000Sdonn cour_connect() 130*27000Sdonn { 131*27000Sdonn char c; 132*27000Sdonn int nc, nl, n; 133*27000Sdonn struct sgttyb sb; 134*27000Sdonn char dialer_buf[64]; 135*27000Sdonn struct baud_msg *bm; 136*27000Sdonn int (*f)(); 137*27000Sdonn 138*27000Sdonn if (cour_swallow("\r\n") == 0) 139*27000Sdonn return (0); 140*27000Sdonn f = signal(SIGALRM, sigALRM); 141*27000Sdonn again: 142*27000Sdonn nc = 0; nl = sizeof(dialer_buf)-1; 143*27000Sdonn bzero(dialer_buf, sizeof(dialer_buf)); 144*27000Sdonn timeout = 0; 145*27000Sdonn for (nc = 0, nl = sizeof(dialer_buf)-1 ; nl > 0 ; nc++, nl--) { 146*27000Sdonn if (setjmp(timeoutbuf)) 147*27000Sdonn break; 148*27000Sdonn alarm(number(value(DIALTIMEOUT))); 149*27000Sdonn n = read(FD, &c, 1); 150*27000Sdonn alarm(0); 151*27000Sdonn if (n <= 0) 152*27000Sdonn break; 153*27000Sdonn c &= 0x7f; 154*27000Sdonn if (c == '\r') { 155*27000Sdonn if (cour_swallow("\n") == 0) 156*27000Sdonn break; 157*27000Sdonn if (!dialer_buf[0]) 158*27000Sdonn goto again; 159*27000Sdonn if (strcmp(dialer_buf, "RINGING") == 0) { 160*27000Sdonn printf("%s\r\n", dialer_buf); 161*27000Sdonn goto again; 162*27000Sdonn } 163*27000Sdonn if (strncmp(dialer_buf, "CONNECT", 164*27000Sdonn sizeof("CONNECT")-1) != 0) 165*27000Sdonn break; 166*27000Sdonn for (bm = baud_msg ; bm ; bm++) 167*27000Sdonn if (strcmp(bm->msg, 168*27000Sdonn dialer_buf+sizeof("CONNECT")-1) == 0) { 169*27000Sdonn if (ioctl(FD, TIOCGETP, &sb) < 0) { 170*27000Sdonn perror("TIOCGETP"); 171*27000Sdonn goto error; 172*27000Sdonn } 173*27000Sdonn sb.sg_ispeed = sb.sg_ospeed = bm->baud; 174*27000Sdonn if (ioctl(FD, TIOCSETP, &sb) < 0) { 175*27000Sdonn perror("TIOCSETP"); 176*27000Sdonn goto error; 177*27000Sdonn } 178*27000Sdonn signal(SIGALRM, f); 179*27000Sdonn if (boolean(value(VERBOSE))) 180*27000Sdonn printf("%s\r\n", dialer_buf); 181*27000Sdonn return (1); 182*27000Sdonn } 183*27000Sdonn break; 184*27000Sdonn } 185*27000Sdonn dialer_buf[nc] = c; 186*27000Sdonn #ifdef notdef 187*27000Sdonn if (boolean(value(VERBOSE))) 188*27000Sdonn putchar(c); 189*27000Sdonn #endif 190*27000Sdonn } 191*27000Sdonn error1: 192*27000Sdonn printf("%s\r\n", dialer_buf); 193*27000Sdonn error: 194*27000Sdonn signal(SIGALRM, f); 195*27000Sdonn return (0); 196*27000Sdonn } 197*27000Sdonn 198*27000Sdonn /* 199*27000Sdonn * This convoluted piece of code attempts to get 200*27000Sdonn * the courier in sync. If you don't have FIONREAD 201*27000Sdonn * there are gory ways to simulate this. 202*27000Sdonn */ 203*27000Sdonn static int 204*27000Sdonn coursync() 205*27000Sdonn { 206*27000Sdonn int already = 0; 207*27000Sdonn 208*27000Sdonn /* 209*27000Sdonn * Toggle DTR to force anyone off that might have left 210*27000Sdonn * the modem connected, and insure a consistent state 211*27000Sdonn * to start from. 212*27000Sdonn * 213*27000Sdonn * If you don't have the ioctl calls to diddle directly 214*27000Sdonn * with DTR, you can always try setting the baud rate to 0. 215*27000Sdonn */ 216*27000Sdonn ioctl(FD, TIOCCDTR, 0); 217*27000Sdonn sleep(2); 218*27000Sdonn ioctl(FD, TIOCSDTR, 0); 219*27000Sdonn while (already++ < MAXRETRY) { 220*27000Sdonn ioctl(FD, TIOCFLUSH, 0); /* flush any clutter */ 221*27000Sdonn write(FD, "\rAT Z\r", 6); /* reset modem */ 222*27000Sdonn sleep(2); 223*27000Sdonn verbose_read(); 224*27000Sdonn write(FD, "AT E0\r", 6); /* turn off echoing */ 225*27000Sdonn sleep(2); 226*27000Sdonn verbose_read(); 227*27000Sdonn ioctl(FD, TIOCFLUSH, 0); /* flush any clutter */ 228*27000Sdonn sleep(1); 229*27000Sdonn write(FD, "AT C1 E0 H0 Q0 X6 V1\r", 21); 230*27000Sdonn if (cour_swallow("\r\nOK\r\n")) { 231*27000Sdonn ioctl(FD, TIOCFLUSH, 0); 232*27000Sdonn return 1; 233*27000Sdonn } 234*27000Sdonn sleep(2); 235*27000Sdonn write(FD, "+++", 3); 236*27000Sdonn sleep(2); 237*27000Sdonn } 238*27000Sdonn write(FD, "\rAT Z\r", 6); 239*27000Sdonn return 0; 240*27000Sdonn } 241*27000Sdonn 242*27000Sdonn #undef write 243*27000Sdonn 244*27000Sdonn cour_write(fd, cp, n) 245*27000Sdonn int fd; 246*27000Sdonn char *cp; 247*27000Sdonn int n; 248*27000Sdonn { 249*27000Sdonn struct sgttyb sb; 250*27000Sdonn if (boolean(value(VERBOSE))) 251*27000Sdonn write(1, cp, n); 252*27000Sdonn ioctl(fd, TIOCGETP, &sb); 253*27000Sdonn ioctl(fd, TIOCSETP, &sb); 254*27000Sdonn cour_nap(); 255*27000Sdonn for ( ; n-- ; cp++) { 256*27000Sdonn write(fd, cp, 1); 257*27000Sdonn ioctl(fd, TIOCGETP, &sb); 258*27000Sdonn ioctl(fd, TIOCSETP, &sb); 259*27000Sdonn cour_nap(); 260*27000Sdonn } 261*27000Sdonn } 262*27000Sdonn 263*27000Sdonn verbose_read() 264*27000Sdonn { 265*27000Sdonn int n = 0; 266*27000Sdonn char buf[BUFSIZ]; 267*27000Sdonn if (!boolean(value(VERBOSE))) 268*27000Sdonn return; 269*27000Sdonn if (ioctl(FD, FIONREAD, &n) < 0) 270*27000Sdonn return; 271*27000Sdonn if (n <= 0) 272*27000Sdonn return; 273*27000Sdonn if (read(FD, buf, n) != n) 274*27000Sdonn return; 275*27000Sdonn write(1, buf, n); 276*27000Sdonn } 277*27000Sdonn 278*27000Sdonn /* 279*27000Sdonn * Code stolen from /usr/src/lib/libc/gen/sleep.c 280*27000Sdonn */ 281*27000Sdonn #include <sys/time.h> 282*27000Sdonn 283*27000Sdonn #define mask(s) (1<<((s)-1)) 284*27000Sdonn #define setvec(vec, a) \ 285*27000Sdonn vec.sv_handler = a; vec.sv_mask = vec.sv_onstack = 0 286*27000Sdonn 287*27000Sdonn static napms = 50; /* Give the courier 50 milliseconds between characters */ 288*27000Sdonn 289*27000Sdonn static int ringring; 290*27000Sdonn 291*27000Sdonn cour_nap() 292*27000Sdonn { 293*27000Sdonn 294*27000Sdonn static int cour_napx(); 295*27000Sdonn int omask; 296*27000Sdonn struct itimerval itv, oitv; 297*27000Sdonn register struct itimerval *itp = &itv; 298*27000Sdonn struct sigvec vec, ovec; 299*27000Sdonn 300*27000Sdonn timerclear(&itp->it_interval); 301*27000Sdonn timerclear(&itp->it_value); 302*27000Sdonn if (setitimer(ITIMER_REAL, itp, &oitv) < 0) 303*27000Sdonn return; 304*27000Sdonn setvec(ovec, SIG_DFL); 305*27000Sdonn omask = sigblock(mask(SIGALRM)); 306*27000Sdonn itp->it_value.tv_sec = napms/1000; 307*27000Sdonn itp->it_value.tv_usec = ((napms%1000)*1000); 308*27000Sdonn setvec(vec, cour_napx); 309*27000Sdonn ringring = 0; 310*27000Sdonn (void) sigvec(SIGALRM, &vec, &ovec); 311*27000Sdonn (void) setitimer(ITIMER_REAL, itp, (struct itimerval *)0); 312*27000Sdonn while (!ringring) 313*27000Sdonn sigpause(omask &~ mask(SIGALRM)); 314*27000Sdonn (void) sigvec(SIGALRM, &ovec, (struct sigvec *)0); 315*27000Sdonn (void) setitimer(ITIMER_REAL, &oitv, (struct itimerval *)0); 316*27000Sdonn (void) sigsetmask(omask); 317*27000Sdonn } 318*27000Sdonn 319*27000Sdonn static 320*27000Sdonn cour_napx() 321*27000Sdonn { 322*27000Sdonn ringring = 1; 323*27000Sdonn } 324