1 #ifndef lint 2 static char sccsid[] = "@(#)condevs.c 5.6 (Berkeley) 08/12/83"; 3 #endif 4 5 /* 6 * Here are various dialers to establish the machine-machine connection. 7 * conn.c/condevs.c was glued together by Mike Mitchell. 8 * The dialers were supplied by many people, to whom we are grateful. 9 * 10 * --------------------------------------------------------------------- 11 * NOTE: 12 * There is a bug that occurs at least on PDP11s due to a limitation of 13 * setjmp/longjmp. If the routine that does a setjmp is interrupted 14 * and longjmp-ed to, it loses its register variables (on a pdp11). 15 * What works is if the routine that does the setjmp 16 * calls a routine and it is the *subroutine* that is interrupted. 17 * 18 * Anyway, in conclusion, condevs.c is plagued with register variables 19 * that are used inside 20 * if (setjmp(...)) { 21 * .... 22 * } 23 * 24 * THE FIX: In dnopn(), for example, delete the 'register' Devices *dev. 25 * (That was causing a core dump; deleting register fixed it.) 26 * Also for dnopn delete 'register' int dnf... . 27 * In pkopn, delete 'register' flds... . 28 * There may be others, especially mcm's version of hysopen. 29 * You could just delete all references to register, that is safest. 30 * This problem might not occur on 4.1bsd, I am not sure. 31 * Tom Truscott 32 */ 33 #include <sys/types.h> 34 #include <errno.h> 35 #include <setjmp.h> 36 #include <signal.h> 37 #include <sgtty.h> 38 #include "uucp.h" 39 40 extern char devSel[]; /* name to pass to delock() in close */ 41 extern int errno, next_fd; 42 extern jmp_buf Sjbuf; 43 extern int alarmtr(); 44 int nulldev(), nodev(), Acuopn(), diropn(), dircls(); 45 46 #ifdef DATAKIT 47 int dkopn(); 48 #endif 49 #ifdef DN11 50 int dnopn(), dncls(); 51 #endif 52 #ifdef HAYES 53 int hysopn(), hyscls(); 54 #endif 55 #ifdef HAYESQ 56 int hysqopn(), hysqcls(); /* a version of hayes that doesn't use ret codes */ 57 #endif 58 #ifdef DF02 59 int df2opn(), df2cls(); 60 #endif 61 #ifdef PNET 62 int pnetopn(); 63 #endif 64 #ifdef VENTEL 65 int ventopn(), ventcls(); 66 #endif 67 #ifdef UNET 68 #include <UNET/unetio.h> 69 #include <UNET/tcp.h> 70 int unetopn(), unetcls(); 71 #endif UNET 72 #ifdef VADIC 73 int vadopn(), vadcls(); 74 #endif VADIC 75 #ifdef RVMACS 76 int rvmacsopn(), rvmacscls(); 77 #endif 78 #ifdef MICOM 79 int micopn(), miccls(); 80 #endif MICOM 81 82 struct condev condevs[] = { 83 { "DIR", "direct", diropn, nulldev, dircls }, 84 #ifdef DATAKIT 85 { "DK", "datakit", dkopn, nulldev, nulldev }, 86 #endif 87 #ifdef PNET 88 { "PNET", "pnet", pnetopn, nulldev, nulldev }, 89 #endif 90 #ifdef UNET 91 { "UNET", "UNET", unetopn, nulldev, unetcls }, 92 #endif UNET 93 #ifdef MICOM 94 { "MICOM", "micom", micopn, nulldev, miccls }, 95 #endif MICOM 96 #ifdef DN11 97 { "ACU", "dn11", Acuopn, dnopn, dncls }, 98 #endif 99 #ifdef HAYES 100 { "ACU", "hayes", Acuopn, hysopn, hyscls }, 101 #endif HAYES 102 #ifdef HAYESQ /* a version of hayes that doesn't use result codes */ 103 { "ACU", "hayesq", Acuopn, hysqopn, hysqcls }, 104 #endif HATESQ 105 #ifdef DF02 106 { "ACU", "DF02", Acuopn, df2opn, df2cls }, 107 #endif 108 #ifdef VENTEL 109 { "ACU", "ventel", Acuopn, ventopn, ventcls }, 110 #endif VENTEL 111 #ifdef VADIC 112 { "ACU", "vadic", Acuopn, vadopn, vadcls }, 113 #endif VADIC 114 #ifdef RVMACS 115 { "ACU", "rvmacs", Acuopn, rvmacsopn, rvmacscls }, 116 #endif RVMACS 117 118 /* Insert new entries before this line */ 119 { NULL, NULL, NULL, NULL, NULL } }; 120 121 /*** 122 * nulldev a null device (returns CF_DIAL) 123 */ 124 int nulldev() 125 { 126 return(CF_DIAL); 127 } 128 129 /*** 130 * nodev a null device (returns CF_NODEV) 131 */ 132 int nodev() 133 { 134 return(CF_NODEV); 135 } 136 137 138 /* 139 * The first things in this file are the generic devices. 140 * Generic devices look through L-devices and call the CU_open routines for 141 * appropriate devices. Some things, like the Unet interface, or direct 142 * connect, do not use the CU_open entry. ACUs must search to find the' 143 * right routine to call. 144 */ 145 146 /*** 147 * diropn(flds) connect to hardware line 148 * char *flds[]; 149 * 150 * return codes: 151 * >0 - file number - ok 152 * FAIL - failed 153 */ 154 155 diropn(flds) 156 register char *flds[]; 157 { 158 register int dcr, status; 159 struct Devices dev; 160 char dcname[20]; 161 FILE *dfp; 162 dfp = fopen(DEVFILE, "r"); 163 ASSERT(dfp != NULL, "CAN'T OPEN", DEVFILE, 0); 164 while ((status = rddev(dfp, &dev)) != FAIL) { 165 if (strcmp(flds[F_CLASS], dev.D_class) != SAME) 166 continue; 167 if (strcmp(flds[F_PHONE], dev.D_line) != SAME) 168 continue; 169 if (mlock(dev.D_line) != FAIL) 170 break; 171 } 172 fclose(dfp); 173 if (status == FAIL) { 174 logent("DEVICE", "NO"); 175 return(CF_NODEV); 176 } 177 178 sprintf(dcname, "/dev/%s", dev.D_line); 179 if (setjmp(Sjbuf)) { 180 delock(dev.D_line); 181 return(FAIL); 182 } 183 signal(SIGALRM, alarmtr); 184 alarm(10); 185 getnextfd(); 186 errno = 0; 187 dcr = open(dcname, 2); /* read/write */ 188 next_fd = -1; 189 if (dcr < 0 && errno == EACCES) 190 logent(dcname, "CAN'T OPEN"); 191 alarm(0); 192 if (dcr < 0) { 193 delock(dev.D_line); 194 return(FAIL); 195 } 196 fflush(stdout); 197 fixline(dcr, dev.D_speed); 198 strcpy(devSel, dev.D_line); /* for latter unlock */ 199 CU_end = dircls; 200 return(dcr); 201 } 202 203 dircls(fd) 204 register int fd; 205 { 206 if (fd > 0) { 207 close(fd); 208 delock(devSel); 209 } 210 } 211 212 #ifdef DATAKIT 213 214 #include <dk.h> 215 #define DKTRIES 2 216 217 /*** 218 * dkopn(flds) make datakit connection 219 * 220 * return codes: 221 * >0 - file number - ok 222 * FAIL - failed 223 */ 224 225 dkopn(flds) 226 char *flds[]; 227 { 228 int dkphone; 229 register char *cp; 230 register ret, i; 231 232 if (setjmp(Sjbuf)) 233 return(FAIL); 234 235 signal(SIGALRM, alarmtr); 236 dkphone = 0; 237 cp = flds[F_PHONE]; 238 while(*cp) 239 dkphone = 10 * dkphone + (*cp++ - '0'); 240 DEBUG(4, "dkphone (%d) ", dkphone); 241 for (i = 0; i < DKTRIES; i++) { 242 getnextfd(); 243 ret = dkdial(D_SH, dkphone, 0); 244 next_fd = -1; 245 DEBUG(4, "dkdial (%d)\n", ret); 246 if (ret > -1) 247 break; 248 } 249 return(ret); 250 } 251 #endif 252 253 #ifdef PNET 254 /*** 255 * pnetopn(flds) 256 * 257 * call remote machine via Purdue network 258 * use dial string as host name, speed as socket number 259 * Author: Steve Bellovin 260 */ 261 262 pnetopn(flds) 263 char *flds[]; 264 { 265 int fd; 266 int socket; 267 register char *cp; 268 269 fd = pnetfile(); 270 DEBUG(4, "pnet fd - %d\n", fd); 271 if (fd < 0) { 272 logent("AVAILABLE DEVICE", "NO"); 273 return(CF_NODEV); 274 } 275 socket = 0; 276 for (cp = flds[F_CLASS]; *cp; cp++) 277 socket = 10*socket + (*cp - '0'); 278 DEBUG(4, "socket - %d\n", socket); 279 if (setjmp(Sjbuf)) { 280 DEBUG(4, "pnet timeout - %s\n", flds[F_PHONE]); 281 return(FAIL); 282 } 283 signal(SIGALRM, alarmtr); 284 DEBUG(4, "host - %s\n", flds[F_PHONE]); 285 alarm(15); 286 if (pnetscon(fd, flds[F_PHONE], socket) < 0) { 287 DEBUG(4, "pnet connect failed - %s\n", flds[F_PHONE]); 288 return(FAIL); 289 } 290 alarm(0); 291 return(fd); 292 } 293 #endif PNET 294 295 #ifdef UNET 296 /*** 297 * unetopn -- make UNET (tcp-ip) connection 298 * 299 * return codes: 300 * >0 - file number - ok 301 * FAIL - failed 302 */ 303 304 /* Default port of uucico server */ 305 #define DFLTPORT 33 306 307 unetopn(flds) 308 register char *flds[]; 309 { 310 register int ret, port; 311 int unetcls(); 312 313 port = atoi(flds[F_PHONE]); 314 if (port <= 0 || port > 255) 315 port = DFLTPORT; 316 DEBUG(4, "unetopn host %s, ", flds[F_NAME]); 317 DEBUG(4, "port %d\n", port); 318 if (setjmp(Sjbuf)) { 319 logent("tcpopen", "TIMEOUT"); 320 endhnent(); /* see below */ 321 return(CF_DIAL); 322 } 323 signal(SIGALRM, alarmtr); 324 alarm(30); 325 ret = tcpopen(flds[F_NAME], port, 0, TO_ACTIVE, "rw"); 326 alarm(0); 327 endhnent(); /* wave magic wand at 3com and incant "eat it, bruce" */ 328 if (ret < 0) { 329 DEBUG(5, "tcpopen failed: errno %d\n", errno); 330 logent("tcpopen", "FAILED"); 331 return(CF_DIAL); 332 } 333 CU_end = unetcls; 334 return(ret); 335 } 336 337 /* 338 * unetcls -- close UNET connection. 339 */ 340 unetcls(fd) 341 register int fd; 342 { 343 DEBUG(4, "UNET CLOSE called\n", 0); 344 if (fd > 0) { 345 /* disable this until a timeout is put in 346 if (ioctl(fd, UIOCCLOSE, STBNULL)) 347 logent("UNET CLOSE", "FAILED"); 348 */ 349 close(fd); 350 DEBUG(4, "closed fd %d\n", fd); 351 } 352 } 353 #endif UNET 354 355 #ifdef MICOM 356 357 /* 358 * micopn: establish connection through a micom. 359 * Returns descriptor open to tty for reading and writing. 360 * Negative values (-1...-7) denote errors in connmsg. 361 * Be sure to disconnect tty when done, via HUPCL or stty 0. 362 */ 363 micopn(flds) 364 register char *flds[]; 365 { 366 extern errno; 367 char *rindex(), *fdig(), dcname[20]; 368 int dh, ok = 0, speed; 369 register struct condev *cd; 370 register FILE *dfp; 371 struct Devices dev; 372 373 dfp = fopen(DEVFILE, "r"); 374 ASSERT(dfp != NULL, "Can't open", DEVFILE, 0); 375 376 signal(SIGALRM, alarmtr); 377 dh = -1; 378 for(cd = condevs; ((cd->CU_meth != NULL)&&(dh < 0)); cd++) { 379 if (snccmp(flds[F_LINE], cd->CU_meth) == SAME) { 380 fseek(dfp, (off_t)0, 0); 381 while(rddev(dfp, &dev) != FAIL) { 382 if (strcmp(flds[F_CLASS], dev.D_class) != SAME) 383 continue; 384 if (snccmp(flds[F_LINE], dev.D_type) != SAME) 385 continue; 386 if (mlock(dev.D_line) == FAIL) 387 continue; 388 389 sprintf(dcname, "/dev/%s", dev.D_line); 390 getnextfd(); 391 alarm(10); 392 if (setjmp(Sjbuf)) { 393 delock(dev.D_line); 394 logent(dev.D_line,"micom open TIMEOUT"); 395 dh = -1; 396 break; 397 } 398 dh = open(dcname, 2); 399 alarm(0); 400 next_fd = -1; 401 if (dh > 0) { 402 break; 403 } 404 devSel[0] = '\0'; 405 delock(dev.D_line); 406 } 407 } 408 } 409 fclose(dfp); 410 if (dh < 0) 411 return(CF_NODEV); 412 413 speed = atoi(fdig(flds[F_CLASS])); 414 fixline(dh, speed); 415 sleep(1); 416 417 /* negotiate with micom */ 418 if (speed != 4800) /* damn their eyes! */ 419 write(dh, "\r", 1); 420 else 421 write(dh, " ", 1); 422 423 DEBUG(4, "wanted %s ", "NAME"); 424 ok = expect("NAME", dh); 425 DEBUG(4, "got %s\n", ok ? "?" : "that"); 426 if (ok == 0) { 427 write(dh, flds[F_PHONE], strlen(flds[F_PHONE])); 428 sleep(1); 429 write(dh, "\r", 1); 430 DEBUG(4, "wanted %s ", "GO"); 431 ok = expect("GO", dh); 432 DEBUG(4, "got %s\n", ok ? "?" : "that"); 433 } 434 435 if (ok != 0) { 436 if (dh > 2) 437 close(dh); 438 DEBUG(4, "micom failed\n", ""); 439 delock(dev.D_line); 440 return(CF_DIAL); 441 } else 442 DEBUG(4, "micom ok\n", ""); 443 444 CU_end = cd->CU_clos; 445 strcat(devSel, dev.D_line); /* for later unlock */ 446 return(dh); 447 448 } 449 450 miccls(fd) 451 register int fd; 452 { 453 454 if (fd > 0) { 455 close(fd); 456 delock(devSel); 457 } 458 } 459 #endif MICOM 460 461 /*** 462 * Acuopn - open an ACU and dial the number. The condevs table 463 * will be searched until a dialing unit is found that is 464 * free. 465 * 466 * return codes: >0 - file number - o.k. 467 * FAIL - failed 468 */ 469 470 char devSel[20]; /* used for later unlock() */ 471 472 Acuopn(flds) 473 register char *flds[]; 474 { 475 char phone[MAXPH+1]; 476 register struct condev *cd; 477 register int fd; 478 register FILE *dfp; 479 struct Devices dev; 480 481 exphone(flds[F_PHONE], phone); 482 devSel[0] = '\0'; 483 DEBUG(4, "Dialing %s\n", phone); 484 dfp = fopen(DEVFILE, "r"); 485 ASSERT(dfp != NULL, "Can't open", DEVFILE, 0); 486 487 for(cd = condevs; cd->CU_meth != NULL; cd++) { 488 if (snccmp(flds[F_LINE], cd->CU_meth) == SAME) { 489 fseek(dfp, (off_t)0, 0); 490 while(rddev(dfp, &dev) != FAIL) { 491 if (strcmp(flds[F_CLASS], dev.D_class) != SAME) 492 continue; 493 if (snccmp(flds[F_LINE], dev.D_type) != SAME) 494 continue; 495 if (dev.D_brand[0] == '\0') 496 logent("Acuopn","No 'brand' name on ACU"); 497 else if (snccmp(dev.D_brand, cd->CU_brand) != SAME) 498 continue; 499 if (mlock(dev.D_line) == FAIL) 500 continue; 501 502 DEBUG(4, "Using %s\n", cd->CU_brand); 503 fd = (*(cd->CU_open))(phone, flds, &dev); 504 if (fd > 0) { 505 CU_end = cd->CU_clos; /* point CU_end at close func */ 506 fclose(dfp); 507 strcpy(devSel, dev.D_line); /* save for later unlock() */ 508 return(fd); 509 } 510 delock(dev.D_line); 511 } 512 } 513 } 514 fclose(dfp); 515 return(FAIL); 516 } 517 518 #ifdef DN11 519 520 /*** 521 * dnopn(ph, flds, dev) dial remote machine 522 * char *ph; 523 * char *flds[]; 524 * struct Devices *dev; 525 * 526 * return codes: 527 * file descriptor - succeeded 528 * FAIL - failed 529 */ 530 531 dnopn(ph, flds, dev) 532 char *ph; 533 char *flds[]; 534 struct Devices *dev; 535 { 536 char dcname[20], dnname[20], phone[MAXPH+2], c = 0; 537 #ifdef SYSIII 538 struct termio ttbuf; 539 #endif 540 int dnf, dcf; 541 int nw, lt, pid, status; 542 unsigned timelim; 543 544 sprintf(dnname, "/dev/%s", dev->D_calldev); 545 errno = 0; 546 547 if (setjmp(Sjbuf)) { 548 logent(dnname, "CAN'T OPEN"); 549 DEBUG(4, "%s Open timed out\n", dnname); 550 return(CF_NODEV); 551 } 552 signal(SIGALRM, alarmtr); 553 getnextfd(); 554 alarm(10); 555 dnf = open(dnname, 1); 556 alarm(0); 557 next_fd = -1; 558 if (dnf < 0 && errno == EACCES) { 559 logent(dnname, "CAN'T OPEN"); 560 logent("DEVICE", "NO"); 561 return(CF_NODEV); 562 } 563 /* rti!trt: avoid passing acu file descriptor to children */ 564 fioclex(dnf); 565 566 sprintf(dcname, "/dev/%s", dev->D_line); 567 sprintf(phone, "%s%s", ph, ACULAST); 568 DEBUG(4, "dc - %s, ", dcname); 569 DEBUG(4, "acu - %s\n", dnname); 570 pid = 0; 571 if (setjmp(Sjbuf)) { 572 logent("DIALUP DN write", "TIMEOUT"); 573 if (pid) 574 kill(pid, 9); 575 delock(dev->D_line); 576 if (dnf) 577 close(dnf); 578 return(FAIL); 579 } 580 signal(SIGALRM, alarmtr); 581 timelim = 5 * strlen(phone); 582 alarm(timelim < 30 ? 30 : timelim); 583 if ((pid = fork()) == 0) { 584 sleep(2); 585 fclose(stdin); 586 fclose(stdout); 587 #ifdef TIOCFLUSH 588 ioctl(dnf, TIOCFLUSH, STBNULL); 589 #endif 590 nw = write(dnf, phone, lt = strlen(phone)); 591 if (nw != lt) { 592 logent("DIALUP ACU write", "FAILED"); 593 exit(1); 594 } 595 DEBUG(4, "ACU write ok%s\n", ""); 596 exit(0); 597 } 598 /* open line - will return on carrier */ 599 /* RT needs a sleep here because it returns immediately from open */ 600 601 #if RT 602 sleep(15); 603 #endif 604 605 getnextfd(); 606 errno = 0; 607 dcf = open(dcname, 2); 608 next_fd = -1; 609 if (dcf < 0 && errno == EACCES) 610 logent(dcname, "CAN'T OPEN"); 611 DEBUG(4, "dcf is %d\n", dcf); 612 if (dcf < 0) { 613 logent("DIALUP LINE open", "FAILED"); 614 alarm(0); 615 kill(pid, 9); 616 close(dnf); 617 delock(dev->D_line); 618 return(FAIL); 619 } 620 /* brl-bmd.351 (Doug Kingston) says the next ioctl is unneeded . */ 621 /* ioctl(dcf, TIOCHPCL, STBNULL);*/ 622 while ((nw = wait(<)) != pid && nw != -1) 623 ; 624 #ifdef SYSIII 625 ioctl(dcf, TCGETA, &ttbuf); 626 if(!(ttbuf.c_cflag & HUPCL)) { 627 ttbuf.c_cflag |= HUPCL; 628 ioctl(dcf, TCSETA, &ttbuf); 629 } 630 #endif 631 alarm(0); 632 fflush(stdout); 633 fixline(dcf, dev->D_speed); 634 DEBUG(4, "Fork Stat %o\n", lt); 635 if (lt != 0) { 636 close(dcf); 637 if (dnf) 638 close(dnf); 639 delock(dev->D_line); 640 return(FAIL); 641 } 642 return(dcf); 643 } 644 645 /*** 646 * dncls() close dn type call unit 647 * 648 * return codes: None 649 */ 650 dncls(fd) 651 register int fd; 652 { 653 if (fd > 0) { 654 close(fd); 655 sleep(5); 656 delock(devSel); 657 } 658 } 659 #endif DN11 660 661 #ifdef DF02 662 /*** 663 * df2opn(ph, flds, dev) dial remote machine 664 * char *ph; 665 * char *flds[]; 666 * struct Devices *dev; 667 * 668 * return codes: 669 * file descriptor - succeeded 670 * FAIL - failed 671 * 672 * Modified 9/28/81 by Bill Shannon (DEC) 673 * Changed to use DEC DF02 or DF03 ACU 674 */ 675 676 677 df2opn(ph, flds, dev) 678 char *ph; 679 char *flds[]; 680 struct Devices *dev; 681 { 682 char dcname[20], dnname[20], phone[MAXPH+2], c = 0; 683 #ifdef SYSIII 684 struct termio ttbuf; 685 #endif 686 int dcf, dnf; 687 int nw, lt, pid, st, status; 688 unsigned timelim; 689 690 sprintf(dnname, "/dev/%s", dev->D_calldev); 691 if (setjmp(Sjbuf)) { 692 logent(dnname, "CAN'T OPEN"); 693 DEBUG(4, "%s Open timed out\n", dnname); 694 return(CF_NODEV); 695 } 696 signal(SIGALRM, alarmtr); 697 getnextfd(); 698 errno = 0; 699 alarm(10); 700 dnf = open(dnname, 2 ); 701 alarm(0); 702 next_fd = -1; 703 if (dnf < 0 && errno == EACCES) { 704 logent(dnname, "CAN'T OPEN"); 705 delock(dev->D_line); 706 logent("DEVICE", "NO"); 707 return(CF_NODEV); 708 } 709 /* rti!trt: avoid passing acu file descriptor to children */ 710 fioclex(dnf); 711 712 sprintf(dcname, "/dev/%s", dev->D_line); 713 fixline(dnf, dev->D_speed); 714 sprintf(phone, "\02%s", ph); 715 DEBUG(4, "dc - %s, ", dcname); 716 DEBUG(4, "acu - %s\n", dnname); 717 pid = 0; 718 if (setjmp(Sjbuf)) { 719 logent("DIALUP DN write", "TIMEOUT"); 720 if (pid) 721 kill(pid, 9); 722 delock(dev->D_line); 723 if (dnf) 724 close(dnf); 725 return(FAIL); 726 } 727 signal(SIGALRM, alarmtr); 728 timelim = 5 * strlen(phone); 729 alarm(timelim < 30 ? 30 : timelim); 730 if ((pid = fork()) == 0) { 731 sleep(2); 732 fclose(stdin); 733 fclose(stdout); 734 #ifdef TIOCFLUSH 735 ioctl(dnf, TIOCFLUSH, STBNULL); 736 #endif 737 write(dnf, "\01", 1); 738 sleep(1); 739 nw = write(dnf, phone, lt = strlen(phone)); 740 if (nw != lt) { 741 logent("DIALUP ACU write", "FAILED"); 742 exit(1); 743 } 744 DEBUG(4, "ACU write ok%s\n", ""); 745 exit(0); 746 } 747 /* open line - will return on carrier */ 748 /* RT needs a sleep here because it returns immediately from open */ 749 750 #if RT 751 sleep(15); 752 #endif 753 754 if (read(dnf, &c, 1) != 1 || c != 'A') 755 dcf = -1; 756 else 757 dcf = 0; 758 DEBUG(4, "dcf is %d\n", dcf); 759 if (dcf < 0) { 760 logent("DIALUP LINE open", "FAILED"); 761 alarm(0); 762 kill(pid, 9); 763 close(dnf); 764 delock(dev->D_line); 765 return(FAIL); 766 } 767 dcf = dnf; 768 dnf = 0; 769 /* brl-bmd.351 (Doug Kingston) says the next ioctl is unneeded . */ 770 /* ioctl(dcf, TIOCHPCL, STBNULL);*/ 771 while ((nw = wait(<)) != pid && nw != -1) 772 ; 773 #ifdef SYSIII 774 ioctl(dcf, TCGETA, &ttbuf); 775 if(!(ttbuf.c_cflag & HUPCL)) { 776 ttbuf.c_cflag |= HUPCL; 777 ioctl(dcf, TCSETA, &ttbuf); 778 } 779 #endif 780 alarm(0); 781 fflush(stdout); 782 fixline(dcf, dev->D_speed); 783 DEBUG(4, "Fork Stat %o\n", lt); 784 if (lt != 0) { 785 close(dcf); 786 if (dnf) 787 close(dnf); 788 delock(dev->D_line); 789 return(FAIL); 790 } 791 return(dcf); 792 } 793 794 /* 795 * df2cls() close the DF02/DF03 call unit 796 * 797 * return codes: none 798 */ 799 800 df2cls(fd) 801 register int fd; 802 { 803 if (fd > 0) { 804 close(fd); 805 sleep(5); 806 delock(devSel); 807 } 808 } 809 #endif DF02 810 811 #ifdef HAYES 812 /*** 813 * hysopn(telno, flds, dev) connect to hayes smartmodem 814 * char *flds[], *dev[]; 815 * 816 * return codes: 817 * >0 - file number - ok 818 * CF_DIAL,CF_DEVICE - failed 819 */ 820 /* 821 * Define HAYSTONE if you have touch tone dialing. 822 */ 823 /*#define HAYSTONE */ 824 825 hysopn(telno, flds, dev) 826 char *telno; 827 char *flds[]; 828 struct Devices *dev; 829 { 830 int dh = -1; 831 extern errno; 832 char dcname[20]; 833 834 sprintf(dcname, "/dev/%s", dev->D_line); 835 DEBUG(4, "dc - %s\n", dcname); 836 if (setjmp(Sjbuf)) { 837 DEBUG(1, "timeout hayes open %s\n", dcname); 838 logent("hayes open", "TIMEOUT"); 839 if (dh >= 0) 840 close(dh); 841 delock(dev->D_line); 842 return(CF_DIAL); 843 } 844 signal(SIGALRM, alarmtr); 845 getnextfd(); 846 alarm(10); 847 dh = open(dcname, 2); /* read/write */ 848 alarm(0); 849 850 /* modem is open */ 851 next_fd = -1; 852 if (dh >= 0) { 853 fixline(dh, dev->D_speed); 854 #ifdef HAYSTONE 855 write(dh, "\rATDT", 5); 856 #else 857 write(dh, "\rATDP", 5); 858 #endif 859 write(dh, telno, strlen(telno)); 860 write(dh, "\r", 1); 861 862 if (expect("CONNECT", dh) != 0) { 863 logent("HSM no carrier", "FAILED"); 864 strcpy(devSel, dev->D_line); 865 hyscls(dh); 866 return(CF_DIAL); 867 } 868 869 } 870 if (dh < 0) { 871 DEBUG(4, "hayes failed\n", ""); 872 delock(dev->D_line); 873 } 874 DEBUG(4, "hayes ok\n", ""); 875 return(dh); 876 } 877 878 hyscls(fd) 879 int fd; 880 { 881 char dcname[20]; 882 struct sgttyb hup, sav; 883 884 if (fd > 0) { 885 sprintf(dcname, "/dev/%s", devSel); 886 DEBUG(4, "Hanging up fd = %d\n", fd); 887 /* 888 * code to drop DTR -- change to 0 baud then back to default. 889 */ 890 gtty(fd, &hup); 891 gtty(fd, &sav); 892 hup.sg_ispeed = B0; 893 hup.sg_ospeed = B0; 894 stty(fd, &hup); 895 sleep(2); 896 stty(fd, &sav); 897 /* 898 * now raise DTR -- close the device & open it again. 899 */ 900 sleep(2); 901 close(fd); 902 sleep(2); 903 fd = open(dcname, 2); 904 /* 905 * Since we have a getty sleeping on this line, when it wakes up it sends 906 * all kinds of garbage to the modem. Unfortunatly, the modem likes to 907 * execute the previous command when it sees the garbage. The previous 908 * command was to dial the phone, so let's make the last command reset 909 * the modem. 910 */ 911 sleep(2); 912 write(fd, "\rATZ\r", 5); 913 close(fd); 914 delock(devSel); 915 } 916 } 917 918 #endif HAYES 919 920 #ifdef HAYESQ 921 /* 922 * New dialout routine to work with Hayes' SMART MODEM 923 * 13-JUL-82, Mike Mitchell 924 * Modified 23-MAR-83 to work with Tom Truscott's (rti!trt) 925 * version of UUCP (ncsu!mcm) 926 * 927 * The modem should be set to NOT send any result codes to 928 * the system (switch 3 up, 4 down). This end will figure out 929 * what is wrong. 930 * 931 * I had lots of problems with the modem sending 932 * result codes since I am using the same modem for both incomming and 933 * outgoing calls. I'd occasionally miss the result code (getty would 934 * grab it), and the connect would fail. Worse yet, the getty would 935 * think the result code was a user name, and send garbage to it while 936 * it was in the command state. I turned off ALL result codes, and hope 937 * for the best. 99% of the time the modem is in the correct state. 938 * Occassionally it doesn't connect, or the phone was busy, etc., and 939 * uucico sits there trying to log in. It eventually times out, calling 940 * clsacu() in the process, so it resets itself for the next attempt. 941 */ 942 943 /* 944 * Define HAYSTONE if touch-tone dialing is to be used. If it is not defined, 945 * Pulse dialing is assumed. 946 */ 947 /*#define HAYSTONE*/ 948 949 hysqopn(telno, flds, dev) 950 char *telno, *flds[]; 951 struct Devices *dev; 952 { 953 char dcname[20], phone[MAXPH+10], c = 0; 954 #ifdef SYSIII 955 struct termio ttbuf; 956 #endif 957 int status, dnf; 958 unsigned timelim; 959 960 signal(SIGALRM, alarmtr); 961 sprintf(dcname, "/dev/%s", dev->D_line); 962 963 getnextfd(); 964 if (setjmp(Sjbuf)) { 965 delock(dev->D_line); 966 logent("DEVICE", "NO"); 967 DEBUG(4, "Open timed out %s", dcname); 968 return(CF_NODEV); 969 } 970 alarm(10); 971 972 if ((dnf = open(dcname, 2)) <= 0) { 973 delock(dev->D_line); 974 logent("DEVICE", "NO"); 975 DEBUG(4, "Can't open %s", dcname); 976 return(CF_NODEV); 977 } 978 979 alarm(0); 980 next_fd = -1; 981 fixline(dnf, dev->D_speed); 982 DEBUG(4, "Hayes port - %s, ", dcname); 983 984 #ifdef HAYSTONE 985 sprintf(phone, "\rATDT%s\r", telno); 986 #else 987 sprintf(phone, "\rATDP%s\r", telno); 988 #endif 989 990 write(dnf, phone, strlen(phone)); 991 992 /* calculate delay time for the other system to answer the phone. 993 * Default is 15 seconds, add 2 seconds for each comma in the phone 994 * number. 995 */ 996 timelim = 150; 997 while(*telno) { 998 c = *telno++; 999 if (c == ',') 1000 timelim += 20; 1001 else { 1002 #ifdef HAYSTONE 1003 timelim += 2; /* .2 seconds per tone */ 1004 } 1005 #else 1006 if (c == '0') timelim += 10; /* .1 second per digit */ 1007 else if (c > '0' && c <= '9') 1008 timelim += (c - '0'); 1009 } 1010 #endif 1011 } 1012 alarm(timelim/10); 1013 if (setjmp(Sjbuf) == 0) { 1014 read(dnf, &c, 1); 1015 alarm(0); 1016 } 1017 1018 return(dnf); 1019 } 1020 1021 hysqcls(fd) 1022 int fd; 1023 { 1024 char dcname[20]; 1025 struct sgttyb hup, sav; 1026 1027 if (fd > 0) { 1028 sprintf(dcname, "/dev/%s", devSel); 1029 DEBUG(4, "Hanging up fd = %d\n", fd); 1030 /* 1031 * code to drop DTR -- change to 0 baud then back to default. 1032 */ 1033 gtty(fd, &hup); 1034 gtty(fd, &sav); 1035 hup.sg_ispeed = B0; 1036 hup.sg_ospeed = B0; 1037 stty(fd, &hup); 1038 sleep(2); 1039 stty(fd, &sav); 1040 /* 1041 * now raise DTR -- close the device & open it again. 1042 */ 1043 sleep(2); 1044 close(fd); 1045 sleep(2); 1046 fd = open(dcname, 2); 1047 /* 1048 * Since we have a getty sleeping on this line, when it wakes up it sends 1049 * all kinds of garbage to the modem. Unfortunatly, the modem likes to 1050 * execute the previous command when it sees the garbage. The previous 1051 * command was to dial the phone, so let's make the last command reset 1052 * the modem. 1053 */ 1054 sleep(2); 1055 write(fd, "\rATZ\r", 5); 1056 close(fd); 1057 delock(devSel); 1058 } 1059 } 1060 1061 #endif HAYESQ 1062 1063 #ifdef VENTEL 1064 ventopn(telno, flds, dev) 1065 char *flds[], *telno; 1066 struct Devices *dev; 1067 { 1068 int dh; 1069 int i, ok = -1; 1070 char dcname[20]; 1071 1072 sprintf(dcname, "/dev/%s", dev->D_line); 1073 if (setjmp(Sjbuf)) { 1074 DEBUG(1, "timeout ventel open\n", ""); 1075 logent("ventel open", "TIMEOUT"); 1076 if (dh >= 0) 1077 close(dh); 1078 delock(dev->D_line); 1079 return(CF_NODEV); 1080 } 1081 signal(SIGALRM, alarmtr); 1082 getnextfd(); 1083 alarm(10); 1084 dh = open(dcname, 2); 1085 next_fd = -1; 1086 if (dh < 0) { 1087 DEBUG(4,"%s\n", errno == 4 ? "no carrier" : "can't open modem"); 1088 delock(dev->D_line); 1089 return(errno == 4 ? CF_DIAL : CF_NODEV); 1090 } 1091 1092 /* modem is open */ 1093 fixline(dh, dev->D_speed); 1094 1095 /* translate - to % and = to & for VenTel */ 1096 DEBUG(4, "calling %s -> ", telno); 1097 for (i = 0; i < strlen(telno); ++i) { 1098 switch(telno[i]) { 1099 case '-': /* delay */ 1100 telno[i] = '%'; 1101 break; 1102 case '=': /* await dial tone */ 1103 telno[i] = '&'; 1104 break; 1105 case '<': 1106 telno[i] = '%'; 1107 break; 1108 } 1109 } 1110 DEBUG(4, "%s\n", telno); 1111 sleep(1); 1112 for(i = 0; i < 5; ++i) { /* make up to 5 tries */ 1113 slowrite(dh, "\r\r");/* awake, thou lowly VenTel! */ 1114 1115 DEBUG(4, "wanted %s ", "$"); 1116 ok = expect("$", dh); 1117 DEBUG(4, "got %s\n", ok ? "?" : "that"); 1118 if (ok != 0) 1119 continue; 1120 slowrite(dh, "K"); /* "K" (enter number) command */ 1121 DEBUG(4, "wanted %s ", "DIAL: "); 1122 ok = expect("DIAL: ", dh); 1123 DEBUG(4, "got %s\n", ok ? "?" : "that"); 1124 if (ok == 0) 1125 break; 1126 } 1127 1128 if (ok == 0) { 1129 slowrite(dh, telno); /* send telno, send \r */ 1130 slowrite(dh, "\r"); 1131 DEBUG(4, "wanted %s ", "ONLINE"); 1132 ok = expect("ONLINE!", dh); 1133 DEBUG(4, "got %s\n", ok ? "?" : "that"); 1134 } 1135 if (ok != 0) { 1136 if (dh > 2) 1137 close(dh); 1138 DEBUG(4, "venDial failed\n", ""); 1139 return(CF_DIAL); 1140 } else 1141 DEBUG(4, "venDial ok\n", ""); 1142 return(dh); 1143 } 1144 1145 1146 /* 1147 * uucpdelay: delay execution for numerator/denominator seconds. 1148 */ 1149 1150 #ifdef INTERVALTIMER 1151 #define uucpdelay(num,denom) intervaldelay(1000000*num/denom) 1152 #include <sys/time.h> 1153 catch alarm sig 1154 SIGALRM 1155 struct itimerval itimerval; 1156 itimerval.itimer_reload = 1157 itimerval.rtime.itimer_interval = 1158 itimerval.rtime.itimer_value = 1159 settimer(ITIMER_REAL, &itimerval); 1160 pause(); 1161 alarm comes in 1162 turn off timer. 1163 #endif INTERVALTIMER 1164 1165 #ifdef FASTTIMER 1166 #define uucpdelay(num,denom) nap(60*num/denom) 1167 /* Sleep in increments of 60ths of second. */ 1168 nap (time) 1169 register int time; 1170 { 1171 static int fd; 1172 1173 if (fd == 0) 1174 fd = open (FASTTIMER, 0); 1175 1176 read (fd, 0, time); 1177 } 1178 #endif FASTTIMER 1179 1180 #ifdef FTIME 1181 #define uucpdelay(num,denom) ftimedelay(1000*num/denom) 1182 #include <sys/timeb.h> 1183 ftimedelay(n) 1184 { 1185 static struct timeb loctime; 1186 ftime(&loctime); 1187 {register i = loctime.millitm; 1188 while (abs((int)(loctime.millitm - i))<n) ftime(&loctime); 1189 } 1190 } 1191 #endif FTIME 1192 1193 #ifdef BUSYLOOP 1194 #define uucpdelay(num,denom) busyloop(CPUSPEED*num/denom) 1195 #define CPUSPEED 1000000 /* VAX 780 is 1MIPS */ 1196 #define DELAY(n) { register long N = (n); while (--N > 0); } 1197 busyloop(n) 1198 { 1199 DELAY(n); 1200 } 1201 #endif BUSYLOOP 1202 1203 slowrite(fd, str) 1204 register char *str; 1205 { 1206 DEBUG(6, "slowrite ", ""); 1207 while (*str) { 1208 DEBUG(6, "%c", *str); 1209 uucpdelay(1,10); /* delay 1/10 second */ 1210 write(fd, str, 1); 1211 str++; 1212 } 1213 DEBUG(6, "\n", ""); 1214 } 1215 1216 1217 ventcls(fd) 1218 int fd; 1219 { 1220 1221 if (fd > 0) { 1222 close(fd); 1223 sleep(5); 1224 delock(devSel); 1225 } 1226 } 1227 #endif VENTEL 1228 1229 #ifdef VADIC 1230 1231 /* 1232 * vadopn: establish dial-out connection through a Racal-Vadic 3450. 1233 * Returns descriptor open to tty for reading and writing. 1234 * Negative values (-1...-7) denote errors in connmsg. 1235 * Be sure to disconnect tty when done, via HUPCL or stty 0. 1236 */ 1237 1238 vadopn(telno, flds, dev) 1239 char *telno; 1240 char *flds[]; 1241 struct Devices *dev; 1242 { 1243 int dh = -1; 1244 int i, ok, er = 0, delay; 1245 extern errno; 1246 char dcname[20]; 1247 1248 sprintf(dcname, "/dev/%s", dev->D_line); 1249 if (setjmp(Sjbuf)) { 1250 DEBUG(1, "timeout vadic open\n", ""); 1251 logent("vadic open", "TIMEOUT"); 1252 if (dh >= 0) 1253 close(dh); 1254 delock(dev->D_line); 1255 return(CF_NODEV); 1256 } 1257 signal(SIGALRM, alarmtr); 1258 getnextfd(); 1259 alarm(10); 1260 dh = open(dcname, 2); 1261 alarm(0); 1262 1263 /* modem is open */ 1264 next_fd = -1; 1265 if (dh < 0) { 1266 delock(dev->D_line); 1267 return(CF_NODEV); 1268 } 1269 fixline(dh, dev->D_speed); 1270 1271 /* translate - to K for Vadic */ 1272 DEBUG(4, "calling %s -> ", telno); 1273 delay = 0; 1274 for (i = 0; i < strlen(telno); ++i) { 1275 switch(telno[i]) { 1276 case '=': /* await dial tone */ 1277 case '-': /* delay */ 1278 case '<': 1279 telno[i] = 'K'; 1280 delay += 5; 1281 break; 1282 } 1283 } 1284 DEBUG(4, "%s\n", telno); 1285 for(i = 0; i < 5; ++i) { /* make 5 tries */ 1286 /* wake up Vadic */ 1287 sendthem("\005\\d", dh); 1288 DEBUG(4, "wanted %s ", "*"); 1289 ok = expect("*", dh); 1290 DEBUG(4, "got %s\n", ok ? "?" : "that"); 1291 if (ok != 0) 1292 continue; 1293 1294 sendthem("D\\d", dh); /* "D" (enter number) command */ 1295 DEBUG(4, "wanted %s ", "NUMBER?\\r\\n"); 1296 ok = expect("NUMBER?\r\n", dh); 1297 DEBUG(4, "got %s\n", ok ? "?" : "that"); 1298 if (ok != 0) 1299 continue; 1300 1301 /* send telno, send \r */ 1302 sendthem(telno, dh); 1303 ok = expect(telno, dh); 1304 if (ok == 0) 1305 ok = expect("\r\n", dh); 1306 DEBUG(4, "got %s\n", ok ? "?" : "that"); 1307 if (ok != 0) 1308 continue; 1309 1310 sendthem("", dh); /* confirm number */ 1311 DEBUG(4, "wanted %s ", "DIALING: "); 1312 ok = expect("DIALING: ", dh); 1313 DEBUG(4, "got %s\n", ok ? "?" : "that"); 1314 if (ok == 0) 1315 break; 1316 } 1317 1318 if (ok == 0) { 1319 sleep(10 + delay); /* give vadic some time */ 1320 DEBUG(4, "wanted ON LINE\\r\\n ", 0); 1321 ok = expect("ON LINE\r\n", dh); 1322 DEBUG(4, "got %s\n", ok ? "?" : "that"); 1323 } 1324 1325 if (ok != 0) { 1326 sendthem("I\\d", dh); /* back to idle */ 1327 if (dh > 2) 1328 close(dh); 1329 DEBUG(4, "vadDial failed\n", ""); 1330 delock(dev->D_line); 1331 return(CF_DIAL); 1332 } 1333 DEBUG(4, "vadic ok\n", ""); 1334 return(dh); 1335 } 1336 1337 vadcls(fd) { 1338 1339 if (fd > 0) { 1340 close(fd); 1341 sleep(5); 1342 delock(devSel); 1343 } 1344 } 1345 1346 #endif VADIC 1347 1348 #ifdef RVMACS 1349 /* 1350 * Racal-Vadic 'RV820' MACS system with 831 adaptor. 1351 * A typical 300 baud L-devices entry is 1352 * ACU /dev/tty10 /dev/tty11,48 300 rvmacs 1353 * where tty10 is the communication line (D_Line), 1354 * tty11 is the dialer line (D_calldev), 1355 * the '4' is the dialer address + modem type (viz. dialer 0, Bell 103), 1356 * and the '8' is the communication port (they are 1-indexed). 1357 * BUGS: 1358 * Only tested with one dialer, one modem 1359 * uses common speed for dialer and communication line. 1360 * UNTESTED 1361 */ 1362 1363 #define STX 02 /* Access Adaptor */ 1364 #define ETX 03 /* Transfer to Dialer */ 1365 #define SI 017 /* Buffer Empty (end of phone number) */ 1366 #define SOH 01 /* Abort */ 1367 1368 rvmacsopn(ph, flds, dev) 1369 char *ph, *flds[]; 1370 struct Devices *dev; 1371 { 1372 register int va, i, child; 1373 register char *p; 1374 char c, acu[20], com[20]; 1375 1376 child = -1; 1377 if ((p = index(dev->D_calldev, ',')) == NULL) { 1378 DEBUG(2, "No dialer/modem specification\n", 0); 1379 goto failret; 1380 } 1381 *p++ = '\0'; 1382 if (setjmp(Sjbuf)) { 1383 logent("rvmacsopn", "TIMEOUT"); 1384 i = CF_DIAL; 1385 goto ret; 1386 } 1387 DEBUG(4, "STARTING CALL\n", 0); 1388 sprintf(acu, "/dev/%s", dev->D_calldev); 1389 getnextfd(); 1390 signal(SIGALRM, alarmtr); 1391 alarm(30); 1392 if ((va = open(acu, 2)) < 0) { 1393 logent(acu, "CAN'T OPEN"); 1394 i = CF_NODEV; 1395 goto ret; 1396 } 1397 fixline(va, dev->D_speed); 1398 1399 p_chwrite(va, STX); /* access adaptor */ 1400 i = *p++ - '0'; 1401 if (i < 0 || i > 7) { 1402 logent(p-1, "Bad dialer address/modem type\n"); 1403 goto failret; 1404 } 1405 p_chwrite(va, i); /* Send Dialer Address Digit */ 1406 i = *p - '0'; 1407 if (i <= 0 || i > 14) { 1408 logent(p-1, "Bad modem address\n"); 1409 goto failret; 1410 } 1411 p_chwrite(va, i-1); /* Send Modem Address Digit */ 1412 write(va, ph, strlen(ph)); /* Send Phone Number */ 1413 p_chwrite(va, SI); /* Send Buffer Empty */ 1414 p_chwrite(va, ETX); /* Initiate Call */ 1415 sprintf(com, "/dev/%s", dev->D_line); 1416 1417 /* create child to open comm line */ 1418 if ((child = fork()) == 0) { 1419 signal(SIGINT, SIG_DFL); 1420 open(com, 0); 1421 sleep(5); 1422 exit(1); 1423 } 1424 1425 if (read(va, &c, 1) != 1) { 1426 logent("ACU READ", "FAILED"); 1427 goto failret; 1428 } 1429 switch(c) { 1430 case 'A': 1431 /* Fine! */ 1432 break; 1433 case 'B': 1434 DEBUG(2, "CALL ABORTED\n", 0); 1435 goto failret; 1436 case 'D': 1437 DEBUG(2, "Dialer format error\n", 0); 1438 goto failret; 1439 case 'E': 1440 DEBUG(2, "Dialer parity error\n", 0); 1441 goto failret; 1442 case 'F': 1443 DEBUG(2, "Phone number too long\n", 0); 1444 goto failret; 1445 case 'G': 1446 DEBUG(2, "Busy signal\n", 0); 1447 goto failret; 1448 default: 1449 DEBUG(2, "Unknown MACS return code '%c'\n", i); 1450 goto failret; 1451 } 1452 /* 1453 * open line - will return on carrier 1454 */ 1455 if ((i = open(com, 2)) < 0) { 1456 if (errno == EIO) 1457 logent("carrier", "LOST"); 1458 else 1459 logent("dialup open", "FAILED"); 1460 goto failret; 1461 } 1462 fixline(i, dev->D_speed); 1463 goto ret; 1464 failret: 1465 i = CF_DIAL; 1466 ret: 1467 alarm(0); 1468 if (child != -1) 1469 kill(child, SIGKILL); 1470 close(va); 1471 return(i); 1472 } 1473 1474 rvmacscls(fd) 1475 register int fd; 1476 { 1477 DEBUG(2, "MACS close %d\n", fd); 1478 p_chwrite(fd, SOH); 1479 /* ioctl(fd, TIOCCDTR, NULL);*/ 1480 close(fd); 1481 } 1482 #endif 1483