1 /* 2 * Copyright (c) 1986, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #ifndef lint 35 static char sccsid[] = "@(#)courier.c 8.1 (Berkeley) 6/6/93"; 36 #endif /* not lint */ 37 38 /* 39 * Routines for calling up on a Courier modem. 40 * Derived from Hayes driver. 41 */ 42 #include "tipconf.h" 43 #include "tip.h" 44 #include "acucommon.h" 45 #include <stdio.h> 46 47 #define MAXRETRY 5 48 49 static void sigALRM(); 50 static int timeout = 0; 51 static int connected = 0; 52 static jmp_buf timeoutbuf, intbuf; 53 static int coursync(); 54 55 cour_dialer(num, acu) 56 register char *num; 57 char *acu; 58 { 59 register char *cp; 60 #if ACULOG 61 char line[80]; 62 #endif 63 static int cour_connect(), cour_swallow(); 64 65 if (boolean(value(VERBOSE))) 66 printf("Using \"%s\"\n", acu); 67 68 acu_hupcl (); 69 70 /* 71 * Get in synch. 72 */ 73 if (!coursync()) { 74 badsynch: 75 printf("can't synchronize with courier\n"); 76 #if ACULOG 77 logent(value(HOST), num, "courier", "can't synch up"); 78 #endif 79 return (0); 80 } 81 cour_write(FD, "AT E0\r", 6); /* turn off echoing */ 82 sleep(1); 83 #ifdef DEBUG 84 if (boolean(value(VERBOSE))) 85 cour_verbose_read(); 86 #endif 87 ioctl(FD, TIOCFLUSH, 0); /* flush any clutter */ 88 cour_write(FD, "AT C1 E0 H0 Q0 X6 V1\r", 21); 89 if (!cour_swallow("\r\nOK\r\n")) 90 goto badsynch; 91 fflush(stdout); 92 cour_write(FD, "AT D", 4); 93 for (cp = num; *cp; cp++) 94 if (*cp == '=') 95 *cp = ','; 96 cour_write(FD, num, strlen(num)); 97 cour_write(FD, "\r", 1); 98 connected = cour_connect(); 99 #if ACULOG 100 if (timeout) { 101 sprintf(line, "%d second dial timeout", 102 number(value(DIALTIMEOUT))); 103 logent(value(HOST), num, "cour", line); 104 } 105 #endif 106 if (timeout) 107 cour_disconnect(); 108 return (connected); 109 } 110 111 cour_disconnect() 112 { 113 /* first hang up the modem*/ 114 ioctl(FD, TIOCCDTR, 0); 115 sleep(1); 116 ioctl(FD, TIOCSDTR, 0); 117 coursync(); /* reset */ 118 close(FD); 119 } 120 121 cour_abort() 122 { 123 cour_write(FD, "\r", 1); /* send anything to abort the call */ 124 cour_disconnect(); 125 } 126 127 static void 128 sigALRM() 129 { 130 printf("\07timeout waiting for reply\n"); 131 timeout = 1; 132 longjmp(timeoutbuf, 1); 133 } 134 135 static int 136 cour_swallow(match) 137 register char *match; 138 { 139 sig_t f; 140 char c; 141 142 f = signal(SIGALRM, sigALRM); 143 timeout = 0; 144 do { 145 if (*match =='\0') { 146 signal(SIGALRM, f); 147 return (1); 148 } 149 if (setjmp(timeoutbuf)) { 150 signal(SIGALRM, f); 151 return (0); 152 } 153 alarm(number(value(DIALTIMEOUT))); 154 read(FD, &c, 1); 155 alarm(0); 156 c &= 0177; 157 #ifdef DEBUG 158 if (boolean(value(VERBOSE))) 159 putchar(c); 160 #endif 161 } while (c == *match++); 162 #ifdef DEBUG 163 if (boolean(value(VERBOSE))) 164 fflush(stdout); 165 #endif 166 signal(SIGALRM, SIG_DFL); 167 return (0); 168 } 169 170 struct baud_msg { 171 char *msg; 172 int baud; 173 } baud_msg[] = { 174 "", B300, 175 " 1200", B1200, 176 " 2400", B2400, 177 " 9600", B9600, 178 " 9600/ARQ", B9600, 179 0, 0, 180 }; 181 182 static int 183 cour_connect() 184 { 185 char c; 186 int nc, nl, n; 187 char dialer_buf[64]; 188 struct baud_msg *bm; 189 sig_t f; 190 191 if (cour_swallow("\r\n") == 0) 192 return (0); 193 f = signal(SIGALRM, sigALRM); 194 again: 195 nc = 0; nl = sizeof(dialer_buf)-1; 196 bzero(dialer_buf, sizeof(dialer_buf)); 197 timeout = 0; 198 for (nc = 0, nl = sizeof(dialer_buf)-1 ; nl > 0 ; nc++, nl--) { 199 if (setjmp(timeoutbuf)) 200 break; 201 alarm(number(value(DIALTIMEOUT))); 202 n = read(FD, &c, 1); 203 alarm(0); 204 if (n <= 0) 205 break; 206 c &= 0x7f; 207 if (c == '\r') { 208 if (cour_swallow("\n") == 0) 209 break; 210 if (!dialer_buf[0]) 211 goto again; 212 if (strcmp(dialer_buf, "RINGING") == 0 && 213 boolean(value(VERBOSE))) { 214 #ifdef DEBUG 215 printf("%s\r\n", dialer_buf); 216 #endif 217 goto again; 218 } 219 if (strncmp(dialer_buf, "CONNECT", 220 sizeof("CONNECT")-1) != 0) 221 break; 222 for (bm = baud_msg ; bm->msg ; bm++) 223 if (strcmp(bm->msg, 224 dialer_buf+sizeof("CONNECT")-1) == 0) { 225 if (!acu_setspeed(bm->baud)) 226 goto error; 227 signal(SIGALRM, f); 228 #ifdef DEBUG 229 if (boolean(value(VERBOSE))) 230 printf("%s\r\n", dialer_buf); 231 #endif 232 return (1); 233 } 234 break; 235 } 236 dialer_buf[nc] = c; 237 #ifdef notdef 238 if (boolean(value(VERBOSE))) 239 putchar(c); 240 #endif 241 } 242 error1: 243 printf("%s\r\n", dialer_buf); 244 error: 245 signal(SIGALRM, f); 246 return (0); 247 } 248 249 /* 250 * This convoluted piece of code attempts to get 251 * the courier in sync. 252 */ 253 static int 254 coursync() 255 { 256 int already = 0; 257 int len; 258 char buf[40]; 259 260 while (already++ < MAXRETRY) { 261 ioctl(FD, TIOCFLUSH, 0); /* flush any clutter */ 262 cour_write(FD, "\rAT Z\r", 6); /* reset modem */ 263 bzero(buf, sizeof(buf)); 264 sleep(1); 265 ioctl(FD, FIONREAD, &len); 266 if (len) { 267 len = read(FD, buf, sizeof(buf)); 268 #ifdef DEBUG 269 buf[len] = '\0'; 270 printf("coursync: (\"%s\")\n\r", buf); 271 #endif 272 if (index(buf, '0') || 273 (index(buf, 'O') && index(buf, 'K'))) 274 return(1); 275 } 276 /* 277 * If not strapped for DTR control, 278 * try to get command mode. 279 */ 280 sleep(1); 281 cour_write(FD, "+++", 3); 282 sleep(1); 283 /* 284 * Toggle DTR to force anyone off that might have left 285 * the modem connected. 286 */ 287 ioctl(FD, TIOCCDTR, 0); 288 sleep(1); 289 ioctl(FD, TIOCSDTR, 0); 290 } 291 cour_write(FD, "\rAT Z\r", 6); 292 return (0); 293 } 294 295 cour_write(fd, cp, n) 296 int fd; 297 char *cp; 298 int n; 299 { 300 #ifdef notdef 301 if (boolean(value(VERBOSE))) 302 write(1, cp, n); 303 #endif 304 acu_flush (); 305 cour_nap(); 306 for ( ; n-- ; cp++) { 307 write(fd, cp, 1); 308 acu_flush (); 309 cour_nap(); 310 } 311 } 312 313 #ifdef DEBUG 314 cour_verbose_read() 315 { 316 int n = 0; 317 char buf[BUFSIZ]; 318 319 if (ioctl(FD, FIONREAD, &n) < 0) 320 return; 321 if (n <= 0) 322 return; 323 if (read(FD, buf, n) != n) 324 return; 325 write(1, buf, n); 326 } 327 #endif 328 329 cour_nap() 330 { 331 acu_nap (50); 332 } 333 334 /* end of courier.c */ 335