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