1: #ifndef lint
   2: static char sccsid[] = "@(#)conn.c	5.10 (Berkeley) 1/24/86";
   3: #endif
   4: 
   5: #include <signal.h>
   6: #include "uucp.h"
   7: #include <setjmp.h>
   8: #include <ctype.h>
   9: #include <errno.h>
  10: #ifdef  USG
  11: #include <termio.h>
  12: #include <fcntl.h>
  13: #endif
  14: #ifndef USG
  15: #include <sgtty.h>
  16: #endif
  17: #ifdef BSD4_2
  18: #include <sys/time.h>
  19: #else
  20: #include <time.h>
  21: #endif
  22: 
  23: #define MAXC 1000
  24: 
  25: extern jmp_buf Sjbuf;
  26: jmp_buf Cjbuf;
  27: extern int errno, onesys;
  28: extern char *sys_errlist[];
  29: extern char MaxGrade, DefMaxGrade;
  30: 
  31: /* Parity control during login procedure */
  32: #define P_ZERO  0
  33: #define P_ONE   1
  34: #define P_EVEN  2
  35: #define P_ODD   3
  36: 
  37: #define ABORT -2
  38: 
  39: char    *AbortOn = NULL;
  40: char    par_tab[128];   /* must be power of two */
  41: int linebaudrate;   /* used for the sleep test in pk1.c */
  42: int next_fd = -1;   /* predicted fd to close interrupted opens */
  43: 
  44: char *PCP = "PCP";  /* PC Pursuit device type */
  45: /*
  46:  *	catch alarm routine for "expect".
  47:  */
  48: alarmtr()
  49: {
  50:     signal(SIGALRM, alarmtr);
  51:     if (next_fd >= 0) {
  52:         if (close(next_fd))
  53:             logent("FAIL", "ACU LINE CLOSE");
  54:         next_fd = -1;
  55:     }
  56:     longjmp(Sjbuf, 1);
  57: }
  58: 
  59: /* This template is for seismo to call ihnp4
  60:  * the 3 lines marked ---> will be overwritten for the appropriate city
  61:  */
  62: #define PCP_BAUD    3
  63: #define PCP_PHONE   4
  64: #define PCP_CALLBACK    8
  65: #define PCP_CITY    10
  66: #define PCP_RPHONE  12
  67: #define NPCFIELDS   15
  68: 
  69: static char *PCFlds[] = {
  70:     "PC-PURSUIT",
  71:     "Any",
  72:     "ACU",
  73:     "1200",
  74:     CNULL,  /* <--- **** Welcome to Telenet PC Pursuit ***** */
  75:     "ABORT",
  76:     "Good", /* Abort of Good bye! */
  77:     ")",    /* <--- Enter your 7-digit phone number (xxx-xxxx) */
  78:     CNULL,  /* ---> 528-1234 */
  79:     "call?",    /* <--- Which city do you wish to call? */
  80:     CNULL,  /* ---> CHICAGO */
  81:     ")",    /* <--- Enter the phone number you wish to call (xxx-xxxx) */
  82:     CNULL,  /* ---> 690-7171 */
  83:     "R)?",  /* <--- You are #1 in the queue. Do you want to wait, or Restart (Y/N/R)? */
  84:     "Y",
  85:     CNULL   /* <--- .....Good Bye! */
  86: };
  87: 
  88: static char PCP_brand[20];
  89: 
  90: /*
  91:  *	place a telephone call to system and login, etc.
  92:  *
  93:  *	return codes:
  94:  *		CF_SYSTEM: don't know system
  95:  *		CF_TIME: wrong time to call
  96:  *		CF_DIAL: call failed
  97:  *		CF_NODEV: no devices available to place call
  98:  *		CF_LOGIN: login/password dialog failed
  99:  *
 100:  *		>0  - file no.  -  connect ok
 101:  */
 102: 
 103: int Dcf = -1;
 104: char *Flds[MAXC/10];
 105: char LineType[10];
 106: extern int LocalOnly;
 107: 
 108: conn(system)
 109: char *system;
 110: {
 111:     int nf;
 112:     char info[MAXC], wkpre[NAMESIZE], file[NAMESIZE];
 113:     register FILE *fsys;
 114:     int fcode = 0;
 115: 
 116:     nf = 0;
 117: 
 118:     fsys = fopen(SYSFILE, "r");
 119:     ASSERT(fsys != NULL, "CAN'T OPEN", SYSFILE, 0);
 120: 
 121:     DEBUG(4, "finds (%s) called\n", system);
 122: keeplooking:
 123:     while((nf = finds(fsys, system, info, Flds)) > 0) {
 124:         strncpy(LineType, Flds[F_LINE], 10);
 125:         if (LocalOnly) {
 126:             if (strcmp("TCP", LineType)
 127:                 && strcmp("DIR", LineType)
 128:                 && strcmp("LOCAL", LineType) ) {
 129:                     fcode = CF_TIME;
 130:                     continue;
 131:             }
 132:         }
 133:         sprintf(wkpre, "%c.%.*s", CMDPRE, SYSNSIZE, Rmtname);
 134:         if (!onesys && MaxGrade != DefMaxGrade &&
 135:             !iswrk(file, "chk", Spool, wkpre))  {
 136:                 fcode = CF_TIME;
 137:                 continue;
 138:         }
 139:         /* For GTE's PC Pursuit */
 140:         if (snccmp(LineType, PCP) == SAME) {
 141:             FILE *dfp;
 142:             int status;
 143:             static struct Devices dev;
 144:             dfp = fopen(DEVFILE, "r");
 145:             ASSERT(dfp != NULL, "Can't open", DEVFILE, 0);
 146:             while ((status=rddev(dfp, &dev)) != FAIL
 147:                 && strcmp(PCP, dev.D_type) != SAME)
 148:                     ;
 149:             fclose(dfp);
 150:             if (status == FAIL)
 151:                 continue;
 152:             if (mlock(PCP) == FAIL) {
 153:                 fcode = CF_NODEV;
 154:                 logent("DEVICE", "NO");
 155:                 continue;
 156:             }
 157:             PCFlds[PCP_BAUD] = dev.D_class;
 158:             PCFlds[PCP_PHONE] = dev.D_calldev;
 159:             PCFlds[PCP_CALLBACK] = dev.D_arg[D_CHAT];
 160:             PCFlds[PCP_CITY] = Flds[F_CLASS];
 161:             PCFlds[PCP_RPHONE] = Flds[F_PHONE];
 162:             strncpy(PCP_brand, dev.D_brand, sizeof(PCP_brand));
 163:             if ((fcode = getto(PCFlds)) < 0)
 164:                 continue;
 165:             Dcf = fcode;
 166:             fcode = login(NPCFIELDS, PCFlds, Dcf);
 167:             clsacu(); /* Hang up, they'll call back */
 168:             if (fcode != SUCCESS) {
 169:                 fcode = CF_DIAL;
 170:                 continue;
 171:             }
 172:             Flds[F_CLASS] = dev.D_class;
 173:             Flds[F_PHONE] = dev.D_line;
 174: 
 175:         } /* end PC Pursuit */
 176:         if ((fcode = getto(Flds)) > 0)
 177:             break;
 178:     }
 179: 
 180:     if (nf <= 0) {
 181:         fclose(fsys);
 182:         return fcode ? fcode : nf;
 183:     }
 184: 
 185:     Dcf = fcode;
 186: 
 187:     if (fcode >= 0 && snccmp(LineType, PCP) == SAME) {
 188:         AbortOn = "Good";   /* .... Good Bye */
 189:         fcode = expect("****~300", Dcf);
 190:         if (fcode != SUCCESS) {
 191:             DEBUG(4, "\nexpect timed out\n", CNULL);
 192:             fcode = CF_DIAL;
 193:         }
 194:     }
 195:     if (fcode >= 0) {
 196:         DEBUG(4, "login %s\n", "called");
 197:         fcode = login(nf, Flds, Dcf);
 198:     }
 199:     if (fcode < 0) {
 200:         clsacu();
 201:         if (fcode == ABORT) {
 202:             fcode = CF_DIAL;
 203:             goto  keeplooking;
 204:         } else {
 205:             fclose(fsys);
 206:             return CF_LOGIN;
 207:         }
 208:     }
 209:     fclose(fsys);
 210:     fioclex(Dcf);
 211:     return Dcf;
 212: }
 213: 
 214: /*
 215:  *	connect to remote machine
 216:  *
 217:  *	return codes:
 218:  *		>0  -  file number - ok
 219:  *		FAIL  -  failed
 220:  */
 221: 
 222: getto(flds)
 223: register char *flds[];
 224: {
 225:     register struct condev *cd;
 226:     int nulldev(), diropn();
 227:     char *line;
 228: 
 229:     DEBUG(4, "getto: call no. %s ", flds[F_PHONE]);
 230:     DEBUG(4, "for sys %s\n", flds[F_NAME]);
 231: 
 232:     if (snccmp(flds[F_LINE], "LOCAL") == SAME)
 233:         line = "ACU";
 234:     else
 235:         line = flds[F_LINE];
 236: #ifdef DIALINOUT
 237:     if (snccmp(line, "ACU") != SAME)
 238:         reenable();
 239: #endif DIALINOUT
 240:     CU_end = nulldev;
 241:     if (snccmp(line, PCP) == SAME) {
 242:         for(cd = condevs; cd->CU_meth != NULL; cd++) {
 243:             if (snccmp(PCP_brand, cd->CU_brand) == SAME) {
 244:                 CU_end = cd->CU_clos;
 245:                 return diropn(flds);
 246:             }
 247:         }
 248:         logent(PCP_brand, "UNSUPPORTED ACU TYPE");
 249:     } else {
 250:         for (cd = condevs; cd->CU_meth != NULL; cd++) {
 251:             if (snccmp(cd->CU_meth, line) == SAME) {
 252:                 DEBUG(4, "Using %s to call\n", cd->CU_meth);
 253:                 return (*(cd->CU_gen))(flds);
 254:             }
 255:         }
 256:         DEBUG(1, "Can't find %s, assuming DIR\n", flds[F_LINE]);
 257:     }
 258:     return diropn(flds);    /* search failed, so use direct */
 259: }
 260: 
 261: /*
 262:  *	close call unit
 263:  *
 264:  *	return codes:  none
 265:  */
 266: 
 267: int (*CU_end)() = nulldev;
 268: clsacu()
 269: {
 270:     /* make *sure* Dcf is no longer exclusive.
 271: 	 * Otherwise dual call-in/call-out modems could get stuck.
 272: 	 * Unfortunately, doing this here is not ideal, but it is the
 273: 	 * easiest place to put the call.
 274: 	 * Hopefully everyone honors the LCK protocol, of course
 275: 	 */
 276: #ifdef  TIOCNXCL
 277:     if (!IsTcpIp && Dcf >= 0 && ioctl(Dcf, TIOCNXCL, STBNULL) < 0)
 278:         DEBUG(5, "clsacu ioctl %s\n", sys_errlist[errno]);
 279: #endif
 280:     if  (setjmp(Sjbuf))
 281:         logent(Rmtname, "CLOSE TIMEOUT");
 282:     else {
 283:         signal(SIGALRM, alarmtr);
 284:         alarm(20);
 285:         (*(CU_end))(Dcf);
 286:         alarm(0);
 287:     }
 288:     if (close(Dcf) == 0) {
 289:         DEBUG(4, "fd %d NOT CLOSED by CU_clos\n", Dcf);
 290:         logent("clsacu", "NOT CLOSED by CU_clos");
 291:     }
 292:     Dcf = -1;
 293:     CU_end = nulldev;
 294: }
 295: 
 296: /*
 297:  *	expand phone number for given prefix and number
 298:  */
 299: 
 300: exphone(in, out)
 301: register char *in, *out;
 302: {
 303:     FILE *fn;
 304:     char pre[MAXPH], npart[MAXPH], tpre[MAXPH], p[MAXPH];
 305:     char buf[BUFSIZ];
 306:     register char *s1;
 307: 
 308:     if (!isascii(*in) || !isalpha(*in)) {
 309:         strcpy(out, in);
 310:         return;
 311:     }
 312: 
 313:     s1=pre;
 314:     while (isascii(*in) && isalpha(*in))
 315:         *s1++ = *in++;
 316:     *s1 = '\0';
 317:     s1 = npart;
 318:     while (*in != '\0')
 319:         *s1++ = *in++;
 320:     *s1 = '\0';
 321: 
 322:     tpre[0] = '\0';
 323:     if ((fn = fopen(DIALFILE, "r")) == NULL)
 324:         DEBUG(2, "CAN'T OPEN %s\n", DIALFILE);
 325:     else {
 326:         while (cfgets(buf, BUFSIZ, fn)) {
 327:             if (sscanf(buf, "%s%s", p, tpre) != 2)
 328:                 continue;
 329:             if (strcmp(p, pre) == SAME)
 330:                 goto found;
 331:             tpre[0] = '\0';
 332:         }
 333:         DEBUG(2, "CAN'T FIND dialcodes prefix '%s'\n", pre);
 334:     found:;
 335:         fclose(fn);
 336:     }
 337: 
 338:     strcpy(out, tpre);
 339:     strcat(out, npart);
 340: }
 341: 
 342: /*
 343:  *	read and decode a line from device file
 344:  *
 345:  *	return code - FAIL at end-of file; 0 otherwise
 346:  */
 347: 
 348: rddev(fp, dev)
 349: register struct Devices *dev;
 350: FILE *fp;
 351: {
 352:     register int na;
 353: 
 354:     if (!cfgets(dev->D_argbfr, sizeof(dev->D_argbfr), fp))
 355:         return FAIL;
 356:     na = getargs(dev->D_argbfr, dev->D_arg, 20);
 357:     ASSERT(na >= 4, "BAD DEVICE ENTRY", dev->D_argbfr, 0);
 358:     if (na == 4) {
 359:         dev->D_brand = "";
 360:         na++;
 361:     }
 362:     dev->D_speed = atoi(fdig(dev->D_class));
 363:     dev->D_numargs = na;
 364:     return 0;
 365: }
 366: 
 367: /*
 368:  *	set system attribute vector
 369:  *
 370:  *	return codes:
 371:  *		>0  -  number of arguments in vector - succeeded
 372:  *		CF_SYSTEM  -  system name not found
 373:  *		CF_TIME  -  wrong time to call
 374:  */
 375: 
 376: finds(fsys, sysnam, info, flds)
 377: char *sysnam, info[], *flds[];
 378: FILE *fsys;
 379: {
 380:     int na;
 381:     int fcode = 0;
 382: 
 383:     /* format of fields
 384: 	 *	0 name;
 385: 	 *	1 time
 386: 	 *	2 acu/hardwired
 387: 	 *	3 speed
 388: 	 *	etc
 389: 	 */
 390:     while (cfgets(info, MAXC, fsys) != NULL) {
 391:         na = getargs(info, flds, MAXC/10);
 392:         if (strncmp(sysnam, flds[F_NAME], MAXBASENAME) != SAME)
 393:             continue;
 394:         if (ifdate(flds[F_TIME]) != FAIL)
 395:             /*  found a good entry  */
 396:             return na;
 397:         DEBUG(2, "Wrong time ('%s') to call\n", flds[F_TIME]);
 398:         fcode = CF_TIME;
 399:     }
 400:     return fcode ? fcode : CF_SYSTEM;
 401: }
 402: 
 403: /*
 404:  *	do login conversation
 405:  *
 406:  *	return codes:  SUCCESS  |  FAIL
 407:  */
 408: 
 409: login(nf, flds, fn)
 410: register char *flds[];
 411: int nf, fn;
 412: {
 413:     register char *want, *altern;
 414:     int k, ok;
 415: 
 416:     ASSERT(nf > 4, "TOO FEW LOG FIELDS", CNULL, nf);
 417:     if (setjmp(Cjbuf))
 418:         return FAIL;
 419:     AbortOn = NULL;
 420:     for (k = F_LOGIN; k < nf; k += 2) {
 421:         want = flds[k];
 422:         ok = FAIL;
 423:         while (ok != SUCCESS) {
 424:             altern = index(want, '-');
 425:             if (altern != NULL)
 426:                 *altern++ = '\0';
 427:             if (strcmp(want, "ABORT") == 0) {
 428:                 AbortOn = flds[k+1];
 429:                 DEBUG(4, "ABORT ON: %s\n", AbortOn);
 430:                 goto nextfield;
 431:             }
 432:             DEBUG(4, "wanted \"%s\"\n", want);
 433:             ok = expect(want, fn);
 434:             DEBUG(4, "got: %s\n", ok ? "?" : "that");
 435:             if (ok == FAIL) {
 436:                 if (altern == NULL) {
 437:                     logent("LOGIN", _FAILED);
 438:                     return FAIL;
 439:                 }
 440:                 want = index(altern, '-');
 441:                 if (want != NULL)
 442:                     *want++ = '\0';
 443:                 sendthem(altern, fn);
 444:             } else
 445:                 if (ok == ABORT) {
 446:                     logent("LOGIN ABORTED", _FAILED);
 447:                     return ABORT;
 448:                 }
 449:         }
 450:         sleep(1);
 451:         if (k+1 < nf)
 452:             sendthem(flds[k+1], fn);
 453: nextfield: ;
 454:     }
 455:     return SUCCESS;
 456: }
 457: 
 458: 
 459: /* conditional table generation to support odd speeds */
 460: struct sg_spds {int sp_val, sp_name;} spds[] = {
 461: #ifdef B50
 462:     {  50,   B50},
 463: #endif
 464: #ifdef B75
 465:     {  75,   B75},
 466: #endif
 467: #ifdef B110
 468:     { 110,  B110},
 469: #endif
 470: #ifdef B150
 471:     { 150,  B150},
 472: #endif
 473: #ifdef B200
 474:     { 200,  B200},
 475: #endif
 476: #ifdef B300
 477:     { 300,  B300},
 478: #endif
 479: #ifdef B600
 480:     {600,   B600},
 481: #endif
 482: #ifdef B1200
 483:     {1200, B1200},
 484: #endif
 485: #ifdef B1800
 486:     {1800, B1800},
 487: #endif
 488: #ifdef B2000
 489:     {2000, B2000},
 490: #endif
 491: #ifdef B2400
 492:     {2400, B2400},
 493: #endif
 494: #ifdef B3600
 495:     {3600, B3600},
 496: #endif
 497: #ifdef B4800
 498:     {4800, B4800},
 499: #endif
 500: #ifdef B7200
 501:     {7200, B7200},
 502: #endif
 503: #ifdef B9600
 504:     {9600, B9600},
 505: #endif
 506: #ifdef B19200
 507:     {19200, B19200},
 508: #endif
 509: #ifdef EXTA
 510:     {19200, EXTA},
 511: #endif
 512:     {0, 0}
 513: };
 514: 
 515: /*
 516:  *	set speed/echo/mode...
 517:  *
 518:  *	return codes:  none
 519:  */
 520: 
 521: fixline(tty, spwant)
 522: int tty, spwant;
 523: {
 524: #ifdef  USG
 525:     struct termio ttbuf;
 526: #else   !USG
 527:     struct sgttyb ttbuf;
 528: #endif !USG
 529:     register struct sg_spds *ps;
 530:     int speed = -1;
 531: 
 532:     for (ps = spds; ps->sp_val; ps++)
 533:         if (ps->sp_val == spwant)
 534:             speed = ps->sp_name;
 535:     ASSERT(speed >= 0, "BAD SPEED", CNULL, speed);
 536: #ifdef  USG
 537:     if (ioctl(tty, TCGETA, &ttbuf) < 0)
 538:         return FAIL;
 539:     /* ttbuf.sg_flags = (ANYP|RAW);
 540: 	ttbuf.sg_ispeed = ttbuf.sg_ospeed = speed; */
 541:     ttbuf.c_iflag = (ushort)0;
 542:     ttbuf.c_oflag = (ushort)0;
 543:     ttbuf.c_cflag = (speed|CS8|HUPCL|CREAD);
 544:     ttbuf.c_lflag = (ushort)0;
 545:     ttbuf.c_cc[VMIN] = 6;
 546:     ttbuf.c_cc[VTIME] = 1;
 547:     if (ioctl(tty, TCSETA, &ttbuf) < 0)
 548:         return FAIL;
 549: #else   !USG
 550:     if (ioctl(tty, TIOCGETP, &ttbuf) < 0)
 551:         return FAIL;
 552:     ttbuf.sg_flags = (ANYP|RAW);
 553:     ttbuf.sg_ispeed = ttbuf.sg_ospeed = speed;
 554:     if (ioctl(tty, TIOCSETP, &ttbuf) < 0)
 555:         return FAIL;
 556: #endif
 557: #ifndef USG
 558:     if (ioctl(tty, TIOCHPCL, STBNULL) < 0)
 559:         return FAIL;
 560:     if (ioctl(tty, TIOCEXCL, STBNULL) < 0)
 561:         return FAIL;
 562: #endif
 563:     linebaudrate = spwant;
 564:     return SUCCESS;
 565: }
 566: 
 567: #define MR 100
 568: 
 569: /*
 570:  *	look for expected string
 571:  *
 572:  *	return codes:
 573:  *		0  -  found
 574:  *		FAIL  -  lost line or too many characters read
 575:  *		some character  -  timed out
 576:  */
 577: 
 578: expect(str, fn)
 579: register char *str;
 580: int fn;
 581: {
 582:     char rdvec[MR];
 583:     register char *rp = rdvec, *strptr;
 584:     int kr, cnt_char;
 585:     char nextch;
 586:     int timo = MAXMSGTIME;
 587: 
 588:     if (*str == '\0' || strcmp(str, "\"\"") == SAME)
 589:         return SUCCESS;
 590:     /* Cleanup str, convert \0xx strings to one char  */
 591:     for (strptr = str; *strptr; strptr++) {
 592:         if (*strptr == '\\')
 593:             switch(*++strptr) {
 594:             case 's':
 595:                 DEBUG(5, "BLANK\n", CNULL);
 596:                 *strptr = ' ';
 597:                 break;
 598:             default:
 599:                 strptr--;  /* back up to backslash */
 600:                 sscanf(strptr + 1,"%o", &cnt_char);
 601:                 DEBUG(6, "BACKSLASHED %02xH\n", cnt_char);
 602:                 *strptr = (char) (cnt_char);
 603:                 strcpy(&strptr[1], &strptr[4]);
 604:             }
 605:     }
 606: 
 607:     strptr = index(str, '~');
 608:     if (strptr != NULL) {
 609:         *strptr++ = '\0';
 610:         timo = atoi(strptr);
 611:         if (timo <= 0)
 612:             timo = MAXMSGTIME;
 613:     }
 614: 
 615:     if (setjmp(Sjbuf))
 616:         return FAIL;
 617:     signal(SIGALRM, alarmtr);
 618:     alarm(timo);
 619:     *rp = 0;
 620:     while (notin(str, rdvec)) {
 621:         int c;
 622:         if(AbortOn != NULL && !notin(AbortOn, rdvec)) {
 623:             DEBUG(1, "Call aborted on '%s'\n", AbortOn);
 624:             alarm(0);
 625:             return ABORT;
 626:         }
 627:         kr = read(fn, &nextch, 1);
 628:         if (kr <= 0) {
 629:             alarm(0);
 630:             DEBUG(4, "lost line kr - %d\n, ", kr);
 631:             logent("LOGIN", "LOST LINE");
 632:             return FAIL;
 633:         }
 634:         c = nextch & 0177;
 635:         if (c == '\0')
 636:             continue;
 637:         DEBUG(4, (isprint(c) || isspace(c)) ? "%c" : "\\%03o", c);
 638:         *rp++ = c;
 639:         if (rp >= rdvec + MR) {
 640:             register char *p;
 641:             for (p = rdvec+MR/2; p < rp; p++)
 642:                 *(p-MR/2) = *p;
 643:             rp -= MR/2;
 644:         }
 645:         *rp = '\0';
 646:     }
 647:     alarm(0);
 648:     return SUCCESS;
 649: }
 650: 
 651: 
 652: /*
 653:  * Determine next file descriptor that would be allocated.
 654:  * This permits later closing of a file whose open was interrupted.
 655:  * It is a UNIX kernel problem, but it has to be handled.
 656:  * unc!smb (Steve Bellovin) probably first discovered it.
 657:  */
 658: getnextfd()
 659: {
 660:     close(next_fd = open("/", 0));
 661: }
 662: 
 663: /*
 664:  *	send line of login sequence
 665:  *
 666:  *	return codes:  none
 667:  */
 668: sendthem(str, fn)
 669: register char *str;
 670: int fn;
 671: {
 672:     register char *strptr;
 673:     int i, n, cr = 1;
 674:     register char c;
 675:     static int p_init = 0;
 676: 
 677:     DEBUG(5, "send \"%s\"\n", str);
 678: 
 679:     if (!p_init) {
 680:         p_init++;
 681:         bld_partab(P_EVEN);
 682:     }
 683: 
 684:     if (prefix("BREAK", str)) {
 685:         sscanf(&str[5], "%1d", &i);
 686:         if (i <= 0 || i > 10)
 687:             i = 3;
 688:         /* send break */
 689:         genbrk(fn, i);
 690:         return;
 691:     }
 692: 
 693:     if (prefix("PAUSE", str)) {
 694:         sscanf(&str[5], "%1d", &i);
 695:         if (i <= 0 || i > 10)
 696:             i = 3;
 697:         /* pause for a while */
 698:         sleep((unsigned)i);
 699:         return;
 700:     }
 701: 
 702:     if (strcmp(str, "EOT") == SAME) {
 703:         p_chwrite(fn, '\04');
 704:         return;
 705:     }
 706: 
 707:     /* Send a '\n' */
 708:     if (strcmp(str, "LF") == SAME) {
 709:         p_chwrite(fn, '\n');
 710:         return;
 711:     }
 712: 
 713:     /* Send a '\r' */
 714:     if (strcmp(str, "CR") == SAME) {
 715:         p_chwrite(fn, '\r');
 716:         return;
 717:     }
 718: 
 719:     /* Set parity as needed */
 720:     if (strcmp(str, "P_ZERO") == SAME) {
 721:         bld_partab(P_ZERO);
 722:         return;
 723:     }
 724:     if (strcmp(str, "P_ONE") == SAME) {
 725:         bld_partab(P_ONE);
 726:         return;
 727:     }
 728:     if (strcmp(str, "P_EVEN") == SAME) {
 729:         bld_partab(P_EVEN);
 730:         return;
 731:     }
 732:     if (strcmp(str, "P_ODD") == SAME) {
 733:         bld_partab(P_ODD);
 734:         return;
 735:     }
 736: 
 737:     /* If "", just send '\r' */
 738:     if (strcmp(str, "\"\"") == SAME) {
 739:         p_chwrite(fn, '\r');
 740:         return;
 741:     }
 742: 
 743:     strptr = str;
 744:     while ((c = *strptr++) != '\0') {
 745:         if (c == '\\') {
 746:             switch(*strptr++) {
 747:             case '\0':
 748:                 DEBUG(5, "TRAILING BACKSLASH IGNORED\n", CNULL);
 749:                 --strptr;
 750:                 continue;
 751:             case 's':
 752:                 DEBUG(5, "BLANK\n", CNULL);
 753:                 c = ' ';
 754:                 break;
 755:             case 'd':
 756:                 DEBUG(5, "DELAY\n", CNULL);
 757:                 sleep(1);
 758:                 continue;
 759:             case 'n':
 760:                 DEBUG(5, "NEW LINE\n", CNULL);
 761:                 c = '\n';
 762:                 break;
 763:             case 'r':
 764:                 DEBUG(5, "RETURN\n", CNULL);
 765:                 c = '\r';
 766:                 break;
 767:             case 'b':
 768:                 if (isdigit(*strptr)) {
 769:                     i = (*strptr++ - '0');
 770:                     if (i <= 0 || i > 10)
 771:                         i = 3;
 772:                 } else
 773:                     i = 3;
 774:                 /* send break */
 775:                 genbrk(fn, i);
 776:                 if (*strptr == '\0')
 777:                     cr = 0;
 778:                 continue;
 779:             case 'c':
 780:                 if (*strptr == '\0') {
 781:                     DEBUG(5, "NO CR\n", CNULL);
 782:                     cr = 0;
 783:                 } else
 784:                     DEBUG(5, "NO CR - IGNORED NOT EOL\n", CNULL);
 785:                 continue;
 786: #define isoctal(x)  ((x >= '0') && (x <= '7'))
 787:             default:
 788:                 if (isoctal(strptr[-1])) {
 789:                     i = 0;
 790:                     n = 0;
 791:                     --strptr;
 792:                     while (isoctal(*strptr) && ++n <= 3)
 793:                         i = i * 8 + (*strptr++ - '0');
 794:                     DEBUG(5, "\\%o\n", i);
 795:                     p_chwrite(fn, (char)i);
 796:                     continue;
 797:                 }
 798:             }
 799:         }
 800:         p_chwrite(fn, c);
 801:     }
 802: 
 803:     if (cr)
 804:         p_chwrite(fn, '\r');
 805:     return;
 806: }
 807: 
 808: p_chwrite(fd, c)
 809: int fd;
 810: char c;
 811: {
 812:     c = par_tab[c&0177];
 813:     if (write(fd, &c, 1) != 1) {
 814:         logent(sys_errlist[errno], "BAD WRITE");
 815:         longjmp(Cjbuf, 2);
 816:     }
 817: }
 818: 
 819: /*
 820:  * generate parity table for use by p_chwrite.
 821:  */
 822: bld_partab(type)
 823: int type;
 824: {
 825:     register int i, j, n;
 826: 
 827:     for (i = 0; i < sizeof(par_tab); i++) {
 828:         n = 0;
 829:         for (j = i&(sizeof(par_tab)-1); j; j = (j-1)&j)
 830:             n++;
 831:         par_tab[i] = i;
 832:         if (type == P_ONE
 833:          || (type == P_EVEN && (n&01) != 0)
 834:          || (type == P_ODD && (n&01) == 0))
 835:             par_tab[i] |= sizeof(par_tab);
 836:     }
 837: }
 838: 
 839: /*
 840:  *	check for occurrence of substring "sh"
 841:  *
 842:  *	return codes:
 843:  *		0  -  found the string
 844:  *		1  -  not in the string
 845:  */
 846: notin(sh, lg)
 847: register char *sh, *lg;
 848: {
 849:     while (*lg != '\0') {
 850:         if (wprefix(sh, lg))
 851:             return 0;
 852:         else
 853:             lg++;
 854:     }
 855:     return 1;
 856: }
 857: 
 858: /*
 859:  *	Allow multiple date specifications separated by ','.
 860:  */
 861: ifdate(p)
 862: register char *p;
 863: {
 864:     register char *np;
 865:     register int ret, g;
 866:     int rtime, i;
 867: 
 868:     /*  pick up retry time for failures  */
 869:     /*  global variable Retrytime is set here  */
 870:     if ((np = index(p, ';')) == NULL) {
 871:         Retrytime = RETRYTIME;
 872:     } else {
 873:         i = sscanf(np+1, "%d", &rtime);
 874:         if (i < 1 || rtime < 0)
 875:             rtime = 5;
 876:         Retrytime  = rtime * 60;
 877:     }
 878: 
 879:     ret = FAIL;
 880:     MaxGrade = '\0';
 881:     do {
 882:         np = strpbrk(p, ",|");  /* prefer , but allow | for compat */
 883:         if (np)
 884:             *np = '\0';
 885:         g = ifadate(p);
 886:         DEBUG(11,"ifadate returns %o\n", g);
 887:         if (g != FAIL) {
 888:             ret = SUCCESS;
 889:             if (g > MaxGrade)
 890:                 MaxGrade = g;
 891:         }
 892:         if (np)
 893:             *np = ',';
 894:         p = np + 1;
 895:     } while (np);
 896:     if (MaxGrade == '\0')
 897:         MaxGrade = DefMaxGrade;
 898:     return ret;
 899: }
 900: 
 901: /*
 902:  *	this routine will check a string (string)
 903:  *	like "MoTu0800-1730" to see if the present
 904:  *	time is within the given limits.
 905:  *	SIDE EFFECT - Retrytime is set
 906:  *
 907:  *	return codes:
 908:  *		0  -  not within limits
 909:  *		1  -  within limits
 910:  */
 911: 
 912: ifadate(string)
 913: char *string;
 914: {
 915:     static char *days[]={
 916:         "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", 0
 917:     };
 918:     time_t clock;
 919:     register char *s = string;
 920:     int i, tl, th, tn, dayok=0;
 921:     struct tm *localtime();
 922:     struct tm *tp;
 923:     char *p, MGrade;
 924: 
 925:     if ((p = index(s, '/')) == NULL)
 926:         MGrade = DefMaxGrade;
 927:     else
 928:         MGrade = p[1];
 929: 
 930:     time(&clock);
 931:     tp = localtime(&clock);
 932:     while (isascii(*s) && isalpha(*s)) {
 933:         for (i = 0; days[i]; i++) {
 934:             if (prefix(days[i], s))
 935:                 if (tp->tm_wday == i)
 936:                     dayok = 1;
 937:         }
 938: 
 939:         if (prefix("Wk", s))
 940:             if (tp->tm_wday >= 1 && tp->tm_wday <= 5)
 941:                 dayok = 1;
 942:         if (prefix("Any", s))
 943:             dayok = 1;
 944:         if (prefix("Evening", s)) {
 945:             /* Sat or Sun */
 946:             if (tp->tm_wday == 6 || tp->tm_wday == 0
 947:                 || tp->tm_hour >= 17 || tp->tm_hour < 8)
 948:                     dayok = 1;
 949:         }
 950:         if (prefix("Night", s)) {
 951:             if (tp->tm_wday == 6  /* Sat */
 952:                 || tp->tm_hour >= 23 || tp->tm_hour < 8
 953:                     /* Sunday before 5pm */
 954:                 || (tp->tm_wday == 0 && tp->tm_hour < 17))
 955:                     dayok = 1;
 956:         }
 957:         if (prefix("NonPeak", s)) { /* For Tymnet and PC Pursuit */
 958:             /* Sat or Sun */
 959:             if (tp->tm_wday == 6 || tp->tm_wday == 0
 960:                 || tp->tm_hour >= 18 || tp->tm_hour < 7)
 961:                     dayok = 1;
 962:         }
 963:         s++;
 964:     }
 965: 
 966:     if (dayok == 0 && s != string)
 967:         return FAIL;
 968:     i = sscanf(s, "%d-%d", &tl, &th);
 969:     if (i < 2)
 970:         return MGrade;
 971:     tn = tp->tm_hour * 100 + tp->tm_min;
 972:     if (th < tl) {      /* crosses midnight */
 973:         if (tl <= tn || tn < th)
 974:             return MGrade;
 975:     } else {
 976:         if (tl <= tn && tn < th)
 977:             return MGrade;
 978:     }
 979:     return FAIL;
 980: }
 981: 
 982: /*
 983:  *	find first digit in string
 984:  *
 985:  *	return - pointer to first digit in string or end of string
 986:  */
 987: char *
 988: fdig(cp)
 989: register char *cp;
 990: {
 991:     register char *c;
 992: 
 993:     for (c = cp; *c; c++)
 994:         if (*c >= '0' && *c <= '9')
 995:             break;
 996:     return c;
 997: }
 998: 
 999: /*
1000:  * Compare strings:  s1>s2: >0  s1==s2: 0  s1<s2: <0
1001:  * Strings are compared as if they contain all capital letters.
1002:  */
1003: snccmp(s1, s2)
1004: register char *s1, *s2;
1005: {
1006:     char c1, c2;
1007: 
1008:     if (islower(*s1))
1009:         c1 = toupper(*s1);
1010:     else
1011:         c1 = *s1;
1012:     if (islower(*s2))
1013:         c2 = toupper(*s2);
1014:     else
1015:         c2 = *s2;
1016: 
1017:     while (c1 == c2) {
1018:         if (*s1++ == '\0')
1019:             return 0;
1020:         s2++;
1021:         if (islower(*s1))
1022:             c1 = toupper(*s1);
1023:         else
1024:             c1 = *s1;
1025:         if (islower(*s2))
1026:             c2 = toupper(*s2);
1027:         else
1028:             c2 = *s2;
1029:     }
1030:     return c1 - c2;
1031: }
1032: 
1033: /*
1034:  * Compare strings:  s1>s2: >0  s1==s2: 0  s1<s2: <0
1035:  * Strings are compared as if they contain all capital letters.
1036:  */
1037: sncncmp(s1, s2, n)
1038: register char *s1, *s2;
1039: register int n;
1040: {
1041:     char c1, c2;
1042: 
1043:     if (islower(*s1))
1044:         c1 = toupper(*s1);
1045:     else
1046:         c1 = *s1;
1047:     if (islower(*s2))
1048:         c2 = toupper(*s2);
1049:     else
1050:         c2 = *s2;
1051: 
1052:     while ( --n >= 0 && c1 == c2) {
1053:         if (*s1++ == '\0')
1054:             return 0;
1055:         s2++;
1056:         if (islower(*s1))
1057:             c1 = toupper(*s1);
1058:         else
1059:             c1 = *s1;
1060:         if (islower(*s2))
1061:             c2 = toupper(*s2);
1062:         else
1063:             c2 = *s2;
1064:     }
1065:     return n<0 ? 0 : (c1 - c2);
1066: }
1067: /*
1068:  * do chat script
1069:  * occurs after local port is opened,
1070:  * before 'dialing' the other machine.
1071:  */
1072: dochat(dev, flds, fd)
1073: register struct Devices *dev;
1074: char *flds[];
1075: int fd;
1076: {
1077:     register int i;
1078:     register char *p;
1079:     char bfr[sizeof(dev->D_argbfr)];
1080: 
1081:     if (dev->D_numargs <= 5)
1082:         return(0);
1083:     DEBUG(4, "dochat called %d\n", dev->D_numargs);
1084:     for (i = 0; i < dev->D_numargs-5; i++) {
1085:         sprintf(bfr, dev->D_arg[D_CHAT+i], flds[F_PHONE]);
1086:         if (strcmp(bfr, dev->D_arg[D_CHAT+i])) {
1087:             p = malloc((unsigned)strlen(bfr)+1);
1088:             if (p != NULL) {
1089:                 strcpy(p, bfr);
1090:                 dev->D_arg[D_CHAT+i] = p;
1091:             }
1092:         }
1093:     }
1094:     /* following is a kludge because login() arglist is a kludge */
1095:     i = login(dev->D_numargs, &dev->D_arg[D_CHAT-5], fd);
1096:     /*
1097: 	 * If login() last did a sendthem(), must pause so things can settle.
1098: 	 * But don't bother if chat failed.
1099: 	 */
1100:     if (i == 0 && (dev->D_numargs&01))
1101:         sleep(2);
1102:     return(i);
1103: }
1104: 
1105: /*
1106:  *	fix kill/echo/raw on line
1107:  *
1108:  *	return codes:  none
1109:  */
1110: fixmode(tty)
1111: register int tty;
1112: {
1113: #ifdef  USG
1114:     struct termio ttbuf;
1115: #else   !USG
1116:     struct sgttyb ttbuf;
1117: #endif	!USG
1118:     register struct sg_spds *ps;
1119:     int speed;
1120: 
1121:     if (IsTcpIp)
1122:         return;
1123: #ifdef  USG
1124:     ioctl(tty, TCGETA, &ttbuf);
1125:     ttbuf.c_iflag = ttbuf.c_oflag = ttbuf.c_lflag = (ushort)0;
1126:     speed = ttbuf.c_cflag &= (CBAUD);
1127:     ttbuf.c_cflag |= (CS8|CREAD);
1128:     ttbuf.c_cc[VMIN] = 6;
1129:     ttbuf.c_cc[VTIME] = 1;
1130:     ioctl(tty, TCSETA, &ttbuf);
1131: #else   !USG
1132:     ioctl(tty, TIOCGETP, &ttbuf);
1133:     ttbuf.sg_flags = (ANYP | RAW);
1134:     ioctl(tty, TIOCSETP, &ttbuf);
1135:     speed = ttbuf.sg_ispeed;
1136:     ioctl(tty, TIOCEXCL, STBNULL);
1137: #endif	!USG
1138: 
1139:     for (ps = spds; ps->sp_val; ps++)
1140:         if (ps->sp_name == speed) {
1141:             linebaudrate = ps->sp_val;
1142:             DEBUG(9,"Incoming baudrate is %d\n", linebaudrate);
1143:             return;
1144:         }
1145:     ASSERT(linebaudrate >= 0, "BAD SPEED", CNULL, speed);
1146: }

