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