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

Defined functions

Acuopn defined in line 266; used 27 times
busyloop defined in line 411; used 1 times
dircls defined in line 248; used 3 times
diropn defined in line 148; used 5 times
disable defined in line 487; used 1 times
enbcall defined in line 522; used 2 times
ftimedelay defined in line 396; used 1 times
genbrk defined in line 435; used 2 times
intervaldelay defined in line 369; used 1 times
nap defined in line 382; used 1 times
nodev defined in line 129; used 1 times
nulldev defined in line 121; used 14 times
reenable defined in line 513; used 4 times
slowrite defined in line 417; never used

Defined variables

condevs defined in line 32; used 1 times
devSel defined in line 264; used 4 times
enbdev defined in line 485; used 8 times
sccsid defined in line 2; never used

Defined macros

BSPEED defined in line 430; used 1 times
CPUSPEED defined in line 409; used 1 times
DELAY defined in line 410; used 1 times
uucpdelay defined in line 408; used 2 times
Last modified: 1986-02-13
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2331
Valid CSS Valid XHTML 1.0 Strict