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

Defined functions

alarmtr defined in line 42; used 4 times
bld_partab defined in line 817; used 5 times
clsacu defined in line 263; used 6 times
conn defined in line 102; used 1 times
exphone defined in line 295; used 1 times
fdig defined in line 982; used 10 times
finds defined in line 371; used 1 times
fixmode defined in line 1105; used 1 times
getto defined in line 216; used 2 times
ifadate defined in line 907; used 1 times
ifdate defined in line 856; used 1 times
login defined in line 404; used 3 times
notin defined in line 841; used 2 times
p_chwrite defined in line 803; used 8 times
sendthem defined in line 663; used 11 times
snccmp defined in line 998; used 15 times
sncncmp defined in line 1032; used 1 times

Defined variables

AbortOn defined in line 33; used 7 times
Cjbuf defined in line 21; used 2 times
Dcf defined in line 97; used 13 times
Flds defined in line 98; used 8 times
LineType defined in line 99; used 6 times
PCFlds defined in line 63; used 7 times
PCP defined in line 38; used 5 times
PCP_brand defined in line 82; used 4 times
linebaudrate defined in line 35; used 4 times
next_fd defined in line 36; used 4 times
par_tab defined in line 34; used 6 times
sccsid defined in line 2; never used
spds defined in line 455; used 2 times

Defined struct's

sg_spds defined in line 455; used 4 times

Defined macros

ABORT defined in line 31; used 4 times
MAXC defined in line 18; used 4 times
MR defined in line 562; used 5 times
NPCFIELDS defined in line 61; used 1 times
PCP_BAUD defined in line 56; used 1 times
PCP_CALLBACK defined in line 58; used 1 times
PCP_CITY defined in line 59; used 1 times
PCP_PHONE defined in line 57; used 1 times
PCP_RPHONE defined in line 60; used 1 times
P_EVEN defined in line 28; used 3 times
P_ODD defined in line 29; used 2 times
P_ONE defined in line 27; used 2 times
P_ZERO defined in line 26; used 1 times
isoctal defined in line 781; used 2 times
Last modified: 1997-10-03
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 6915
Valid CSS Valid XHTML 1.0 Strict