|
|
1.1 ! root 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: } ! 1147:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.