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