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