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: }