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