|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)condevs.c 5.15 (Berkeley) 2/12/86"; ! 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: ASSERT(dfp != NULL, "CAN'T OPEN", DEVFILE, 0); ! 165: while ((status = rddev(dfp, &dev)) != FAIL) { ! 166: #ifdef VMSDTR /* Modem control on vms(works dtr) */ ! 167: /* If we find MOD in the device type field we go into action */ ! 168: if (strcmp(dev.D_type, "MOD") == SAME) { ! 169: modem_control = 1; ! 170: DEBUG(7, "Setting Modem control to %d",modem_control); ! 171: } ! 172: if (strcmp(flds[F_CLASS], dev.D_class) != SAME) ! 173: continue; ! 174: /* ! 175: * Modem control on vms(works dtr) Take anything in MOD class. ! 176: * It probably should work differently anyway so we can have ! 177: * multiple hardwired lines. ! 178: */ ! 179: if (!modem_control&&strcmp(flds[F_PHONE], dev.D_line) != SAME) ! 180: #else !VMSDTR ! 181: if (strcmp(flds[F_CLASS], dev.D_class) != SAME) ! 182: continue; ! 183: if (strcmp(flds[F_PHONE], dev.D_line) != SAME) ! 184: #endif !VMSDTR ! 185: continue; ! 186: if (mlock(dev.D_line) != FAIL) ! 187: break; ! 188: } ! 189: fclose(dfp); ! 190: if (status == FAIL) { ! 191: logent("DEVICE", "NO"); ! 192: return CF_NODEV; ! 193: } ! 194: ! 195: sprintf(dcname, "/dev/%s", dev.D_line); ! 196: if (setjmp(Sjbuf)) { ! 197: DEBUG(4, "Open timed out\n", CNULL); ! 198: delock(dev.D_line); ! 199: return CF_DIAL; ! 200: } ! 201: signal(SIGALRM, alarmtr); ! 202: /* For PC Pursuit, it could take a while to call back */ ! 203: alarm( strcmp(flds[F_LINE], "PCP") ? 10 : MAXMSGTIME*4 ); ! 204: getnextfd(); ! 205: errno = 0; ! 206: DEBUG(4,"Opening %s\n",dcname); ! 207: dcr = open(dcname, 2); /* read/write */ ! 208: #ifdef VMSDTR /* Modem control on vms(works dtr) */ ! 209: fflush(stdout); ! 210: if (modem_control) { /* Did we have MOD in the device type field ? */ ! 211: /* Sense the current terminal setup and save it */ ! 212: if ((ret = sys$qiow(_$EFN,(fd_fab_pointer[dcr]->fab).fab$l_stv, ! 213: IO$_SENSEMODE,iosb,0,0,mode,8,0,0,0,0)) ! 214: != SS$_NORMAL) { ! 215: DEBUG(7, "ret status on sense failed on Modem sense=%x<", ret); ! 216: return CF_DIAL; ! 217: } ! 218: mode[1] |= TT$M_MODEM; /* Or in modem control(DTR) */ ! 219: /* Now set the new terminal characteristics */ ! 220: /* This is temporary and will go away when we let go of it */ ! 221: if ((ret = sys$qiow(_$EFN,(fd_fab_pointer[dcr]->fab).fab$l_stv, ! 222: IO$_SETMODE,iosb,0,0,mode,8,0,0,0,0)) ! 223: != SS$_NORMAL) { ! 224: DEBUG(7, "ret status on sense failed on Modem setup=%x<", ret); ! 225: return CF_DIAL; ! 226: } ! 227: } ! 228: #endif VMSDTR ! 229: next_fd = -1; ! 230: alarm(0); ! 231: if (dcr < 0) { ! 232: if (errno == EACCES) ! 233: logent(dev.D_line, "CANT OPEN"); ! 234: DEBUG(4, "OPEN FAILED: errno %d\n", errno); ! 235: delock(dev.D_line); ! 236: return CF_DIAL; ! 237: } ! 238: fflush(stdout); ! 239: if (fixline(dcr, dev.D_speed) == FAIL) { ! 240: DEBUG(4, "FIXLINE FAILED\n", CNULL); ! 241: return CF_DIAL; ! 242: } ! 243: strcpy(devSel, dev.D_line); /* for latter unlock */ ! 244: CU_end = dircls; ! 245: return dcr; ! 246: } ! 247: ! 248: dircls(fd) ! 249: register int fd; ! 250: { ! 251: if (fd > 0) { ! 252: close(fd); ! 253: delock(devSel); ! 254: } ! 255: } ! 256: ! 257: /* ! 258: * open an ACU and dial the number. The condevs table ! 259: * will be searched until a dialing unit is found that is free. ! 260: * ! 261: * return codes: >0 - file number - o.k. ! 262: * FAIL - failed ! 263: */ ! 264: char devSel[20]; /* used for later unlock() */ ! 265: ! 266: Acuopn(flds) ! 267: register char *flds[]; ! 268: { ! 269: char phone[MAXPH+1]; ! 270: register struct condev *cd; ! 271: register int fd, acustatus; ! 272: register FILE *dfp; ! 273: struct Devices dev; ! 274: int retval = CF_NODEV; ! 275: char nobrand[MAXPH], *line; ! 276: ! 277: exphone(flds[F_PHONE], phone); ! 278: if (snccmp(flds[F_LINE], "LOCAL") == SAME) ! 279: line = "ACU"; ! 280: else ! 281: line = flds[F_LINE]; ! 282: devSel[0] = '\0'; ! 283: nobrand[0] = '\0'; ! 284: DEBUG(4, "Dialing %s\n", phone); ! 285: dfp = fopen(DEVFILE, "r"); ! 286: ASSERT(dfp != NULL, "Can't open", DEVFILE, 0); ! 287: ! 288: acustatus = 0; /* none found, none locked */ ! 289: while (rddev(dfp, &dev) != FAIL) { ! 290: /* ! 291: * for each ACU L.sys line, try at most twice ! 292: * (TRYCALLS) to establish carrier. The old way tried every ! 293: * available dialer, which on big sites takes forever! ! 294: * Sites with a single auto-dialer get one try. ! 295: * Sites with multiple dialers get a try on each of two ! 296: * different dialers. ! 297: * To try 'harder' to connect to a remote site, ! 298: * use multiple L.sys entries. ! 299: */ ! 300: if (acustatus > TRYCALLS) ! 301: break; ! 302: if (strcmp(flds[F_CLASS], dev.D_class) != SAME) ! 303: continue; ! 304: if (snccmp(line, dev.D_type) != SAME) ! 305: continue; ! 306: if (dev.D_brand[0] == '\0') { ! 307: logent("Acuopn","No 'brand' name on ACU"); ! 308: continue; ! 309: } ! 310: for(cd = condevs; cd->CU_meth != NULL; cd++) { ! 311: if (snccmp(line, cd->CU_meth) == SAME) { ! 312: if (snccmp(dev.D_brand, cd->CU_brand) == SAME) ! 313: break; ! 314: strncpy(nobrand, dev.D_brand, sizeof nobrand); ! 315: } ! 316: } ! 317: ! 318: if (mlock(dev.D_line) == FAIL) { ! 319: acustatus++; ! 320: continue; ! 321: } ! 322: if (acustatus < 1) ! 323: acustatus = 1; /* has been found */ ! 324: #ifdef DIALINOUT ! 325: #ifdef ALLACUINOUT ! 326: if (1) { ! 327: #else !ALLACUINOUT ! 328: if (snccmp("inout", dev.D_calldev) == SAME) { ! 329: #endif !ALLACUINOUT ! 330: if (disable(dev.D_line) == FAIL) { ! 331: delock(dev.D_line); ! 332: continue; ! 333: } ! 334: } else ! 335: reenable(); ! 336: #endif DIALINOUT ! 337: ! 338: DEBUG(4, "Using %s\n", cd->CU_brand); ! 339: acustatus++; ! 340: fd = (*(cd->CU_open))(phone, flds, &dev); ! 341: if (fd > 0) { ! 342: CU_end = cd->CU_clos; /* point CU_end at close func */ ! 343: fclose(dfp); ! 344: strcpy(devSel, dev.D_line); /* save for later unlock() */ ! 345: return fd; ! 346: } else ! 347: delock(dev.D_line); ! 348: retval = CF_DIAL; ! 349: } ! 350: fclose(dfp); ! 351: if (acustatus == 0) { ! 352: if (nobrand[0]) ! 353: logent(nobrand, "unsupported ACU type"); ! 354: else ! 355: logent("L-devices", "No appropriate ACU"); ! 356: } ! 357: if (acustatus == 1) ! 358: logent("DEVICE", "NO"); ! 359: return retval; ! 360: } ! 361: ! 362: /* ! 363: * intervaldelay: delay execution for numerator/denominator seconds. ! 364: */ ! 365: ! 366: #ifdef INTERVALTIMER ! 367: #include <sys/time.h> ! 368: #define uucpdelay(num,denom) intervaldelay(num,denom) ! 369: intervaldelay(num,denom) ! 370: int num, denom; ! 371: { ! 372: struct timeval tv; ! 373: tv.tv_sec = num / denom; ! 374: tv.tv_usec = (num * 1000000L / denom ) % 1000000L; ! 375: (void) select (0, (int *)0, (int *)0, (int *)0, &tv); ! 376: } ! 377: #endif INTERVALTIMER ! 378: ! 379: #ifdef FASTTIMER ! 380: #define uucpdelay(num,denom) nap(60*num/denom) ! 381: /* Sleep in increments of 60ths of second. */ ! 382: nap (time) ! 383: register int time; ! 384: { ! 385: static int fd; ! 386: ! 387: if (fd == 0) ! 388: fd = open (FASTTIMER, 0); ! 389: ! 390: read (fd, 0, time); ! 391: } ! 392: #endif FASTTIMER ! 393: ! 394: #ifdef FTIME ! 395: #define uucpdelay(num,denom) ftimedelay(1000*num/denom) ! 396: ftimedelay(n) ! 397: { ! 398: static struct timeb loctime; ! 399: register i = loctime.millitm; ! 400: ! 401: ftime(&loctime); ! 402: while (abs((int)(loctime.millitm - i))<n) ftime(&loctime) ! 403: ; ! 404: } ! 405: #endif FTIME ! 406: ! 407: #ifdef BUSYLOOP ! 408: #define uucpdelay(num,denom) busyloop(CPUSPEED*num/denom) ! 409: #define CPUSPEED 1000000 /* VAX 780 is 1MIPS */ ! 410: #define DELAY(n) { register long N = (n); while (--N > 0); } ! 411: busyloop(n) ! 412: { ! 413: DELAY(n); ! 414: } ! 415: #endif BUSYLOOP ! 416: ! 417: slowrite(fd, str) ! 418: register char *str; ! 419: { ! 420: DEBUG(6, "slowrite ", CNULL); ! 421: while (*str) { ! 422: DEBUG(6, "%c", *str); ! 423: uucpdelay(1, 10); /* delay 1/10 second */ ! 424: write(fd, str, 1); ! 425: str++; ! 426: } ! 427: DEBUG(6, "\n", CNULL); ! 428: } ! 429: ! 430: #define BSPEED B150 ! 431: ! 432: /* ! 433: * send a break ! 434: */ ! 435: genbrk(fn, bnulls) ! 436: register int fn, bnulls; ! 437: { ! 438: #ifdef USG ! 439: if (ioctl(fn, TCSBRK, STBNULL) < 0) ! 440: DEBUG(5, "break TCSBRK %s\n", sys_errlist[errno]); ! 441: #else !USG ! 442: # ifdef TIOCSBRK ! 443: if (ioctl(fn, TIOCSBRK, STBNULL) < 0) ! 444: DEBUG(5, "break TIOCSBRK %s\n", sys_errlist[errno]); ! 445: # ifdef TIOCCBRK ! 446: uucpdelay(bnulls, 10); ! 447: if (ioctl(fn, TIOCCBRK, STBNULL) < 0) ! 448: DEBUG(5, "break TIOCCBRK %s\n", sys_errlist[errno]); ! 449: # endif TIOCCBRK ! 450: DEBUG(4, "ioctl %f second break\n", (float) bnulls/10 ); ! 451: # else !TIOCSBRK ! 452: struct sgttyb ttbuf; ! 453: register int sospeed; ! 454: ! 455: if (ioctl(fn, TIOCGETP, &ttbuf) < 0) ! 456: DEBUG(5, "break TIOCGETP %s\n", sys_errlist[errno]); ! 457: sospeed = ttbuf.sg_ospeed; ! 458: ttbuf.sg_ospeed = BSPEED; ! 459: if (ioctl(fn, TIOCSETP, &ttbuf) < 0) ! 460: DEBUG(5, "break TIOCSETP %s\n", sys_errlist[errno]); ! 461: if (write(fn, "\0\0\0\0\0\0\0\0\0\0\0\0", bnulls) != bnulls) { ! 462: badbreak: ! 463: logent(sys_errlist[errno], "BAD WRITE genbrk"); ! 464: alarm(0); ! 465: longjmp(Sjbuf, 3); ! 466: } ! 467: ttbuf.sg_ospeed = sospeed; ! 468: if (ioctl(fn, TIOCSETP, &ttbuf) < 0) ! 469: DEBUG(5, "break ioctl %s\n", sys_errlist[errno]); ! 470: if (write(fn, "@", 1) != 1) ! 471: goto badbreak; ! 472: DEBUG(4, "sent BREAK nulls - %d\n", bnulls); ! 473: #endif !TIOCSBRK ! 474: #endif !USG ! 475: } ! 476: ! 477: ! 478: #ifdef DIALINOUT ! 479: /* DIALIN/OUT CODE (WLS) */ ! 480: /* ! 481: * disable and reenable: allow a single line to be use for dialin/dialout ! 482: * ! 483: */ ! 484: ! 485: char enbdev[16]; ! 486: ! 487: disable(dev) ! 488: register char *dev; ! 489: { ! 490: register char *rdev; ! 491: ! 492: /* strip off directory prefixes */ ! 493: rdev = dev; ! 494: while (*rdev) ! 495: rdev++; ! 496: while (--rdev >= dev && *rdev != '/') ! 497: ; ! 498: rdev++; ! 499: ! 500: if (enbdev[0]) { ! 501: if (strcmp(enbdev, rdev) == SAME) ! 502: return SUCCESS; /* already disabled */ ! 503: delock(enbdev); ! 504: reenable(); /* else, reenable the old one */ ! 505: } ! 506: DEBUG(4, "Disable %s\n", rdev); ! 507: if (enbcall("disable", rdev) == FAIL) ! 508: return FAIL; ! 509: strcpy(enbdev, rdev); ! 510: return SUCCESS; ! 511: } ! 512: ! 513: reenable() ! 514: { ! 515: if (enbdev[0] == '\0') ! 516: return; ! 517: DEBUG(4, "Reenable %s\n", enbdev); ! 518: (void) enbcall("enable", enbdev); ! 519: enbdev[0] = '\0'; ! 520: } ! 521: ! 522: enbcall(type, dev) ! 523: char *type, *dev; ! 524: { ! 525: int pid; ! 526: register char *p; ! 527: int fildes[2]; ! 528: int status; ! 529: FILE *fil; ! 530: char buf[80]; ! 531: ! 532: fflush(stderr); ! 533: fflush(stdout); ! 534: pipe(fildes); ! 535: if ((pid = fork()) == 0) { ! 536: DEBUG(4, DIALINOUT, CNULL); ! 537: DEBUG(4, " %s", type); ! 538: DEBUG(4, " %s\n", dev); ! 539: close(fildes[0]); ! 540: close(0); close(1); close(2); ! 541: open("/dev/null",0); ! 542: dup(fildes[1]); dup(fildes[1]); ! 543: setuid(geteuid()); /* for chown(uid()) in acu program */ ! 544: execl(DIALINOUT, "acu", type, dev, 0); ! 545: exit(-1); ! 546: } ! 547: if (pid<0) ! 548: return FAIL; ! 549: ! 550: close(fildes[1]); ! 551: fil = fdopen(fildes[0],"r"); ! 552: if (fil!=NULL) { ! 553: #ifdef BSD4_2 ! 554: setlinebuf(fil); ! 555: #endif BSD4_2 ! 556: while (fgets(buf, sizeof buf, fil) != NULL) { ! 557: p = buf + strlen(buf) - 1; ! 558: if (*p == '\n') ! 559: *p = '\0'; ! 560: logent(buf,"ACUCNTRL:"); ! 561: } ! 562: } ! 563: while(wait(&status) != pid) ! 564: ; ! 565: fclose(fil); ! 566: return status ? FAIL : SUCCESS; ! 567: } ! 568: #endif DIALINOUT
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.