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