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