Defined functions

alarmtr defined in line 48; used 4 times
bld_partab defined in line 822; used 5 times
clsacu defined in line 268; used 6 times
conn defined in line 108; used 1 times
dochat defined in line 1072; never used
expect defined in line 578; used 2 times
exphone defined in line 300; used 1 times
fdig defined in line 987; used 2 times
finds defined in line 376; used 1 times
fixline defined in line 521; used 1 times
fixmode defined in line 1110; used 1 times
getnextfd defined in line 658; used 1 times
getto defined in line 222; used 2 times
ifadate defined in line 912; used 1 times
ifdate defined in line 861; used 1 times
login defined in line 409; used 3 times
notin defined in line 846; used 2 times
p_chwrite defined in line 808; used 7 times
rddev defined in line 348; used 3 times
sendthem defined in line 668; used 2 times
snccmp defined in line 1003; used 12 times
sncncmp defined in line 1037; used 1 times

Defined variables

AbortOn defined in line 39; used 7 times
Cjbuf defined in line 26; used 2 times
Dcf defined in line 103; used 13 times
Flds defined in line 104; used 8 times
LineType defined in line 105; used 6 times
PCFlds defined in line 69; used 7 times
PCP defined in line 44; used 5 times
PCP_brand defined in line 88; used 4 times
linebaudrate defined in line 41; used 4 times
next_fd defined in line 42; used 4 times
par_tab defined in line 40; used 6 times
sccsid defined in line 2; never used
spds defined in line 460; used 2 times

Defined struct's

sg_spds defined in line 460; used 4 times

Defined macros

ABORT defined in line 37; used 4 times
MAXC defined in line 23; used 4 times
MR defined in line 567; used 5 times
NPCFIELDS defined in line 67; used 1 times
PCP_BAUD defined in line 62; used 1 times
PCP_CALLBACK defined in line 64; used 1 times
PCP_CITY defined in line 65; used 1 times
PCP_PHONE defined in line 63; used 1 times
PCP_RPHONE defined in line 66; used 1 times
P_EVEN defined in line 34; used 3 times
P_ODD defined in line 35; used 2 times
P_ONE defined in line 33; used 2 times
P_ZERO defined in line 32; used 1 times
isoctal defined in line 786; used 2 times
Last modified: 1986-02-01
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4295
Valid CSS Valid XHTML 1.0 Strict