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