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