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

Defined functions

Acuopn defined in line 263; used 27 times
busyloop defined in line 407; used 1 times
dircls defined in line 245; used 3 times
diropn defined in line 145; used 5 times
disable defined in line 483; used 1 times
enbcall defined in line 518; used 2 times
ftimedelay defined in line 392; used 1 times
genbrk defined in line 431; used 7 times
intervaldelay defined in line 365; used 1 times
nap defined in line 378; used 1 times
nodev defined in line 126; used 1 times
nulldev defined in line 118; used 15 times
reenable defined in line 509; used 4 times

Defined variables

condevs defined in line 29; used 1 times
devSel defined in line 261; used 4 times
enbdev defined in line 481; used 8 times
sccsid defined in line 2; never used

Defined macros

BSPEED defined in line 426; used 1 times
CPUSPEED defined in line 405; used 1 times
DELAY defined in line 406; used 1 times
uucpdelay defined in line 404; used 2 times
Last modified: 1997-10-03
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4325
Valid CSS Valid XHTML 1.0 Strict