1: #ifndef lint 2: static char sccsid[] = "@(#)condevs.c 5.5 (Berkeley) 7/19/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: char sendnum[80]; 1248: 1249: sprintf(dcname, "/dev/%s", dev->D_line); 1250: if (setjmp(Sjbuf)) { 1251: DEBUG(1, "timeout vadic open\n", ""); 1252: logent("vadic open", "TIMEOUT"); 1253: if (dh >= 0) 1254: close(dh); 1255: delock(dev->D_line); 1256: return(CF_NODEV); 1257: } 1258: signal(SIGALRM, alarmtr); 1259: getnextfd(); 1260: alarm(10); 1261: dh = open(dcname, 2); 1262: alarm(0); 1263: 1264: /* modem is open */ 1265: next_fd = -1; 1266: if (dh < 0) { 1267: delock(dev->D_line); 1268: return(CF_NODEV); 1269: } 1270: fixline(dh, dev->D_speed); 1271: 1272: /* translate - to K for Vadic */ 1273: DEBUG(4, "calling %s -> ", telno); 1274: delay = 0; 1275: for (i = 0; i < strlen(telno); ++i) { 1276: switch(telno[i]) { 1277: case '=': /* await dial tone */ 1278: case '-': /* delay */ 1279: case '<': 1280: telno[i] = 'K'; 1281: delay += 5; 1282: break; 1283: } 1284: } 1285: DEBUG(4, "%s\n", telno); 1286: for(i = 0; i < 5; ++i) { /* make 5 tries */ 1287: /* wake up Vadic */ 1288: sendthem("\005\\d", dh); 1289: DEBUG(4, "wanted %s ", "*"); 1290: ok = expect("*", dh); 1291: DEBUG(4, "got %s\n", ok ? "?" : "that"); 1292: if (ok != 0) 1293: continue; 1294: 1295: sendthem("D\\d", dh); /* "D" (enter number) command */ 1296: DEBUG(4, "wanted %s ", "NUMBER?\\r\\n"); 1297: ok = expect("NUMBER?\r\n", dh); 1298: DEBUG(4, "got %s\n", ok ? "?" : "that"); 1299: if (ok != 0) 1300: continue; 1301: 1302: /* send telno, send \r */ 1303: sendthem(telno, dh); 1304: ok = expect(telno, dh); 1305: if (ok == 0) 1306: ok = expect("\r\n", dh); 1307: DEBUG(4, "got %s\n", ok ? "?" : "that"); 1308: if (ok != 0) 1309: continue; 1310: 1311: sendthem("", dh); /* confirm number */ 1312: DEBUG(4, "wanted %s ", "DIALING: "); 1313: ok = expect("DIALING: ", dh); 1314: DEBUG(4, "got %s\n", ok ? "?" : "that"); 1315: if (ok == 0) 1316: break; 1317: } 1318: 1319: if (ok == 0) { 1320: sleep(10 + delay); /* give vadic some time */ 1321: DEBUG(4, "wanted ON LINE\\r\\n ", 0); 1322: ok = expect("ON LINE\r\n", dh); 1323: DEBUG(4, "got %s\n", ok ? "?" : "that"); 1324: } 1325: 1326: if (ok != 0) { 1327: sendthem("I\\d", dh); /* back to idle */ 1328: if (dh > 2) 1329: close(dh); 1330: DEBUG(4, "vadDial failed\n", ""); 1331: delock(dev->D_line); 1332: return(CF_DIAL); 1333: } 1334: DEBUG(4, "vadic ok\n", ""); 1335: return(dh); 1336: } 1337: 1338: vadcls(fd) { 1339: 1340: if (fd > 0) { 1341: close(fd); 1342: sleep(5); 1343: delock(devSel); 1344: } 1345: } 1346: 1347: #endif VADIC 1348: 1349: #ifdef RVMACS 1350: /* 1351: * Racal-Vadic 'RV820' MACS system with 831 adaptor. 1352: * A typical 300 baud L-devices entry is 1353: * ACU /dev/tty10 /dev/tty11,48 300 rvmacs 1354: * where tty10 is the communication line (D_Line), 1355: * tty11 is the dialer line (D_calldev), 1356: * the '4' is the dialer address + modem type (viz. dialer 0, Bell 103), 1357: * and the '8' is the communication port (they are 1-indexed). 1358: * BUGS: 1359: * Only tested with one dialer, one modem 1360: * uses common speed for dialer and communication line. 1361: * UNTESTED 1362: */ 1363: 1364: #define STX 02 /* Access Adaptor */ 1365: #define ETX 03 /* Transfer to Dialer */ 1366: #define SI 017 /* Buffer Empty (end of phone number) */ 1367: #define SOH 01 /* Abort */ 1368: 1369: rvmacsopn(ph, flds, dev) 1370: char *ph, *flds[]; 1371: struct Devices *dev; 1372: { 1373: register int va, i, child; 1374: register char *p; 1375: char c, acu[20], com[20]; 1376: 1377: child = -1; 1378: if ((p = index(dev->D_calldev, ',')) == NULL) { 1379: DEBUG(2, "No dialer/modem specification\n", 0); 1380: goto failret; 1381: } 1382: *p++ = '\0'; 1383: if (setjmp(Sjbuf)) { 1384: logent("rvmacsopn", "TIMEOUT"); 1385: i = CF_DIAL; 1386: goto ret; 1387: } 1388: DEBUG(4, "STARTING CALL\n", 0); 1389: sprintf(acu, "/dev/%s", dev->D_calldev); 1390: getnextfd(); 1391: signal(SIGALRM, alarmtr); 1392: alarm(30); 1393: if ((va = open(acu, 2)) < 0) { 1394: logent(acu, "CAN'T OPEN"); 1395: i = CF_NODEV; 1396: goto ret; 1397: } 1398: fixline(va, dev->D_speed); 1399: 1400: p_chwrite(va, STX); /* access adaptor */ 1401: i = *p++ - '0'; 1402: if (i < 0 || i > 7) { 1403: logent(p-1, "Bad dialer address/modem type\n"); 1404: goto failret; 1405: } 1406: p_chwrite(va, i); /* Send Dialer Address Digit */ 1407: i = *p - '0'; 1408: if (i <= 0 || i > 14) { 1409: logent(p-1, "Bad modem address\n"); 1410: goto failret; 1411: } 1412: p_chwrite(va, i-1); /* Send Modem Address Digit */ 1413: write(va, ph, strlen(ph)); /* Send Phone Number */ 1414: p_chwrite(va, SI); /* Send Buffer Empty */ 1415: p_chwrite(va, ETX); /* Initiate Call */ 1416: sprintf(com, "/dev/%s", dev->D_line); 1417: 1418: /* create child to open comm line */ 1419: if ((child = fork()) == 0) { 1420: signal(SIGINT, SIG_DFL); 1421: open(com, 0); 1422: sleep(5); 1423: exit(1); 1424: } 1425: 1426: if (read(va, &c, 1) != 1) { 1427: logent("ACU READ", "FAILED"); 1428: goto failret; 1429: } 1430: switch(c) { 1431: case 'A': 1432: /* Fine! */ 1433: break; 1434: case 'B': 1435: DEBUG(2, "CALL ABORTED\n", 0); 1436: goto failret; 1437: case 'D': 1438: DEBUG(2, "Dialer format error\n", 0); 1439: goto failret; 1440: case 'E': 1441: DEBUG(2, "Dialer parity error\n", 0); 1442: goto failret; 1443: case 'F': 1444: DEBUG(2, "Phone number too long\n", 0); 1445: goto failret; 1446: case 'G': 1447: DEBUG(2, "Busy signal\n", 0); 1448: goto failret; 1449: default: 1450: DEBUG(2, "Unknown MACS return code '%c'\n", i); 1451: goto failret; 1452: } 1453: /* 1454: * open line - will return on carrier 1455: */ 1456: if ((i = open(com, 2)) < 0) { 1457: if (errno == EIO) 1458: logent("carrier", "LOST"); 1459: else 1460: logent("dialup open", "FAILED"); 1461: goto failret; 1462: } 1463: fixline(i, dev->D_speed); 1464: goto ret; 1465: failret: 1466: i = CF_DIAL; 1467: ret: 1468: alarm(0); 1469: if (child != -1) 1470: kill(child, SIGKILL); 1471: close(va); 1472: return(i); 1473: } 1474: 1475: rvmacscls(fd) 1476: register int fd; 1477: { 1478: DEBUG(2, "MACS close %d\n", fd); 1479: p_chwrite(fd, SOH); 1480: /* ioctl(fd, TIOCCDTR, NULL);*/ 1481: close(fd); 1482: } 1483: #endif