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