|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)condevs.c 5.20 (Berkeley) 5/4/88"; ! 3: #endif ! 4: ! 5: extern int errno; ! 6: extern char *sys_errlist[]; ! 7: ! 8: /* ! 9: * Here are various dialers to establish the machine-machine connection. ! 10: * conn.c/condevs.c was glued together by Mike Mitchell. ! 11: * The dialers were supplied by many people, to whom we are grateful. ! 12: * ! 13: * --------------------------------------------------------------------- ! 14: * NOTE: ! 15: * There is a bug that occurs at least on PDP11s due to a limitation of ! 16: * setjmp/longjmp. If the routine that does a setjmp is interrupted ! 17: * and longjmp-ed to, it loses its register variables (on a pdp11). ! 18: * What works is if the routine that does the setjmp ! 19: * calls a routine and it is the *subroutine* that is interrupted. ! 20: * ! 21: * Anyway, in conclusion, condevs.c is plagued with register variables ! 22: * that are used inside ! 23: * if (setjmp(...)) { ! 24: * .... ! 25: * } ! 26: * ! 27: * THE FIX: Don't declare variables to be register ! 28: */ ! 29: ! 30: #include "condevs.h" ! 31: ! 32: struct condev condevs[] = { ! 33: { "DIR", "direct", diropn, nulldev, dircls }, ! 34: #ifdef DATAKIT ! 35: { "DK", "datakit", dkopn, nulldev, nulldev }, ! 36: #endif DATAKIT ! 37: #ifdef PNET ! 38: { "PNET", "pnet", pnetopn, nulldev, nulldev }, ! 39: #endif PNET ! 40: #ifdef UNETTCP ! 41: { "TCP", "TCP", unetopn, nulldev, unetcls }, ! 42: #endif UNETTCP ! 43: #ifdef BSDTCP ! 44: { "TCP", "TCP", bsdtcpopn, nulldev, bsdtcpcls }, ! 45: #endif BSDTCP ! 46: #ifdef MICOM ! 47: { "MICOM", "micom", micopn, nulldev, miccls }, ! 48: #endif MICOM ! 49: #ifdef DN11 ! 50: { "ACU", "dn11", Acuopn, dnopn, dncls }, ! 51: #endif DN11 ! 52: #ifdef HAYES ! 53: { "ACU", "hayes", Acuopn, hyspopn, hyscls }, ! 54: { "ACU", "hayespulse", Acuopn, hyspopn, hyscls }, ! 55: { "ACU", "hayestone", Acuopn, hystopn, hyscls }, ! 56: { "WATS", "hayestone", Acuopn, hystopn, hyscls }, ! 57: #endif HAYES ! 58: #ifdef HAYES2400 ! 59: { "ACU", "hayes2400", Acuopn, hyspopn24, hyscls24 }, ! 60: { "ACU", "hayes2400pulse", Acuopn, hyspopn24, hyscls24 }, ! 61: { "ACU", "hayes2400tone", Acuopn, hystopn24, hyscls24 }, ! 62: #endif HAYES2400 ! 63: #ifdef HAYESQ /* a version of hayes that doesn't use result codes */ ! 64: { "ACU", "hayesq", Acuopn, hysqpopn, hysqcls }, ! 65: { "ACU", "hayesqpulse", Acuopn, hysqpopn, hysqcls }, ! 66: { "ACU", "hayesqtone", Acuopn, hysqtopn, hysqcls }, ! 67: #endif HAYESQ ! 68: #ifdef CDS224 ! 69: { "ACU", "cds224", Acuopn, cdsopn224, cdscls224}, ! 70: #endif CDS224 ! 71: #ifdef NOVATION ! 72: { "ACU", "novation", Acuopn, novopn, novcls}, ! 73: #endif NOVATION ! 74: #ifdef DF02 ! 75: { "ACU", "DF02", Acuopn, df2opn, df2cls }, ! 76: #endif DF02 ! 77: #ifdef DF112 ! 78: { "ACU", "DF112P", Acuopn, df12popn, df12cls }, ! 79: { "ACU", "DF112T", Acuopn, df12topn, df12cls }, ! 80: #endif DF112 ! 81: #ifdef VENTEL ! 82: { "ACU", "ventel", Acuopn, ventopn, ventcls }, ! 83: #endif VENTEL ! 84: #ifdef PENRIL ! 85: { "ACU", "penril", Acuopn, penopn, pencls }, ! 86: #endif PENRIL ! 87: #ifdef VADIC ! 88: { "ACU", "vadic", Acuopn, vadopn, vadcls }, ! 89: #endif VADIC ! 90: #ifdef VA212 ! 91: { "ACU", "va212", Acuopn, va212opn, va212cls }, ! 92: #endif VA212 ! 93: #ifdef VA811S ! 94: { "ACU", "va811s", Acuopn, va811opn, va811cls }, ! 95: #endif VA811S ! 96: #ifdef VA820 ! 97: { "ACU", "va820", Acuopn, va820opn, va820cls }, ! 98: { "WATS", "va820", Acuopn, va820opn, va820cls }, ! 99: #endif VA820 ! 100: #ifdef RVMACS ! 101: { "ACU", "rvmacs", Acuopn, rvmacsopn, rvmacscls }, ! 102: #endif RVMACS ! 103: #ifdef VMACS ! 104: { "ACU", "vmacs", Acuopn, vmacsopn, vmacscls }, ! 105: #endif VMACS ! 106: #ifdef SYTEK ! 107: { "SYTEK", "sytek", sykopn, nulldev, sykcls }, ! 108: #endif SYTEK ! 109: #ifdef ATT2224 ! 110: { "ACU", "att", Acuopn, attopn, attcls }, ! 111: #endif ATT2224 ! 112: ! 113: ! 114: /* Insert new entries before this line */ ! 115: { NULL, NULL, NULL, NULL, NULL } ! 116: }; ! 117: ! 118: /* ! 119: * nulldev a null device (returns CF_DIAL) ! 120: */ ! 121: nulldev() ! 122: { ! 123: return CF_DIAL; ! 124: } ! 125: ! 126: /* ! 127: * nodev a null device (returns CF_NODEV) ! 128: */ ! 129: nodev() ! 130: { ! 131: return CF_NODEV; ! 132: } ! 133: ! 134: /* ! 135: * Generic devices look through L-devices and call the CU_open routines for ! 136: * appropriate devices. Some things, like the tcp/ip interface, or direct ! 137: * connect, do not use the CU_open entry. ACUs must search to find the ! 138: * right routine to call. ! 139: */ ! 140: ! 141: /* ! 142: * diropn(flds) connect to hardware line ! 143: * ! 144: * return codes: ! 145: * > 0 - file number - ok ! 146: * FAIL - failed ! 147: */ ! 148: diropn(flds) ! 149: register char *flds[]; ! 150: { ! 151: register int dcr, status; ! 152: struct Devices dev; ! 153: char dcname[20]; ! 154: FILE *dfp; ! 155: #ifdef VMSDTR /* Modem control on vms(works dtr) */ ! 156: int modem_control; ! 157: short iosb[4]; ! 158: int sys$qiow(); /* use this for long reads on vms */ ! 159: int ret; ! 160: long mode[2]; ! 161: modem_control = 0; ! 162: #endif ! 163: dfp = fopen(DEVFILE, "r"); ! 164: if (dfp == NULL) { ! 165: syslog(LOG_ERR, "fopen(%s) failed: %m", DEVFILE); ! 166: cleanup(FAIL); ! 167: } ! 168: while ((status = rddev(dfp, &dev)) != FAIL) { ! 169: #ifdef VMSDTR /* Modem control on vms(works dtr) */ ! 170: /* If we find MOD in the device type field we go into action */ ! 171: if (strcmp(dev.D_type, "MOD") == SAME) { ! 172: modem_control = 1; ! 173: DEBUG(7, "Setting Modem control to %d",modem_control); ! 174: } ! 175: if (strcmp(flds[F_CLASS], dev.D_class) != SAME) ! 176: continue; ! 177: /* ! 178: * Modem control on vms(works dtr) Take anything in MOD class. ! 179: * It probably should work differently anyway so we can have ! 180: * multiple hardwired lines. ! 181: */ ! 182: if (!modem_control&&strcmp(flds[F_PHONE], dev.D_line) != SAME) ! 183: #else !VMSDTR ! 184: if (strcmp(flds[F_CLASS], dev.D_class) != SAME) ! 185: continue; ! 186: if (strcmp(flds[F_PHONE], dev.D_line) != SAME) ! 187: #endif !VMSDTR ! 188: continue; ! 189: if (mlock(dev.D_line) != FAIL) ! 190: break; ! 191: } ! 192: fclose(dfp); ! 193: if (status == FAIL) { ! 194: logent("DEVICE", "NO"); ! 195: return CF_NODEV; ! 196: } ! 197: ! 198: sprintf(dcname, "/dev/%s", dev.D_line); ! 199: if (setjmp(Sjbuf)) { ! 200: DEBUG(4, "Open timed out\n", CNULL); ! 201: delock(dev.D_line); ! 202: return CF_DIAL; ! 203: } ! 204: signal(SIGALRM, alarmtr); ! 205: /* For PC Pursuit, it could take a while to call back */ ! 206: alarm( strcmp(flds[F_LINE], "PCP") ? 10 : MAXMSGTIME*4 ); ! 207: getnextfd(); ! 208: errno = 0; ! 209: DEBUG(4,"Opening %s\n",dcname); ! 210: dcr = open(dcname, 2); /* read/write */ ! 211: #ifdef VMSDTR /* Modem control on vms(works dtr) */ ! 212: fflush(stdout); ! 213: if (modem_control) { /* Did we have MOD in the device type field ? */ ! 214: /* Sense the current terminal setup and save it */ ! 215: if ((ret = sys$qiow(_$EFN,(fd_fab_pointer[dcr]->fab).fab$l_stv, ! 216: IO$_SENSEMODE,iosb,0,0,mode,8,0,0,0,0)) ! 217: != SS$_NORMAL) { ! 218: DEBUG(7, "ret status on sense failed on Modem sense=%x<", ret); ! 219: return CF_DIAL; ! 220: } ! 221: mode[1] |= TT$M_MODEM; /* Or in modem control(DTR) */ ! 222: /* Now set the new terminal characteristics */ ! 223: /* This is temporary and will go away when we let go of it */ ! 224: if ((ret = sys$qiow(_$EFN,(fd_fab_pointer[dcr]->fab).fab$l_stv, ! 225: IO$_SETMODE,iosb,0,0,mode,8,0,0,0,0)) ! 226: != SS$_NORMAL) { ! 227: DEBUG(7, "ret status on sense failed on Modem setup=%x<", ret); ! 228: return CF_DIAL; ! 229: } ! 230: } ! 231: #endif VMSDTR ! 232: next_fd = -1; ! 233: alarm(0); ! 234: if (dcr < 0) { ! 235: if (errno == EACCES) ! 236: logent(dev.D_line, "CANT OPEN"); ! 237: DEBUG(4, "OPEN FAILED: errno %d\n", errno); ! 238: delock(dev.D_line); ! 239: return CF_DIAL; ! 240: } ! 241: fflush(stdout); ! 242: if (fixline(dcr, dev.D_speed) == FAIL) { ! 243: DEBUG(4, "FIXLINE FAILED\n", CNULL); ! 244: return CF_DIAL; ! 245: } ! 246: strcpy(devSel, dev.D_line); /* for latter unlock */ ! 247: CU_end = dircls; ! 248: return dcr; ! 249: } ! 250: ! 251: dircls(fd) ! 252: register int fd; ! 253: { ! 254: if (fd > 0) { ! 255: close(fd); ! 256: delock(devSel); ! 257: } ! 258: } ! 259: ! 260: /* ! 261: * open an ACU and dial the number. The condevs table ! 262: * will be searched until a dialing unit is found that is free. ! 263: * ! 264: * return codes: >0 - file number - o.k. ! 265: * FAIL - failed ! 266: */ ! 267: char devSel[20]; /* used for later unlock() */ ! 268: ! 269: Acuopn(flds) ! 270: register char *flds[]; ! 271: { ! 272: char phone[MAXPH+1]; ! 273: register struct condev *cd; ! 274: register int fd, acustatus; ! 275: register FILE *dfp; ! 276: struct Devices dev; ! 277: int retval = CF_NODEV; ! 278: char nobrand[MAXPH], *line; ! 279: ! 280: exphone(flds[F_PHONE], phone); ! 281: if (snccmp(flds[F_LINE], "LOCAL") == SAME) ! 282: line = "ACU"; ! 283: else ! 284: line = flds[F_LINE]; ! 285: devSel[0] = '\0'; ! 286: nobrand[0] = '\0'; ! 287: DEBUG(4, "Dialing %s\n", phone); ! 288: dfp = fopen(DEVFILE, "r"); ! 289: if (dfp == NULL) { ! 290: syslog(LOG_ERR, "fopen(%s) failed: %m", DEVFILE); ! 291: cleanup(FAIL); ! 292: } ! 293: ! 294: acustatus = 0; /* none found, none locked */ ! 295: while (rddev(dfp, &dev) != FAIL) { ! 296: /* ! 297: * for each ACU L.sys line, try at most twice ! 298: * (TRYCALLS) to establish carrier. The old way tried every ! 299: * available dialer, which on big sites takes forever! ! 300: * Sites with a single auto-dialer get one try. ! 301: * Sites with multiple dialers get a try on each of two ! 302: * different dialers. ! 303: * To try 'harder' to connect to a remote site, ! 304: * use multiple L.sys entries. ! 305: */ ! 306: if (acustatus > TRYCALLS) ! 307: break; ! 308: if (strcmp(flds[F_CLASS], dev.D_class) != SAME) ! 309: continue; ! 310: if (snccmp(line, dev.D_type) != SAME) ! 311: continue; ! 312: if (dev.D_brand[0] == '\0') { ! 313: logent("Acuopn","No 'brand' name on ACU"); ! 314: continue; ! 315: } ! 316: for(cd = condevs; cd->CU_meth != NULL; cd++) { ! 317: if (snccmp(line, cd->CU_meth) == SAME) { ! 318: if (snccmp(dev.D_brand, cd->CU_brand) == SAME) { ! 319: nobrand[0] = '\0'; ! 320: break; ! 321: } ! 322: strncpy(nobrand, dev.D_brand, sizeof nobrand); ! 323: } ! 324: } ! 325: ! 326: if (acustatus < 1) ! 327: acustatus = 1; /* has been found */ ! 328: ! 329: if (mlock(dev.D_line) == FAIL) ! 330: continue; ! 331: ! 332: #ifdef DIALINOUT ! 333: #ifdef ALLACUINOUT ! 334: if (1) { ! 335: #else !ALLACUINOUT ! 336: if (snccmp("inout", dev.D_calldev) == SAME) { ! 337: #endif !ALLACUINOUT ! 338: if (disable(dev.D_line) == FAIL) { ! 339: delock(dev.D_line); ! 340: continue; ! 341: } ! 342: } else ! 343: reenable(); ! 344: #endif DIALINOUT ! 345: ! 346: DEBUG(4, "Using %s\n", cd->CU_brand); ! 347: acustatus++; ! 348: fd = (*(cd->CU_open))(phone, flds, &dev); ! 349: if (fd > 0) { ! 350: CU_end = cd->CU_clos; /* point CU_end at close func */ ! 351: fclose(dfp); ! 352: strcpy(devSel, dev.D_line); /* save for later unlock() */ ! 353: return fd; ! 354: } else ! 355: delock(dev.D_line); ! 356: retval = CF_DIAL; ! 357: } ! 358: fclose(dfp); ! 359: if (acustatus == 0) { ! 360: if (nobrand[0]) ! 361: logent(nobrand, "unsupported ACU type"); ! 362: else ! 363: logent("L-devices", "No appropriate ACU"); ! 364: } ! 365: if (acustatus == 1) ! 366: logent("DEVICE", "NO"); ! 367: return retval; ! 368: } ! 369: ! 370: /* ! 371: * intervaldelay: delay execution for numerator/denominator seconds. ! 372: */ ! 373: ! 374: #ifdef INTERVALTIMER ! 375: #include <sys/time.h> ! 376: #define uucpdelay(num,denom) intervaldelay(num,denom) ! 377: intervaldelay(num,denom) ! 378: int num, denom; ! 379: { ! 380: struct timeval tv; ! 381: tv.tv_sec = num / denom; ! 382: tv.tv_usec = (num * 1000000L / denom ) % 1000000L; ! 383: (void) select (0, (int *)0, (int *)0, (int *)0, &tv); ! 384: } ! 385: #endif INTERVALTIMER ! 386: ! 387: #ifdef FASTTIMER ! 388: #define uucpdelay(num,denom) nap(60*num/denom) ! 389: /* Sleep in increments of 60ths of second. */ ! 390: nap (time) ! 391: register int time; ! 392: { ! 393: static int fd; ! 394: ! 395: if (fd == 0) ! 396: fd = open (FASTTIMER, 0); ! 397: ! 398: read (fd, 0, time); ! 399: } ! 400: #endif FASTTIMER ! 401: ! 402: #ifdef FTIME ! 403: #define uucpdelay(num,denom) ftimedelay(1000*num/denom) ! 404: ftimedelay(n) ! 405: { ! 406: static struct timeb loctime; ! 407: register i = loctime.millitm; ! 408: ! 409: ftime(&loctime); ! 410: while (abs((int)(loctime.millitm - i))<n) ftime(&loctime) ! 411: ; ! 412: } ! 413: #endif FTIME ! 414: ! 415: #ifdef BUSYLOOP ! 416: #define uucpdelay(num,denom) busyloop(CPUSPEED*num/denom) ! 417: #define CPUSPEED 1000000 /* VAX 780 is 1MIPS */ ! 418: #define DELAY(n) { register long N = (n); while (--N > 0); } ! 419: busyloop(n) ! 420: { ! 421: DELAY(n); ! 422: } ! 423: #endif BUSYLOOP ! 424: ! 425: slowrite(fd, str) ! 426: register char *str; ! 427: { ! 428: DEBUG(6, "slowrite ", CNULL); ! 429: while (*str) { ! 430: DEBUG(6, "%c", *str); ! 431: uucpdelay(1, 10); /* delay 1/10 second */ ! 432: write(fd, str, 1); ! 433: str++; ! 434: } ! 435: DEBUG(6, "\n", CNULL); ! 436: } ! 437: ! 438: #define BSPEED B150 ! 439: ! 440: /* ! 441: * send a break ! 442: */ ! 443: genbrk(fn, bnulls) ! 444: register int fn, bnulls; ! 445: { ! 446: #ifdef USG ! 447: if (ioctl(fn, TCSBRK, STBNULL) < 0) ! 448: DEBUG(5, "break TCSBRK %s\n", sys_errlist[errno]); ! 449: #else !USG ! 450: # ifdef TIOCSBRK ! 451: if (ioctl(fn, TIOCSBRK, STBNULL) < 0) ! 452: DEBUG(5, "break TIOCSBRK %s\n", sys_errlist[errno]); ! 453: # ifdef TIOCCBRK ! 454: uucpdelay(bnulls, 10); ! 455: if (ioctl(fn, TIOCCBRK, STBNULL) < 0) ! 456: DEBUG(5, "break TIOCCBRK %s\n", sys_errlist[errno]); ! 457: # endif TIOCCBRK ! 458: DEBUG(4, "ioctl %f second break\n", (float) bnulls/10 ); ! 459: # else !TIOCSBRK ! 460: struct sgttyb ttbuf; ! 461: register int sospeed; ! 462: ! 463: if (ioctl(fn, TIOCGETP, &ttbuf) < 0) ! 464: DEBUG(5, "break TIOCGETP %s\n", sys_errlist[errno]); ! 465: sospeed = ttbuf.sg_ospeed; ! 466: ttbuf.sg_ospeed = BSPEED; ! 467: if (ioctl(fn, TIOCSETP, &ttbuf) < 0) ! 468: DEBUG(5, "break TIOCSETP %s\n", sys_errlist[errno]); ! 469: if (write(fn, "\0\0\0\0\0\0\0\0\0\0\0\0", bnulls) != bnulls) { ! 470: badbreak: ! 471: logent(sys_errlist[errno], "BAD WRITE genbrk"); ! 472: alarm(0); ! 473: longjmp(Sjbuf, 3); ! 474: } ! 475: ttbuf.sg_ospeed = sospeed; ! 476: if (ioctl(fn, TIOCSETP, &ttbuf) < 0) ! 477: DEBUG(5, "break ioctl %s\n", sys_errlist[errno]); ! 478: if (write(fn, "@", 1) != 1) ! 479: goto badbreak; ! 480: DEBUG(4, "sent BREAK nulls - %d\n", bnulls); ! 481: #endif !TIOCSBRK ! 482: #endif !USG ! 483: } ! 484: ! 485: ! 486: #ifdef DIALINOUT ! 487: /* DIALIN/OUT CODE (WLS) */ ! 488: /* ! 489: * disable and reenable: allow a single line to be use for dialin/dialout ! 490: * ! 491: */ ! 492: ! 493: char enbdev[16]; ! 494: ! 495: disable(dev) ! 496: register char *dev; ! 497: { ! 498: register char *rdev; ! 499: ! 500: /* strip off directory prefixes */ ! 501: rdev = dev; ! 502: while (*rdev) ! 503: rdev++; ! 504: while (--rdev >= dev && *rdev != '/') ! 505: ; ! 506: rdev++; ! 507: ! 508: if (enbdev[0]) { ! 509: if (strcmp(enbdev, rdev) == SAME) ! 510: return SUCCESS; /* already disabled */ ! 511: delock(enbdev); ! 512: reenable(); /* else, reenable the old one */ ! 513: } ! 514: DEBUG(4, "Disable %s\n", rdev); ! 515: if (enbcall("disable", rdev) == FAIL) ! 516: return FAIL; ! 517: strcpy(enbdev, rdev); ! 518: return SUCCESS; ! 519: } ! 520: ! 521: reenable() ! 522: { ! 523: if (enbdev[0] == '\0') ! 524: return; ! 525: DEBUG(4, "Reenable %s\n", enbdev); ! 526: (void) enbcall("enable", enbdev); ! 527: enbdev[0] = '\0'; ! 528: } ! 529: ! 530: enbcall(type, dev) ! 531: char *type, *dev; ! 532: { ! 533: int pid; ! 534: register char *p; ! 535: int fildes[2]; ! 536: int status; ! 537: FILE *fil; ! 538: char buf[80]; ! 539: ! 540: fflush(stderr); ! 541: fflush(stdout); ! 542: pipe(fildes); ! 543: if ((pid = fork()) == 0) { ! 544: DEBUG(4, DIALINOUT, CNULL); ! 545: DEBUG(4, " %s", type); ! 546: DEBUG(4, " %s\n", dev); ! 547: close(fildes[0]); ! 548: close(0); close(1); close(2); ! 549: open("/dev/null",0); ! 550: dup(fildes[1]); dup(fildes[1]); ! 551: setuid(geteuid()); /* for chown(uid()) in acu program */ ! 552: execl(DIALINOUT, "acu", type, dev, Rmtname, (char *)0); ! 553: exit(-1); ! 554: } ! 555: if (pid<0) ! 556: return FAIL; ! 557: ! 558: close(fildes[1]); ! 559: fil = fdopen(fildes[0],"r"); ! 560: if (fil!=NULL) { ! 561: #ifdef BSD4_2 ! 562: setlinebuf(fil); ! 563: #endif BSD4_2 ! 564: while (fgets(buf, sizeof buf, fil) != NULL) { ! 565: p = buf + strlen(buf) - 1; ! 566: if (*p == '\n') ! 567: *p = '\0'; ! 568: DEBUG(4, "ACUCNTRL: %s\n", buf); ! 569: } ! 570: } ! 571: while(wait(&status) != pid) ! 572: ; ! 573: fclose(fil); ! 574: return status ? FAIL : SUCCESS; ! 575: } ! 576: #endif DIALINOUT
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.