1: /* 2: * Copyright (c) 1983 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[] = "@(#)penril.c 5.1 (Berkeley) 4/30/85"; 9: #endif not lint 10: 11: /* 12: * Routines for calling up on a Penril Modem 13: * The Penril is expected to be strapped for local echo (just like uucp) 14: */ 15: #include "tip.h" 16: 17: #define MAXRETRY 5 18: 19: static int sigALRM(); 20: static int timeout = 0; 21: static jmp_buf buftimeout; 22: 23: /* 24: * some sleep calls have been replaced by this macro 25: * because some penril modems require two <cr>s in less than 26: * a second in order to 'wake up'... yes, it is dirty... 27: */ 28: #define delay(num,denom) busyloop(CPUSPEED*num/denom) 29: #define CPUSPEED 1000000 /* VAX 780 is 1MIPS */ 30: #define DELAY(n) { register long N = (n); while (--N > 0); } 31: busyloop(n) { DELAY(n); } 32: 33: pen_dialer(num, acu) 34: register char *num; 35: char *acu; 36: { 37: register char *cp; 38: register int connected = 0; 39: char *msg, *index(), line[80]; 40: 41: /* 42: * Get in synch with a couple of carriage returns 43: */ 44: if (!pensync(FD)) { 45: printf("can't synchronize with penril\n"); 46: #ifdef ACULOG 47: logent(value(HOST), num, "penril", "can't synch up"); 48: #endif 49: return (0); 50: } 51: if (boolean(value(VERBOSE))) 52: printf("\ndialing..."); 53: fflush(stdout); 54: ioctl(FD, TIOCHPCL, 0); 55: echo("#k$\r$\n$D$I$A$L$:$ "); 56: for (cp = num; *cp; cp++) { 57: delay(1, 10); 58: write(FD, cp, 1); 59: } 60: delay(1, 10); 61: write(FD, "\r", 1); 62: gobble('\n', line); 63: if (gobble('\n', line)) 64: connected = gobble('O', line) && gobble('K', line); 65: ioctl(FD, TIOCFLUSH); 66: #ifdef ACULOG 67: if (timeout) { 68: sprintf(line, "%d second dial timeout", 69: number(value(DIALTIMEOUT))); 70: logent(value(HOST), num, "penril", line); 71: } 72: #endif 73: if (timeout) 74: pen_disconnect(); /* insurance */ 75: if (connected || timeout || !boolean(value(VERBOSE))) 76: return (connected); 77: /* call failed, parse response for user */ 78: cp = index(line, '\r'); 79: if (cp) 80: *cp = '\0'; 81: for (cp = line; cp = index(cp, ' '); cp++) 82: if (cp[1] == ' ') 83: break; 84: if (cp) { 85: while (*cp == ' ') 86: cp++; 87: msg = cp; 88: while (*cp) { 89: if (isupper(*cp)) 90: *cp = tolower(*cp); 91: cp++; 92: } 93: printf("%s...", msg); 94: } 95: return (connected); 96: } 97: 98: pen_disconnect() 99: { 100: 101: close(FD); 102: } 103: 104: pen_abort() 105: { 106: 107: write(FD, "\03", 1); 108: close(FD); 109: } 110: 111: static int 112: echo(s) 113: register char *s; 114: { 115: char c; 116: 117: while (c = *s++) switch (c) { 118: 119: case '$': 120: read(FD, &c, 1); 121: s++; 122: break; 123: 124: case '#': 125: c = *s++; 126: write(FD, &c, 1); 127: break; 128: 129: default: 130: write(FD, &c, 1); 131: read(FD, &c, 1); 132: } 133: } 134: 135: static int 136: sigALRM() 137: { 138: 139: printf("\07timeout waiting for reply\n"); 140: timeout = 1; 141: longjmp(buftimeout, 1); 142: } 143: 144: static int 145: gobble(match, response) 146: register char match; 147: char response[]; 148: { 149: register char *cp = response; 150: char c; 151: int (*f)(); 152: 153: signal(SIGALRM, sigALRM); 154: timeout = 0; 155: do { 156: if (setjmp(buftimeout)) { 157: signal(SIGALRM, f); 158: *cp = '\0'; 159: return (0); 160: } 161: alarm(number(value(DIALTIMEOUT))); 162: read(FD, cp, 1); 163: alarm(0); 164: c = (*cp++ &= 0177); 165: #ifdef notdef 166: if (boolean(value(VERBOSE))) 167: putchar(c); 168: #endif 169: } while (c != '\n' && c != match); 170: signal(SIGALRM, SIG_DFL); 171: *cp = '\0'; 172: return (c == match); 173: } 174: 175: #define min(a,b) ((a)>(b)?(b):(a)) 176: /* 177: * This convoluted piece of code attempts to get 178: * the penril in sync. If you don't have FIONREAD 179: * there are gory ways to simulate this. 180: */ 181: static int 182: pensync(fd) 183: { 184: int already = 0, nread; 185: long temp; 186: char buf[60]; 187: 188: /* 189: * Toggle DTR to force anyone off that might have left 190: * the modem connected, and insure a consistent state 191: * to start from. 192: * 193: * If you don't have the ioctl calls to diddle directly 194: * with DTR, you can always try setting the baud rate to 0. 195: */ 196: ioctl(FD, TIOCCDTR, 0); 197: sleep(1); 198: ioctl(FD, TIOCSDTR, 0); 199: while (already < MAXRETRY) { 200: /* 201: * After reseting the modem, send it two \r's to 202: * autobaud on. Make sure to delay between them 203: * so the modem can frame the incoming characters. 204: */ 205: write(fd, "\r", 1); 206: sleep(2); 207: if (ioctl(fd, FIONREAD, &temp) < 0) { 208: perror("tip: ioctl"); 209: continue; 210: } 211: nread = temp; 212: while (nread > 0) { 213: read(fd, buf, min(nread, 70)); 214: if (((buf[nread - 6] & 0177) == 'B') && 215: ((buf[nread - 5] & 0177) == 'P') && 216: ((buf[nread - 4] & 0177) == 'S') && 217: ((buf[nread - 1] & 0177) == '>')) 218: return (1); 219: nread -= min(nread, 70); 220: } 221: sleep(1); 222: already++; 223: } 224: return (0); 225: }